Browse Source

Use TSingleDagChild et. al in Compiler-AST.

MethodNode, BlockNode, ReturnNode
are known single-child parents.
Others are known to be no-child leafs
or to derive children, not store them.

Also use new #sequenceNode / #expression
accessors in code where previously
dagChildren first / single / last / do:
were used; including parser.
Herby Vojčík 4 years ago
parent
commit
72cf503117

+ 11 - 0
lang/API-CHANGES.txt

@@ -13,6 +13,10 @@
   + javaScriptConstructor:
 + BlockClosure >>
   + tryIfTrue:catch:
++ BlockNode >>
+  + dagChild
+  + sequenceNode
+  + sequenceNode:
 + ExternallyKnownVar >>
   + isExternallyKnownVar
 + IRInstruction >>
@@ -21,8 +25,15 @@
   + asReceiver
 + IRVariable >>
   + asReceiver
++ MethodNode >>
+  + dagChild
+  + sequenceNode:
 + PseudoVar
   + asReceiver
++ ReturnNode >>
+  + dagChild
+  + expression
+  + expression:
 + SemanticAnalyzer >>
   + errorInvalidAssignment:
   + isVariableKnown:inPackage:

+ 3 - 3
lang/base/parser.js

@@ -274,7 +274,7 @@ define(["./boot"], function(__boot) {
         peg$c90 = "^",
         peg$c91 = peg$literalExpectation("^", false),
         peg$c92 = function(expression) {
-        	return newNode($globals.ReturnNode)._dagChildren_([expression]);
+        	return newNode($globals.ReturnNode)._expression_(expression);
         },
         peg$c93 = "|",
         peg$c94 = peg$literalExpectation("|", false),
@@ -300,7 +300,7 @@ define(["./boot"], function(__boot) {
         peg$c106 = function(params, temps, statements) {
         	return newNode($globals.BlockNode)
         		._parameters_(params || [])
-        		._dagChildren_([newSequenceNode($globals.BlockSequenceNode, temps, statements)]);
+        		._sequenceNode_(newSequenceNode($globals.BlockSequenceNode, temps, statements));
         },
         peg$c107 = function(selector) {
         	return newNode($globals.SendNode)._selector_(selector);
@@ -338,7 +338,7 @@ define(["./boot"], function(__boot) {
         			._selector_(pattern[0])
         			._arguments_(pattern[1])
         			._pragmas_((aPragmas || []).concat(zPragmas || []))
-        			._dagChildren_([newSequenceNode($globals.SequenceNode, temps, statements)]);
+        			._sequenceNode_(newSequenceNode($globals.SequenceNode, temps, statements));
         	},
         peg$c119 = function(receiver, tail) { return tail.length > 0 && tail[tail.length-1]._selector() === '->' },
         peg$c120 = function(receiver, tail) {

+ 3 - 3
lang/base/parser.pegjs

@@ -157,7 +157,7 @@ assignment = variable:variable ws ':=' ws expression:expression {
 }
 
 ret = '^' ws expression:expression {
-	return newNode($globals.ReturnNode)._dagChildren_([expression]);
+	return newNode($globals.ReturnNode)._expression_(expression);
 }
 
 temps = '|' vars:(ws variable:identifier {return variable;})* ws '|' {
@@ -185,7 +185,7 @@ wsStatements =
 block = '[' params:wsBlockParamList? ws temps:temps? statements:wsStatements? maybeDotsWs ']' {
 	return newNode($globals.BlockNode)
 		._parameters_(params || [])
-		._dagChildren_([newSequenceNode($globals.BlockSequenceNode, temps, statements)]);
+		._sequenceNode_(newSequenceNode($globals.BlockSequenceNode, temps, statements));
 }
 
 operand = reference / literal / subexpression
@@ -246,7 +246,7 @@ method =
 			._selector_(pattern[0])
 			._arguments_(pattern[1])
 			._pragmas_((aPragmas || []).concat(zPragmas || []))
-			._dagChildren_([newSequenceNode($globals.SequenceNode, temps, statements)]);
+			._sequenceNode_(newSequenceNode($globals.SequenceNode, temps, statements));
 	}
 
 associationSend =

+ 190 - 62
lang/src/Compiler-AST.js

@@ -111,24 +111,6 @@ return false;
 }; }),
 $globals.ASTNode);
 
-$core.addMethod(
-$core.method({
-selector: "isSequenceNode",
-protocol: "testing",
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "isSequenceNode\x0a\x09^ false",
-referencedClasses: [],
-//>>excludeEnd("ide");
-pragmas: [],
-messageSends: []
-}, function ($methodClass){ return function (){
-var self=this,$self=this;
-return false;
-
-}; }),
-$globals.ASTNode);
-
 $core.addMethod(
 $core.method({
 selector: "isSuper",
@@ -591,17 +573,17 @@ selector: "dagChildren",
 protocol: "accessing",
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: [],
-source: "dagChildren\x0a\x09^ Array with: self left with: self right",
-referencedClasses: ["Array"],
+source: "dagChildren\x0a\x09^ { self left. self right }",
+referencedClasses: [],
 //>>excludeEnd("ide");
 pragmas: [],
-messageSends: ["with:with:", "left", "right"]
+messageSends: ["left", "right"]
 }, function ($methodClass){ return function (){
 var self=this,$self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-return $recv($globals.Array)._with_with_($self._left(),$self._right());
+return [$self._left(),$self._right()];
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 }, function($ctx1) {$ctx1.fill(self,"dagChildren",{})});
 //>>excludeEnd("ctx");
@@ -684,7 +666,7 @@ $globals.AssignmentNode);
 
 
 
-$core.addClass("BlockNode", $globals.ASTNode, ["parameters", "scope"], "Compiler-AST");
+$core.addClass("BlockNode", $globals.ASTNode, ["parameters", "scope", "sequenceNode"], "Compiler-AST");
 //>>excludeStart("ide", pragmas.excludeIdeData);
 $globals.BlockNode.comment="I represent an block closure node.";
 //>>excludeEnd("ide");
@@ -711,6 +693,29 @@ return $recv(aVisitor)._visitBlockNode_(self);
 }; }),
 $globals.BlockNode);
 
+$core.addMethod(
+$core.method({
+selector: "dagChild",
+protocol: "accessing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "dagChild\x0a\x09^ self sequenceNode",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: ["sequenceNode"]
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $self._sequenceNode();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"dagChild",{})});
+//>>excludeEnd("ctx");
+}; }),
+$globals.BlockNode);
+
 $core.addMethod(
 $core.method({
 selector: "parameters",
@@ -797,6 +802,43 @@ return self;
 }; }),
 $globals.BlockNode);
 
