Compiler addSlot: #SyntaxNode valued: Cloneable derive. Compiler SyntaxNode addSlot: #type. node@(Compiler SyntaxNode traits) evaluate "This is the method invoking compile-time evaluation." [| block | block: (Compiler BlockNode newFor: node). (ByteCompiler clone compile: block) value ]. node@(Compiler SyntaxNode traits) walk: block "Implements a depth-first do:-style iteration through SyntaxNodes, a code/tree-walker." [ block value: node. Nil ]. node@(Compiler SyntaxNode traits) transform: block "This method transforms the tree by the block closure. Only transformChildren: needs to be overridden." [ (block value: node) transformChildren: block ]. node@(Compiler SyntaxNode traits) transformChildren: block "Act on each of a node's children. This gets overridden for the various compound node types." [ node ]. node@(Compiler SyntaxNode traits) deepCopy: scope [ node ]. node@(Compiler SyntaxNode traits) deepCopy [ node deepCopy: Compiler LobbyNode ]. Compiler addSlot: #AnnotationNode valued: Compiler SyntaxNode derive. Compiler AnnotationNode addSlot: #value. ann@(Compiler AnnotationNode traits) walk: block [ block value: ann. ann value walk: block ]. ann@(Compiler AnnotationNode traits) transformChildren: block [ ann value: (ann value transform: block). ann ]. ann@(Compiler AnnotationNode traits) deepCopy: scope [| newAnn | newAnn: ann clone. newAnn value: (ann value deepCopy: scope). newAnn ]. "Annotations are nodes that annotate the expression they contain." Compiler addSlot: #ModeNode valued: Compiler AnnotationNode derive. Compiler ModeNode addSlot: #mode. "Modes are nodes that control the interpretation of the expression they annotate." Compiler addSlot: #CommentNode valued: Compiler AnnotationNode derive. Compiler CommentNode addSlot: #comment. "Comments are nodes that contain the expression that they annotate." Compiler addSlot: #ImplicitArgumentNode valued: Compiler SyntaxNode derive. "Implicit arguments include anything sent to the local context, as well as the lobby." Compiler addSlot: #MacroNode valued: Compiler SyntaxNode derive. Compiler MacroNode addSlot: #selector. Compiler MacroNode addSlot: #arguments. "Macro nodes are just like regular message-sends, except being applied at compile-time." macro@(Compiler MacroNode traits) walk: block [ block value: macro. macro arguments do: [| :argument | argument walk: block ] ]. macro@(Compiler MacroNode traits) transformChildren: block [ macro arguments doWithIndex: [| :argument :index | macro arguments at: index put: (argument transform: block) ]. macro ]. macro@(Compiler MacroNode traits) deepCopy: scope [| newMacro | newMacro: macro clone. newMacro arguments: (macro arguments collect: [| :argument | argument deepCopy: scope]). newMacro ]. Compiler addSlot: #UnaryMacroNode valued: Compiler MacroNode derive. Compiler addSlot: #BinaryMacroNode valued: Compiler MacroNode derive. Compiler addSlot: #KeywordMacroNode valued: Compiler MacroNode derive. Compiler addSlot: #MessageNode valued: Compiler SyntaxNode derive. Compiler MessageNode addSlot: #selector. Compiler MessageNode addSlot: #arguments. message@(Compiler MessageNode traits) walk: block [ block value: message. message arguments do: [| :argument | argument walk: block ] ]. message@(Compiler MessageNode traits) transformChildren: block [ message arguments doWithIndex: [| :argument :index | message arguments at: index put: (argument transform: block) ]. message ]. message@(Compiler MessageNode traits) deepCopy: scope [| newMessage | newMessage: message clone. newMessage arguments: (message arguments collect: [| :argument | argument deepCopy: scope]). newMessage ]. Compiler addSlot: #UnaryMessageNode valued: Compiler MessageNode derive. Compiler addSlot: #BinaryMessageNode valued: Compiler MessageNode derive. Compiler addSlot: #KeywordMessageNode valued: Compiler MessageNode derive. Compiler addSlot: #LiteralNode valued: Compiler SyntaxNode derive. Compiler LiteralNode addSlot: #value. node@(Compiler LiteralNode traits) evaluate "A literal just evaluates to its expression-value." [ node value ]. Compiler addSlot: #CompoundStatementNode valued: Compiler SyntaxNode derive. Compiler CompoundStatementNode addSlot: #statements valued: {}. group@(Compiler CompoundStatementNode traits) walk: block [ block value: group. group statements do: [| :statement | statement walk: block ] ]. group@(Compiler CompoundStatementNode traits) transformChildren: block [ group statements doWithIndex: [| :statement :index | group statements at: index put: (statement transform: block) ]. group ]. Compiler addSlot: #ArrayNode valued: Compiler CompoundStatementNode derive. group@(Compiler ArrayNode traits) deepCopy: scope [| newArray | newGroup: group clone. newGroup statements: (group statements collect: [| :statement | statement deepCopy: scope]). newGroup ]. Compiler addSlot: #ParenthesisNode valued: Compiler CompoundStatementNode derive. Compiler addSlot: #LobbyNode valued: Compiler SyntaxNode derive. _@(Compiler LobbyNode traits) depth [ 0 ]. _@(Compiler LobbyNode traits) parentScope [ error: 'The lobby has no parent scope.' ]. _@(Compiler LobbyNode traits) findVariable: _ [ Nil ]. Compiler addSlot: #BlockNode valued: Compiler CompoundStatementNode derive. Compiler BlockNode addSlot: #parentScope. Compiler BlockNode addSlot: #depth valued: 0. Compiler BlockNode addSlot: #inputVariables valued: {}. Compiler BlockNode addSlot: #freeVariables valued: Dictionary newEmpty. Compiler BlockNode addSlot: #localVariables valued: Dictionary newEmpty. Compiler BlockNode addSlot: #heapOffset valued: 0. Compiler BlockNode addSlot: #stackOffset valued: 0. b@(Compiler BlockNode traits) newFor: body@(Compiler SyntaxNode traits) "Creates a new BlockNode with the given node as the body." [| newB | newB: b clone. newB statements: {body}. newB ]. b@(Compiler BlockNode traits) newFor: body@(Compiler ParenthesisNode traits) "Takes the statements as the body of the new block." [| newB | newB: b clone. newB statements: body statements. newB ]. b@(Compiler BlockNode traits) newFor: body@(Compiler BlockNode traits) "Creates a block node with the header and body of the source block." [| newB | newB: b clone. newB addVariablesFrom: body. newB statements: body statements. newB ]. b@(Compiler BlockNode traits) walk: block [ block value: b. b localVariables keysDo: [| :variable | variable walk: block ]. b statements do: [| :statement | statement walk: block ] ]. b@(Compiler BlockNode traits) transformChildren: block [ b statements doWithIndex: [| :statement :index | b statements at: index put: (statement transform: block) ]. b ]. block@(Compiler BlockNode traits) findVariable: name [| scope | scope: block. scope freeVariables at: name ifPresent: [| :variable | ^ variable ]. [ scope localVariables at: name ifPresent: [| :variable | variable scope == block ifFalse: [block freeVariables at: name put: variable]. ^ variable ]. scope: scope parentScope. scope == Compiler LobbyNode ] whileFalse. Nil ]. b@(Compiler BlockNode traits) deepCopy: scope [| newBlock | newBlock: b clone. newBlock parentScope: scope. newBlock localVariables: Dictionary newEmpty. b localVariables keysAndValuesDo: [| :name :variable | newBlock localVariables at: name put: (variable deepCopy: scope) ]. newBlock inputVariables: (b inputVariables collect: [| :variable | newBlock localVariables at: variable name ]). newBlock freeVariables: Dictionary newEmpty. b freeVariables keysDo: [| :name | newBlock findVariable: name ]. newBlock statements: (b statements collect: [| :statement | statement deepCopy: newBlock ]). newBlock ]. dst@(Compiler BlockNode traits) addVariablesFrom: src@(Compiler BlockNode traits) [| variables | variables: (WriteStream newOn: {}). src localVariables keysAndValuesDo: [| :name :variable | (dst localVariables includesKey: name) ifTrue: [ name: (('|' ; (dst localVariables size as: String)) as: Symbol). variable name: name ]. dst localVariables at: name put: variable. variables nextPut: variable ]. src freeVariables keysAndValuesDo: [| :name :variable | dst freeVariables at: name put: variable ]. variables contents ]. Compiler addSlot: #MethodNode valued: Compiler BlockNode derive. Compiler MethodNode addSlot: #selector. Compiler MethodNode addSlot: #roles. b@(Compiler BlockNode traits) newFor: body@(Compiler MethodNode traits) "Overrides the BlockNode variant since a method definition's contents must not be inlined." [| newB | newB: b clone. newB statements: {body}. newB ]. method@(Compiler MethodNode traits) walk: block [ resend. roles do: [| :role | role ifNotNil: [role walk: block] ] ]. method@(Compiler MethodNode traits) transformChildren: block [ method roles doWithIndex: [| :role :index | role ifNotNil: [method roles at: index put: (role transform: block)] ]. resend ]. method@(Compiler MethodNode traits) deepCopy: scope [| newMethod | newMethod: resend. newMethod roles: (method roles collect: [| :role | role ifNotNil: [role deepCopy: scope] ]). newMethod ]. Compiler addSlot: #VariableNode valued: Compiler SyntaxNode derive. Compiler VariableNode addSlot: #name. Compiler VariableNode addSlot: #scope. Compiler VariableNode addSlot: #stackOffset. Compiler VariableNode addSlot: #heapOffset. var@(Compiler VariableNode traits) deepCopy: scope [ scope findVariable: var name ]. Compiler addSlot: #LoadVariableNode valued: Compiler SyntaxNode derive. Compiler LoadVariableNode addSlot: #variable. load@(Compiler LoadVariableNode traits) deepCopy: scope [| newLoad | (scope findVariable: load variable name) ifNil: [ newLoad: Compiler UnaryMessageNode clone. newLoad selector: load variable name. newLoad arguments: { Compiler ImplicitArgumentNode } ] ifNotNil: [ newLoad: load clone. newLoad variable: (load variable deepCopy: scope) ] newLoad ]. Compiler addSlot: #StoreVariableNode valued: Compiler SyntaxNode derive. Compiler StoreVariableNode addSlot: #variable. Compiler StoreVariableNode addSlot: #value. store@(Compiler StoreVariableNode traits) walk: block [ block value: store. store value walk: block ]. store@(Compiler StoreVariableNode traits) transformChildren: block [ store value: (store value transform: block). store ]. store@(Compiler StoreVariableNode traits) deepCopy: scope [| newStore | (scope findVariable: store variable name) ifNil: [ newStore: Compiler KeywordMessageNode clone. newStore selector: ((store variable name as: String) ; ':' as: Symbol). newStore arguments: { Compiler ImplicitArgumentNode. store value deepCopy: scope } ] ifNotNil: [ newStore: store clone. newStore variable: (store variable deepCopy: scope). newStore value: (store value deepCopy: scope) ]. newStore ]. Compiler addSlot: #ReturnNode. Compiler ReturnNode: Compiler SyntaxNode derive. Compiler ReturnNode addSlot: #value. ret@(Compiler ReturnNode traits) walk: block [ block value: ret. ret value walk: block ]. ret@(Compiler ReturnNode traits) deepCopy: scope [| newRet | newRet: ret clone. newRet value: (ret value deepCopy: scope). newRet ]. Compiler addSlot: #ReturnCloseNode valued: Compiler ReturnNode derive. Compiler addSlot: #ReturnFarNode valued: Compiler ReturnNode derive. Compiler addSlot: #ResendNode valued: Compiler SyntaxNode derive.