123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696 |
- Smalltalk current createPackage: 'Compiler-Visitors' properties: #{}!
- AbstractCodeGenerator subclass: #ImpCodeGenerator
- instanceVariableNames: 'stream nestedBlocks earlyReturn currentSelector unknownVariables tempVariables messageSends referencedClasses classReferenced argVariables mutables target lazyVars realVarNames'
- package: 'Compiler-Visitors'!
- !ImpCodeGenerator methodsFor: 'accessing'!
- argVariables
- ^argVariables copy
- !
- knownVariables
- ^self pseudoVariables
- addAll: self tempVariables;
- addAll: self argVariables;
- yourself
- !
- tempVariables
- ^tempVariables copy
- !
- unknownVariables
- ^unknownVariables copy
- ! !
- !ImpCodeGenerator methodsFor: 'compilation DSL'!
- aboutToModifyState
- | list old |
- list := mutables.
- mutables := Set new.
- old := self switchTarget: nil.
- list do: [ :each | | value |
- self switchTarget: each.
- self realAssign: (lazyVars at: each)
- ].
- self switchTarget: old
- !
- ifValueWanted: aBlock
- target ifNotNil: aBlock
- !
- isolated: node
- ^ self visit: node targetBeing: self nextLazyvarName
- !
- isolatedUse: node
- | old |
- old := self switchTarget: self nextLazyvarName.
- self visit: node.
- ^self useValueNamed: (self switchTarget: old)
- !
- lazyAssign: aString dependsOnState: aBoolean
- (lazyVars includesKey: target)
- ifTrue: [ lazyVars at: target put: aString. aBoolean ifTrue: [ mutables add: target ] ]
- ifFalse: [ self realAssign: aString ]
- !
- lazyAssignExpression: aString
- self lazyAssign: aString dependsOnState: true
- !
- lazyAssignValue: aString
- self lazyAssign: aString dependsOnState: false
- !
- makeTargetRealVariable
- (lazyVars includesKey: target) ifTrue: [
- lazyVars removeKey: target.
- lazyVars at: 'assigned ',target put: nil. "<-- only to retain size, it is used in nextLazyvarName"
- realVarNames add: target ].
- !
- nextLazyvarName
- | name |
- name := '$', lazyVars size asString.
- lazyVars at: name put: name.
- ^name
- !
- nilIfValueWanted
- target ifNotNil: [ self lazyAssignValue: 'nil' ]
- !
- realAssign: aString
- | closer |
- aString ifNotEmpty: [
- self aboutToModifyState.
- closer := ''.
- self ifValueWanted: [ stream nextPutAll:
- (target = '^' ifTrue: ['return '] ifFalse: [
- target = '!!' ifTrue: [ closer := ']'. 'throw $early=['] ifFalse: [
- target, '=']]) ].
- self makeTargetRealVariable.
- stream nextPutAll: aString, closer, ';', self mylf ]
- !
- switchTarget: aString
- | old |
- old := target.
- target := aString.
- ^old
- !
- useValueNamed: key
- | val |
- (realVarNames includes: key) ifTrue: [ ^key ].
- mutables remove: key.
- ^lazyVars at: key
- !
- visit: aNode targetBeing: aString
- | old |
- old := self switchTarget: aString.
- self visit: aNode.
- ^ self switchTarget: old.
- ! !
- !ImpCodeGenerator methodsFor: 'compiling'!
- compileNode: aNode
- stream := '' writeStream.
- self visit: aNode.
- ^stream contents
- ! !
- !ImpCodeGenerator methodsFor: 'initialization'!
- initialize
- super initialize.
- stream := '' writeStream.
- unknownVariables := #().
- tempVariables := #().
- argVariables := #().
- messageSends := #().
- classReferenced := #().
- mutables := Set new.
- realVarNames := Set new.
- lazyVars := HashedCollection new.
- target := nil
- ! !
- !ImpCodeGenerator methodsFor: 'optimizations'!
- checkClass: aClassName for: receiver
- self prvCheckClass: aClassName for: receiver.
- stream nextPutAll: '{'
- !
- checkClass: aClassName for: receiver includeIf: aBoolean
- self prvCheckClass: aClassName for: receiver.
- stream nextPutAll: (aBoolean ifTrue: ['if(('] ifFalse: ['if(!!(']), (self useValueNamed: receiver), ')) {'
- !
- inline: aSelector receiver: receiver argumentNodes: aCollection
- "-- Booleans --"
- (aSelector = 'ifFalse:') ifTrue: [
- aCollection first isBlockNode ifTrue: [
- self checkClass: 'Boolean' for: receiver includeIf: false.
- self prvPutAndElse: [ self visit: aCollection first nodes first ].
- self prvPutAndElse: [ self nilIfValueWanted ].
- ^true]].
- (aSelector = 'ifTrue:') ifTrue: [
- aCollection first isBlockNode ifTrue: [
- self checkClass: 'Boolean' for: receiver includeIf: true.
- self prvPutAndElse: [ self visit: aCollection first nodes first ].
- self prvPutAndElse: [ self nilIfValueWanted ].
- ^true]].
- (aSelector = 'ifTrue:ifFalse:') ifTrue: [
- (aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [
- self checkClass: 'Boolean' for: receiver includeIf: true.
- self prvPutAndElse: [ self visit: aCollection first nodes first ].
- self prvPutAndElse: [ self visit: aCollection second nodes first ].
- ^true]].
- (aSelector = 'ifFalse:ifTrue:') ifTrue: [
- (aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [
- self checkClass: 'Boolean' for: receiver includeIf: false.
- self prvPutAndElse: [ self visit: aCollection first nodes first ].
- self prvPutAndElse: [ self visit: aCollection second nodes first ].
- ^true]].
- "-- Numbers --"
- (aSelector = '<') ifTrue: [ | operand |
- operand := self isolatedUse: aCollection first.
- self checkClass: 'Number' for: receiver.
- self prvPutAndElse: [
- self lazyAssignExpression: '(', (self useValueNamed: receiver), '<', operand, ')' ].
- ^{ VerbatimNode new value: operand }].
- (aSelector = '<=') ifTrue: [ | operand |
- operand := self isolatedUse: aCollection first.
- self checkClass: 'Number' for: receiver.
- self prvPutAndElse: [
- self lazyAssignExpression: '(', (self useValueNamed: receiver), '<=', operand, ')' ].
- ^{ VerbatimNode new value: operand }].
- (aSelector = '>') ifTrue: [ | operand |
- operand := self isolatedUse: aCollection first.
- self checkClass: 'Number' for: receiver.
- self prvPutAndElse: [
- self lazyAssignExpression: '(', (self useValueNamed: receiver), '>', operand, ')' ].
- ^{ VerbatimNode new value: operand }].
- (aSelector = '>=') ifTrue: [ | operand |
- operand := self isolatedUse: aCollection first.
- self checkClass: 'Number' for: receiver.
- self prvPutAndElse: [
- self lazyAssignExpression: '(', (self useValueNamed: receiver), '>=', operand, ')' ].
- ^{ VerbatimNode new value: operand }].
- (aSelector = '+') ifTrue: [ | operand |
- operand := self isolatedUse: aCollection first.
- self checkClass: 'Number' for: receiver.
- self prvPutAndElse: [
- self lazyAssignExpression: '(', (self useValueNamed: receiver), '+', operand, ')' ].
- ^{ VerbatimNode new value: operand }].
- (aSelector = '-') ifTrue: [ | operand |
- operand := self isolatedUse: aCollection first.
- self checkClass: 'Number' for: receiver.
- self prvPutAndElse: [
- self lazyAssignExpression: '(', (self useValueNamed: receiver), '-', operand, ')' ].
- ^{ VerbatimNode new value: operand }].
- (aSelector = '*') ifTrue: [ | operand |
- operand := self isolatedUse: aCollection first.
- self checkClass: 'Number' for: receiver.
- self prvPutAndElse: [
- self lazyAssignExpression: '(', (self useValueNamed: receiver), '*', operand, ')' ].
- ^{ VerbatimNode new value: operand }].
- (aSelector = '/') ifTrue: [ | operand |
- operand := self isolatedUse: aCollection first.
- self checkClass: 'Number' for: receiver.
- self prvPutAndElse: [
- self lazyAssignExpression: '(', (self useValueNamed: receiver), '/', operand, ')' ].
- ^{ VerbatimNode new value: operand }].
- ^nil
- !
- inlineLiteral: aSelector receiverNode: anObject argumentNodes: aCollection
- | inlined |
- inlined := false.
-
- "-- BlockClosures --"
- (aSelector = 'whileTrue:') ifTrue: [
- (anObject isBlockNode and: [aCollection first isBlockNode]) ifTrue: [ | old |
- self prvWhileConditionStatement: 'for(;;){' pre: 'if (!!(' condition: anObject post: ')) {'.
- stream nextPutAll: 'break}', self mylf.
- self prvPutAndClose: [ self visit: aCollection first nodes first targetBeing: nil ].
- inlined := true]].
- (aSelector = 'whileFalse:') ifTrue: [
- (anObject isBlockNode and: [aCollection first isBlockNode]) ifTrue: [ | old |
- self prvWhileConditionStatement: 'for(;;){' pre: 'if ((' condition: anObject post: ')) {'.
- stream nextPutAll: 'break}', self mylf.
- self prvPutAndClose: [ self visit: aCollection first nodes first targetBeing: nil ].
- inlined := true]].
- (aSelector = 'whileTrue') ifTrue: [
- anObject isBlockNode ifTrue: [
- self prvWhileConditionStatement: 'do{' pre: '}while((' condition: anObject post: '));', self mylf.
- inlined := true]].
- (aSelector = 'whileFalse') ifTrue: [
- anObject isBlockNode ifTrue: [
- self prvWhileConditionStatement: 'do{' pre: '}while(!!(' condition: anObject post: '));', self mylf.
- inlined := true]].
- "-- Numbers --"
- (#('+' '-' '*' '/' '<' '<=' '>=' '>') includes: aSelector) ifTrue: [
- (self prvInlineNumberOperator: aSelector on: anObject and: aCollection first) ifTrue: [
- inlined := true]].
-
- "-- UndefinedObject --"
- (aSelector = 'ifNil:') ifTrue: [
- aCollection first isBlockNode ifTrue: [ | rcv |
- self aboutToModifyState.
- rcv := self isolatedUse: anObject.
- rcv = 'super' ifTrue: [ rcv := 'self' ].
- self makeTargetRealVariable.
- stream nextPutAll: 'if((', rcv, ') === nil || (', rcv, ') == null) {'.
- self prvPutAndElse: [ self visit: aCollection first nodes first ].
- self prvPutAndClose: [ self lazyAssignValue: rcv ].
- inlined := true]].
- (aSelector = 'ifNotNil:') ifTrue: [
- aCollection first isBlockNode ifTrue: [ | rcv |
- self aboutToModifyState.
- rcv := self isolatedUse: anObject.
- rcv = 'super' ifTrue: [ rcv := 'self' ].
- self makeTargetRealVariable.
- stream nextPutAll: 'if((', rcv, ') !!== nil && (', rcv, ') !!= null) {'.
- self prvPutAndElse: [ self visit: aCollection first nodes first ].
- self prvPutAndClose: [ self lazyAssignValue: rcv ].
- inlined := true]].
- (aSelector = 'ifNil:ifNotNil:') ifTrue: [
- (aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [ | rcv |
- self aboutToModifyState.
- rcv := self isolatedUse: anObject.
- rcv = 'super' ifTrue: [ rcv := 'self' ].
- self makeTargetRealVariable.
- stream nextPutAll: 'if((', rcv, ') === nil || (', rcv, ') == null) {'.
- self prvPutAndElse: [ self visit: aCollection first nodes first ].
- self prvPutAndClose: [ self visit: aCollection second nodes first ].
- inlined := true]].
- (aSelector = 'ifNotNil:ifNil:') ifTrue: [
- (aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [ | rcv |
- self aboutToModifyState.
- rcv := self isolatedUse: anObject.
- rcv = 'super' ifTrue: [ rcv := 'self' ].
- self makeTargetRealVariable.
- stream nextPutAll: 'if((', rcv, ') !!== nil && (', rcv, ') !!= null) {'.
- self prvPutAndElse: [ self visit: aCollection first nodes first ].
- self prvPutAndClose: [ self visit: aCollection second nodes first ].
- inlined := true]].
- (aSelector = 'isNil') ifTrue: [ | rcv |
- rcv := self isolatedUse: anObject.
- rcv = 'super' ifTrue: [ rcv := 'self' ].
- self lazyAssignValue: '((', rcv, ') === nil || (', rcv, ') == null)'.
- inlined := true].
- (aSelector = 'notNil') ifTrue: [ | rcv |
- rcv := self isolatedUse: anObject.
- rcv = 'super' ifTrue: [ rcv := 'self' ].
- self lazyAssignValue: '((', rcv, ') !!== nil && (', rcv, ') !!= null)'.
- inlined := true].
- ^inlined
- !
- isNode: aNode ofClass: aClass
- ^aNode isValueNode and: [
- aNode value class = aClass or: [
- aNode value = 'self' and: [self currentClass = aClass]]]
- !
- prvCheckClass: aClassName for: receiver
- self makeTargetRealVariable.
- self aboutToModifyState.
- stream nextPutAll: 'if((', (self useValueNamed: receiver), ').klass === smalltalk.', aClassName, ') '
- !
- prvInlineNumberOperator: aSelector on: receiverNode and: operandNode
- (aSelector = aSelector) ifTrue: [
- (self isNode: receiverNode ofClass: Number) ifTrue: [
- | rcv operand |
- rcv := self isolated: receiverNode.
- operand := self isolated: operandNode.
- self lazyAssignValue: ((self useValueNamed: rcv), aSelector, (self useValueNamed: operand)).
- ^true]].
- ^false
- !
- prvWhileConditionStatement: stmtString pre: preString condition: anObject post: postString
- | x |
- stream nextPutAll: stmtString.
- x := self isolatedUse: anObject nodes first.
- x ifEmpty: [ x := '"should not reach - receiver includes ^"' ].
- stream nextPutAll: preString, x, postString.
- self nilIfValueWanted
- ! !
- !ImpCodeGenerator methodsFor: 'output'!
- mylf
- ^String lf, ((Array new: nestedBlocks+2) join: String tab)
- !
- prvPutAndClose: aBlock
- aBlock value.
- stream nextPutAll: '}', self mylf
- !
- prvPutAndElse: aBlock
- aBlock value.
- stream nextPutAll: '} else {'
- !
- putTemps: temps
- temps ifNotEmpty: [
- stream nextPutAll: 'var '.
- temps do: [:each | | temp |
- temp := self safeVariableNameFor: each.
- tempVariables add: temp.
- stream nextPutAll: temp, '=nil'] separatedBy: [ stream nextPutAll: ',' ].
- stream nextPutAll: ';', self mylf
- ]
- ! !
- !ImpCodeGenerator methodsFor: 'testing'!
- assert: aBoolean
- aBoolean ifFalse: [ self error: 'assertion failed' ]
- !
- performOptimizations
- ^self class performOptimizations
- ! !
- !ImpCodeGenerator methodsFor: 'visiting'!
- send: aSelector to: aReceiver arguments: aCollection superSend: aBoolean
- | args |
- args := self isolated: (DynamicArrayNode new nodes: aCollection; yourself).
- self lazyAssignExpression: (String streamContents: [ :str |
- str nextPutAll: 'smalltalk.send('.
- str nextPutAll: (self useValueNamed: aReceiver).
- str nextPutAll: ', "', aSelector asSelector, '", '.
- str nextPutAll: (self useValueNamed: args).
- aBoolean ifTrue: [
- str nextPutAll: ', smalltalk.', (self classNameFor: self currentClass superclass)].
- str nextPutAll: ')'
- ])
- !
- sequenceOfNodes: nodes temps: temps
- nodes isEmpty
- ifFalse: [ | old index |
- self putTemps: temps.
- old :=self switchTarget: nil.
- index := 0.
- nodes do: [:each |
- index := index + 1.
- index = nodes size ifTrue: [ self switchTarget: old ].
- self visit: each ]]
- ifTrue: [ self nilIfValueWanted ]
- !
- visit: aNode
- aNode accept: self
- !
- visitAssignmentNode: aNode
- | olds oldt |
- olds := stream.
- stream := '' writeStream.
- oldt := self switchTarget: self nextLazyvarName.
- self visit: aNode left.
- self assert: (lazyVars at: target) ~= target.
- self switchTarget: (self useValueNamed: (self switchTarget: nil)).
- self assert: (lazyVars includesKey: target) not.
- stream := olds.
- self visit: aNode right.
- olds := self switchTarget: oldt.
- self ifValueWanted: [ self lazyAssignExpression: olds ]
- !
- visitBlockNode: aNode
- | oldt olds oldm |
- self assert: aNode nodes size = 1.
- oldt := self switchTarget: '^'.
- olds := stream.
- stream := '' writeStream.
- stream nextPutAll: '(function('.
- aNode parameters
- do: [:each |
- tempVariables add: each.
- stream nextPutAll: each]
- separatedBy: [stream nextPutAll: ', '].
- stream nextPutAll: '){'.
- nestedBlocks := nestedBlocks + 1.
- oldm := mutables.
- mutables := Set new.
- self visit: aNode nodes first.
- self assert: mutables isEmpty.
- mutables := oldm.
- nestedBlocks := nestedBlocks - 1.
- stream nextPutAll: '})'.
- self switchTarget: oldt.
- oldt := stream contents.
- stream := olds.
- self lazyAssignExpression: oldt
- !
- visitBlockSequenceNode: aNode
- self sequenceOfNodes: aNode nodes temps: aNode temps
- !
- visitCascadeNode: aNode
- | rcv |
- rcv := self isolated: aNode receiver.
- self aboutToModifyState.
- rcv := self useValueNamed: rcv.
- aNode nodes do: [:each |
- each receiver: (VerbatimNode new value: rcv) ].
- self sequenceOfNodes: aNode nodes temps: #()
- !
- visitClassReferenceNode: aNode
- (referencedClasses includes: aNode value) ifFalse: [
- referencedClasses add: aNode value].
- self lazyAssignExpression: '(smalltalk.', aNode value, ' || ', aNode value, ')'
- !
- visitDynamicArrayNode: aNode
- | args |
- args :=aNode nodes collect: [ :node | self isolated: node ].
- self lazyAssignValue: (String streamContents: [ :str |
- str nextPutAll: '['.
- args
- do: [:each | str nextPutAll: (self useValueNamed: each) ]
- separatedBy: [str nextPutAll: ', '].
- str nextPutAll: ']'
- ])
- !
- visitDynamicDictionaryNode: aNode
- | elements |
- elements := self isolated: (DynamicArrayNode new nodes: aNode nodes; yourself).
- self lazyAssignValue: 'smalltalk.HashedCollection._fromPairs_(', (self useValueNamed: elements), ')'
- !
- visitFailure: aFailure
- self error: aFailure asString
- !
- visitJSStatementNode: aNode
- self aboutToModifyState.
- stream nextPutAll: ';', (aNode source replace: '>>' with: '>'), ';', self mylf
- !
- visitMethodNode: aNode
- | str currentSelector |
- currentSelector := aNode selector asSelector.
- nestedBlocks := 0.
- earlyReturn := false.
- messageSends := #().
- referencedClasses := #().
- unknownVariables := #().
- tempVariables := #().
- argVariables := #().
- lazyVars := HashedCollection new.
- mutables := Set new.
- realVarNames := Set new.
- stream
- nextPutAll: 'smalltalk.method({'; lf;
- nextPutAll: 'selector: "', aNode selector, '",'; lf.
- stream nextPutAll: 'source: ', self source asJavascript, ',';lf.
- stream nextPutAll: 'fn: function('.
- aNode arguments
- do: [:each |
- argVariables add: each.
- stream nextPutAll: each]
- separatedBy: [stream nextPutAll: ', '].
- stream
- nextPutAll: '){var self=this;', self mylf.
- str := stream.
- stream := '' writeStream.
- self switchTarget: nil.
- self assert: aNode nodes size = 1.
- self visit: aNode nodes first.
- realVarNames ifNotEmpty: [ str nextPutAll: 'var ', (realVarNames asArray join: ','), ';', self mylf ].
- earlyReturn ifTrue: [
- str nextPutAll: 'var $early={}; try{', self mylf].
- str nextPutAll: stream contents.
- stream := str.
- (aNode nodes first nodes notEmpty and: [ |checker|
- checker := ReturnNodeChecker new.
- checker visit: aNode nodes first nodes last.
- checker wasReturnNode]) ifFalse: [ self switchTarget: '^'. self lazyAssignValue: 'self'. self switchTarget: nil ].
- earlyReturn ifTrue: [
- stream nextPutAll: '} catch(e) {if(e===$early) return e[0]; throw e}'].
- stream nextPutAll: '}'.
- stream
- nextPutAll: ',', String lf, 'messageSends: ';
- nextPutAll: messageSends asJavascript, ','; lf;
- nextPutAll: 'args: ', argVariables asJavascript, ','; lf;
- nextPutAll: 'referencedClasses: ['.
- referencedClasses
- do: [:each | stream nextPutAll: each printString]
- separatedBy: [stream nextPutAll: ','].
- stream nextPutAll: ']'.
- stream nextPutAll: '})'.
- self assert: mutables isEmpty
- !
- visitReturnNode: aNode
- self assert: aNode nodes size = 1.
- nestedBlocks > 0 ifTrue: [
- earlyReturn := true].
- self
- visit: aNode nodes first
- targetBeing: (nestedBlocks > 0 ifTrue: ['!!'] ifFalse: ['^']).
- self lazyAssignValue: ''
- !
- visitSendNode: aNode
- | receiver superSend rcv |
- (messageSends includes: aNode selector) ifFalse: [
- messageSends add: aNode selector].
-
- self performOptimizations
- ifTrue: [
- (self inlineLiteral: aNode selector receiverNode: aNode receiver argumentNodes: aNode arguments) ifTrue: [ ^self ].
- ].
- rcv := self isolated: aNode receiver.
- superSend := (lazyVars at: rcv ifAbsent: []) = 'super'.
- superSend ifTrue: [ mutables remove: rcv. lazyVars at: rcv put: 'self' ].
- self performOptimizations
- ifTrue: [ | inline |
- inline := self inline: aNode selector receiver: rcv argumentNodes: aNode arguments.
- inline ifNotNil: [ | args |
- args := inline = true ifTrue: [ aNode arguments ] ifFalse: [ inline ].
- self prvPutAndClose: [ self send: aNode selector to: rcv arguments: args superSend: superSend ].
- ^self ]].
- self send: aNode selector to: rcv arguments: aNode arguments superSend: superSend
- !
- visitSequenceNode: aNode
- aNode nodes isEmpty ifFalse: [
- self sequenceOfNodes: aNode nodes temps: aNode temps ]
- !
- visitValueNode: aNode
- self lazyAssignValue: aNode value asJavascript
- !
- visitVariableNode: aNode
- | varName |
- (self currentClass allInstanceVariableNames includes: aNode value)
- ifTrue: [self lazyAssignExpression: 'self[''@', aNode value, ''']']
- ifFalse: [
- varName := self safeVariableNameFor: aNode value.
- (self knownVariables includes: varName)
- ifFalse: [
- unknownVariables add: aNode value.
- aNode assigned
- ifTrue: [self lazyAssignExpression: varName]
- ifFalse: [self lazyAssignExpression: '(typeof ', varName, ' == ''undefined'' ? nil : ', varName, ')']]
- ifTrue: [
- aNode value = 'thisContext'
- ifTrue: [self lazyAssignExpression: '(smalltalk.getThisContext())']
- ifFalse: [(self pseudoVariables includes: varName)
- ifTrue: [ self lazyAssignValue: varName ]
- ifFalse: [ self lazyAssignExpression: varName]]]]
- !
- visitVerbatimNode: aNode
- self lazyAssignValue: aNode value
- ! !
- ImpCodeGenerator class instanceVariableNames: 'performOptimizations'!
- !ImpCodeGenerator class methodsFor: 'accessing'!
- performOptimizations
- ^performOptimizations ifNil: [true]
- !
- performOptimizations: aBoolean
- performOptimizations := aBoolean
- ! !
- NodeVisitor subclass: #ReturnNodeChecker
- instanceVariableNames: 'wasReturnNode'
- package: 'Compiler-Visitors'!
- !ReturnNodeChecker methodsFor: 'accessing'!
- wasReturnNode
- ^wasReturnNode
- ! !
- !ReturnNodeChecker methodsFor: 'initializing'!
- initialize
- wasReturnNode := false
- ! !
- !ReturnNodeChecker methodsFor: 'visiting'!
- visitReturnNode: aNode
- wasReturnNode := true
- ! !
|