+$core.addMethod(
+$core.method({
+selector: "sequenceNode",
+protocol: "accessing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "sequenceNode\x0a\x09^ sequenceNode",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: []
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+return $self.sequenceNode;
+
+}; }),
+$globals.BlockNode);
+
+$core.addMethod(
+$core.method({
+selector: "sequenceNode:",
+protocol: "accessing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["anObject"],
+source: "sequenceNode: anObject\x0a\x09sequenceNode := anObject",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: []
+}, function ($methodClass){ return function (anObject){
+var self=this,$self=this;
+$self.sequenceNode=anObject;
+return self;
+
+}; }),
+$globals.BlockNode);
+
 
 
 $core.addClass("CascadeNode", $globals.ASTNode, ["receiver"], "Compiler-AST");
@@ -970,7 +1012,7 @@ $globals.JSStatementNode);
 
 
 
-$core.addClass("MethodNode", $globals.ASTNode, ["selector", "arguments", "pragmas", "scope", "classReferences", "sendIndexes"], "Compiler-AST");
+$core.addClass("MethodNode", $globals.ASTNode, ["selector", "arguments", "pragmas", "scope", "classReferences", "sendIndexes", "sequenceNode"], "Compiler-AST");
 //>>excludeStart("ide", pragmas.excludeIdeData);
 $globals.MethodNode.comment="I represent an method node.\x0a\x0aA method node must be the root and only method node of a valid AST.";
 //>>excludeEnd("ide");
@@ -1082,6 +1124,29 @@ return self;
 }; }),
 $globals.MethodNode);
 
+$core.addMethod(
+$core.method({
+selector: "dagChild",
+protocol: "accessing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "dagChild\x0a\x09^ self sequenceNode",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: ["sequenceNode"]
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $self._sequenceNode();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"dagChild",{})});
+//>>excludeEnd("ctx");
+}; }),
+$globals.MethodNode);
+
 $core.addMethod(
 $core.method({
 selector: "messageSends",
@@ -1288,37 +1353,40 @@ selector: "sequenceNode",
 protocol: "accessing",
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: [],
-source: "sequenceNode\x0a\x09^ self dagChildren detect: [ :one | one isSequenceNode ] ifNone: [ nil ]",
+source: "sequenceNode\x0a\x09^ sequenceNode",
 referencedClasses: [],
 //>>excludeEnd("ide");
 pragmas: [],
-messageSends: ["detect:ifNone:", "dagChildren", "isSequenceNode"]
+messageSends: []
 }, function ($methodClass){ return function (){
 var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-return $recv($self._dagChildren())._detect_ifNone_((function(one){
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx2) {
-//>>excludeEnd("ctx");
-return $recv(one)._isSequenceNode();
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({one:one},$ctx1,1)});
-//>>excludeEnd("ctx");
-}),(function(){
-return nil;
+return $self.sequenceNode;
 
-}));
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"sequenceNode",{})});
-//>>excludeEnd("ctx");
 }; }),
 $globals.MethodNode);
 
+$core.addMethod(
+$core.method({
+selector: "sequenceNode:",
+protocol: "accessing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aSequenceNode"],
+source: "sequenceNode: aSequenceNode\x0a\x09sequenceNode := aSequenceNode",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: []
+}, function ($methodClass){ return function (aSequenceNode){
+var self=this,$self=this;
+$self.sequenceNode=aSequenceNode;
+return self;
+
+}; }),
+$globals.MethodNode);
 
 
-$core.addClass("ReturnNode", $globals.ASTNode, ["scope"], "Compiler-AST");
+
+$core.addClass("ReturnNode", $globals.ASTNode, ["scope", "expression"], "Compiler-AST");
 //>>excludeStart("ide", pragmas.excludeIdeData);
 $globals.ReturnNode.comment="I represent an return node. At the AST level, there is not difference between a local return or non-local return.";
 //>>excludeEnd("ide");
@@ -1345,6 +1413,77 @@ return $recv(aVisitor)._visitReturnNode_(self);
 }; }),
 $globals.ReturnNode);
 
+$core.addMethod(
+$core.method({
+selector: "dagChild",
+protocol: "accessing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "dagChild\x0a\x09^ self expression",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: ["expression"]
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $self._expression();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"dagChild",{})});
+//>>excludeEnd("ctx");
+}; }),
+$globals.ReturnNode);
+
+$core.addMethod(
+$core.method({
+selector: "expression",
+protocol: "accessing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "expression\x0a\x09^ expression ifNil: [ nodes first ]",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: ["ifNil:", "first"]
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1,$receiver;
+$1=$self.expression;
+if(($receiver = $1) == null || $receiver.a$nil){
+return $recv($self.nodes)._first();
+} else {
+return $1;
+}
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"expression",{})});
+//>>excludeEnd("ctx");
+}; }),
+$globals.ReturnNode);
+
+$core.addMethod(
+$core.method({
+selector: "expression:",
+protocol: "accessing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["anObject"],
+source: "expression: anObject\x0a\x09expression := anObject",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: []
+}, function ($methodClass){ return function (anObject){
+var self=this,$self=this;
+$self.expression=anObject;
+return self;
+
+}; }),
+$globals.ReturnNode);
+
 $core.addMethod(
 $core.method({
 selector: "isReturnNode",
@@ -1751,24 +1890,6 @@ return $recv(aVisitor)._visitSequenceNode_(self);
 }; }),
 $globals.SequenceNode);
 
