Added a Binding Syntax node and implemented bindTo: to use it, enforcing immutable...
[cslatevm.git] / src / syntax / node.slate
blobf8ee6d52bac1dfce81dad7a1cda612b5f252ab81
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
16 [overrideThis].
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."
35   node
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."
42   node
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]]
57     ifFalse: [node source
58                 ifNil: ['Nil']
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)
67 [x value = y value].
69 ann@(nodes Annotation traits) walk: block
71   block applyWith: ann.
72   ann value walk: block
75 ann@(nodes Annotation traits) transformChildren: block
77   ann value: (ann value transformBy: block).
78   ann
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
101 the lobby."
103 node1@(nodes ImplicitArgument traits) = node2@(nodes ImplicitArgument traits)
104 [True].
106 node@(nodes ImplicitArgument traits) evaluateIn: namespace
107 "The default is to simply return the namespace as the result."
108 [namespace].
110 nodes define: #Message &parents: {nodes Node}
111   &slots: {#selector -> #'' . #arguments -> #{}}.
112 "Represents a message send."
114 m@(nodes Message traits) prototypeFor: selector
116   `conditions: (
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
138   resend.
139   message arguments do: #(_ walk: block) `er
142 message@(nodes Message traits) transformChildren: block
144   message arguments infect: #(_ transformBy: block) `er.
145   message
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)
158     &optionals: opts
161 b@(nodes Node traits) allSelectorsSent
162 "Answer a Set of all selectors sent in the source."
164   [| :result |
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:
194     (opts
195       ifNotNil:
196         [nodes OptionalKeywords new `>>
197            [message := macro.
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
205   `conditions: (
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
231   `conditions: (
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}
242   &slots: {#message}.
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.
253   w
256 w@(nodes MessageWrapper traits) walk: block
258   block applyWith: w.
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
279   resend.
280   opts arguments
281     do: #(walk: block) `er
284 opts@(nodes OptionalKeywords traits) transformChildren: block
286   resend.
287   opts arguments infect: #(_ transformBy: block) `er.
288   opts
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:
299     ([| :result |
300        opts keywords with: opts arguments
301          do: [| :key :arg | result nextPutAll: {key intern. arg evaluateIn: namespace}]
302      ] writingAs: #{})
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
316   resend.
317   rest arguments do: #(_ walk: block) `er
320 rest@(nodes RestArguments traits) transformChildren: block
322   resend.
323   rest arguments infect: #(_ transformBy: block) `er.
324   rest
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)
341     &optionals: opts
344 nodes define: #Placeholder &parents: {nodes Node}.
346 node@(nodes Node traits) as: _@(nodes Placeholder traits)
348   node
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
359   ph
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 |
383   count := 0.
384   pattern walk:
385     [| :node |
386      `conditions: (
387         [node == nodes Placeholder]
388           -> [count += 1].
389         [node == nodes ImplicitArgument /\ [countedImplicit isNil]]
390           -> [countedImplicit := node. count += 1]
391     )].
392   count
395 pattern@(nodes Pattern traits) isComplete
396 "Answers whether it can be evaluated successfully."
398   pattern walk: [| :node | node == nodes Placeholder ifTrue: [^ False]].
399   True
402 pattern@(nodes Pattern traits) completeWith: values
403 [| valuesIn countedImplicit |
404   valuesIn := values reader.
405   pattern transformBy:
406     [| :node |
407      valuesIn isAtEnd
408        ifTrue: [node]
409        ifFalse:
410          [`conditions: (
411             [node == nodes ImplicitArgument /\ [countedImplicit isNil]]
412               -> [countedImplicit := node. valuesIn next].
413             [node == nodes Placeholder]
414               -> [valuesIn next]
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
433 directly."
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)
451 [x value = y value].
453 node@(nodes Literal traits) evaluateIn: namespace
454 "A literal just evaluates to its expression-value."
455 [node value].
457 b@(nodes Node traits) allLiterals
458 "Answer an Array of all literal values from the source."
460   [| :result |
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
480   resend.
481   group statements do: #(_ walk: block) `er
484 group@(nodes CompoundStatement traits) transformChildren: block
486   group statements infect: #(_ transformBy: block) `er.
487   group
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
508     ifTrue: [Nil]
509     ifFalse:
510       [group statements allButLastDo: #(_ evaluateIn: namespace) `er.
511        group statements last evaluateIn: namespace]
514 group@(nodes Parenthesis traits) parenthesize
516   group
519 node@(nodes Node traits) parenthesize
521   {node} 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
547   node
550 _@(nodes Namespace traits) findVariable: _
551 "Present for compatibility with Block findVariable:."
552 [Nil].
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
565 accepts one."
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."
576   resend
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."
591   block compile do
594 block@(nodes Block traits) evaluateIn: namespace
595 "Compile the block and return it."
596 [block compile].
598 b@(nodes Block traits) new
600   resend `>>
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])
625     ifTrue:
626       [var name := block uniqueVariableName].
627   var scope := block.
628   block localVariables := block localVariables ; { var }.
629   var
632 block@(nodes Block traits) addVariableNamed: name
633 "Creates a new Variable with the given name and adds it as a local,
634 then returning it."
635 [block addVariable: (nodes Variable clone `setting: #{#name} to: {name})].
637 block@(nodes Block traits) uniqueVariableName &prefix: prefix
638 [| nameIndex |
639   prefix `defaultsTo: '_'.
640   nameIndex := 0.
641   [nameIndex < 100 /\
642      [(block findVariable: (prefix ; nameIndex printString) intern) isNotNil]]
643     whileTrue:
644       [nameIndex += 1].
645   nameIndex < 100
646     ifFalse:
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,
660 then returning it."
661 [| var |
662   var := block addVariableNamed: name.
663   block inputVariables := block inputVariables ; { var }.
664   var
667 block@(nodes Block traits) addInputVariable &name: name &prefix: prefix
668 "Calls addInputVariable: with a name guaranteed not to clash with other such
669 names."
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,
677 then returning it."
678 [| var |
679   var := block addVariableNamed: name.
680   block optionalKeywords := block optionalKeywords ; { key intern }.
681   block optionalVariables := block optionalVariables ; { var }.
682   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
693 a Namespace."
694 [| scope |
695   scope := block.
696   [scope parentScope isSameAs: nodes Namespace]
697     whileFalse: [scope := scope parentScope].
698   scope
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."
708 [| scope |
709   (block hasVariableNamed: name) ifFalse:
710     [scope := block.
711      [(scope hasVariableNamed: name) \/ [scope parentScope isSameAs: nodes Namespace]]
712        whileFalse: [scope := scope parentScope]].
713   scope
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."
720   block localVariables
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."
733 [| result |
734   result := block new.
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].
740   result
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 `>>
747    [| :newBlock |
748     parentScope := scope.
749     localVariables :=
750       b localVariables collect:
751         [| :var newVar | var clone `>> [scope := newBlock. ]].
752     inputVariables :=
753       b inputVariables collect: [| :var | newBlock findVariable: var name].
754     optionalVariables :=
755       b optionalVariables collect: [| :var | newBlock findVariable: var name].
756     restVariable :=
757       b restVariable ifNotNil: [newBlock findVariable: b restVariable name].
758     statements :=
759       b statements collect: #(deepCopy: newBlock) `er.
760   ]
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]].
789   False
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]].
797   False
800 b@(nodes Block traits) allSelectorsSent
802   [| :result |
803    b walk:
804      [| :node |
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]]].
810    ] writingAs: Set
813 b@(nodes Block traits) allSelectorsSentToVar: var
814 "Answers the Set of all selectors called in this method on the Variable object."
815 [| loadExpr |
816   loadExpr := var load.
817   [| :result |
818    b statements walk:
819      [| :expr | (expr is: nodes Message)
820         /\ [expr arguments includes: loadExpr]
821         ifTrue: [result nextPut: expr selector]]
822    ] writingAs: Set
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
835   [| :result |
836    b inputVariables keysDo:
837      [| :index | result ; (b allSelectorsSentToInputAt: index)].
838    ] writingAs: Set
841 b@(nodes Block traits) allSelectorsSentImplicitly
843   [| :result |
844    b statements walk:
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]]]].
850    ] writingAs: Set
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
872   resend.
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]].
879   resend
882 method@(nodes MethodDefinition traits) deepCopy: scope &into: target
884   resend `>>
885     [roles := method roles
886        collect: [| :role | role ifNotNil: [role deepCopy: scope]]. ]
889 method@(nodes MethodDefinition traits) evaluateIn: namespace
891   resend
892     asMethod: method selector
893     on: (method roles collect: #(evaluateIn: namespace) `er)
896 nodes define: #Signature &parents: {nodes Node} &slots: {
897   #selector.
898   #roles -> #{}.
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
908   resend `>>
909     [selector := Nil.
910      roles := sig roles new.
911      inputVariables := sig inputVariables new.
912      restVariable := Nil.
913      optionalKeywords := sig optionalKeywords new.
914      optionalVariables := sig optionalVariables new. ]
917 method@(nodes MethodDefinition traits) as: sig@(nodes Signature traits)
919   sig new `>>
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)
931   method new `>>
932     [| :result |
933      selector := sig selector.
934      roles := sig roles.
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
958   resend `>>
959     [roles := sig roles
960        collect: [| :role | role ifNotNil: [role deepCopy: scope]]. ]
963 sig@(nodes Signature traits) evaluateIn: namespace
965   sig
968 nodes define: #Variable &parents: {nodes Node} &slots: {
969   #name -> #''.
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}
1019   &slots: {#value}.
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
1041   resend.
1042   store value walk: block
1045 store@(nodes StoreVariable traits) transformChildren: block
1047   store value := store value transformBy: block.
1048   store
1051 store@(nodes StoreVariable traits) deepCopy: scope
1053   (scope findVariable: store variable name)
1054     ifNil:
1055       [nodes KeywordMessage
1056         sending: store variable name name ; ':'
1057         to: {nodes ImplicitArgument. store value deepCopy: scope}]
1058     ifNotNilDo:
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}
1066     &optionals: opts
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
1079   resend.
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.
1091   ret
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)
1114 [True].
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."
1121   [| :calls |
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."
1130   [| :calls |
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."
1138 [| count |
1139   count := 0.
1140   n walk: [| :_ | count += 1].
1141   count
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]].
1148   False