amber/st/Compiler-Semantic.st in resin-0.3.1 vs amber/st/Compiler-Semantic.st in resin-0.4.0
- old
+ new
@@ -9,10 +9,14 @@
I am attached to a ScopeVar and method/block nodes.
Each context (method/closure) get a fresh scope that inherits from its outer scope.!
!LexicalScope methodsFor: 'accessing'!
+alias
+ ^ '$ctx', self scopeLevel asString
+!
+
allVariableNames
^ self args keys, self temps keys
!
args
@@ -68,13 +72,14 @@
pseudoVars
^ self methodScope pseudoVars
!
scopeLevel
- ^ (self outerScope
- ifNil: [ 0 ]
- ifNotNil: [ self outerScope scopeLevel ]) + 1
+ self outerScope ifNil: [ ^ 1 ].
+ self isInlined ifTrue: [ ^ self outerScope scopeLevel ].
+
+ ^ self outerScope scopeLevel + 1
!
temps
^ temps ifNil: [ temps := Dictionary new ]
! !
@@ -100,11 +105,12 @@
isBlockScope
^ self isMethodScope not
!
isInlined
- ^ self instruction isInlined
+ ^ self instruction notNil and: [
+ self instruction isInlined ]
!
isMethodScope
^ false
! !
@@ -368,11 +374,11 @@
isUnknownVar
^ true
! !
NodeVisitor subclass: #SemanticAnalyzer
- instanceVariableNames: 'currentScope theClass classReferences messageSends'
+ instanceVariableNames: 'currentScope theClass classReferences messageSends superSends'
package: 'Compiler-Semantic'!
!SemanticAnalyzer commentStamp!
I semantically analyze the abstract syntax tree and annotate it with informations such as non local returns and variable scopes.!
!SemanticAnalyzer methodsFor: 'accessing'!
@@ -383,10 +389,14 @@
messageSends
^ messageSends ifNil: [ messageSends := Dictionary new ]
!
+superSends
+ ^ superSends ifNil: [ superSends := Dictionary new ]
+!
+
theClass
^ theClass
!
theClass: aClass
@@ -400,23 +410,28 @@
variableName: aString;
signal
!
errorUnknownVariable: aNode
- "Throw an error if the variable is undeclared in the global JS scope (i.e. window)"
+ "Throw an error if the variable is undeclared in the global JS scope (i.e. window).
+ We allow four variable names in addition: `jQuery`, `window`, `process` and `global`
+ for nodejs and browser environments.
+
+ This is only to make sure compilation works on both browser-based and nodejs environments.
+ The ideal solution would be to use a pragma instead"
- | notDefined |
-
- notDefined := <eval('typeof ' + aNode._value() + ' == "undefined"')>.
-
- notDefined
- ifTrue: [
- UnknownVariableError new
- variableName: aNode value;
- signal ]
- ifFalse: [
- currentScope methodScope unknownVariables add: aNode value. ]
+ | identifier |
+ identifier := aNode value.
+
+ ((#('jQuery' 'window' 'process' 'global') includes: identifier) not
+ and: [ self isVariableGloballyUndefined: identifier ])
+ ifTrue: [
+ UnknownVariableError new
+ variableName: aNode value;
+ signal ]
+ ifFalse: [
+ currentScope methodScope unknownVariables add: aNode value ]
! !
!SemanticAnalyzer methodsFor: 'factory'!
newBlockScope
@@ -450,10 +465,16 @@
(currentScope lookupVariable: aString) ifNotNil: [
self errorShadowingVariable: aString ]
! !
+!SemanticAnalyzer methodsFor: 'testing'!
+
+isVariableGloballyUndefined: aString
+ <return eval('typeof ' + aString + ' == "undefined"')>
+! !
+
!SemanticAnalyzer methodsFor: 'visiting'!
visitAssignmentNode: aNode
super visitAssignmentNode: aNode.
aNode left beAssigned
@@ -499,11 +520,12 @@
super visitMethodNode: aNode.
aNode
classReferences: self classReferences;
- messageSends: self messageSends keys.
+ messageSends: self messageSends keys;
+ superSends: self superSends keys.
self popScope
!
visitReturnNode: aNode
aNode scope: currentScope.
@@ -516,13 +538,16 @@
visitSendNode: aNode
aNode receiver value = 'super'
ifTrue: [
aNode superSend: true.
- aNode receiver value: 'self' ]
+ aNode receiver value: 'self'.
+ self superSends at: aNode selector ifAbsentPut: [ Set new ].
+ (self superSends at: aNode selector) add: aNode ]
+
ifFalse: [ (IRSendInliner inlinedSelectors includes: aNode selector) ifTrue: [
aNode shouldBeInlined: true.
- aNode receiver isValueNode ifFalse: [ aNode receiver shouldBeAliased: true ] ] ].
+ aNode receiver shouldBeAliased: true ] ].
self messageSends at: aNode selector ifAbsentPut: [ Set new ].
(self messageSends at: aNode selector) add: aNode.
aNode index: (self messageSends at: aNode selector) size.