1 ensureNamespace: #nodes &delegate: True.
3 nodes define: #Node &parents: {Cloneable} &slots:
4 {#type -> Types Any. "The annotated type, by the inferencer or manually."
5 #source -> Nil. "The source of the lexer stream"
6 #lineNumber -> Nil "The line number in the source code at which the node was read."}.
7 "The general syntax object for expressions."
9 node@(nodes Node traits) new
10 [resend `setting: #{#type. #lineNumber} to: {Types Any. Nil}].
12 node@(nodes Node traits) evaluate
13 [node evaluateIn: lobby].
15 node@(nodes Node traits) evaluateIn: namespace
18 node@(nodes Node traits) walk: block
19 "A depth-first do:-style iteration through Nodes; a code/tree-walker."
21 block applyWith: node.
24 node@(nodes Node traits) transformBy: block
25 "Transforms the tree's nodes in-place by the block closure.
26 Only transformChildren: needs to be overridden."
28 (block applyWith: node) transformChildren: block
31 node@(nodes Node traits) transformChildren: block
32 "Act on each of a node's children in-place.
33 This gets overridden for the various compound node types."
38 node@(nodes Node traits) deepCopy: scope
39 "Copies the entire syntax tree, with the given scope as the lexical reference.
40 This gets overridden for each type that is compound or relates to the scope."
45 node@(nodes Node traits) deepCopy
46 "Copies the entire syntax tree with the (default) scope being the lobby."
48 node deepCopy: nodes Ground
51 node@(nodes Node traits) definitionLocation
53 (node source hasSlotNamed: #resource)
54 ifTrue: [node source resource locator
55 ifNil: ['stdin:' ; (node lineNumber - 2) printString]
56 ifNotNilDo: [| :loc | (loc as: String) ; ':' ; node lineNumber printString]]
59 ifNotNil: [node source printString ; ':' ; node lineNumber printString]]
62 nodes define: #Annotation &parents: {nodes Node}
63 &slots: {#value "The annotated node."}.
64 "A wrapper for other Nodes that adds an annotative object."
66 x@(nodes Annotation traits) = y@(nodes Annotation traits)
69 ann@(nodes Annotation traits) walk: block
75 ann@(nodes Annotation traits) transformChildren: block
77 ann value: (ann value transformBy: block).
81 ann@(nodes Annotation traits) deepCopy: scope
82 [ann clone `setting: #{#value} to: {ann value deepCopy: scope}].
84 ann@(nodes Annotation traits) evaluateIn: namespace
85 [ann value evaluateIn: namespace].
87 nodes define: #Comment &parents: {nodes Annotation}
88 &slots: {#comment -> '' "The comment object, an empty String by default."}.
89 "Comments are nodes that contain the expression that they annotate."
91 x@(nodes Comment traits) = y@(nodes Comment traits)
92 [x value = y value /\ [x comment = y comment]].
94 node@(nodes Node traits) comment: comment
95 "Returns a new Comment with the given comment wrapping the original
96 Node. Usable as a macro."
97 [nodes Comment clone `setting: #{#comment. #value} to: {comment evaluate. node}].
99 nodes define: #ImplicitArgument &parents: {nodes Node}.
100 "Implicit arguments include anything sent to the local context, as well as
103 node1@(nodes ImplicitArgument traits) = node2@(nodes ImplicitArgument traits)
106 node@(nodes ImplicitArgument traits) evaluateIn: namespace
107 "The default is to simply return the namespace as the result."
110 nodes define: #Message &parents: {nodes Node}
111 &slots: {#selector -> #'' . #arguments -> #{}}.
112 "Represents a message send."
114 m@(nodes Message traits) prototypeFor: selector
117 [Syntax isUnarySelector: selector] -> [nodes UnaryMessage].
118 [Syntax isBinarySelector: selector] -> [nodes BinaryMessage]
119 ) otherwise: [nodes KeywordMessage]
122 message@(nodes Message traits) sending: selector to: arguments
123 [(message prototypeFor: selector) clone `setting: #{#selector. #arguments} to:
124 {selector intern. arguments}].
126 x@(nodes Message traits) as: y@(nodes Message traits)
127 [y sending: x selector to: x arguments].
129 node1@(nodes Message traits) = node2@(nodes Message traits)
131 node1 selector = node2 selector
132 /\ [node1 isSameAs: node2]
133 /\ [node1 arguments = node2 arguments]
136 message@(nodes Message traits) walk: block
139 message arguments do: #(_ walk: block) `er
142 message@(nodes Message traits) transformChildren: block
144 message arguments infect: #(_ transformBy: block) `er.
148 message@(nodes Message traits) deepCopy: scope
150 message clone `>> [arguments := message arguments collect: #(deepCopy: scope) `er. ]
153 message@(nodes Message traits) evaluateIn: namespace &optionals: opts
154 "Overridden to support the evaluateIn: for ImplicitArgument."
156 message selector sendTo:
157 (message arguments collect: #(evaluateIn: namespace) `er)
161 b@(nodes Node traits) allSelectorsSent
162 "Answer a Set of all selectors sent in the source."
165 b walk: [| :node | (node is: nodes Message) ifTrue:
166 [result nextPut: node selector.
167 ({#sendTo:. #sendTo:through:} includes: result selector)
168 /\ [node arguments first is: Symbol]
169 ifTrue: [result nextPut: node arguments first]]]]
170 writingAs: IdentitySet
173 nodes define: #UnaryMessage &parents: {nodes Message}.
175 message@(nodes UnaryMessage traits) sending: selector
176 "Send the selector to the implicit context."
177 [message sending: selector to: {nodes ImplicitArgument}].
179 node@(nodes UnaryMessage traits) argument
180 [node arguments first].
182 nodes define: #BinaryMessage &parents: {nodes Message}.
183 nodes define: #KeywordMessage &parents: {nodes Message}.
185 nodes define: #Macro &parents: {nodes Message}.
186 "Macro nodes are just like regular message-sends, except being applied at
187 compile-time to the Node trees for the expressions."
189 macro@(nodes Macro traits) evaluateIn: namespace &optionals: opts
190 "Evaluate the expansion. Should this be relied on? (I.e. should this throw a
191 condition which is resumable via macro-expansion?)"
193 (macro macroExpand &optionals:
196 [nodes OptionalKeywords new `>>
198 keywords := opts atAll: (0 below: opts size by: 2).
199 arguments := opts atAll: (1 below: opts size by: 2). ]]))
200 evaluateIn: namespace
203 m@(nodes Macro traits) prototypeFor: selector
206 [Syntax isUnarySelector: selector] -> [nodes UnaryMacro].
207 [Syntax isBinarySelector: selector] -> [nodes BinaryMacro]
208 ) otherwise: [nodes KeywordMacro]
211 nodes define: #UnaryMacro &parents: {nodes Macro}.
212 nodes define: #BinaryMacro &parents: {nodes Macro}.
213 nodes define: #KeywordMacro &parents: {nodes Macro}.
215 nodes define: #Deferred &parents: {nodes Message}.
216 "Deferred nodes are just like regular message-sends, except being applied
217 only when all argument promises are entirely resolved."
219 message@(nodes Message traits) deferred
220 [message as: nodes Deferred].
222 message@(nodes Deferred traits) evaluateIn: namespace &optionals: opts
224 (message arguments collect: #(evaluateIn: namespace) `er)
225 whenFulfilled: [| *args |
226 message selector sendTo: args &optionals: opts]
229 m@(nodes Deferred traits) prototypeFor: selector
232 [Syntax isUnarySelector: selector] -> [nodes UnaryDeferred].
233 [Syntax isBinarySelector: selector] -> [nodes BinaryDeferred]
234 ) otherwise: [nodes KeywordDeferred]
237 nodes define: #UnaryDeferred &parents: {nodes Deferred}.
238 nodes define: #BinaryDeferred &parents: {nodes Deferred}.
239 nodes define: #KeywordDeferred &parents: {nodes Deferred}.
241 nodes define: #MessageWrapper &parents: {nodes Node}
244 w@(nodes MessageWrapper traits) for: message
245 [w new `setting: #{#message} to: {message}].
247 w@(nodes MessageWrapper traits) selector
248 [w message selector].
250 w@(nodes MessageWrapper traits) transformChildren: block
252 w message := w message transformBy: block.
256 w@(nodes MessageWrapper traits) walk: block
259 w message walk: block.
262 w@(nodes MessageWrapper traits) deepCopy: scope
264 w clone `>> [message := w message deepCopy: scope. ]
267 nodes define: #OptionalKeywords &parents: {nodes MessageWrapper}
268 &slots: {#keywords -> {}. #arguments -> {}}.
269 "Annotates a Message with optional keywords and values given."
271 x@(nodes OptionalKeywords traits) = y@(nodes OptionalKeywords traits)
272 [x message = y message /\ [x keywords = y keywords] /\ [x arguments = y arguments]].
274 opts@(nodes OptionalKeywords traits) new
275 [resend clone `setting: #{#keywords. #arguments} to: #{{}. {}}].
277 opts@(nodes OptionalKeywords traits) walk: block
281 do: #(walk: block) `er
284 opts@(nodes OptionalKeywords traits) transformChildren: block
287 opts arguments infect: #(_ transformBy: block) `er.
291 opts@(nodes OptionalKeywords traits) deepCopy: scope
293 resend `>> [arguments := opts arguments collect: #(deepCopy: scope) `er. ]
296 opts@(nodes OptionalKeywords traits) evaluateIn: namespace
298 opts message evaluateIn: namespace &optionals:
300 opts keywords with: opts arguments
301 do: [| :key :arg | result nextPutAll: {key intern. arg evaluateIn: namespace}]
305 nodes define: #RestArguments &parents: {nodes MessageWrapper}
306 &slots: {#arguments}.
308 x@(nodes RestArguments traits) = y@(nodes RestArguments traits)
309 [x message = y message /\ [x arguments = y arguments]].
311 rest@(nodes RestArguments traits) new
312 [resend clone `setting: #{#arguments} to: #{{}}].
314 rest@(nodes RestArguments traits) walk: block
317 rest arguments do: #(_ walk: block) `er
320 rest@(nodes RestArguments traits) transformChildren: block
323 rest arguments infect: #(_ transformBy: block) `er.
327 rest@(nodes RestArguments traits) deepCopy: scope
329 resend `>> [arguments := rest arguments collect: #(deepCopy: scope) `er. ]
332 rest@(nodes RestArguments traits) allArguments
334 rest message arguments ; rest arguments
337 rest@(nodes RestArguments traits) evaluateIn: namespace &optionals: opts
339 rest selector sendTo:
340 (rest allArguments collect: #(evaluateIn: namespace) `er)
344 nodes define: #Placeholder &parents: {nodes Node}.
346 node@(nodes Node traits) as: _@(nodes Placeholder traits)
351 node@(nodes UnaryMessage traits) as: ph@(nodes Placeholder traits)
353 node selector = #_ /\ [node arguments first == nodes ImplicitArgument]
354 ifTrue: [ph] ifFalse: [node]
357 ph@(nodes Placeholder traits) evaluateIn: namespace &optionals: opts
362 nodes define: #Pattern &parents: {nodes MessageWrapper}.
363 "Pattern nodes are just like regular message-sends, except having only
364 some arguments filled initially at parse-time. They may be treated as
365 records or curry-able message-sends."
367 pattern@(nodes Pattern traits) keywords
368 [pattern selector keywords].
370 pattern@(nodes Pattern traits) values
371 [pattern message arguments].
373 nodes Pattern traits define: #BlankTokens &builder:
374 [{nodes Placeholder. nodes ImplicitArgument}].
376 pattern@(nodes Pattern traits) isPlaceholder: node
378 pattern BlankTokens includes: node
381 pattern@(nodes Pattern traits) arity
382 [| count countedImplicit |
387 [node == nodes Placeholder]
389 [node == nodes ImplicitArgument /\ [countedImplicit isNil]]
390 -> [countedImplicit := node. count += 1]
395 pattern@(nodes Pattern traits) isComplete
396 "Answers whether it can be evaluated successfully."
398 pattern walk: [| :node | node == nodes Placeholder ifTrue: [^ False]].
402 pattern@(nodes Pattern traits) completeWith: values
403 [| valuesIn countedImplicit |
404 valuesIn := values reader.
411 [node == nodes ImplicitArgument /\ [countedImplicit isNil]]
412 -> [countedImplicit := node. valuesIn next].
413 [node == nodes Placeholder]
415 ) otherwise: [node]]]
418 pattern@(nodes Pattern traits) deepCopy: scope
420 pattern for: (pattern message deepCopy: scope)
423 pattern@(nodes Pattern traits) evaluateIn: namespace &optionals: opts
424 "Patterns are auto-quasiquoting, in that their arguments get evaluated,
425 but the message is not sent."
427 pattern for: pattern message clone `>>
428 [arguments := pattern message arguments collect: #(evaluateIn: namespace) `er. ]
431 nodes define: #Literal &parents: {nodes Node} &slots: {#value}.
432 "The syntax for a literal Slate object, i.e. something the Lexer can create
435 nodes Literal traits define: #ReusableValues &builder: [Dictionary new].
436 nodes Literal traits define: #Nil &builder: [nodes Literal clone].
438 l@(nodes Literal traits) noteReusable: obj
439 [l ReusableValues at: obj ifAbsentPut:
440 [l new `setting: #{#value} to: {obj}]].
442 [| :each | nodes Literal noteReusable: each] for:
443 {Array new. ByteArray new. #''. ''}.
445 node@(nodes Literal traits) for: obj
446 [node ReusableValues at: obj ifAbsent: [node new `setting: #{#value} to: {obj}]].
448 node@(nodes Literal traits) for: _@Nil [node Nil].
450 x@(nodes Literal traits) = y@(nodes Literal traits)
453 node@(nodes Literal traits) evaluateIn: namespace
454 "A literal just evaluates to its expression-value."
457 b@(nodes Node traits) allLiterals
458 "Answer an Array of all literal values from the source."
461 b walk: [| :node | (node is: nodes Literal) ifTrue:
462 [result nextPut: node value]]] writingAs: #{}
465 nodes define: #CompoundStatement &parents: {nodes Node}
466 &slots: {#statements -> #{}}.
468 array@(Sequence traits) as: group@(nodes CompoundStatement traits)
469 [group new `setting: #{#statements} to: {array as: group statements}].
471 group@(nodes CompoundStatement traits) size
472 "The number of statements/elements in the expression."
473 [group statements size].
475 node1@(nodes CompoundStatement traits) = node2@(nodes CompoundStatement traits)
476 [(node1 isSameAs: node2) /\ [node1 statements = node2 statements]].
478 group@(nodes CompoundStatement traits) walk: block
481 group statements do: #(_ walk: block) `er
484 group@(nodes CompoundStatement traits) transformChildren: block
486 group statements infect: #(_ transformBy: block) `er.
490 group@(nodes CompoundStatement traits) deepCopy: scope
492 (group statements collect:
493 #(_ deepCopy: scope) `er) as: group
496 nodes define: #Array &parents: {nodes CompoundStatement}.
498 group@(nodes Array traits) evaluateIn: namespace
500 group statements collect: #(evaluateIn: namespace) `er
503 nodes define: #Parenthesis &parents: {nodes CompoundStatement}.
505 group@(nodes Parenthesis traits) evaluateIn: namespace
507 group statements isEmpty
510 [group statements allButLastDo: #(_ evaluateIn: namespace) `er.
511 group statements last evaluateIn: namespace]
514 group@(nodes Parenthesis traits) parenthesize
519 node@(nodes Node traits) parenthesize
524 seq@(Sequence traits) parenthesize
526 seq size = 1 ifTrue: [seq first] ifFalse: [seq as: nodes Parenthesis]
529 nodes define: #Namespace &parents: {nodes Node} &slots: {#namespace -> lobby}.
531 node@(nodes Namespace traits) for: namespace
532 [node new `setting: #{#namespace} to: {namespace}].
534 node1@(nodes Namespace traits) = node2@(nodes Namespace traits)
535 [node1 namespace = node2 namespace].
537 _@(nodes Namespace traits) evaluateIn: namespace
538 [shouldNotImplement].
540 _@(nodes Namespace traits) parentScope
542 error: 'The top-level namespace has no parent scope.'
545 node@(nodes Namespace traits) topLevel
550 _@(nodes Namespace traits) findVariable: _
551 "Present for compatibility with Block findVariable:."
554 namespace@(nodes Namespace traits) includesScope: scope
555 [namespace == scope].
557 nodes define: #Ground &builder: [nodes Namespace for: lobby].
559 nodes define: #Block &parents: {nodes CompoundStatement} &slots:
560 {#parentScope -> nodes Ground.
561 #inputVariables -> #{}.
562 "Holds Variable nodes representing the block's inputs in order."
563 #restVariable -> Nil.
564 "Holds a Variable node representing the block's rest parameter if it
566 #optionalKeywords -> #{}.
567 #optionalVariables -> #{}.
568 "Holds Variable nodes representing the block's optional local slots."
569 #localVariables -> #{}
570 "Holds Variable nodes representing the block's local slots (including
571 inputs in order and optionals)."}.
573 node1@(nodes Block traits) = node2@(nodes Block traits)
574 "TODO: ensure this is correct and that local variable order is ignored."
577 /\ [node1 inputVariables = node2 inputVariables]
578 /\ [node1 parentScope = node2 parentScope]
579 /\ [node1 localVariables = node2 localVariables]
582 block@(nodes Block traits) compile
583 "Invoke the VM ByteCompiler."
585 VM SSACompiler new generate: block result: Nil
588 block@(nodes Block traits) compileAndRun
589 "Compile the block using the VM ByteCompiler and then run it."
594 block@(nodes Block traits) evaluateIn: namespace
595 "Compile the block and return it."
598 b@(nodes Block traits) new
601 [inputVariables := b inputVariables new.
602 localVariables := b localVariables new.
603 optionalKeywords := b optionalKeywords new.
604 optionalVariables := b optionalVariables new.
605 restVariable := Nil. ]
608 b@(nodes Block traits) body: body@(nodes Node traits)
609 "Makes a given Node the body."
610 [b statements := {body}].
612 b@(nodes Block traits) body: body@(nodes Parenthesis traits)
613 "Takes the statements as the body of the block."
614 [b statements := body statements].
616 b@(nodes Block traits) newFor: body@(nodes Node traits)
617 "Creates a new Block with the given node as the body."
618 [b new `>> [body := body. ]].
620 block@(nodes Block traits) addVariable: var
621 "Adds the Variable node to the block's locals and sets it as the
622 variable's scope (used to compile closures properly), and answers it."
624 (block localVariables anySatisfy: [| :other | other name = var name])
626 [var name := block uniqueVariableName].
628 block localVariables := block localVariables ; { var }.
632 block@(nodes Block traits) addVariableNamed: name
633 "Creates a new Variable with the given name and adds it as a local,
635 [block addVariable: (nodes Variable clone `setting: #{#name} to: {name})].
637 block@(nodes Block traits) uniqueVariableName &prefix: prefix
639 prefix `defaultsTo: '_'.
642 [(block findVariable: (prefix ; nameIndex printString) intern) isNotNil]]
647 [error: 'Could not generate a unique variable name.'].
648 (prefix ; nameIndex printString) intern
651 block@(nodes Block traits) addVariable &name: name &prefix: prefix
652 "Calls addVariable: with a name guaranteed not to clash with other such names."
654 name `defaultsTo: (block uniqueVariableName &prefix: prefix).
655 block addVariableNamed: name
658 block@(nodes Block traits) addInputVariableNamed: name
659 "Creates a new Variable with the given name and adds it as an input,
662 var := block addVariableNamed: name.
663 block inputVariables := block inputVariables ; { var }.
667 block@(nodes Block traits) addInputVariable &name: name &prefix: prefix
668 "Calls addInputVariable: with a name guaranteed not to clash with other such
671 name `defaultsTo: (block uniqueVariableName &prefix: prefix).
672 block addInputVariableNamed: name
675 block@(nodes Block traits) addOptionalKeyword: key named: name
676 "Creates a new Variable with the given name and adds it as an optional,
679 var := block addVariableNamed: name.
680 block optionalKeywords := block optionalKeywords ; { key intern }.
681 block optionalVariables := block optionalVariables ; { var }.
685 block@(nodes Block traits) topLevel
686 "Recurses up the scope to find the top-level scope."
688 block parentScope topLevel
691 block@(nodes Block traits) outermostBlock
692 "Answers the outermost scope that is still a Block or MethodDefinition and not
696 [scope parentScope isSameAs: nodes Namespace]
697 whileFalse: [scope := scope parentScope].
701 block@(nodes Block traits) hasVariableNamed: name
703 block localVariables anySatisfy: [| :var | name =~ var name]
706 block@(nodes Block traits) outermostScopeNotBinding: name
707 "Answers the outermost scope that does not have a given binding or slot."
709 (block hasVariableNamed: name) ifFalse:
711 [(scope hasVariableNamed: name) \/ [scope parentScope isSameAs: nodes Namespace]]
712 whileFalse: [scope := scope parentScope]].
716 block@(nodes Block traits) findVariable: name
717 "Searches through the current scope, and then upward, for the entry
718 corresponding to the given name, and answers what it can find, or Nil if none."
721 detect: [| :var | name =~ var name]
722 ifNone: [block parentScope findVariable: name]
725 block@(nodes Block traits) includesScope: scope
726 [block == scope \/ [block parentScope includesScope: scope]].
728 block@(nodes Block traits) from: varNames to: codeBlock &locals: localNames &linkVariables: linkVariables
729 "Takes an Array of symbol names or Nil's for unnamed variables, and runs the
730 code block with corresponding VariableNodes as inputs. The code block is
731 expected to return the method body expression. The method then answers a new
732 Block with that method body and those input variables."
735 varNames do: [| :var | result addInputVariable &name: var].
736 localNames ifNotNil: [localNames do: [| :var | result addVariable &name: var]].
737 "ASSUME: newFor: does not clear inputs."
738 result body := codeBlock applyTo: result localVariables.
739 linkVariables ifNotNil: [result linkVariables].
743 b@(nodes Block traits) deepCopy: scope &into: target
744 "Copies up to the level of the given scope, and sets the scope to that one."
746 (target ifNil: [b]) clone `>>
748 parentScope := scope.
750 b localVariables collect:
751 [| :var newVar | var clone `>> [scope := newBlock. ]].
753 b inputVariables collect: [| :var | newBlock findVariable: var name].
755 b optionalVariables collect: [| :var | newBlock findVariable: var name].
757 b restVariable ifNotNil: [newBlock findVariable: b restVariable name].
759 b statements collect: #(deepCopy: newBlock) `er.
763 block@(nodes Block traits) deepCopy &into: target
764 "Copies the entire syntax tree with the (default) scope being the block's parent."
766 block deepCopy: block parentScope
769 block@(nodes Block traits) as: target@(nodes Block traits)
770 "This should allow Block and MethodDefinition objects to be converted (with
771 loss of Signature information, of course."
772 [block deepCopy &into: target].
774 block@(nodes Block traits) arity
775 [block inputVariables size].
777 dst@(nodes Block traits) addVariablesFrom: src@(nodes Block traits)
778 "Copies over the local variable entries from the source block to the
779 destination. Answers the locals found."
781 src localVariables do: #(dst addVariable: _) `er
784 b@(nodes Block traits) modifiesOwnVariables
785 "Answers whether there are any direct variable stores."
786 "TODO: Avoid re-implementing detect:!"
788 b walk: [| :node | (node is: nodes StoreVariable) ifTrue: [^ True]].
792 b@(nodes Block traits) modifiesInputVariables
793 "Answers whether there are any direct variable stores to inputs."
795 b walk: [| :node | (node is: nodes StoreVariable) /\
796 [b inputVariables includes: node variable] ifTrue: [^ True]].
800 b@(nodes Block traits) allSelectorsSent
805 (node isSameAs: nodes LoadVariable) \/
806 [node isSameAs: nodes StoreVariable]
807 ifTrue: [result nextPut: node variable name]
808 ifFalse: [(node is: nodes Message)
809 ifTrue: [result nextPut: node selector]]].
813 b@(nodes Block traits) allSelectorsSentToVar: var
814 "Answers the Set of all selectors called in this method on the Variable object."
816 loadExpr := var load.
819 [| :expr | (expr is: nodes Message)
820 /\ [expr arguments includes: loadExpr]
821 ifTrue: [result nextPut: expr selector]]
825 b@(nodes Block traits) allSelectorsSentToInputAt: argIndex
826 "Answers the Set of all selectors called in this method on the argument object."
828 (b inputVariables acceptsKey: argIndex)
829 ifTrue: [b allSelectorsSentToVar: (b inputVariables at: argIndex)]
830 ifFalse: [error: 'No such input argument.']
833 b@(nodes Block traits) allSelectorsSentToInputs
836 b inputVariables keysDo:
837 [| :index | result ; (b allSelectorsSentToInputAt: index)].
841 b@(nodes Block traits) allSelectorsSentImplicitly
845 [| :node | (node is: nodes Message)
846 ifTrue: [node arguments do:
847 [| :arg | (arg is: nodes LoadVariable) /\
848 [arg variable = nodes ImplicitArgument]
849 ifTrue: [result nextPut: node selector]]]].
853 nodes define: #MethodDefinition &parents: {nodes Block}
854 &slots: {#selector. #roles -> #{}}.
855 "The object representing the definition of a Method."
857 method@(nodes MethodDefinition traits) new
858 [resend `>> [selector := Nil. roles := method roles new. ]].
860 method@(nodes MethodDefinition traits) of: selector on: roles
861 from: varNames to: codeBlock &locals: localNames &linkVariables: linkVariables
863 (method from: varNames to: codeBlock &locals: localNames &linkVariables: linkVariables) `>>
864 [selector := selector. roles := roles. ]
867 node1@(nodes MethodDefinition traits) = node2@(nodes MethodDefinition traits)
868 [resend /\ [node1 selector = node2 selector] /\ [node1 roles = node2 roles]].
870 method@(nodes MethodDefinition traits) walk: block
873 method roles do: [| :role | role ifNotNil: [role walk: block]]
876 method@(nodes MethodDefinition traits) transformChildren: block
878 method roles infect: [| :role | role ifNotNil: [role transformBy: block]].
882 method@(nodes MethodDefinition traits) deepCopy: scope &into: target
885 [roles := method roles
886 collect: [| :role | role ifNotNil: [role deepCopy: scope]]. ]
889 method@(nodes MethodDefinition traits) evaluateIn: namespace
892 asMethod: method selector
893 on: (method roles collect: #(evaluateIn: namespace) `er)
896 nodes define: #Signature &parents: {nodes Node} &slots: {
899 #inputVariables -> #{}.
900 #restVariable -> Nil.
901 #optionalKeywords -> #{}.
902 #optionalVariables -> #{}
904 "The object representing the definition of a Method without the body."
906 sig@(nodes Signature traits) new
910 roles := sig roles new.
911 inputVariables := sig inputVariables new.
913 optionalKeywords := sig optionalKeywords new.
914 optionalVariables := sig optionalVariables new. ]
917 method@(nodes MethodDefinition traits) as: sig@(nodes Signature traits)
920 [selector := method selector.
921 roles := method roles.
922 inputVariables := method inputVariables.
923 inputVariables do: [| :var | var scope := Nil].
924 restVariable := method restVariable.
925 optionalKeywords := method optionalKeywords.
926 optionalVariables := method optionalVariables. ]
929 sig@(nodes Signature traits) as: method@(nodes MethodDefinition traits)
933 selector := sig selector.
935 inputVariables := sig inputVariables copy.
936 inputVariables do: [| :var | var scope := result].
937 localVariables := result inputVariables copy.
938 restVariable := sig restVariable.
939 optionalKeywords := sig optionalKeywords.
940 optionalVariables := sig optionalVariables. ]
943 node1@(nodes Signature traits) = node2@(nodes Signature traits)
944 [node1 selector = node2 selector /\ [node1 roles = node2 roles]].
946 sig@(nodes Signature traits) walk: block
948 sig roles do: [| :role | role ifNotNil: [role walk: block]]
951 sig@(nodes Signature traits) transformChildren: block
953 sig roles infect: [| :role | role ifNotNil: [role transformBy: block]].
956 sig@(nodes Signature traits) deepCopy: scope &into: target
960 collect: [| :role | role ifNotNil: [role deepCopy: scope]]. ]
963 sig@(nodes Signature traits) evaluateIn: namespace
968 nodes define: #Variable &parents: {nodes Node} &slots: {
970 #scope -> nodes Ground
973 node1@(nodes Variable traits) = node2@(nodes Variable traits)
974 [node1 name = node2 name /\ [node1 scope = node2 scope]].
976 var@(nodes Variable traits) deepCopy: scope
978 scope findVariable: var name
981 var@(nodes Variable traits) isImmutable [False].
983 nodes define: #Binding &parents: {nodes Variable}.
985 var@(nodes Binding traits) isImmutable [True].
987 nodes define: #RestVariable &parents: {nodes Variable}.
989 nodes define: #VariableOperation &parents: {nodes Node} &slots: {#variable}.
991 nodes define: #LoadVariable &parents: {nodes VariableOperation} &slots: {}.
993 load@(nodes LoadVariable traits) from: variable
994 [load new `setting: #{#variable} to: {variable}].
996 var@(nodes Variable traits) load
997 [nodes LoadVariable from: var].
999 node1@(nodes LoadVariable traits) = node2@(nodes LoadVariable traits)
1000 [node1 variable = node2 variable].
1002 load@(nodes LoadVariable traits) deepCopy: scope
1004 (scope findVariable: load variable name)
1005 ifNil: [nodes UnaryMessage
1006 sending: load variable name
1007 to: {nodes ImplicitArgument}]
1008 ifNotNilDo: #(load from: _) `er
1011 load@(nodes LoadVariable traits) evaluateIn: namespace &optionals: opts
1013 load variable name sendTo: {namespace} &optionals: opts
1016 nodes define: #LoadRestVariable &parents: {nodes LoadVariable}.
1018 nodes define: #StoreVariable &parents: {nodes VariableOperation}
1021 store@(nodes StoreVariable traits) of: value into: variable
1022 [store new `setting: #{#value. #variable} to: {value. variable}].
1024 var@(nodes Variable traits) store: value
1025 [nodes StoreVariable of: value into: var].
1027 var@(nodes Binding traits) store: value
1028 [error: 'Cannot rebind'].
1030 load@(nodes LoadVariable traits) store: value
1031 [load variable store: value].
1033 store@(nodes StoreVariable traits) load
1034 [store variable load].
1036 node1@(nodes StoreVariable traits) = node2@(nodes StoreVariable traits)
1037 [node1 variable = node2 variable /\ [node1 value = node2 value]].
1039 store@(nodes StoreVariable traits) walk: block
1042 store value walk: block
1045 store@(nodes StoreVariable traits) transformChildren: block
1047 store value := store value transformBy: block.
1051 store@(nodes StoreVariable traits) deepCopy: scope
1053 (scope findVariable: store variable name)
1055 [nodes KeywordMessage
1056 sending: store variable name name ; ':'
1057 to: {nodes ImplicitArgument. store value deepCopy: scope}]
1059 [| :var | store of: (store value deepCopy: scope) into: var]
1062 store@(nodes StoreVariable traits) evaluateIn: namespace &optionals: opts
1064 (store variable name name ; ':') intern
1065 sendTo: {namespace. store value evaluateIn: namespace}
1069 nodes define: #Return &parents: {nodes Node} &slots: {#value}.
1071 ret@(nodes Return traits) of: value
1072 [ret new `setting: #{#value} to: {value}].
1074 node1@(nodes Return traits) = node2@(nodes Return traits)
1075 [node1 value = node2 value /\ [node1 isSameAs: node2]].
1077 ret@(nodes Return traits) walk: block
1080 ret value walk: block
1083 ret@(nodes Return traits) deepCopy: scope
1085 ret of: (ret value deepCopy: scope)
1088 ret@(nodes Return traits) transformChildren: block
1090 ret value := ret value transformBy: block.
1094 nodes define: #ReturnClose &parents: {nodes Return}.
1096 ret@(nodes ReturnClose traits) selector [#^].
1098 nodes define: #ReturnFar &parents: {nodes Return}.
1100 ret@(nodes ReturnFar traits) selector [#^^].
1102 nodes define: #ReturnLevel &parents: {nodes Return} &slots: {#level -> 1}.
1104 ret@(nodes ReturnLevel traits) selector [('^' ; ret level printString) intern].
1106 ret@(nodes ReturnLevel traits) by: offset
1107 [ret new `setting: #{#level} to: {offset}].
1109 nodes define: #Resend &parents: {nodes Node}.
1111 _@(nodes Resend traits) selector [ #resend ].
1113 node1@(nodes Resend traits) = node2@(nodes Resend traits)
1116 "Non-core utilities follow."
1118 n@(nodes Node traits) allSelectorsSent
1119 "Answer a Set of selectors for the messages sent in this parse tree."
1122 n walk: [| :node | (node is: nodes Message)
1123 ifTrue: [calls nextPut: node selector]]]
1124 writingAs: (IdentitySet new &capacity: 100)
1127 n@(nodes Node traits) allMacroSelectorsSent
1128 "Answer a Set of selectors for the macro-messages sent in this parse tree."
1131 n walk: [| :node | (node is: nodes Macro)
1132 ifTrue: [calls nextPut: node selector]]]
1133 writingAs: (IdentitySet new &capacity: 100)
1136 n@(nodes Node traits) nodeCount
1137 "Answer the number of nodes in this tree, analogous to the size of the tree."
1140 n walk: [| :_ | count += 1].
1144 n@(nodes Node traits) hasExplicitReturn
1145 "Answer whether there is an explicit/early return call."
1147 n walk: [| :node | (node is: nodes Return) ifTrue: [^ True]].