Visitor.st
author Claus Gittinger <cg@exept.de>
Tue, 09 Jul 2019 20:55:17 +0200
changeset 24417 03b083548da2
parent 23193 0cd93aab464a
child 24791 b74d57425436
permissions -rw-r--r--
#REFACTORING by exept class: Smalltalk class changed: #recursiveInstallAutoloadedClassesFrom:rememberIn:maxLevels:noAutoload:packageTop:showSplashInLevels: Transcript showCR:(... bindWith:...) -> Transcript showCR:... with:...

"{ Encoding: utf8 }"

"
 COPYRIGHT (c) 2002 by eXept Software AG
              All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"
"{ Package: 'stx:libbasic' }"

"{ NameSpace: Smalltalk }"

Object subclass:#Visitor
	instanceVariableNames:''
	classVariableNames:''
	poolDictionaries:''
	category:'System-Visiting'
!

!Visitor class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 2002 by eXept Software AG
              All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"
!

documentation
"
    This class is abstract and implements the visitor pattern.
    It defines #visitXXX:with: messages for various kinds of objects.
    Any of these messages is eventually mapped to #visitObject:with:.

    When a class redefines #acceptVisitor:with:, an method has to be defined here, too.

    Subclasses have to define at least #visitObject:with:

    [author:]
        Stefan Vogel (stefan@zwerg)

    [see also:]
        Object>>acceptVisitor:with:
"
! !

!Visitor class methodsFor:'queries'!

isAbstract
    "Return if this class is an abstract class.
     True is returned here for myself only; false for subclasses.
     Abstract subclasses must redefine this again."

    ^ self == Visitor.
! !

!Visitor methodsFor:'helpers'!

doesNotUnderstand:aMessage
    "catch unimplemented #visitXXX:with: messages and redirect them to #visitObject:with:.
     maybe someone implemented an #acceptVisitor:with: in the XXX class and didn't
     implement the corresponding method here.

     This should not happen, and a error message is printed, because this can also
     occur due to a typo."

    |selector args|

    selector := aMessage selector.
    ((selector startsWith:'visit') and:[selector endsWith:'with:']) ifTrue:[
        ('Visitor: unimplemented #', selector, ' in class ', self className, '. Please define as #visitObject:with:') errorPrintCR.
        args := aMessage arguments.
        ^ self visitObject:(args at:1) with:(args at:2).
    ].

    ^ super doesNotUnderstand:aMessage

    "
       Visitor new visitFoo:#foo with:'arg'
    "
!

visitChildrenOf:anObject
    "recursively enumerate anObjects refs, visiting each of the child objects.
     nil children are not visited"

    |instVarNames theClass
     sz "{ Class: SmallInteger }"|

    theClass := anObject class.
    sz := theClass instSize.
    sz ~~ 0 ifTrue:[
        instVarNames := theClass allInstVarNames.
        1 to:sz do:[:i |  |ref|
            ref := anObject instVarAt:i.
            ref notNil ifTrue:[
                ref acceptVisitor:self with:(instVarNames at:i).
                self nextObject.
            ].
        ].
    ].

    theClass isVariable ifTrue:[
        sz := anObject basicSize.
        sz ~~ 0 ifTrue:[
            1 to:sz do:[:i |
                (anObject basicAt:i) acceptVisitor:self with:i.
                self nextObject.
            ]
        ].
    ].

    "Modified (comment): / 09-11-2017 / 10:46:55 / mawalch"
! !

!Visitor methodsFor:'subclass responsibility'!

nextObject
    "this is sent, when a new Object is going to be visited.
     Subclasses may redefine this to perform specific actions"

    ^ self 
!

visitObject:anObject with:aParameter
    "visit an object. Subclasses must at least implement this method"

    self subclassResponsibility
!

visitProtoObject:anObject with:aParameter
    "visit a proto object."

    "/ ^ self visitObject:anObject with:aParameter
    self subclassResponsibility

    "Created: / 04-07-2018 / 00:43:49 / Claus Gittinger"
! !

!Visitor methodsFor:'visiting smalltalk types'!

visitBehavior:aSymbol with:aParameter
    "visit a class - fallback here is to call visitObject"

    self visitObject:aSymbol with:aParameter
!

visitBitArray:aByteArray with:aParameter
    "visit an absolute time value"

    self visitSequenceableCollection:aByteArray with:aParameter
!

visitBlock:aBlock with:aParameter

    self visitObject:aBlock with:aParameter
!

visitBoolean:aBoolean with:aParameter
    "visit a Boolean - fallback here is to call visitObject"

    self visitObject:aBoolean with:aParameter
!

visitByteArray:aByteArray with:aParameter
    "visit a ByteArray value"

    self visitSequenceableCollection:aByteArray with:aParameter
!

visitCharacter:aCharacter with:aParameter
    "visit a Character - fallback here is to call visitObject"

    self visitObject:aCharacter with:aParameter
!

visitCollection:aCollection with:aParameter
    "visit a Collection - fallback here is to call visitObject"

    self visitObject:aCollection with:aParameter
!

visitDate:aDate with:aParameter
    "visit a date value - fallback here is to call visitObject"

    self visitObject:aDate with:aParameter
!

visitDictionary:aDictionary with:aParameter
    "visit a Dictionary"

    self visitCollection:aDictionary with:aParameter
!

visitFloat:aFloat with:aParameter
    "visit a Float"

    self visitNumber:aFloat with:aParameter
!

visitFraction:aFraction with:aParameter
    "visit a Fraction"

    self visitNumber:aFraction with:aParameter
!

visitInteger:anInteger with:aParameter
    "visit an Integer"

    self visitNumber:anInteger with:aParameter
!

visitInterval:anInterval with:aParameter
    "intervals are a special flavor of sequenceable collection (saving memory)
     We treat it as SequenceableCollection by default.
     Encoders that do a dense representation, redefine this to #visitObject"

    ^ self visitSequenceableCollection:anInterval with:aParameter
!

visitNilWith:aParameter
    "visit nil - fallback here is to call visitObject"

    self visitObject:nil with:aParameter
!

visitNumber:aNumber with:aParameter
    "visit any number  - fallback here is to call visitObject"

    self visitObject:aNumber with:aParameter
!

visitSequenceableCollection:aCollection with:aParameter
    "visit a SequenceableCollection"

    self visitCollection:aCollection with:aParameter
!

visitSet:aCollection with:aParameter
    "visit a Set"

    self visitCollection:aCollection with:aParameter
!

visitStream:aStream with:aParameter
    "visit a Stream - fallback here is to call visitObject"

    self visitObject:aStream with:aParameter
!

visitString:aString with:aParameter
    "visit a String - fallback here is to call visitObject"

    self visitObject:aString with:aParameter
!

visitSymbol:aSymbol with:aParameter
    "visit a Symbol"

    ^ self visitString:aSymbol with:aParameter
!

visitTime:aTime with:aParameter
    "visit a time value - fallback here is to call visitObject"

    self visitObject:aTime with:aParameter
!

visitTimestamp:aTimestamp with:aParameter
    "visit an timestamp value - fallback here is to call visitObject"

    self visitObject:aTimestamp with:aParameter
!

visitUtcTimestamp:aTimestamp with:aParameter
    "visit an UTC timestamp value - fallback here is to call visitObject"

    self visitTimestamp:aTimestamp with:aParameter
! !

!Visitor class methodsFor:'documentation'!

version
    ^ '$Header$'
!

version_CVS
    ^ '$Header$'
! !