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 copyWith: var.
632 block@(nodes Block traits) addVariableNamed: name &varType: varType
633 "Creates a new Variable with the given name and adds it as a local,
636 varType `defaultsTo: nodes Variable.
638 detect: [| :var | var name = name /\ [var isSameAs: varType]]
639 ifNone: [block addVariable: (varType named: name)]
642 block@(nodes Block traits) uniqueVariableName &prefix: prefix
644 prefix `defaultsTo: '_'.
647 [(block findVariable: (prefix ; nameIndex printString) intern) isNotNil]]
652 [error: 'Could not generate a unique variable name.'].
653 (prefix ; nameIndex printString) intern
656 block@(nodes Block traits) addVariable &name: name &prefix: prefix
657 "Calls addVariable: with a name guaranteed not to clash with other such names."
659 name `defaultsTo: (block uniqueVariableName &prefix: prefix).
660 block addVariableNamed: name
663 block@(nodes Block traits) addInputVariableNamed: name
664 "Creates a new Variable with the given name and adds it as an input,
667 var := block addVariableNamed: name.
668 block inputVariables := block inputVariables copyWith: var.
672 block@(nodes Block traits) addInputVariable &name: name &prefix: prefix
673 "Calls addInputVariable: with a name guaranteed not to clash with other such
676 name `defaultsTo: (block uniqueVariableName &prefix: prefix).
677 block addInputVariableNamed: name
680 block@(nodes Block traits) addOptionalKeyword: key named: name
681 "Creates a new Variable with the given name and adds it as an optional,
684 var := block addVariableNamed: name.
685 block optionalKeywords := block optionalKeywords copyWith: key intern.
686 block optionalVariables := block optionalVariables copyWith: var.
690 block@(nodes Block traits) topLevel
691 "Recurses up the scope to find the top-level scope."
693 block parentScope topLevel
696 block@(nodes Block traits) outermostBlock
697 "Answers the outermost scope that is still a Block or MethodDefinition and not
701 [scope parentScope isSameAs: nodes Namespace]
702 whileFalse: [scope := scope parentScope].
706 block@(nodes Block traits) hasVariableNamed: name
708 block localVariables anySatisfy: [| :var | name =~ var name]
711 block@(nodes Block traits) outermostScopeNotBinding: name
712 "Answers the outermost scope that does not have a given binding or slot."
714 (block hasVariableNamed: name) ifFalse:
716 [(scope hasVariableNamed: name) \/ [scope parentScope isSameAs: nodes Namespace]]
717 whileFalse: [scope := scope parentScope]].
721 block@(nodes Block traits) findVariable: name
722 "Searches through the current scope, and then upward, for the entry
723 corresponding to the given name, and answers what it can find, or Nil if none."
726 detect: [| :var | name =~ var name]
727 ifNone: [block parentScope findVariable: name]
730 block@(nodes Block traits) includesScope: scope
731 [block == scope \/ [block parentScope includesScope: scope]].
733 block@(nodes Block traits) from: varNames to: codeBlock &locals: localNames &linkVariables: linkVariables
734 "Takes an Array of symbol names or Nil's for unnamed variables, and runs the
735 code block with corresponding VariableNodes as inputs. The code block is
736 expected to return the method body expression. The method then answers a new
737 Block with that method body and those input variables."
740 varNames do: [| :var | result addInputVariable &name: var].
741 localNames ifNotNil: [localNames do: [| :var | result addVariable &name: var]].
742 "ASSUME: newFor: does not clear inputs."
743 result body := codeBlock applyTo: result localVariables.
744 linkVariables ifNotNil: [result linkVariables].
748 b@(nodes Block traits) deepCopy: scope &into: target
749 "Copies up to the level of the given scope, and sets the scope to that one."
751 (target ifNil: [b]) clone `>>
753 parentScope := scope.
755 b localVariables collect:
756 [| :var newVar | var clone `>> [scope := newBlock. ]].
758 b inputVariables collect: [| :var | newBlock findVariable: var name].
760 b optionalVariables collect: [| :var | newBlock findVariable: var name].
762 b restVariable ifNotNil: [newBlock findVariable: b restVariable name].
764 b statements collect: #(deepCopy: newBlock) `er.
768 block@(nodes Block traits) deepCopy &into: target
769 "Copies the entire syntax tree with the (default) scope being the block's parent."
771 block deepCopy: block parentScope
774 block@(nodes Block traits) as: target@(nodes Block traits)
775 "This should allow Block and MethodDefinition objects to be converted (with
776 loss of Signature information, of course."
777 [block deepCopy &into: target].
779 block@(nodes Block traits) arity
780 [block inputVariables size].
782 dst@(nodes Block traits) addVariablesFrom: src@(nodes Block traits)
783 "Copies over the local variable entries from the source block to the
784 destination. Answers the locals found."
786 src localVariables do: #(dst addVariable: _) `er
789 b@(nodes Block traits) modifiesOwnVariables
790 "Answers whether there are any direct variable stores."
791 "TODO: Avoid re-implementing detect:!"
793 b walk: [| :node | (node is: nodes StoreVariable) ifTrue: [^ True]].
797 b@(nodes Block traits) modifiesInputVariables
798 "Answers whether there are any direct variable stores to inputs."
800 b walk: [| :node | (node is: nodes StoreVariable) /\
801 [b inputVariables includes: node variable] ifTrue: [^ True]].
805 b@(nodes Block traits) allSelectorsSent
810 (node isSameAs: nodes LoadVariable) \/
811 [node isSameAs: nodes StoreVariable]
812 ifTrue: [result nextPut: node variable name]
813 ifFalse: [(node is: nodes Message)
814 ifTrue: [result nextPut: node selector]]].
818 b@(nodes Block traits) allSelectorsSentTo: var@(nodes Variable traits)
819 "Answers the Set of all selectors called in this method on the Variable object."
821 loadExpr := var load.
824 [| :statement | statement walk:
825 [| :expr | (expr is: nodes Message) /\ [expr arguments includes: loadExpr]
826 ifTrue: [result nextPut: expr selector]]]] writingAs: Set
829 b@(nodes Block traits) allSelectorsSentToInputAt: argIndex
830 "Answers the Set of all selectors called in this method on the argument object."
832 (b inputVariables acceptsKey: argIndex)
833 ifTrue: [b allSelectorsSentTo: (b inputVariables at: argIndex)]
834 ifFalse: [error: 'No such input argument.']
837 b@(nodes Block traits) allSelectorsSentToInputs
840 b inputVariables keysDo:
841 [| :index | result ; (b allSelectorsSentToInputAt: index)]
845 b@(nodes Block traits) bodyIncludesImplicitSends
848 [| :statement | statement walk:
849 [| :node | (node is: nodes Message) /\
850 [node arguments includes: nodes ImplicitArgument]
855 b@(nodes Block traits) allSelectorsSentImplicitly
859 [| :statement | statement walk:
860 [| :node | (node is: nodes Message) ifTrue:
863 arg = nodes ImplicitArgument
864 \/ [(arg is: nodes LoadVariable)
865 /\ [arg variable = nodes ImplicitArgument]]
866 ifTrue: [result nextPut: node selector]]]]]] writingAs: Set
869 nodes define: #MethodDefinition &parents: {nodes Block}
870 &slots: {#selector. #roles -> #{}}.
871 "The object representing the definition of a Method."
873 method@(nodes MethodDefinition traits) new
874 [resend `>> [selector := Nil. roles := method roles new. ]].
876 method@(nodes MethodDefinition traits) of: selector on: roles
877 from: varNames to: codeBlock &locals: localNames &linkVariables: linkVariables
879 (method from: varNames to: codeBlock &locals: localNames &linkVariables: linkVariables) `>>
880 [selector := selector. roles := roles. ]
883 node1@(nodes MethodDefinition traits) = node2@(nodes MethodDefinition traits)
884 [resend /\ [node1 selector = node2 selector] /\ [node1 roles = node2 roles]].
886 method@(nodes MethodDefinition traits) walk: block
889 method roles do: [| :role | role ifNotNil: [role walk: block]]
892 method@(nodes MethodDefinition traits) transformChildren: block
894 method roles infect: [| :role | role ifNotNil: [role transformBy: block]].
898 method@(nodes MethodDefinition traits) deepCopy: scope &into: target
901 [roles := method roles
902 collect: [| :role | role ifNotNil: [role deepCopy: scope]]. ]
905 method@(nodes MethodDefinition traits) evaluateIn: namespace
908 asMethod: method selector
909 on: (method roles collect: #(evaluateIn: namespace) `er)
912 nodes define: #Signature &parents: {nodes Node} &slots: {
915 #inputVariables -> #{}.
916 #restVariable -> Nil.
917 #optionalKeywords -> #{}.
918 #optionalVariables -> #{}
920 "The object representing the definition of a Method without the body."
922 sig@(nodes Signature traits) new
926 roles := sig roles new.
927 inputVariables := sig inputVariables new.
929 optionalKeywords := sig optionalKeywords new.
930 optionalVariables := sig optionalVariables new. ]
933 method@(nodes MethodDefinition traits) as: sig@(nodes Signature traits)
936 [selector := method selector.
937 roles := method roles.
938 inputVariables := method inputVariables.
939 inputVariables do: [| :var | var scope := Nil].
940 restVariable := method restVariable.
941 optionalKeywords := method optionalKeywords.
942 optionalVariables := method optionalVariables. ]
945 sig@(nodes Signature traits) as: method@(nodes MethodDefinition traits)
949 selector := sig selector.
951 inputVariables := sig inputVariables copy.
952 inputVariables do: [| :var | var scope := result].
953 localVariables := result inputVariables copy.
954 restVariable := sig restVariable.
955 optionalKeywords := sig optionalKeywords.
956 optionalVariables := sig optionalVariables. ]
959 node1@(nodes Signature traits) = node2@(nodes Signature traits)
960 [node1 selector = node2 selector /\ [node1 roles = node2 roles]].
962 sig@(nodes Signature traits) walk: block
964 sig roles do: [| :role | role ifNotNil: [role walk: block]]
967 sig@(nodes Signature traits) transformChildren: block
969 sig roles infect: [| :role | role ifNotNil: [role transformBy: block]].
972 sig@(nodes Signature traits) deepCopy: scope &into: target
976 collect: [| :role | role ifNotNil: [role deepCopy: scope]]. ]
979 sig@(nodes Signature traits) evaluateIn: namespace
984 nodes define: #Variable &parents: {nodes Node} &slots: {
986 #scope -> nodes Ground
989 node1@(nodes Variable traits) = node2@(nodes Variable traits)
990 [node1 name = node2 name /\ [node1 scope = node2 scope]].
992 var@(nodes Variable traits) named: name
994 var clone `>> [name := name. ]
997 var@(nodes Variable traits) deepCopy: scope
999 scope findVariable: var name
1002 var@(nodes Variable traits) isImmutable [False].
1004 nodes define: #Binding &parents: {nodes Variable}.
1006 var@(nodes Binding traits) isImmutable [True].
1008 nodes define: #RestVariable &parents: {nodes Variable}.
1010 nodes define: #VariableOperation &parents: {nodes Node} &slots: {#variable}.
1012 nodes define: #LoadVariable &parents: {nodes VariableOperation} &slots: {}.
1014 load@(nodes LoadVariable traits) from: variable
1015 [load new `setting: #{#variable} to: {variable}].
1017 var@(nodes Variable traits) load
1018 [nodes LoadVariable from: var].
1020 node1@(nodes LoadVariable traits) = node2@(nodes LoadVariable traits)
1021 [node1 variable = node2 variable].
1023 load@(nodes LoadVariable traits) deepCopy: scope
1025 (scope findVariable: load variable name)
1026 ifNil: [nodes UnaryMessage
1027 sending: load variable name
1028 to: {nodes ImplicitArgument}]
1029 ifNotNilDo: #(load from: _) `er
1032 load@(nodes LoadVariable traits) evaluateIn: namespace &optionals: opts
1034 load variable name sendTo: {namespace} &optionals: opts
1037 nodes define: #LoadRestVariable &parents: {nodes LoadVariable}.
1039 nodes define: #StoreVariable &parents: {nodes VariableOperation}
1042 store@(nodes StoreVariable traits) of: value into: variable
1043 [store new `setting: #{#value. #variable} to: {value. variable}].
1045 var@(nodes Variable traits) store: value
1046 [nodes StoreVariable of: value into: var].
1048 var@(nodes Binding traits) store: value
1049 [error: 'Cannot rebind'].
1051 load@(nodes LoadVariable traits) store: value
1052 [load variable store: value].
1054 store@(nodes StoreVariable traits) load
1055 [store variable load].
1057 node1@(nodes StoreVariable traits) = node2@(nodes StoreVariable traits)
1058 [node1 variable = node2 variable /\ [node1 value = node2 value]].
1060 store@(nodes StoreVariable traits) walk: block
1063 store value walk: block
1066 store@(nodes StoreVariable traits) transformChildren: block
1068 store value := store value transformBy: block.
1072 store@(nodes StoreVariable traits) deepCopy: scope
1074 (scope findVariable: store variable name)
1076 [nodes KeywordMessage
1077 sending: store variable name name ; ':'
1078 to: {nodes ImplicitArgument. store value deepCopy: scope}]
1080 [| :var | store of: (store value deepCopy: scope) into: var]
1083 store@(nodes StoreVariable traits) evaluateIn: namespace &optionals: opts
1085 (store variable name name ; ':') intern
1086 sendTo: {namespace. store value evaluateIn: namespace}
1090 nodes define: #Return &parents: {nodes Node} &slots: {#value}.
1092 ret@(nodes Return traits) of: value
1093 [ret new `setting: #{#value} to: {value}].
1095 node1@(nodes Return traits) = node2@(nodes Return traits)
1096 [node1 value = node2 value /\ [node1 isSameAs: node2]].
1098 ret@(nodes Return traits) walk: block
1101 ret value walk: block
1104 ret@(nodes Return traits) deepCopy: scope
1106 ret of: (ret value deepCopy: scope)
1109 ret@(nodes Return traits) transformChildren: block
1111 ret value := ret value transformBy: block.
1115 nodes define: #ReturnClose &parents: {nodes Return}.
1117 ret@(nodes ReturnClose traits) selector [#^].
1119 nodes define: #ReturnFar &parents: {nodes Return}.
1121 ret@(nodes ReturnFar traits) selector [#^^].
1123 nodes define: #ReturnLevel &parents: {nodes Return} &slots: {#level -> 1}.
1125 ret@(nodes ReturnLevel traits) selector [('^' ; ret level printString) intern].
1127 ret@(nodes ReturnLevel traits) by: offset
1128 [ret new `setting: #{#level} to: {offset}].
1130 nodes define: #Resend &parents: {nodes Node}.
1132 _@(nodes Resend traits) selector [ #resend ].
1134 node1@(nodes Resend traits) = node2@(nodes Resend traits)
1137 "Non-core utilities follow."
1139 n@(nodes Node traits) allSelectorsSent
1140 "Answer a Set of selectors for the messages sent in this parse tree."
1143 n walk: [| :node | (node is: nodes Message)
1144 ifTrue: [calls nextPut: node selector]]]
1145 writingAs: (IdentitySet new &capacity: 100)
1148 n@(nodes Node traits) allMacroSelectorsSent
1149 "Answer a Set of selectors for the macro-messages sent in this parse tree."
1152 n walk: [| :node | (node is: nodes Macro)
1153 ifTrue: [calls nextPut: node selector]]]
1154 writingAs: (IdentitySet new &capacity: 100)
1157 n@(nodes Node traits) nodeCount
1158 "Answer the number of nodes in this tree, analogous to the size of the tree."
1161 n walk: [| :_ | count += 1].
1165 n@(nodes Node traits) hasExplicitReturn
1166 "Answer whether there is an explicit/early return call."
1168 n walk: [| :node | (node is: nodes Return) ifTrue: [^ True]].