-$core.addMethod(
-$core.method({
-selector: "isSequenceNode",
-protocol: "testing",
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "isSequenceNode\x0a\x09^ true",
-referencedClasses: [],
-//>>excludeEnd("ide");
-pragmas: [],
-messageSends: []
-}, function ($methodClass){ return function (){
-var self=this,$self=this;
-return true;
-
-}; }),
-$globals.SequenceNode);
-
 $core.addMethod(
 $core.method({
 selector: "temps",
@@ -2657,6 +2778,13 @@ return $self._visitDagNode_(aNode);
 $globals.NodeVisitor);
 
 
+$core.setTraitComposition([{trait: $globals.TDerivedDagChildren}], $globals.AssignmentNode);
+$core.setTraitComposition([{trait: $globals.TSingleDagChild}], $globals.BlockNode);
+$core.setTraitComposition([{trait: $globals.TDagSink}], $globals.JSStatementNode);
+$core.setTraitComposition([{trait: $globals.TSingleDagChild}], $globals.MethodNode);
+$core.setTraitComposition([{trait: $globals.TSingleDagChild}], $globals.ReturnNode);
+$core.setTraitComposition([{trait: $globals.TDerivedDagChildren}], $globals.SendNode);
+$core.setTraitComposition([{trait: $globals.TDagSink}], $globals.ValueNode);
 $core.setTraitComposition([{trait: $globals.TPragmator}], $globals.AstPragmator);
 
 $core.addMethod(

+ 44 - 15
lang/src/Compiler-AST.st

@@ -118,10 +118,6 @@ isReturnNode
 	^ false
 !
 
-isSequenceNode
-	^ false
-!
-
 isSuper
 	^ false
 ! !
@@ -135,7 +131,7 @@ I represent an assignment node.!
 !AssignmentNode methodsFor: 'accessing'!
 
 dagChildren
-	^ Array with: self left with: self right
+	^ { self left. self right }
 !
 
 left
@@ -161,13 +157,17 @@ acceptDagVisitor: aVisitor
 ! !
 
 ASTNode subclass: #BlockNode
-	slots: {#parameters. #scope}
+	slots: {#parameters. #scope. #sequenceNode}
 	package: 'Compiler-AST'!
 !BlockNode commentStamp!
 I represent an block closure node.!
 
 !BlockNode methodsFor: 'accessing'!
 
+dagChild
+	^ self sequenceNode
+!
+
 parameters
 	^ parameters ifNil: [ parameters := Array new ]
 !
@@ -182,6 +182,14 @@ scope
 
 scope: aLexicalScope
 	scope := aLexicalScope
+!
+
+sequenceNode
+	^ sequenceNode
+!
+
+sequenceNode: anObject
+	sequenceNode := anObject
 ! !
 
 !BlockNode methodsFor: 'visiting'!
@@ -255,7 +263,7 @@ acceptDagVisitor: aVisitor
 ! !
 
 ASTNode subclass: #MethodNode
-	slots: {#selector. #arguments. #pragmas. #scope. #classReferences. #sendIndexes}
+	slots: {#selector. #arguments. #pragmas. #scope. #classReferences. #sendIndexes. #sequenceNode}
 	package: 'Compiler-AST'!
 !MethodNode commentStamp!
 I represent an method node.
@@ -280,6 +288,10 @@ classReferences: aCollection
 	classReferences := aCollection
 !
 
+dagChild
+	^ self sequenceNode
+!
+
 messageSends
 	^ self sendIndexes keys
 !
@@ -321,7 +333,11 @@ sendIndexes: aDictionary
 !
 
 sequenceNode
-	^ self dagChildren detect: [ :one | one isSequenceNode ] ifNone: [ nil ]
+	^ sequenceNode
+!
+
+sequenceNode: aSequenceNode
+	sequenceNode := aSequenceNode
 ! !
 
 !MethodNode methodsFor: 'visiting'!
@@ -331,13 +347,25 @@ acceptDagVisitor: aVisitor
 ! !
 
 ASTNode subclass: #ReturnNode
-	slots: {#scope}
+	slots: {#scope. #expression}
 	package: 'Compiler-AST'!
 !ReturnNode commentStamp!
 I represent an return node. At the AST level, there is not difference between a local return or non-local return.!
 
 !ReturnNode methodsFor: 'accessing'!
 
+dagChild
+	^ self expression
+!
+
+expression
+	^ expression ifNil: [ nodes first ]
+!
+
+expression: anObject
+	expression := anObject
+!
+
 scope
 	^ scope
 !
@@ -444,12 +472,6 @@ temps: aCollection
 	temps := aCollection
 ! !
 
-!SequenceNode methodsFor: 'testing'!
-
-isSequenceNode
-	^ true
-! !
-
 !SequenceNode methodsFor: 'visiting'!
 
 acceptDagVisitor: aVisitor
@@ -684,6 +706,13 @@ visitVariableNode: aNode
 	^ self visitDagNode: aNode
 ! !
 
+AssignmentNode setTraitComposition: {TDerivedDagChildren} asTraitComposition!
+BlockNode setTraitComposition: {TSingleDagChild} asTraitComposition!
+JSStatementNode setTraitComposition: {TDagSink} asTraitComposition!
+MethodNode setTraitComposition: {TSingleDagChild} asTraitComposition!
+ReturnNode setTraitComposition: {TSingleDagChild} asTraitComposition!
+SendNode setTraitComposition: {TDerivedDagChildren} asTraitComposition!
+ValueNode setTraitComposition: {TDagSink} asTraitComposition!
 AstPragmator setTraitComposition: {TPragmator} asTraitComposition!
 ! !
 

+ 25 - 42
lang/src/Compiler-IR.js

@@ -390,11 +390,11 @@ selector: "visitBlockNode:",
 protocol: "visiting",
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aNode"],
-source: "visitBlockNode: aNode\x0a\x09| closure |\x0a\x09closure := IRClosure new\x0a\x09\x09arguments: aNode parameters;\x0a\x09\x09requiresSmalltalkContext: aNode requiresSmalltalkContext;\x0a\x09\x09scope: aNode scope;\x0a\x09\x09yourself.\x0a\x09aNode scope temps do: [ :each |\x0a\x09\x09closure add: (IRTempDeclaration new\x0a\x09\x09\x09name: each name;\x0a\x09\x09\x09scope: aNode scope;\x0a\x09\x09\x09yourself) ].\x0a\x09aNode dagChildren do: [ :each | closure add: (self visit: each) ].\x0a\x09^ closure",
+source: "visitBlockNode: aNode\x0a\x09| closure |\x0a\x09closure := IRClosure new\x0a\x09\x09arguments: aNode parameters;\x0a\x09\x09requiresSmalltalkContext: aNode requiresSmalltalkContext;\x0a\x09\x09scope: aNode scope;\x0a\x09\x09yourself.\x0a\x09aNode scope temps do: [ :each |\x0a\x09\x09closure add: (IRTempDeclaration new\x0a\x09\x09\x09name: each name;\x0a\x09\x09\x09scope: aNode scope;\x0a\x09\x09\x09yourself) ].\x0a\x09closure add: (self visit: aNode sequenceNode).\x0a\x09^ closure",
 referencedClasses: ["IRClosure", "IRTempDeclaration"],
 //>>excludeEnd("ide");
 pragmas: [],
-messageSends: ["arguments:", "new", "parameters", "requiresSmalltalkContext:", "requiresSmalltalkContext", "scope:", "scope", "yourself", "do:", "temps", "add:", "name:", "name", "dagChildren", "visit:"]
+messageSends: ["arguments:", "new", "parameters", "requiresSmalltalkContext:", "requiresSmalltalkContext", "scope:", "scope", "yourself", "do:", "temps", "add:", "name:", "name", "visit:", "sequenceNode"]
 }, function ($methodClass){ return function (aNode){
 var self=this,$self=this;
 var closure;
@@ -423,7 +423,7 @@ closure=[$recv($1)._yourself()
 ,$ctx1.sendIdx["yourself"]=1
 //>>excludeEnd("ctx");
 ][0];
-[$recv($recv([$recv(aNode)._scope()
+$recv($recv([$recv(aNode)._scope()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 ,$ctx1.sendIdx["scope"]=2
 //>>excludeEnd("ctx");
@@ -444,20 +444,8 @@ return [$recv($2)._add_($3)
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)});
 //>>excludeEnd("ctx");
-}))
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["do:"]=1
-//>>excludeEnd("ctx");
-][0];
-$recv($recv(aNode)._dagChildren())._do_((function(each){
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx2) {
-//>>excludeEnd("ctx");
-return $recv(closure)._add_($self._visit_(each));
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,2)});
-//>>excludeEnd("ctx");
 }));
+$recv(closure)._add_($self._visit_($recv(aNode)._sequenceNode()));
 return closure;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 }, function($ctx1) {$ctx1.fill(self,"visitBlockNode:",{aNode:aNode,closure:closure})});
@@ -725,11 +713,11 @@ selector: "visitMethodNode:",
 protocol: "visiting",
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aNode"],
-source: "visitMethodNode: aNode\x0a\x0a\x09self method: (IRMethod new\x0a\x09\x09source: self source crlfSanitized;\x0a\x09\x09pragmas: (aNode pragmas collect: [ :each |\x0a\x09\x09\x09Message\x0a\x09\x09\x09\x09selector: each selector\x0a\x09\x09\x09\x09arguments: (each arguments collect: [ :eachArg |\x0a\x09\x09\x09\x09\x09eachArg isString ifTrue: [ eachArg crlfSanitized ] ifFalse: [ eachArg ]])]);\x0a\x09\x09theClass: self theClass;\x0a\x09\x09arguments: aNode arguments;\x0a\x09\x09selector: aNode selector;\x0a\x09\x09sendIndexes: aNode sendIndexes;\x0a\x09\x09requiresSmalltalkContext: aNode requiresSmalltalkContext;\x0a\x09\x09classReferences: aNode classReferences;\x0a\x09\x09scope: aNode scope;\x0a\x09\x09yourself).\x0a\x0a\x09aNode scope temps do: [ :each |\x0a\x09\x09self method add: (IRTempDeclaration new\x0a\x09\x09\x09name: each name;\x0a\x09\x09\x09scope: aNode scope;\x0a\x09\x09\x09yourself) ].\x0a\x0a\x09self method dagChildren addAll: (self visitAllChildren: aNode).\x0a\x0a\x09aNode scope hasLocalReturn ifFalse: [self method\x0a\x09\x09add: (IRReturn new\x0a\x09\x09\x09add: (IRVariable new\x0a\x09\x09\x09\x09variable: (aNode scope pseudoVars at: 'self');\x0a\x09\x09\x09\x09yourself);\x0a\x09\x09\x09yourself);\x0a\x09\x09add: (IRVerbatim new source: ';', String lf; yourself) ].\x0a\x0a\x09^ self method",
+source: "visitMethodNode: aNode\x0a\x0a\x09self method: (IRMethod new\x0a\x09\x09source: self source crlfSanitized;\x0a\x09\x09pragmas: (aNode pragmas collect: [ :each |\x0a\x09\x09\x09Message\x0a\x09\x09\x09\x09selector: each selector\x0a\x09\x09\x09\x09arguments: (each arguments collect: [ :eachArg |\x0a\x09\x09\x09\x09\x09eachArg isString ifTrue: [ eachArg crlfSanitized ] ifFalse: [ eachArg ]])]);\x0a\x09\x09theClass: self theClass;\x0a\x09\x09arguments: aNode arguments;\x0a\x09\x09selector: aNode selector;\x0a\x09\x09sendIndexes: aNode sendIndexes;\x0a\x09\x09requiresSmalltalkContext: aNode requiresSmalltalkContext;\x0a\x09\x09classReferences: aNode classReferences;\x0a\x09\x09scope: aNode scope;\x0a\x09\x09yourself).\x0a\x0a\x09aNode scope temps do: [ :each |\x0a\x09\x09self method add: (IRTempDeclaration new\x0a\x09\x09\x09name: each name;\x0a\x09\x09\x09scope: aNode scope;\x0a\x09\x09\x09yourself) ].\x0a\x0a\x09self method add: (self visit: aNode sequenceNode).\x0a\x0a\x09aNode scope hasLocalReturn ifFalse: [self method\x0a\x09\x09add: (IRReturn new\x0a\x09\x09\x09add: (IRVariable new\x0a\x09\x09\x09\x09variable: (aNode scope pseudoVars at: 'self');\x0a\x09\x09\x09\x09yourself);\x0a\x09\x09\x09yourself);\x0a\x09\x09add: (IRVerbatim new source: ';', String lf; yourself) ].\x0a\x0a\x09^ self method",
 referencedClasses: ["IRMethod", "Message", "IRTempDeclaration", "IRReturn", "IRVariable", "IRVerbatim", "String"],
 //>>excludeEnd("ide");
 pragmas: [],
-messageSends: ["method:", "source:", "new", "crlfSanitized", "source", "pragmas:", "collect:", "pragmas", "selector:arguments:", "selector", "arguments", "ifTrue:ifFalse:", "isString", "theClass:", "theClass", "arguments:", "selector:", "sendIndexes:", "sendIndexes", "requiresSmalltalkContext:", "requiresSmalltalkContext", "classReferences:", "classReferences", "scope:", "scope", "yourself", "do:", "temps", "add:", "method", "name:", "name", "addAll:", "dagChildren", "visitAllChildren:", "ifFalse:", "hasLocalReturn", "variable:", "at:", "pseudoVars", ",", "lf"]
+messageSends: ["method:", "source:", "new", "crlfSanitized", "source", "pragmas:", "collect:", "pragmas", "selector:arguments:", "selector", "arguments", "ifTrue:ifFalse:", "isString", "theClass:", "theClass", "arguments:", "selector:", "sendIndexes:", "sendIndexes", "requiresSmalltalkContext:", "requiresSmalltalkContext", "classReferences:", "classReferences", "scope:", "scope", "yourself", "do:", "temps", "add:", "method", "name:", "name", "visit:", "sequenceNode", "ifFalse:", "hasLocalReturn", "variable:", "at:", "pseudoVars", ",", "lf"]
 }, function ($methodClass){ return function (aNode){
 var self=this,$self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
@@ -843,11 +831,15 @@ return [$recv($4)._add_($5)
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,5)});
 //>>excludeEnd("ctx");
 }));
-$recv($recv([$self._method()
+[$recv([$self._method()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 ,$ctx1.sendIdx["method"]=2
 //>>excludeEnd("ctx");
-][0])._dagChildren())._addAll_($self._visitAllChildren_(aNode));
+][0])._add_($self._visit_($recv(aNode)._sequenceNode()))
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+,$ctx1.sendIdx["add:"]=2
+//>>excludeEnd("ctx");
+][0];
 $7=$recv([$recv(aNode)._scope()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 ,$ctx1.sendIdx["scope"]=4
@@ -877,7 +869,7 @@ $11=[$recv($12)._yourself()
 ][0];
 [$recv($10)._add_($11)
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["add:"]=3
+,$ctx1.sendIdx["add:"]=4
 //>>excludeEnd("ctx");
 ][0];
 $9=[$recv($10)._yourself()
@@ -887,7 +879,7 @@ $9=[$recv($10)._yourself()
 ][0];
 [$recv($8)._add_($9)
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["add:"]=2
+,$ctx1.sendIdx["add:"]=3
 //>>excludeEnd("ctx");
 ][0];
 $14=$recv($globals.IRVerbatim)._new();
@@ -937,41 +929,32 @@ selector: "visitReturnNode:",
 protocol: "visiting",
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aNode"],
-source: "visitReturnNode: aNode\x0a\x09| return |\x0a\x09return := aNode nonLocalReturn\x0a\x09\x09ifTrue: [ IRNonLocalReturn new ]\x0a\x09\x09ifFalse: [ IRReturn new ].\x0a\x09return scope: aNode scope.\x0a\x09aNode dagChildren do: [ :each |\x0a\x09\x09return add: (self visitOrAlias: each) ].\x0a\x09^ return",
+source: "visitReturnNode: aNode\x0a\x09^ (aNode nonLocalReturn\x0a\x09\x09ifTrue: [ IRNonLocalReturn new ]\x0a\x09\x09ifFalse: [ IRReturn new ])\x0a\x09\x09scope: aNode scope;\x0a\x09\x09add: (self visitOrAlias: aNode expression);\x0a\x09\x09yourself\x0a",
 referencedClasses: ["IRNonLocalReturn", "IRReturn"],
 //>>excludeEnd("ide");
 pragmas: [],
-messageSends: ["ifTrue:ifFalse:", "nonLocalReturn", "new", "scope:", "scope", "do:", "dagChildren", "add:", "visitOrAlias:"]
+messageSends: ["scope:", "ifTrue:ifFalse:", "nonLocalReturn", "new", "scope", "add:", "visitOrAlias:", "expression", "yourself"]
 }, function ($methodClass){ return function (aNode){
 var self=this,$self=this;
-var return_;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-var $1;
-$1=$recv(aNode)._nonLocalReturn();
-if($core.assert($1)){
-return_=[$recv($globals.IRNonLocalReturn)._new()
+var $2,$1;
+$2=$recv(aNode)._nonLocalReturn();
+if($core.assert($2)){
+$1=[$recv($globals.IRNonLocalReturn)._new()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 ,$ctx1.sendIdx["new"]=1
 //>>excludeEnd("ctx");
 ][0];
 } else {
-return_=$recv($globals.IRReturn)._new();
+$1=$recv($globals.IRReturn)._new();
 }
-$recv(return_)._scope_($recv(aNode)._scope());
-$recv($recv(aNode)._dagChildren())._do_((function(each){
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx2) {
-//>>excludeEnd("ctx");
-return $recv(return_)._add_($self._visitOrAlias_(each));
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,3)});
-//>>excludeEnd("ctx");
-}));
-return return_;
+$recv($1)._scope_($recv(aNode)._scope());
+$recv($1)._add_($self._visitOrAlias_($recv(aNode)._expression()));
+return $recv($1)._yourself();
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"visitReturnNode:",{aNode:aNode,return_:return_})});
+}, function($ctx1) {$ctx1.fill(self,"visitReturnNode:",{aNode:aNode})});
 //>>excludeEnd("ctx");
 }; }),
 $globals.IRASTTranslator);

