"
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' }"
ParseNode subclass:#AssignmentNode
instanceVariableNames:'variable expression lineNr'
classVariableNames:''
poolDictionaries:''
category:'System-Compiler-Support'
!
!AssignmentNode 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, representing assignments.
This is a helper class for the compiler.
[author:]
Claus Gittinger
"
! !
!AssignmentNode class methodsFor:'instance creation'!
variable:v expression:e
^ (self basicNew) variable:v expression:e
! !
!AssignmentNode methodsFor:'accessing'!
expression
^ expression
!
lineNumber
"return lineNr"
^ lineNr
"Created: / 14.5.1998 / 19:30:49 / cg"
!
lineNumber:something
"set lineNr"
lineNr := something.
"Created: / 14.5.1998 / 19:30:54 / cg"
!
variable
^ variable
"Created: 19.6.1997 / 17:08:58 / cg"
!
variable:v expression:e
variable := v.
expression := e.
"/ any block, which gets assigned to something
"/ cannot be inlined.
e isBlockNode ifTrue:[
e possiblyInlined:false
]
! !
!AssignmentNode methodsFor:'code generation'!
checkIncDecOn:aStream
"check if we can use incMvar / decMvar instruction.
If so, code it and return true.
Otherwise, return false."
|sel erec arg code|
(variable type == #MethodVariable) ifTrue:[
expression isBinaryMessage ifTrue:[
sel := expression selector.
erec := expression receiver.
((sel == #+) or:[sel == #-]) ifTrue:[
(erec type == #MethodVariable) ifTrue:[
(erec index == variable index) ifTrue:[
arg := expression arg1.
arg isConstant ifTrue:[
(arg value == 1) ifTrue:[
(sel == #+) ifTrue:[
code := #incMethodVar
] ifFalse:[
code := #decMethodVar
].
aStream nextPut:code; nextPut:(expression lineNumber); nextPut:(variable index).
^ true
]
]
]
]
]
]
].
^ false
"Modified: 1.3.1996 / 00:08:02 / cg"
!
codeForSideEffectOn:aStream inBlock:b for:aCompiler
(self checkIncDecOn:aStream) ifTrue:[^ self].
self codeNormalOn:aStream valueNeeded:false inBlock:b for:aCompiler
"Modified: 4.9.1995 / 14:38:10 / claus"
"Modified: 1.3.1996 / 00:42:10 / cg"
!
codeNormalOn:aStream valueNeeded:forValue inBlock:b for:aCompiler
|isSend litIdx selLitIdx|
isSend := expression isMessage.
(lineNr notNil
and:[isSend not]) ifTrue:[
self codeLineNumber:lineNr on:aStream for:aCompiler
].
"/ must do workspace variables here, because these
"/ need the receiver (the valueHolder) to be pushed first,
"/ then the value which is to be stored.
"/ finally, a #value: message is generated.
(variable type == #WorkspaceVariable) ifTrue:[
"/ this is done by keeping the valueHolder in the literalArray,
"/ and coding a #value: message here.
litIdx := aCompiler addLiteral:variable token.
aStream nextPut:#pushLitS; nextPut:litIdx.
expression codeOn:aStream inBlock:b for:aCompiler.
selLitIdx := aCompiler addLiteral:#value:.
selLitIdx <= 255 ifTrue:[
aStream nextPut:#send1; nextPut:(lineNr ? 1); nextPut:selLitIdx.
] ifFalse:[
aStream nextPut:#sendL; nextPut:(lineNr ? 1); nextPut:selLitIdx; nextPut:0; nextPut:1 "nargs".
].
aStream nextPut:#drop.
forValue ifTrue:[
(expression isConstant or:[expression isVariable]) ifTrue:[
expression codeOn:aStream inBlock:b for:aCompiler.
] ifFalse:[
"/ fetch value from the holder - sigh
aStream nextPut:#pushLitS; nextPut:litIdx.
selLitIdx := aCompiler addLiteral:#value.
selLitIdx <= 255 ifTrue:[
aStream nextPut:#send0; nextPut:(lineNr ? 1); nextPut:selLitIdx.
] ifFalse:[
aStream nextPut:#sendL; nextPut:(lineNr ? 1); nextPut:selLitIdx; nextPut:0; nextPut:1 "nargs".
].
]
].
^ self
].
expression codeOn:aStream inBlock:b for:aCompiler.
expression isBlock ifTrue:[
variable isLocal ifTrue:[
aStream nextPut:#blockRef
]
].
(lineNr notNil
and:[isSend]) ifTrue:[
self codeLineNumber:lineNr on:aStream for:aCompiler
].
variable codeStoreOn:aStream inBlock:b valueNeeded:forValue for:aCompiler
"Modified: 4.9.1995 / 14:38:10 / claus"
"Created: 1.3.1996 / 00:41:43 / cg"
"Modified: 21.10.1996 / 16:26:33 / cg"
!
codeOn:aStream inBlock:b for:aCompiler
(self checkIncDecOn:aStream) ifTrue:[
expression receiver codeOn:aStream inBlock:b for:aCompiler.
^ self
].
self codeNormalOn:aStream valueNeeded:true inBlock:b for:aCompiler
"Modified: 1.3.1996 / 00:42:21 / cg"
! !
!AssignmentNode methodsFor:'enumerating'!
nodeDo:anEnumerator
"helper for parse tree walking"
^ anEnumerator doAssignment:self variable:variable value:expression
"Modified: 19.6.1997 / 16:37:50 / cg"
! !
!AssignmentNode methodsFor:'evaluation'!
evaluateIn:anEnvironment
|value|
value := expression evaluateIn:anEnvironment.
variable store:value.
^ value
! !
!AssignmentNode methodsFor:'printing & storing'!
printOn:aStream indent:i
variable printOn:aStream.
self printOperatorOn:aStream.
expression printOn:aStream
!
printOperatorOn:aStream
aStream nextPutAll:' := '.
! !
!AssignmentNode methodsFor:'queries'!
collectBlocksInto:aCollection
expression collectBlocksInto:aCollection.
"Created: 11.1.1997 / 20:54:30 / cg"
!
isAssignment
"return true, if this is a node for an assignment"
^ true
!
precedence
^ 0
"Created: / 20-04-2005 / 14:11:09 / cg"
! !
!AssignmentNode class methodsFor:'documentation'!
version
^ '$Header: /cvs/stx/stx/libcomp/AssignmentNode.st,v 1.36 2005-04-20 14:43:10 cg Exp $'
! !