SystemOrganization addCategory: #'AST-Semantic'! SystemOrganization addCategory: #'AST-Semantic-Scope'! SystemOrganization addCategory: #'AST-Semantic-Binding'! SystemOrganization addCategory: #'AST-Semantic-Tests'! !RBVariableNode methodsFor: '*ast-semantic-accessing' stamp: 'lr 5/11/2010 22:23'! variableBinding ^ self propertyAt: #variableBinding ifAbsent: [ self semanticAnnotationMissing ]! ! RBProgramNodeVisitor subclass: #RBSemanticAnnotator instanceVariableNames: 'scope' classVariableNames: '' poolDictionaries: '' category: 'AST-Semantic'! !RBSemanticAnnotator methodsFor: 'visitor-dispatching' stamp: 'lr 4/27/2010 15:29'! acceptBlockNode: aNode self scope: aNode with: RBBlockScope during: [ super acceptBlockNode: aNode ]! ! !RBSemanticAnnotator methodsFor: 'visitor-dispatching' stamp: 'lr 4/27/2010 15:27'! acceptMethodNode: aNode self scope: aNode with: RBMethodScope during: [ super acceptMethodNode: aNode ]! ! !RBSemanticAnnotator methodsFor: 'visitor-dispatching' stamp: 'lr 4/27/2010 15:40'! acceptSequenceNode: aNode aNode temporaries do: [ :each | scope add: (RBTemporaryBinding node: each) ]. aNode statements do: [ :each | self visitNode: each ]! ! !RBSemanticAnnotator methodsFor: 'visitor-dispatching' stamp: 'lr 6/4/2010 15:00'! acceptVariableNode: aNode | binding | binding := scope lookup: aNode name ifAbsent: [ RBUndeclaredBinding node: aNode ]. aNode propertyAt: #variableBinding put: binding. binding addAccessor: aNode. aNode isUsed ifTrue: [ binding addReader: aNode ]. aNode isWrite ifTrue: [ binding addWriter: aNode ]! ! !RBSemanticAnnotator methodsFor: 'private' stamp: 'lr 4/28/2010 09:21'! scope: aNode with: aClass during: aBlock scope := aClass parent: scope node: aNode. ^ aBlock ensure: [ scope := scope parent ]! ! !RBSemanticAnnotator methodsFor: 'visiting' stamp: 'lr 5/11/2010 22:25'! start: aProgramNode self visitNode: aProgramNode methodNode! ! !RBSemanticAnnotator methodsFor: 'deprecated' stamp: 'lr 5/29/2010 20:57'! start: aProgramNode class: aBehavior ^ aProgramNode annotateInClass: aBehavior! ! !RBSemanticAnnotator methodsFor: 'visiting' stamp: 'lr 5/29/2010 20:27'! start: aProgramNode scope: aLexicalScope scope := aLexicalScope. self start: aProgramNode! ! !RBSemanticAnnotator methodsFor: 'visiting' stamp: 'lr 4/27/2010 15:34'! visitArgument: aNode scope add: (RBArgumentBinding node: aNode)! ! Object subclass: #RBLexicalScope instanceVariableNames: 'bindings' classVariableNames: '' poolDictionaries: '' category: 'AST-Semantic-Scope'! !RBLexicalScope class methodsFor: 'instance creation' stamp: 'lr 4/28/2010 09:16'! new ^ self basicNew initialize! ! !RBLexicalScope methodsFor: 'adding' stamp: 'lr 4/28/2010 09:25'! add: aVariableBinding "Add aVariableBinding to the receving scope." ^ bindings at: aVariableBinding name put: (aVariableBinding setScope: self)! ! !RBLexicalScope methodsFor: 'private' stamp: 'lr 4/27/2010 15:15'! basicBindingOf: aString ^ nil! ! !RBLexicalScope methodsFor: 'querying' stamp: 'lr 4/28/2010 09:25'! bindingOf: aString "Answer the local binding of aString or nil." ^ bindings at: aString ifAbsent: [ | binding | binding := (self basicBindingOf: aString) ifNil: [ ^ nil ]. self add: binding ]! ! !RBLexicalScope methodsFor: 'initialization' stamp: 'lr 4/28/2010 09:23'! initialize bindings := RBSmallDictionary new! ! !RBLexicalScope methodsFor: 'testing' stamp: 'lr 5/11/2010 19:11'! isBlockScope ^ false! ! !RBLexicalScope methodsFor: 'testing' stamp: 'lr 5/11/2010 19:11'! isLiteralScope ^ false! ! !RBLexicalScope methodsFor: 'testing' stamp: 'lr 5/11/2010 19:11'! isMethodScope ^ false! ! !RBLexicalScope methodsFor: 'testing' stamp: 'lr 5/11/2010 19:11'! isRootScope ^ false! ! !RBLexicalScope methodsFor: 'testing' stamp: 'lr 5/11/2010 19:11'! isVariableScope ^ false! ! !RBLexicalScope methodsFor: 'querying' stamp: 'lr 4/27/2010 15:14'! lookup: aString "Lookup the variable aString in the receiving scope, throw an error if not found." ^ self lookup: aString ifAbsent: [ self error: 'No binding for ' , aString printString , ' found.' ]! ! !RBLexicalScope methodsFor: 'querying' stamp: 'lr 4/28/2010 09:19'! lookup: aString ifAbsent: aBlock "Lookup the variable aString in the receiving scope, evaluate aBlock if not found." self subclassResponsibility! ! RBLexicalScope subclass: #RBOwnedScope instanceVariableNames: 'parent' classVariableNames: '' poolDictionaries: '' category: 'AST-Semantic-Scope'! RBOwnedScope subclass: #RBClassScope instanceVariableNames: 'class' classVariableNames: '' poolDictionaries: '' category: 'AST-Semantic-Scope'! !RBClassScope class methodsFor: 'instance creation' stamp: 'lr 4/28/2010 09:22'! parent: aLexicalScope class: aBehavior ^ (self parent: aLexicalScope) setClass: aBehavior! ! !RBClassScope methodsFor: 'initialization' stamp: 'lr 4/27/2010 13:48'! setClass: aBehavior class := aBehavior! ! !RBClassScope methodsFor: 'accessing' stamp: 'lr 4/27/2010 13:48'! theClass ^ class! ! RBClassScope subclass: #RBLiteralScope instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'AST-Semantic-Scope'! !RBLiteralScope methodsFor: 'private' stamp: 'lr 4/27/2010 15:41'! basicBindingOf: aString ^ (class bindingOf: aString) ifNotNil: [ :binding | RBLiteralBinding binding: binding ]! ! !RBLiteralScope methodsFor: 'testing' stamp: 'lr 5/11/2010 19:12'! isLiteralScope ^ true! ! RBClassScope subclass: #RBVariableScope instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'AST-Semantic-Scope'! !RBVariableScope methodsFor: 'testing' stamp: 'lr 5/11/2010 19:12'! isVariableScope ^ true! ! !RBVariableScope methodsFor: 'initialization' stamp: 'lr 4/27/2010 15:21'! setClass: aClass super setClass: aClass. aClass allInstVarNames keysAndValuesDo: [ :index :name | self add: (RBInstanceBinding name: name index: index) ]! ! RBOwnedScope subclass: #RBNodedScope instanceVariableNames: 'node' classVariableNames: '' poolDictionaries: '' category: 'AST-Semantic-Scope'! RBNodedScope subclass: #RBBlockScope instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'AST-Semantic-Scope'! !RBBlockScope methodsFor: 'testing' stamp: 'lr 5/11/2010 19:12'! isBlockScope ^ true! ! RBNodedScope subclass: #RBMethodScope instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'AST-Semantic-Scope'! !RBMethodScope methodsFor: 'testing' stamp: 'lr 5/11/2010 19:12'! isMethodScope ^ true! ! !RBNodedScope class methodsFor: 'instance creation' stamp: 'lr 4/28/2010 09:22'! parent: aLexicalScope node: aProgramNode ^ (self parent: aLexicalScope) setNode: aProgramNode! ! !RBNodedScope methodsFor: 'accessing' stamp: 'lr 4/27/2010 13:29'! node "Answer the program node that defines this scope." ^ node! ! !RBNodedScope methodsFor: 'initialization' stamp: 'lr 4/27/2010 15:19'! setNode: aProgramNode node := aProgramNode. node propertyAt: #lexicalScope put: self! ! !RBOwnedScope class methodsFor: 'instance creation' stamp: 'lr 4/28/2010 09:18'! parent: aLexicalScope ^ self new setParent: aLexicalScope! ! !RBOwnedScope methodsFor: 'querying' stamp: 'lr 4/28/2010 09:20'! lookup: aString ifAbsent: aBlock ^ (self bindingOf: aString) ifNil: [ parent lookup: aString ifAbsent: aBlock ]! ! !RBOwnedScope methodsFor: 'accessing' stamp: 'lr 4/28/2010 09:17'! parent "Answer the owning scope." ^ parent! ! !RBOwnedScope methodsFor: 'initialization' stamp: 'lr 4/28/2010 09:18'! setParent: aLexicalScope parent := aLexicalScope! ! RBLexicalScope subclass: #RBRootScope instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'AST-Semantic-Scope'! !RBRootScope methodsFor: 'initialization' stamp: 'lr 4/27/2010 14:35'! initialize super initialize. self add: RBSelfBinding new. self add: RBSuperBinding new. self add: RBContextBinding new! ! !RBRootScope methodsFor: 'testing' stamp: 'lr 5/11/2010 19:12'! isRootScope ^ true! ! !RBRootScope methodsFor: 'querying' stamp: 'lr 4/27/2010 14:10'! lookup: aString ifAbsent: aBlock ^ bindings at: aString ifAbsent: aBlock! ! Object subclass: #RBVariableBinding instanceVariableNames: 'scope accessors readers writers' classVariableNames: '' poolDictionaries: '' category: 'AST-Semantic-Binding'! RBVariableBinding subclass: #RBInstanceBinding instanceVariableNames: 'name index' classVariableNames: '' poolDictionaries: '' category: 'AST-Semantic-Binding'! !RBInstanceBinding class methodsFor: 'instance creation' stamp: 'lr 4/27/2010 14:29'! name: aString index: anInteger ^ self new initializeName: aString index: anInteger! ! !RBInstanceBinding methodsFor: 'accessing' stamp: 'lr 4/27/2010 14:14'! index ^ index! ! !RBInstanceBinding methodsFor: 'initialization' stamp: 'lr 4/27/2010 14:15'! initializeName: aString index: anInteger name := aString. index := anInteger! ! !RBInstanceBinding methodsFor: 'testing-type' stamp: 'lr 4/28/2010 09:36'! isInstanceBinding ^ true! ! !RBInstanceBinding methodsFor: 'accessing' stamp: 'lr 4/27/2010 14:14'! name ^ name! ! RBVariableBinding subclass: #RBLiteralBinding instanceVariableNames: 'binding' classVariableNames: '' poolDictionaries: '' category: 'AST-Semantic-Binding'! !RBLiteralBinding class methodsFor: 'instance creation' stamp: 'lr 4/27/2010 14:58'! binding: aBinding ^ self new initializeBinding: aBinding! ! !RBLiteralBinding methodsFor: 'accessing' stamp: 'lr 4/27/2010 14:57'! binding ^ binding! ! !RBLiteralBinding methodsFor: 'initialization' stamp: 'lr 4/27/2010 14:58'! initializeBinding: aBinding binding := aBinding! ! !RBLiteralBinding methodsFor: 'testing-type' stamp: 'lr 4/28/2010 09:36'! isLiteralBinding ^ true! ! !RBLiteralBinding methodsFor: 'accessing' stamp: 'lr 4/27/2010 14:57'! name ^ binding key asString! ! RBVariableBinding subclass: #RBLocalBinding instanceVariableNames: 'node' classVariableNames: '' poolDictionaries: '' category: 'AST-Semantic-Binding'! RBLocalBinding subclass: #RBArgumentBinding instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'AST-Semantic-Binding'! !RBArgumentBinding methodsFor: 'testing-type' stamp: 'lr 4/28/2010 09:36'! isArgumentBinding ^ true! ! !RBArgumentBinding methodsFor: 'testing' stamp: 'lr 4/27/2010 15:28'! isReadonly ^ true! ! !RBLocalBinding class methodsFor: 'instance creation' stamp: 'lr 4/27/2010 14:07'! node: aNode ^ self new setNode: aNode! ! !RBLocalBinding methodsFor: 'accessing' stamp: 'lr 4/27/2010 14:36'! name ^ node name! ! !RBLocalBinding methodsFor: 'accessing' stamp: 'lr 4/27/2010 13:59'! node "Answer the declaring or defining node." ^ node! ! !RBLocalBinding methodsFor: 'initialization' stamp: 'lr 4/27/2010 15:31'! setNode: aNode node := aNode. node propertyAt: #variableBinding put: self! ! RBLocalBinding subclass: #RBTemporaryBinding instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'AST-Semantic-Binding'! !RBTemporaryBinding methodsFor: 'testing-type' stamp: 'lr 4/28/2010 09:36'! isTemporaryBinding ^ true! ! RBLocalBinding subclass: #RBUndeclaredBinding instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'AST-Semantic-Binding'! !RBUndeclaredBinding methodsFor: 'testing-type' stamp: 'lr 4/28/2010 09:36'! isUndeclaredBinding ^ true! ! RBVariableBinding subclass: #RBSpecialBinding instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'AST-Semantic-Binding'! RBSpecialBinding subclass: #RBContextBinding instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'AST-Semantic-Binding'! !RBContextBinding methodsFor: 'testing-type' stamp: 'lr 4/28/2010 09:29'! isContextBinding ^ true! ! !RBContextBinding methodsFor: 'accessing' stamp: 'lr 4/27/2010 14:34'! name ^ 'thisContext'! ! RBSpecialBinding subclass: #RBSelfBinding instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'AST-Semantic-Binding'! !RBSelfBinding methodsFor: 'testing-type' stamp: 'lr 4/28/2010 09:29'! isSelfBinding ^ true! ! !RBSelfBinding methodsFor: 'accessing' stamp: 'lr 4/27/2010 14:34'! name ^ 'self'! ! !RBSpecialBinding methodsFor: 'testing' stamp: 'lr 4/27/2010 14:35'! isReadonly ^ true! ! RBSpecialBinding subclass: #RBSuperBinding instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'AST-Semantic-Binding'! !RBSuperBinding methodsFor: 'testing-type' stamp: 'lr 4/28/2010 09:29'! isSuperBinding ^ true! ! !RBSuperBinding methodsFor: 'accessing' stamp: 'lr 4/27/2010 14:34'! name ^ 'super'! ! !RBVariableBinding class methodsFor: 'instance creation' stamp: 'lr 4/27/2010 14:07'! new ^ self basicNew initialize! ! !RBVariableBinding methodsFor: 'accessing' stamp: 'lr 6/4/2010 15:03'! accessors "Answer the nodes that access the receiver." ^ accessors! ! !RBVariableBinding methodsFor: 'protected' stamp: 'lr 6/4/2010 14:59'! addAccessor: aProgramNode accessors := accessors copyWith: aProgramNode! ! !RBVariableBinding methodsFor: 'protected' stamp: 'lr 5/11/2010 22:28'! addReader: aProgramNode readers := readers copyWith: aProgramNode! ! !RBVariableBinding methodsFor: 'protected' stamp: 'lr 5/11/2010 22:28'! addWriter: aProgramNode writers := writers copyWith: aProgramNode! ! !RBVariableBinding methodsFor: 'initialization' stamp: 'lr 6/4/2010 14:59'! initialize accessors := readers := writers := #()! ! !RBVariableBinding methodsFor: 'testing' stamp: 'lr 6/4/2010 15:03'! isAccessed "Answer true if the receiving binding is accessed." ^ self accessors notEmpty! ! !RBVariableBinding methodsFor: 'testing-type' stamp: 'lr 4/28/2010 09:35'! isArgumentBinding ^ false! ! !RBVariableBinding methodsFor: 'testing-type' stamp: 'lr 4/28/2010 09:34'! isContextBinding ^ false! ! !RBVariableBinding methodsFor: 'testing-type' stamp: 'lr 4/28/2010 09:35'! isInstanceBinding ^ false! ! !RBVariableBinding methodsFor: 'testing-type' stamp: 'lr 4/28/2010 09:35'! isLiteralBinding ^ false! ! !RBVariableBinding methodsFor: 'testing' stamp: 'lr 4/28/2010 09:33'! isRead "Answer true if the receiving binding is read." ^ self readers notEmpty! ! !RBVariableBinding methodsFor: 'testing' stamp: 'lr 4/27/2010 14:35'! isReadonly "Answer if the receiving binding is readonly." ^ false! ! !RBVariableBinding methodsFor: 'testing-type' stamp: 'lr 4/28/2010 09:34'! isSelfBinding ^ false! ! !RBVariableBinding methodsFor: 'testing-type' stamp: 'lr 4/28/2010 09:34'! isSuperBinding ^ false! ! !RBVariableBinding methodsFor: 'testing-type' stamp: 'lr 4/28/2010 09:35'! isTemporaryBinding ^ false! ! !RBVariableBinding methodsFor: 'testing-type' stamp: 'lr 4/28/2010 09:35'! isUndeclaredBinding ^ false! ! !RBVariableBinding methodsFor: 'testing' stamp: 'lr 4/28/2010 09:33'! isWritten "Answer true if the receiving binding is written." ^ self writers notEmpty! ! !RBVariableBinding methodsFor: 'accessing' stamp: 'lr 4/27/2010 14:30'! name "Answer the name of the variable." self subclassResponsibility! ! !RBVariableBinding methodsFor: 'printing' stamp: 'lr 4/27/2010 14:30'! printOn: aStream super printOn: aStream. aStream nextPutAll: ' name: '; print: self name! ! !RBVariableBinding methodsFor: 'accessing' stamp: 'lr 5/11/2010 22:17'! readers "Answer the nodes that read from the receiver." ^ readers! ! !RBVariableBinding methodsFor: 'accessing' stamp: 'lr 4/27/2010 14:06'! scope "Answer the owning scope." ^ scope! ! !RBVariableBinding methodsFor: 'initialization' stamp: 'lr 4/27/2010 14:06'! setScope: aLexicalScope scope := aLexicalScope! ! !RBVariableBinding methodsFor: 'accessing' stamp: 'lr 5/11/2010 22:18'! writers "Answer the nodes that write to the receiver." ^ writers! ! !RBProgramNode methodsFor: '*ast-semantic-actions' stamp: 'lr 5/29/2010 20:34'! annotateInClass: aBehavior self annotateInScope: (RBVariableScope parent: (RBLiteralScope parent: RBRootScope new class: aBehavior) class: aBehavior)! ! !RBProgramNode methodsFor: '*ast-semantic-actions' stamp: 'lr 5/29/2010 20:32'! annotateInScope: aScope self semanticAnnotatorClass new start: self scope: aScope! ! !RBProgramNode methodsFor: '*ast-semantic-accessing' stamp: 'lr 5/11/2010 22:23'! lexicalScope ^ self propertyAt: #lexicalScope ifAbsent: [ self parent isNil ifFalse: [ self parent lexicalScope ] ifTrue: [ self semanticAnnotationMissing ] ]! ! !RBProgramNode methodsFor: '*ast-semantic-private' stamp: 'lr 5/29/2010 21:01'! semanticAnnotationMissing self error: 'Semantic annotation missing, please use #annotateInClass: to annotate the AST'! ! !RBProgramNode methodsFor: '*ast-semantic-private' stamp: 'lr 5/29/2010 20:24'! semanticAnnotatorClass ^ RBSemanticAnnotator! ! TestCase subclass: #RBSemanticTest instanceVariableNames: 'instVar' classVariableNames: 'ClassVar' poolDictionaries: '' category: 'AST-Semantic-Tests'! !RBSemanticTest class methodsFor: 'accessing' stamp: 'lr 4/27/2010 16:17'! packageNamesUnderTest ^ #('AST-Semantic')! ! !RBSemanticTest methodsFor: 'utilities' stamp: 'lr 5/29/2010 20:33'! parseExpression: aString ^ (RBParser parseExpression: aString) annotateInClass: self class; yourself! ! !RBSemanticTest methodsFor: 'utilities' stamp: 'lr 5/29/2010 20:33'! parseMethod: aString ^ (RBParser parseMethod: aString) annotateInClass: self class; yourself! ! !RBSemanticTest methodsFor: 'testing-bindings' stamp: 'lr 6/4/2010 15:02'! testBlockArgumentBinding | tree binding | tree := self parseExpression: '[ :arg | ]'. binding := tree arguments first variableBinding. self assert: binding isArgumentBinding. self deny: binding isContextBinding. self deny: binding isInstanceBinding. self deny: binding isLiteralBinding. self deny: binding isSelfBinding. self deny: binding isSuperBinding. self deny: binding isTemporaryBinding. self deny: binding isUndeclaredBinding. self deny: binding isAccessed. self assert: binding accessors isEmpty. self deny: binding isRead. self assert: binding readers isEmpty. self deny: binding isWritten. self assert: binding writers isEmpty. self assert: binding isReadonly. self assert: binding name = 'arg'. self assert: binding node = tree arguments first. self assert: binding scope = tree lexicalScope! ! !RBSemanticTest methodsFor: 'testing-scopes' stamp: 'lr 5/11/2010 21:56'! testBlockScope | tree scope | tree := self parseExpression: '[ :arg | | tmp | ]'. scope := tree lexicalScope. self assert: scope isBlockScope. self deny: scope isLiteralScope. self deny: scope isMethodScope. self deny: scope isRootScope. self deny: scope isVariableScope. self assert: scope node = tree. self assert: (scope lookup: 'arg') isArgumentBinding. self assert: (scope lookup: 'arg') scope = scope. self assert: (scope lookup: 'arg') name = 'arg'. self assert: (scope lookup: 'tmp') isTemporaryBinding. self assert: (scope lookup: 'tmp') scope = scope. self assert: (scope lookup: 'tmp') name = 'tmp'. self should: [ scope lookup: 'something' ] raise: Error. self assert: (scope lookup: 'something' ifAbsent: [ #nothing ]) = #nothing ! ! !RBSemanticTest methodsFor: 'testing-bindings' stamp: 'lr 6/4/2010 15:01'! testBlockTemporaryBinding | tree binding | tree := self parseExpression: '[ | tmp | ]'. binding := tree body temporaries first variableBinding. self deny: binding isArgumentBinding. self deny: binding isContextBinding. self deny: binding isInstanceBinding. self deny: binding isLiteralBinding. self deny: binding isSelfBinding. self deny: binding isSuperBinding. self assert: binding isTemporaryBinding. self deny: binding isUndeclaredBinding. self deny: binding isAccessed. self assert: binding accessors isEmpty. self deny: binding isRead. self assert: binding readers isEmpty. self deny: binding isWritten. self assert: binding writers isEmpty. self deny: binding isReadonly. self assert: binding name = 'tmp'. self assert: binding node = tree body temporaries first. self assert: binding scope = tree lexicalScope! ! !RBSemanticTest methodsFor: 'testing-fixtures' stamp: 'lr 5/26/2010 18:48'! testCascadeReceiver | tree receiver receiver1 receiver2 | tree := self parseExpression: 'self foo; bar'. receiver := tree receiver. receiver1 := tree messages first receiver. receiver2 := tree messages last receiver. self assert: receiver variableBinding = receiver1 variableBinding. self assert: receiver variableBinding = receiver2 variableBinding! ! !RBSemanticTest methodsFor: 'testing-bindings' stamp: 'lr 6/4/2010 15:03'! testClassVariableBinding | tree binding | tree := self parseExpression: 'ClassVar'. binding := tree variableBinding. self deny: binding isArgumentBinding. self deny: binding isContextBinding. self deny: binding isInstanceBinding. self assert: binding isLiteralBinding. self deny: binding isSelfBinding. self deny: binding isSuperBinding. self deny: binding isTemporaryBinding. self deny: binding isUndeclaredBinding. self assert: binding isAccessed. self deny: binding accessors isEmpty. self deny: binding isRead. self assert: binding readers isEmpty. self deny: binding isWritten. self assert: binding writers isEmpty. self deny: binding isReadonly. self assert: binding name = 'ClassVar'. self assert: binding binding = (self class bindingOf: 'ClassVar'). self assert: binding scope notNil! ! !RBSemanticTest methodsFor: 'testing-bindings' stamp: 'lr 6/4/2010 15:04'! testGlobalVariableBinding | tree binding | tree := self parseExpression: self class name. binding := tree variableBinding. self deny: binding isArgumentBinding. self deny: binding isContextBinding. self deny: binding isInstanceBinding. self assert: binding isLiteralBinding. self deny: binding isSelfBinding. self deny: binding isSuperBinding. self deny: binding isTemporaryBinding. self deny: binding isUndeclaredBinding. self assert: binding isAccessed. self deny: binding accessors isEmpty. self deny: binding isRead. self assert: binding readers isEmpty. self deny: binding isWritten. self assert: binding writers isEmpty. self deny: binding isReadonly. self assert: binding name = self class name. self assert: binding binding = (self class bindingOf: self class name). self assert: binding scope notNil! ! !RBSemanticTest methodsFor: 'testing-bindings' stamp: 'lr 6/4/2010 15:04'! testInstanceVariableBinding | tree binding | tree := self parseExpression: 'instVar'. binding := tree variableBinding. self deny: binding isArgumentBinding. self deny: binding isContextBinding. self assert: binding isInstanceBinding. self deny: binding isLiteralBinding. self deny: binding isSelfBinding. self deny: binding isSuperBinding. self deny: binding isTemporaryBinding. self deny: binding isUndeclaredBinding. self assert: binding isAccessed. self deny: binding accessors isEmpty. self deny: binding isRead. self assert: binding readers isEmpty. self deny: binding isWritten. self assert: binding writers isEmpty. self deny: binding isReadonly. self assert: binding name = 'instVar'. self assert: binding index = 2. self assert: binding scope notNil! ! !RBSemanticTest methodsFor: 'testing-scopes' stamp: 'lr 5/11/2010 22:34'! testLiteralScope | scope literals | scope := RBLiteralScope parent: RBRootScope new class: RBMessageNode. self deny: scope isBlockScope. self assert: scope isLiteralScope. self deny: scope isMethodScope. self deny: scope isRootScope. self deny: scope isVariableScope. self assert: scope theClass = RBMessageNode. literals := OrderedCollection new. literals addAll: (RBMessageNode allClassVarNames). literals addAll: (RBProgramNode allSubclasses collect: [ :each | each name ]). literals do: [ :name | self assert: (scope lookup: name) isLiteralBinding. self assert: (scope lookup: name) scope = scope. self assert: (scope lookup: name) name = name ]. self assert: (scope lookup: 'self') scope = scope parent. self assert: (scope lookup: 'super') scope = scope parent. self assert: (scope lookup: 'thisContext') scope = scope parent. self should: [ scope lookup: 'something' ] raise: Error. self assert: (scope lookup: 'something' ifAbsent: [ #nothing ]) = #nothing ! ! !RBSemanticTest methodsFor: 'testing-bindings' stamp: 'lr 6/4/2010 15:02'! testMethodArgumentBinding | tree binding | tree := self parseMethod: 'foo: arg'. binding := tree arguments first variableBinding. self assert: binding isArgumentBinding. self deny: binding isContextBinding. self deny: binding isInstanceBinding. self deny: binding isLiteralBinding. self deny: binding isSelfBinding. self deny: binding isSuperBinding. self deny: binding isTemporaryBinding. self deny: binding isUndeclaredBinding. self deny: binding isAccessed. self assert: binding accessors isEmpty. self deny: binding isRead. self assert: binding readers isEmpty. self deny: binding isWritten. self assert: binding writers isEmpty. self assert: binding isReadonly. self assert: binding name = 'arg'. self assert: binding node = tree arguments first. self assert: binding scope = tree lexicalScope! ! !RBSemanticTest methodsFor: 'testing-scopes' stamp: 'lr 5/11/2010 21:56'! testMethodScope | tree scope | tree := self parseMethod: 'foo: arg | tmp |'. scope := tree lexicalScope. self deny: scope isBlockScope. self deny: scope isLiteralScope. self assert: scope isMethodScope. self deny: scope isRootScope. self deny: scope isVariableScope. self assert: scope node = tree. self assert: (scope lookup: 'arg') isArgumentBinding. self assert: (scope lookup: 'arg') scope = scope. self assert: (scope lookup: 'arg') name = 'arg'. self assert: (scope lookup: 'tmp') isTemporaryBinding. self assert: (scope lookup: 'tmp') scope = scope. self assert: (scope lookup: 'tmp') name = 'tmp'. self should: [ scope lookup: 'something' ] raise: Error. self assert: (scope lookup: 'something' ifAbsent: [ #nothing ]) = #nothing ! ! !RBSemanticTest methodsFor: 'testing-bindings' stamp: 'lr 6/4/2010 15:02'! testMethodTemporaryBinding | tree binding | tree := self parseMethod: 'foo | tmp |'. binding := tree body temporaries first variableBinding. self deny: binding isArgumentBinding. self deny: binding isContextBinding. self deny: binding isInstanceBinding. self deny: binding isLiteralBinding. self deny: binding isSelfBinding. self deny: binding isSuperBinding. self assert: binding isTemporaryBinding. self deny: binding isUndeclaredBinding. self deny: binding isAccessed. self assert: binding accessors isEmpty. self deny: binding isRead. self assert: binding readers isEmpty. self deny: binding isWritten. self assert: binding writers isEmpty. self deny: binding isReadonly. self assert: binding name = 'tmp'. self assert: binding node = tree body temporaries first. self assert: binding scope = tree lexicalScope! ! !RBSemanticTest methodsFor: 'testing' stamp: 'lr 5/11/2010 23:06'! testMissing self should: [ RBSequenceNode new lexicalScope ] raise: Error. self should: [ RBVariableNode new variableBinding ] raise: Error! ! !RBSemanticTest methodsFor: 'testing' stamp: 'lr 5/11/2010 23:08'! testReadWriter | tree binding | tree := self parseExpression: '| var | ^ var := 1'. binding := tree lexicalScope bindingOf: 'var'. self assert: binding node = tree temporaries first. self assert: binding readers size = 1. self assert: binding readers first = tree statements first value variable. self assert: binding writers size = 1. self assert: binding writers first = tree statements first value variable.! ! !RBSemanticTest methodsFor: 'testing' stamp: 'lr 5/11/2010 23:07'! testReader | tree binding | tree := self parseExpression: '| var | ^ var'. binding := tree lexicalScope bindingOf: 'var'. self assert: binding node = tree temporaries first. self assert: binding readers size = 1. self assert: binding readers first = tree statements first value. self assert: binding writers isEmpty! ! !RBSemanticTest methodsFor: 'testing-scopes' stamp: 'lr 5/11/2010 19:20'! testRootScope | scope | scope := RBRootScope new. self deny: scope isBlockScope. self deny: scope isLiteralScope. self deny: scope isMethodScope. self assert: scope isRootScope. self deny: scope isVariableScope. self assert: (scope lookup: 'self') isSelfBinding. self assert: (scope lookup: 'self') scope = scope. self assert: (scope lookup: 'super') isSuperBinding. self assert: (scope lookup: 'super') scope = scope. self assert: (scope lookup: 'thisContext') isContextBinding. self assert: (scope lookup: 'thisContext') scope = scope. self should: [ scope lookup: 'something' ] raise: Error. self assert: (scope lookup: 'something' ifAbsent: [ #nothing ]) = #nothing ! ! !RBSemanticTest methodsFor: 'testing-bindings' stamp: 'lr 6/4/2010 15:04'! testSpecialContextBinding | tree binding | tree := self parseExpression: 'thisContext'. binding := tree variableBinding. self deny: binding isArgumentBinding. self assert: binding isContextBinding. self deny: binding isInstanceBinding. self deny: binding isLiteralBinding. self deny: binding isSelfBinding. self deny: binding isSuperBinding. self deny: binding isTemporaryBinding. self deny: binding isUndeclaredBinding. self assert: binding isAccessed. self deny: binding accessors isEmpty. self deny: binding isRead. self assert: binding readers isEmpty. self deny: binding isWritten. self assert: binding writers isEmpty. self assert: binding isReadonly. self assert: binding name = 'thisContext'. self deny: binding scope isNil! ! !RBSemanticTest methodsFor: 'testing-bindings' stamp: 'lr 6/4/2010 15:04'! testSpecialSelfBinding | tree binding | tree := self parseExpression: 'self'. binding := tree variableBinding. self deny: binding isArgumentBinding. self deny: binding isContextBinding. self deny: binding isInstanceBinding. self deny: binding isLiteralBinding. self assert: binding isSelfBinding. self deny: binding isSuperBinding. self deny: binding isTemporaryBinding. self deny: binding isUndeclaredBinding. self assert: binding isAccessed. self deny: binding accessors isEmpty. self deny: binding isRead. self assert: binding readers isEmpty. self deny: binding isWritten. self assert: binding writers isEmpty. self assert: binding isReadonly. self assert: binding name = 'self'. self deny: binding scope isNil! ! !RBSemanticTest methodsFor: 'testing-bindings' stamp: 'lr 6/4/2010 15:04'! testSpecialSuperBinding | tree binding | tree := self parseExpression: 'super'. binding := tree variableBinding. self deny: binding isArgumentBinding. self deny: binding isContextBinding. self deny: binding isInstanceBinding. self deny: binding isLiteralBinding. self deny: binding isSelfBinding. self assert: binding isSuperBinding. self deny: binding isTemporaryBinding. self deny: binding isUndeclaredBinding. self assert: binding isAccessed. self deny: binding accessors isEmpty. self deny: binding isRead. self assert: binding readers isEmpty. self deny: binding isWritten. self assert: binding writers isEmpty. self assert: binding isReadonly. self assert: binding name = 'super'. self deny: binding scope isNil! ! !RBSemanticTest methodsFor: 'testing-bindings' stamp: 'lr 6/4/2010 15:04'! testUndeclaredBinding | tree binding | tree := self parseExpression: '[ undecl ]'. binding := tree body statements first variableBinding. self deny: binding isArgumentBinding. self deny: binding isContextBinding. self deny: binding isInstanceBinding. self deny: binding isLiteralBinding. self deny: binding isSelfBinding. self deny: binding isSuperBinding. self deny: binding isTemporaryBinding. self assert: binding isUndeclaredBinding. self assert: binding isAccessed. self deny: binding accessors isEmpty. self deny: binding isRead. self assert: binding readers isEmpty. self deny: binding isWritten. self assert: binding writers isEmpty. self deny: binding isReadonly. self assert: binding name = 'undecl'. self assert: binding node = tree body statements first. self assert: binding scope isNil! ! !RBSemanticTest methodsFor: 'testing-scopes' stamp: 'lr 5/11/2010 22:34'! testVariableScope | scope | scope := RBVariableScope parent: RBRootScope new class: RBMessageNode. self deny: scope isBlockScope. self deny: scope isLiteralScope. self deny: scope isMethodScope. self deny: scope isRootScope. self assert: scope isVariableScope. self assert: scope theClass = RBMessageNode. RBMessageNode allInstVarNames keysAndValuesDo: [ :index :name | self assert: (scope lookup: name) isInstanceBinding. self assert: (scope lookup: name) scope = scope. self assert: (scope lookup: name) name = name. self assert: (scope lookup: name) index = index ]. self assert: (scope lookup: 'self') scope = scope parent. self assert: (scope lookup: 'super') scope = scope parent. self assert: (scope lookup: 'thisContext') scope = scope parent. self should: [ scope lookup: 'something' ] raise: Error. self assert: (scope lookup: 'something' ifAbsent: [ #nothing ]) = #nothing ! ! !RBSemanticTest methodsFor: 'testing' stamp: 'lr 5/11/2010 23:06'! testWriter | tree binding | tree := self parseExpression: '| var | var := 1'. binding := tree lexicalScope bindingOf: 'var'. self assert: binding node = tree temporaries first. self assert: binding readers isEmpty. self assert: binding writers size = 1. self assert: binding writers first = tree statements first variable! !