ParseNode.st
author Claus Gittinger <cg@exept.de>
Thu, 28 Mar 2019 16:29:59 +0100
changeset 4402 365edc34920c
parent 4368 5a11adf556d7
child 4471 970c73f20faf
permissions -rw-r--r--
#REFACTORING by cg class: ObjectFileLoader class changed: #createLoadableObjectFor:

"{ Encoding: utf8 }"

"
 COPYRIGHT (c) 1989 by Claus Gittinger
	      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:libcomp' }"

"{ NameSpace: Smalltalk }"

Object subclass:#ParseNode
	instanceVariableNames:'parent type comments parenthized startPosition endPosition
		attributes'
	classVariableNames:''
	poolDictionaries:''
	category:'System-Compiler-Support'
!

!ParseNode class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1989 by Claus Gittinger
	      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
"
    node for parse-trees; abstract class
    This is a helper class for the compiler.

    [author:]
        Claus Gittinger
"
! !

!ParseNode class methodsFor:'instance creation'!

type:t
    ^ (self basicNew) type:t
! !

!ParseNode methodsFor:'accessing'!

enclosingBlock
    "Return closest enclosing block node or nil"

    | block |
    block := parent.
    [ block notNil and:[block realNode isBlockNode not] ] whileTrue:[
        block := block realNode parent.
    ].
    ^block.

    "Created: / 16-02-2012 / 22:46:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

endPosition
    "the node's last character position in the original source"

    ^ endPosition
!

endPosition:aCharacterPosition

    endPosition := aCharacterPosition

    "Modified: / 28-07-2011 / 10:03:53 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

line

    "Compatibility"

    ^self lineNumber

    "Created: / 09-07-2011 / 22:30:38 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

lineNumber

    ^nil

    "Created: / 09-07-2011 / 22:30:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

lineNumber:dummy
    "set linenumber - ignored here"

    ^ self
!

parent

    ^parent

    "Created: / 11-07-2011 / 17:36:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

parent: aParseNode

    parent := aParseNode

    "Created: / 11-07-2011 / 17:36:33 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

parenthesized
    ^ parenthized ? false
!

parenthesized:aBoolean
    parenthized := aBoolean
!

parenthized
    "obsolete - typo in message name - use parenthesized"

    ^ parenthized ? false
!

parenthized:aBoolean
    "obsolete - typo in message name - use parenthesized:"

    parenthized := aBoolean
!

realNode
    ^ self
!

selectorPartPositions:selectorPartPositions
    "/ ignored here, but implemented because sent without checking 
    "/ when parsing keyword messages to an optimized messageNode
    "/ (which become optimized to a constantNode by the folder)

    "Created: / 28-08-2013 / 21:17:22 / cg"
!

selectorPosition:aCharacterPosition
    "ignored here"

    "Created: 5.8.1997 / 16:32:17 / cg"
!

startPosition
    "the node's character position in the original source"

    ^ startPosition
!

startPosition:start

    startPosition := start

    "Modified: / 08-04-2011 / 22:03:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

startPosition:start endPosition: end
    startPosition := start.
    endPosition := end.

    "Created: / 11-07-2011 / 17:44:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 15-02-2019 / 14:39:10 / Claus Gittinger"
!

type
    "return the nodes type"

    ^ type
! !

!ParseNode methodsFor:'attributes access'!

objectAttributes

    ^attributes

    "Created: / 09-07-2011 / 12:17:55 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

objectAttributes: anObject

    attributes := anObject

    "Created: / 09-07-2011 / 12:18:08 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!ParseNode methodsFor:'checks'!

plausibilityCheckIn:aParser
    ^ nil
! !

!ParseNode methodsFor:'code generation'!

codeForSideEffectOn:aStream inBlock:b for:aCompiler
    "generate code for this statement - value not needed"

    self codeOn:aStream inBlock:b for:aCompiler.
    aStream nextPut:#drop
!

codeForSimpleReturnOn:aStream inBlock:b lineNumber:lineNrOrNil for:aCompiler
    "generate code to return myself as a simple method return"

    self codeOn:aStream inBlock:b for:aCompiler.
    lineNrOrNil notNil ifTrue:[
        self codeLineNumber:lineNrOrNil on:aStream for:aCompiler
    ].
    aStream nextPut:#retTop.


!

codeInlineOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler
    "generate code for this statement - value is needed"

    self codeOn:aStream inBlock:b for:aCompiler.
!

codeLineNumber:nr on:codeStream for:aCompiler
    "generate lineNumber information"

    aCompiler codeLineNumber:nr on:codeStream
!

codeOn:aStream inBlock:codeBlock for:aCompiler
    ^ self subclassResponsibility
! !

!ParseNode methodsFor:'code generation helpers'!

emitPushGlobalWithLiteralIndex:litIndex on:aTokenCodeStream for:aCompiler
    litIndex <= 255 ifTrue:[
        aTokenCodeStream nextPut:#pushGlobalS; nextPut:litIndex
    ] ifFalse:[
        litIndex <= 16rFFFF ifTrue:[
            aTokenCodeStream nextPut:#pushGlobalL; nextPut:litIndex; nextPut:0
        ] ifFalse:[
            aTokenCodeStream nextPut:#pushGlobalVL; nextPut:0; nextPut:litIndex; nextPut:0; nextPut:0; nextPut:0
        ].
    ].
!

emitPushLiteral:value on:aTokenCodeStream for:aCompiler
    |index|

    index := aCompiler addLiteral:value.
    self emitPushLiteralIndex:index on:aTokenCodeStream for:aCompiler
!

emitPushLiteralIndex:index on:aTokenCodeStream for:aCompiler
    index <= 8 ifTrue:[
        aTokenCodeStream 
            nextPut:(#(pushLit1 pushLit2 pushLit3 pushLit4
                       pushLit5 pushLit6 pushLit7 pushLit8) at:index).
    ] ifFalse:[
        index <= 255 ifTrue:[
            aTokenCodeStream nextPut:#pushLitS; nextPut:index
        ] ifFalse:[
            index <= 16rFFFF ifTrue:[
                aTokenCodeStream nextPut:#pushLitL; nextPut:index; nextPut:0
            ] ifFalse:[
                aTokenCodeStream nextPut:#pushLitVL; nextPut:0; nextPut:index; nextPut:0; nextPut:0; nextPut:0
            ]
        ].
    ].
!