+ 7 - 9
lang/src/Compiler-IR.st

@@ -124,7 +124,7 @@ visitBlockNode: aNode
 			name: each name;
 			scope: aNode scope;
 			yourself) ].
-	aNode dagChildren do: [ :each | closure add: (self visit: each) ].
+	closure add: (self visit: aNode sequenceNode).
 	^ closure
 !
 
@@ -199,7 +199,7 @@ visitMethodNode: aNode
 			scope: aNode scope;
 			yourself) ].
 
-	self method dagChildren addAll: (self visitAllChildren: aNode).
+	self method add: (self visit: aNode sequenceNode).
 
 	aNode scope hasLocalReturn ifFalse: [self method
 		add: (IRReturn new
@@ -219,14 +219,12 @@ visitOrAlias: aNode
 !
 
 visitReturnNode: aNode
-	| return |
-	return := aNode nonLocalReturn
+	^ (aNode nonLocalReturn
 		ifTrue: [ IRNonLocalReturn new ]
-		ifFalse: [ IRReturn new ].
-	return scope: aNode scope.
-	aNode dagChildren do: [ :each |
-		return add: (self visitOrAlias: each) ].
-	^ return
+		ifFalse: [ IRReturn new ])
+		scope: aNode scope;
+		add: (self visitOrAlias: aNode expression);
+		yourself
 !
 
 visitSendNode: aNode

+ 3 - 3
lang/src/Compiler-Interpreter.js

@@ -239,11 +239,11 @@ selector: "valueWithPossibleArguments:",
 protocol: "evaluating",
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aCollection"],
-source: "valueWithPossibleArguments: aCollection\x0a\x09| context sequenceNode |\x0a\x09context := outerContext newInnerContext.\x0a\x0a\x09\x22Interpret a copy of the sequence node to avoid creating a new AIBlockClosure\x22\x0a\x09sequenceNode := node dagChildren first copy\x0a\x09\x09parent: nil;\x0a\x09\x09yourself.\x0a\x09\x09\x0a\x09\x22Define locals in the context\x22\x0a\x09sequenceNode temps do: [ :each |\x0a\x09\x09context defineLocal: each ].\x0a\x09\x09\x0a\x09\x22Populate the arguments into the context locals\x22\x09\x0a\x09node parameters withIndexDo: [ :each :index |\x0a\x09\x09context defineLocal: each.\x0a\x09\x09context localAt: each put: (aCollection at: index ifAbsent: [ nil ]) ].\x0a\x0a\x09\x22Interpret the first node of the BlockSequenceNode\x22\x0a\x09context interpreter\x0a\x09\x09node: sequenceNode;\x0a\x09\x09enterNode;\x0a\x09\x09proceed.\x0a\x09\x09\x0a\x09outerContext interpreter\x0a\x09\x09setNonLocalReturnFromContext: context.\x0a\x09\x09\x0a\x09^ context interpreter pop",
+source: "valueWithPossibleArguments: aCollection\x0a\x09| context sequenceNode |\x0a\x09context := outerContext newInnerContext.\x0a\x0a\x09\x22Interpret a copy of the sequence node to avoid creating a new AIBlockClosure\x22\x0a\x09sequenceNode := node sequenceNode copy\x0a\x09\x09parent: nil;\x0a\x09\x09yourself.\x0a\x09\x09\x0a\x09\x22Define locals in the context\x22\x0a\x09sequenceNode temps do: [ :each |\x0a\x09\x09context defineLocal: each ].\x0a\x09\x09\x0a\x09\x22Populate the arguments into the context locals\x22\x09\x0a\x09node parameters withIndexDo: [ :each :index |\x0a\x09\x09context defineLocal: each.\x0a\x09\x09context localAt: each put: (aCollection at: index ifAbsent: [ nil ]) ].\x0a\x0a\x09\x22Interpret the first node of the BlockSequenceNode\x22\x0a\x09context interpreter\x0a\x09\x09node: sequenceNode;\x0a\x09\x09enterNode;\x0a\x09\x09proceed.\x0a\x09\x09\x0a\x09outerContext interpreter\x0a\x09\x09setNonLocalReturnFromContext: context.\x0a\x09\x09\x0a\x09^ context interpreter pop",
 referencedClasses: [],
 //>>excludeEnd("ide");
 pragmas: [],
-messageSends: ["newInnerContext", "parent:", "copy", "first", "dagChildren", "yourself", "do:", "temps", "defineLocal:", "withIndexDo:", "parameters", "localAt:put:", "at:ifAbsent:", "node:", "interpreter", "enterNode", "proceed", "setNonLocalReturnFromContext:", "pop"]
+messageSends: ["newInnerContext", "parent:", "copy", "sequenceNode", "yourself", "do:", "temps", "defineLocal:", "withIndexDo:", "parameters", "localAt:put:", "at:ifAbsent:", "node:", "interpreter", "enterNode", "proceed", "setNonLocalReturnFromContext:", "pop"]
 }, function ($methodClass){ return function (aCollection){
 var self=this,$self=this;
 var context,sequenceNode;
@@ -252,7 +252,7 @@ return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
 var $1,$2;
 context=$recv($self.outerContext)._newInnerContext();
-$1=$recv($recv($recv($self.node)._dagChildren())._first())._copy();
+$1=$recv($recv($self.node)._sequenceNode())._copy();
 $recv($1)._parent_(nil);
 sequenceNode=$recv($1)._yourself();
 $recv($recv(sequenceNode)._temps())._do_((function(each){

+ 1 - 1
lang/src/Compiler-Interpreter.st

@@ -60,7 +60,7 @@ valueWithPossibleArguments: aCollection
 	context := outerContext newInnerContext.
 
 	"Interpret a copy of the sequence node to avoid creating a new AIBlockClosure"
-	sequenceNode := node dagChildren first copy
+	sequenceNode := node sequenceNode copy
 		parent: nil;
 		yourself.
 		

+ 36 - 96
lang/src/Compiler-Tests.js

@@ -2793,11 +2793,11 @@ selector: "testScope",
 protocol: "tests",
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: [],
-source: "testScope\x0a\x09| src ast |\x0a\x0a\x09src := 'foo | a | a + 1. [ | b | b := a ]'.\x0a\x09ast := Smalltalk parse: src.\x0a\x09analyzer visit: ast.\x0a\x0a\x09self deny: ast dagChildren first dagChildren last scope == ast scope.",
+source: "testScope\x0a\x09| src ast |\x0a\x0a\x09src := 'foo | a | a + 1. [ | b | b := a ]'.\x0a\x09ast := Smalltalk parse: src.\x0a\x09analyzer visit: ast.\x0a\x0a\x09self deny: ast sequenceNode dagChildren last scope == ast scope.",
 referencedClasses: ["Smalltalk"],
 //>>excludeEnd("ide");
 pragmas: [],
-messageSends: ["parse:", "visit:", "deny:", "==", "scope", "last", "dagChildren", "first"]
+messageSends: ["parse:", "visit:", "deny:", "==", "scope", "last", "dagChildren", "sequenceNode"]
 }, function ($methodClass){ return function (){
 var self=this,$self=this;
 var src,ast;
@@ -2807,11 +2807,7 @@ return $core.withContext(function($ctx1) {
 src="foo | a | a + 1. [ | b | b := a ]";
 ast=$recv($globals.Smalltalk)._parse_(src);
 $recv($self.analyzer)._visit_(ast);
-$self._deny_($recv([$recv($recv([$recv($recv($recv(ast)._dagChildren())._first())._dagChildren()
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["dagChildren"]=1
-//>>excludeEnd("ctx");
-][0])._last())._scope()
+$self._deny_($recv([$recv($recv($recv($recv(ast)._sequenceNode())._dagChildren())._last())._scope()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 ,$ctx1.sendIdx["scope"]=1
 //>>excludeEnd("ctx");
@@ -2829,11 +2825,11 @@ selector: "testScope2",
 protocol: "tests",
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: [],
-source: "testScope2\x0a\x09| src ast |\x0a\x0a\x09src := 'foo | a | a + 1. [ [ | b | b := a ] ]'.\x0a\x09ast := Smalltalk parse: src.\x0a\x09analyzer visit: ast.\x0a\x0a\x09self deny: ast dagChildren first dagChildren last dagChildren first dagChildren first scope == ast scope.",
+source: "testScope2\x0a\x09| src ast |\x0a\x0a\x09src := 'foo | a | a + 1. [ [ | b | b := a ] ]'.\x0a\x09ast := Smalltalk parse: src.\x0a\x09analyzer visit: ast.\x0a\x0a\x09self deny: ast sequenceNode dagChildren last sequenceNode dagChildren first scope == ast scope.",
 referencedClasses: ["Smalltalk"],
 //>>excludeEnd("ide");
 pragmas: [],
-messageSends: ["parse:", "visit:", "deny:", "==", "scope", "first", "dagChildren", "last"]
+messageSends: ["parse:", "visit:", "deny:", "==", "scope", "first", "dagChildren", "sequenceNode", "last"]
 }, function ($methodClass){ return function (){
 var self=this,$self=this;
 var src,ast;
@@ -2843,27 +2839,15 @@ return $core.withContext(function($ctx1) {
 src="foo | a | a + 1. [ [ | b | b := a ] ]";
 ast=$recv($globals.Smalltalk)._parse_(src);
 $recv($self.analyzer)._visit_(ast);
-$self._deny_($recv([$recv([$recv([$recv([$recv([$recv($recv([$recv($recv($recv(ast)._dagChildren())._first())._dagChildren()
+$self._deny_($recv([$recv($recv([$recv([$recv($recv($recv($recv(ast)._sequenceNode())._dagChildren())._last())._sequenceNode()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["dagChildren"]=3
-//>>excludeEnd("ctx");
-][0])._last())._dagChildren()
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["dagChildren"]=2
-//>>excludeEnd("ctx");
-][0])._first()
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["first"]=2
+,$ctx1.sendIdx["sequenceNode"]=1
 //>>excludeEnd("ctx");
 ][0])._dagChildren()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 ,$ctx1.sendIdx["dagChildren"]=1
 //>>excludeEnd("ctx");
-][0])._first()
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["first"]=1
-//>>excludeEnd("ctx");
-][0])._scope()
+][0])._first())._scope()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 ,$ctx1.sendIdx["scope"]=1
 //>>excludeEnd("ctx");
@@ -2881,11 +2865,11 @@ selector: "testScopeLevel",
 protocol: "tests",
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: [],
-source: "testScopeLevel\x0a\x09| src ast |\x0a\x0a\x09src := 'foo | a | a + 1. [ [ | b | b := a ] ]'.\x0a\x09ast := Smalltalk parse: src.\x0a\x09analyzer visit: ast.\x0a\x0a\x09self assert: ast scope scopeLevel equals: 1.\x0a\x09self assert: ast dagChildren first dagChildren last dagChildren first dagChildren first scope scopeLevel equals: 3",
+source: "testScopeLevel\x0a\x09| src ast |\x0a\x0a\x09src := 'foo | a | a + 1. [ [ | b | b := a ] ]'.\x0a\x09ast := Smalltalk parse: src.\x0a\x09analyzer visit: ast.\x0a\x0a\x09self assert: ast scope scopeLevel equals: 1.\x0a\x09self assert: ast sequenceNode dagChildren last sequenceNode dagChildren first scope scopeLevel equals: 3",
 referencedClasses: ["Smalltalk"],
 //>>excludeEnd("ide");
 pragmas: [],
-messageSends: ["parse:", "visit:", "assert:equals:", "scopeLevel", "scope", "first", "dagChildren", "last"]
+messageSends: ["parse:", "visit:", "assert:equals:", "scopeLevel", "scope", "first", "dagChildren", "sequenceNode", "last"]
 }, function ($methodClass){ return function (){
 var self=this,$self=this;
 var src,ast;
@@ -2908,27 +2892,15 @@ $recv($self.analyzer)._visit_(ast);
 ,$ctx1.sendIdx["assert:equals:"]=1
 //>>excludeEnd("ctx");
 ][0];
-$self._assert_equals_($recv($recv([$recv([$recv([$recv([$recv($recv([$recv($recv($recv(ast)._dagChildren())._first())._dagChildren()
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["dagChildren"]=3
-//>>excludeEnd("ctx");
-][0])._last())._dagChildren()
+$self._assert_equals_($recv($recv($recv([$recv([$recv($recv($recv($recv(ast)._sequenceNode())._dagChildren())._last())._sequenceNode()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["dagChildren"]=2
-//>>excludeEnd("ctx");
-][0])._first()
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["first"]=2
+,$ctx1.sendIdx["sequenceNode"]=1
 //>>excludeEnd("ctx");
 ][0])._dagChildren()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 ,$ctx1.sendIdx["dagChildren"]=1
 //>>excludeEnd("ctx");
-][0])._first()
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["first"]=1
-//>>excludeEnd("ctx");
-][0])._scope())._scopeLevel(),(3));
+][0])._first())._scope())._scopeLevel(),(3));
 return self;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 }, function($ctx1) {$ctx1.fill(self,"testScopeLevel",{src:src,ast:ast})});
@@ -3163,11 +3135,11 @@ selector: "testVariablesLookup",
 protocol: "tests",
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: [],
-source: "testVariablesLookup\x0a\x09| src ast |\x0a\x0a\x09src := 'foo | a | a + 1. [ | b | b := a ]'.\x0a\x09ast := Smalltalk parse: src.\x0a\x09analyzer visit: ast.\x0a\x0a\x09\x22Binding for `a` in the message send\x22\x0a\x09self assert: ast dagChildren first dagChildren first receiver binding isTempVar.\x0a\x09self assert: ast dagChildren first dagChildren first receiver binding scope == ast scope.\x0a\x0a\x09\x22Binding for `b`\x22\x0a\x09self assert: ast dagChildren first dagChildren last dagChildren first dagChildren first left binding isTempVar.\x0a\x09self assert: ast dagChildren first dagChildren last dagChildren first dagChildren first left binding scope == ast dagChildren first dagChildren last scope.",
+source: "testVariablesLookup\x0a\x09| src ast |\x0a\x0a\x09src := 'foo | a | a + 1. [ | b | b := a ]'.\x0a\x09ast := Smalltalk parse: src.\x0a\x09analyzer visit: ast.\x0a\x0a\x09\x22Binding for `a` in the message send\x22\x0a\x09self assert: ast sequenceNode dagChildren first receiver binding isTempVar.\x0a\x09self assert: ast sequenceNode dagChildren first receiver binding scope == ast scope.\x0a\x0a\x09\x22Binding for `b`\x22\x0a\x09self assert: ast sequenceNode dagChildren last sequenceNode dagChildren first left binding isTempVar.\x0a\x09self assert: ast sequenceNode dagChildren last sequenceNode dagChildren first left binding scope == ast sequenceNode dagChildren last scope.",
 referencedClasses: ["Smalltalk"],
 //>>excludeEnd("ide");
 pragmas: [],
-messageSends: ["parse:", "visit:", "assert:", "isTempVar", "binding", "receiver", "first", "dagChildren", "==", "scope", "left", "last"]
+messageSends: ["parse:", "visit:", "assert:", "isTempVar", "binding", "receiver", "first", "dagChildren", "sequenceNode", "==", "scope", "left", "last"]
 }, function ($methodClass){ return function (){
 var self=this,$self=this;
 var src,ast;
@@ -3177,13 +3149,9 @@ return $core.withContext(function($ctx1) {
 src="foo | a | a + 1. [ | b | b := a ]";
 ast=$recv($globals.Smalltalk)._parse_(src);
 $recv($self.analyzer)._visit_(ast);
-[$self._assert_([$recv([$recv([$recv([$recv([$recv([$recv([$recv(ast)._dagChildren()
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["dagChildren"]=2
-//>>excludeEnd("ctx");
-][0])._first()
+[$self._assert_([$recv([$recv([$recv([$recv([$recv([$recv(ast)._sequenceNode()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["first"]=2
+,$ctx1.sendIdx["sequenceNode"]=1
 //>>excludeEnd("ctx");
 ][0])._dagChildren()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
@@ -3210,21 +3178,17 @@ $recv($self.analyzer)._visit_(ast);
 ,$ctx1.sendIdx["assert:"]=1
 //>>excludeEnd("ctx");
 ][0];
-[$self._assert_([$recv([$recv([$recv($recv([$recv([$recv([$recv([$recv(ast)._dagChildren()
+[$self._assert_([$recv([$recv([$recv($recv([$recv([$recv([$recv(ast)._sequenceNode()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["dagChildren"]=4
-//>>excludeEnd("ctx");
-][0])._first()
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["first"]=4
+,$ctx1.sendIdx["sequenceNode"]=2
 //>>excludeEnd("ctx");
 ][0])._dagChildren()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["dagChildren"]=3
+,$ctx1.sendIdx["dagChildren"]=2
 //>>excludeEnd("ctx");
 ][0])._first()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["first"]=3
+,$ctx1.sendIdx["first"]=2
 //>>excludeEnd("ctx");
 ][0])._receiver())._binding()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
@@ -3247,37 +3211,29 @@ $recv($self.analyzer)._visit_(ast);
 ,$ctx1.sendIdx["assert:"]=2
 //>>excludeEnd("ctx");
 ][0];
-[$self._assert_($recv([$recv([$recv([$recv([$recv([$recv([$recv([$recv([$recv([$recv([$recv(ast)._dagChildren()
+[$self._assert_($recv([$recv([$recv([$recv([$recv([$recv([$recv([$recv([$recv(ast)._sequenceNode()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["dagChildren"]=8
-//>>excludeEnd("ctx");
-][0])._first()
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["first"]=7
+,$ctx1.sendIdx["sequenceNode"]=4
 //>>excludeEnd("ctx");
 ][0])._dagChildren()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["dagChildren"]=7
+,$ctx1.sendIdx["dagChildren"]=4
 //>>excludeEnd("ctx");
 ][0])._last()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 ,$ctx1.sendIdx["last"]=1
 //>>excludeEnd("ctx");
-][0])._dagChildren()
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["dagChildren"]=6
-//>>excludeEnd("ctx");
-][0])._first()
+][0])._sequenceNode()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["first"]=6
+,$ctx1.sendIdx["sequenceNode"]=3
 //>>excludeEnd("ctx");
 ][0])._dagChildren()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["dagChildren"]=5
+,$ctx1.sendIdx["dagChildren"]=3
 //>>excludeEnd("ctx");
 ][0])._first()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["first"]=5
+,$ctx1.sendIdx["first"]=3
 //>>excludeEnd("ctx");
 ][0])._left()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
@@ -3292,47 +3248,31 @@ $recv($self.analyzer)._visit_(ast);
 ,$ctx1.sendIdx["assert:"]=3
 //>>excludeEnd("ctx");
 ][0];
-$self._assert_($recv([$recv($recv($recv([$recv([$recv([$recv([$recv([$recv([$recv([$recv([$recv(ast)._dagChildren()
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["dagChildren"]=12
-//>>excludeEnd("ctx");
-][0])._first()
+$self._assert_($recv([$recv($recv($recv($recv([$recv([$recv([$recv([$recv([$recv(ast)._sequenceNode()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["first"]=10
+,$ctx1.sendIdx["sequenceNode"]=6
 //>>excludeEnd("ctx");
 ][0])._dagChildren()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["dagChildren"]=11
+,$ctx1.sendIdx["dagChildren"]=6
 //>>excludeEnd("ctx");
 ][0])._last()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 ,$ctx1.sendIdx["last"]=2
 //>>excludeEnd("ctx");
-][0])._dagChildren()
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["dagChildren"]=10
-//>>excludeEnd("ctx");
-][0])._first()
+][0])._sequenceNode()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["first"]=9
+,$ctx1.sendIdx["sequenceNode"]=5
 //>>excludeEnd("ctx");
 ][0])._dagChildren()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["dagChildren"]=9
-//>>excludeEnd("ctx");
-][0])._first()
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["first"]=8
+,$ctx1.sendIdx["dagChildren"]=5
 //>>excludeEnd("ctx");
-][0])._left())._binding())._scope()
+][0])._first())._left())._binding())._scope()
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 ,$ctx1.sendIdx["scope"]=3
 //>>excludeEnd("ctx");
-][0]).__eq_eq($recv($recv([$recv($recv($recv(ast)._dagChildren())._first())._dagChildren()
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-,$ctx1.sendIdx["dagChildren"]=13
-//>>excludeEnd("ctx");
-][0])._last())._scope()));
+][0]).__eq_eq($recv($recv($recv($recv(ast)._sequenceNode())._dagChildren())._last())._scope()));
 return self;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 }, function($ctx1) {$ctx1.fill(self,"testVariablesLookup",{src:src,ast:ast})});

+ 7 - 7
lang/src/Compiler-Tests.st

@@ -736,7 +736,7 @@ testScope
 	ast := Smalltalk parse: src.
 	analyzer visit: ast.
 
-	self deny: ast dagChildren first dagChildren last scope == ast scope.
+	self deny: ast sequenceNode dagChildren last scope == ast scope.
 !
 
 testScope2
@@ -746,7 +746,7 @@ testScope2
 	ast := Smalltalk parse: src.
 	analyzer visit: ast.
 
-	self deny: ast dagChildren first dagChildren last dagChildren first dagChildren first scope == ast scope.
+	self deny: ast sequenceNode dagChildren last sequenceNode dagChildren first scope == ast scope.
 !
 
 testScopeLevel
@@ -757,7 +757,7 @@ testScopeLevel
 	analyzer visit: ast.
 
 	self assert: ast scope scopeLevel equals: 1.
-	self assert: ast dagChildren first dagChildren last dagChildren first dagChildren first scope scopeLevel equals: 3
+	self assert: ast sequenceNode dagChildren last sequenceNode dagChildren first scope scopeLevel equals: 3
 !
 
 testUnknownVariables
@@ -821,12 +821,12 @@ testVariablesLookup
 	analyzer visit: ast.
 
 	"Binding for `a` in the message send"
-	self assert: ast dagChildren first dagChildren first receiver binding isTempVar.
-	self assert: ast dagChildren first dagChildren first receiver binding scope == ast scope.
+	self assert: ast sequenceNode dagChildren first receiver binding isTempVar.
+	self assert: ast sequenceNode dagChildren first receiver binding scope == ast scope.
 
 	"Binding for `b`"
-	self assert: ast dagChildren first dagChildren last dagChildren first dagChildren first left binding isTempVar.
-	self assert: ast dagChildren first dagChildren last dagChildren first dagChildren first left binding scope == ast dagChildren first dagChildren last scope.
+	self assert: ast sequenceNode dagChildren last sequenceNode dagChildren first left binding isTempVar.
+	self assert: ast sequenceNode dagChildren last sequenceNode dagChildren first left binding scope == ast sequenceNode dagChildren last scope.
 ! !
 
 SemanticAnalyzerTest subclass: #AISemanticAnalyzerTest