emitSendLiteralIndex:litIndex numArgs:nargs line:lineNr on:aStream for:aCompiler
    lineNr >= 255 ifTrue:[
        self codeLineNumber: lineNr on: aStream for:aCompiler.  
    ].
    (litIndex <= 255) ifTrue:[
        nargs <= 3 ifTrue:[
            aStream 
                nextPut:(#(send0 send1 send2 send3) at:(nargs+1)); nextPut:lineNr; 
                nextPut:litIndex.
            ^ self.
        ].
        aStream 
            nextPut:#send; nextPut:lineNr; 
            nextPut:litIndex; 
            nextPut:nargs.
        ^ self.
    ].

    (litIndex <= 16rFFFF) ifTrue:[
        aStream 
            nextPut:#sendL; nextPut:lineNr; 
            nextPut:litIndex; nextPut:0; 
            nextPut:nargs.
        ^ self.
    ].

    aStream 
        nextPut:#sendVL; nextPut:0; nextPut:lineNr; 
        nextPut:litIndex; nextPut:0; nextPut:0; nextPut:0; 
        nextPut:nargs.

    "Modified: / 13-04-2013 / 11:02:20 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

emitStoreGlobalWithLiteralIndex:litIndex on:aTokenCodeStream for:aCompiler
    litIndex <= 255 ifTrue:[
        aTokenCodeStream nextPut:#storeGlobalS; nextPut:litIndex
    ] ifFalse:[
        litIndex <= 16rFFFF ifTrue:[
            aTokenCodeStream nextPut:#storeGlobalL; nextPut:litIndex; nextPut:0
        ] ifFalse:[
            aTokenCodeStream nextPut:#storeGlobalVL; nextPut:0; nextPut:litIndex; nextPut:0; nextPut:0; nextPut:0; nextPut:0
        ].
    ].
!

emitSuperSendLiteralIndex:litIndex classLiteralIndex:clsLitIndex numArgs:nargs line:lineNr on:aStream for:aCompiler
    lineNr >= 255 ifTrue:[
        self codeLineNumber: lineNr on: aStream for:aCompiler.  
    ].
    (litIndex <= 255 and:[clsLitIndex <= 255]) ifTrue:[
        aStream 
            nextPut:#superSend; nextPut:lineNr; 
            nextPut:litIndex; 
            nextPut:nargs; 
            nextPut:clsLitIndex.
    ] ifFalse:[
        (litIndex <= 16rFFFF and:[clsLitIndex <= 16rFFFF]) ifTrue:[
            aStream 
                nextPut:#superSendL; nextPut:lineNr; 
                nextPut:litIndex; nextPut:0; 
                nextPut:nargs; 
                nextPut:clsLitIndex; nextPut:0.
        ] ifFalse:[
            aStream 
                nextPut:#superSendVL; nextPut:0; nextPut:lineNr; 
                nextPut:litIndex; nextPut:0; nextPut:0; nextPut:0;
                nextPut:nargs; 
                nextPut:clsLitIndex; nextPut:0; nextPut:0; nextPut:0.
        ].
    ].

    "Modified: / 13-04-2013 / 11:01:51 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!ParseNode methodsFor:'enumeration'!

allNodesDo:aBlock
    "evaluate aBlock for each variable-node here and in subnodes"

    aBlock value:self.
    self allSubNodesDo:aBlock.
!

allSubNodesDo:aBlock
    "/ self subclassResponsibility.
!

messageNodesDo:aBlock
    "evaluate aBlock for each message-node here and in subnodes"

    self messagesDo:aBlock
!

messageSelectors
    "return a collection of message selectors"

    |setOfSymbols|

    setOfSymbols := Set new.
    self messageSelectorsDo:[:each | setOfSymbols add:each ].
    ^ setOfSymbols
!

messageSelectorsDo:aBlock
    "evaluate aBlock for each message-selector here and in subnodes"

    ^ self
!

messages
    "return a collection of messageNodes"

    |setOfMessages|

    setOfMessages := Set new.
    self messagesDo:[:each | setOfMessages add:each ].
    ^ setOfMessages
!

messagesDo:aBlock
    "evaluate aBlock for each message-node here and in subnodes"

    ^ self
!

variableNodesDo:aBlock
    "evaluate aBlock for each variable-node here and in subnodes"

    ^ self
! !

!ParseNode methodsFor:'evaluation'!

evaluate
    ^ self evaluateIn:nil
!

evaluateForCascade
    ^ self evaluateForCascadeIn:nil
!

evaluateForCascadeIn:anEnvironment
    ^ self evaluateIn:anEnvironment
!

evaluateIn:anEnvironment
    self subclassResponsibility
!

isStatement
^false.

    "Created: / 22-02-2011 / 16:29:50 / Jakub <zelenja7@fel.cvut.cz>"
! !

!ParseNode methodsFor:'printing & storing'!

printOn:aStream
    "append a user printed representation of the receiver to aStream.
     The format is suitable for a human - not meant to be read back."

    self printOn:aStream indent:0
!

printOn:aStream indent:indent
    "append a user printed representation of the receiver to aStream.
     The format is suitable for a human - not meant to be read back."

    self subclassResponsibility

    "Created: / 20-04-2005 / 14:21:46 / cg"
!

printOn:aStream indent:indent parenthized:parenthized
    parenthized ifTrue:[
        aStream nextPutAll:'('
    ].
    self printOn:aStream indent:indent.
    parenthized ifTrue:[
        aStream nextPutAll:')'
    ].

    "Created: / 20-04-2005 / 14:21:28 / cg"
! !

!ParseNode methodsFor:'private'!

type:t
    "set the nodes type"

    type := t
! !

!ParseNode methodsFor:'queries'!

canReuseAsArg:anotherNode
    ^ false

    "Created: 14.4.1996 / 00:43:08 / cg"
!

collectBlocksInto:aCollection
    ^ self

    "Created: 23.10.1996 / 15:45:00 / cg"
!

containsReturn
    ^ false
!

positionToInsertPeriodForStatementSeparation
    ^ self endPosition + (parenthized == true ifTrue:1 ifFalse:0)

    "Created: 14.4.1996 / 00:43:08 / cg"
!

precedence
    ^ 9999
!

withConstantValueDo:aBlock
    "return true, if this evaluates to a constant value
     and evaluate aBlock with it"

    ^ false
! !

!ParseNode methodsFor:'testing'!

isAssignment
    "return true, if this is a node for an assignment"

    ^ false
!

isBinaryMessage
    "return true, if this is a node for a binary send"

    ^ false
!

isBlockNode
    "return true, if this is a node for a block"

    ^ false
!

isBreakPointNode
    ^ false

    "Created: / 05-07-2011 / 21:14:01 / cg"
!

isCascade
    ^ false

    "Created: / 16.7.1998 / 20:11:33 / cg"
!

isCascadeToSuper
    ^ false

    "Created: / 16.7.1998 / 19:51:07 / cg"
!

isConstant
    "return true, if this is a node for a constant"

    ^ false
!

isConstantNumber
    "return true, if this is a node for a constant number"

    ^ false

    "Created: / 16-06-2018 / 08:47:03 / Claus Gittinger"
!

isErrorNode
    ^ false
!

isFunctionCallNode
    ^ false

    "Created: / 13-12-2018 / 22:35:28 / Claus Gittinger"
!

isFunctionNode
    ^ false

    "Created: / 08-02-2019 / 10:53:58 / Claus Gittinger"
!

isGlobal
    "return true, if this is a node for a global variable"

    ^ false
!

isGlobalNamed:globalName
    "return true, if this is a node for a particular global variable"

    ^ false

    "Created: / 05-03-2007 / 15:13:23 / cg"
!

isGlobalVariable
    ^ false
!

isImmutable
    "not used with ST/X - 
     for JavaScript nodes return true here."

    ^ true
!

isImplicitJavaScriptMessage
    "return true, if this is a node for an implicit getter/setter send"

    ^ false

    "Created: / 05-07-2010 / 14:11:41 / cg"
!

isInnerFunction
    ^ false
!

isInnerJavaScriptBlock
    ^ false
!

isJAVA
    "Return true, if receiver is global variable node JAVA.
     Used to highlight Java class references."

    ^false

    "Created: / 19-04-2012 / 09:36:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

isJavaPackageReference
    "Return true, given node is JAVA package reference in form:
        JAVA package1 package2 
    "

    ^false

    "Created: / 19-04-2012 / 09:53:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

isJavaScriptAndExpression
    ^ false
!

isJavaScriptArrayAccess
    "return true, if this is a node for a javascript array reference i.e. expr[]"

    ^ false

    "Created: / 05-07-2010 / 14:04:27 / cg"
!

isJavaScriptBlock
    "return true, if this is a node for a javascript block"

    ^ false

    "Created: / 09-06-2010 / 01:53:19 / cg"
!

isJavaScriptClassNode
    ^ false
!

isJavaScriptConditionalExpression
    "return true, if this is a node for a ?: expression"

    ^ false

    "Created: / 09-06-2010 / 01:55:15 / cg"
!

isJavaScriptOrExpression
    ^ false
!

isLiteral
    "for compatibility with RB-AST"

    ^ self isConstant
!

isLocalVariable
    ^ false
!

isMessage
    "return true, if this is a node for a message expression"

    ^ false
!

isMethodNode
    ^ false
!

isMethodVariable
    ^ false
!

isNew
    "return true, if this is a new XXXX node"

    ^ false
!

isPostIncDec
    "for JavaScript"

    ^ false
!

isPreIncDec
    "for JavaScript"

    ^ false
!

isPrimary
    "return true, if this is a node for a primary (i.e. non-send)"

    ^ false
!

isReturnNode
    "return true, if this is a node for a return expression"

    ^ false
!

isSelector
    ^ false

    "Created: / 28-02-2019 / 10:25:05 / Stefan Vogel"
!

isSelf
    "return true, if this is a self-node"

    ^ false
!

isStatementNode
    "return true, if this is a statement node"
    
    ^ false

    "Created: / 13-06-2011 / 11:26:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

isSuper
    "return true, if this is a super-node"

    ^ false
!

isThis
    "for JavaScript"

    ^ false
!

isUnaryMessage
    "return true, if this is a node for a unary send"

    ^ false
!

isVariable
    "return true, if this is a node for a variable"

    ^ false

    "Created: 14.4.1996 / 00:46:44 / cg"
!

isVariableNode
    "return true, if this is a node for a variable"

    ^ self isVariable

    "Created: / 12-09-2011 / 09:32:17 / cg"
! !

!ParseNode class methodsFor:'documentation'!

version
    ^ '$Header$'
!

version_CVS
    ^ '$Header$'
! !