MessageNode.st
changeset 140 1ef1d1395146
parent 135 aa4f7b8f121e
child 148 ef0e604209ec
--- a/MessageNode.st	Sat Nov 18 17:59:14 1995 +0100
+++ b/MessageNode.st	Thu Nov 23 03:15:59 1995 +0100
@@ -11,10 +11,10 @@
 "
 
 ParseNode subclass:#MessageNode
-       instanceVariableNames:'receiver selector argArray lineNr'
-       classVariableNames:''
-       poolDictionaries:''
-       category:'System-Compiler-Support'
+	 instanceVariableNames:'receiver selector argArray lineNr'
+	 classVariableNames:''
+	 poolDictionaries:''
+	 category:'System-Compiler-Support'
 !
 
 !MessageNode class methodsFor:'documentation'!
@@ -33,14 +33,14 @@
 "
 !
 
-version
-    ^ '$Header: /cvs/stx/stx/libcomp/MessageNode.st,v 1.31 1995-11-11 15:30:33 cg Exp $'
-!
-
 documentation
 "
     node for parse-trees, representing message sends
 "
+!
+
+version
+    ^ '$Header: /cvs/stx/stx/libcomp/MessageNode.st,v 1.32 1995-11-23 02:13:47 cg Exp $'
 ! !
 
 !MessageNode class methodsFor:'instance creation'!
@@ -49,6 +49,52 @@
     ^ (self basicNew) receiver:recNode selector:selectorString args:nil lineno:0
 !
 
+receiver:recNode selector:selectorString arg1:argNode1 arg2:argNode2 fold:folding
+    |result recVal argVal selector|
+
+    "
+     This is just a demonstration - of how complex constants can be folded.
+     This was inspired by some discussion in c.l.s about enhancing the language - I prefer
+     enhancing the compiler ....
+     The following optimization will convert '#(...) with:#(...) collect:[...]' into an array constant,
+     allowing a constant arrays of complex objects.
+
+     Notice: this method is normally disabled - its just a demo after all.
+    "
+    folding ifTrue:[
+	"do constant folding ..."
+	(recNode isConstant and:[argNode1 isConstant]) ifTrue:[
+	    "check if we can do it ..."
+	    selector := selectorString asSymbolIfInterned.
+	    selector notNil ifTrue:[
+		recVal := recNode evaluate.
+		(recVal respondsTo:selector) ifTrue:[
+		    "
+		     we could do much more here - but then, we need a dependency from
+		     the folded selectors method to the method we generate code for ...
+		     limit optimizations to those that will never change
+		     (or - if you change them - you will crash so bad ...)
+		    "
+		    argVal := argNode1 evaluate.
+		    ((recVal isMemberOf:Array) and:[argVal isMemberOf:Array]) ifTrue:[
+			(selector == #with:collect:) ifTrue:[
+			    (argNode2 isMemberOf:BlockNode) ifTrue:[
+				(SignalSet anySignal catch:[
+				    result := recVal perform:selector with:argVal with:(argNode2 evaluate).
+				]) ifTrue:[
+				    ^ 'error in constant expression'
+				].
+				^ ConstantNode type:(ConstantNode typeOfConstant:result) value:result
+			    ]
+			]
+		    ]
+		]
+	    ]
+	]
+    ].
+    ^ (self basicNew) receiver:recNode selector:selectorString args:(Array with:argNode1 with:argNode2) lineno:0
+!
+
 receiver:recNode selector:selectorString arg:argNode
     ^ self receiver:recNode selector:selectorString arg:argNode fold:true
 !
@@ -132,52 +178,6 @@
     ^ (self basicNew) receiver:recNode selector:selectorString args:(Array with:argNode) lineno:0
 !
 
-receiver:recNode selector:selectorString arg1:argNode1 arg2:argNode2 fold:folding
-    |result recVal argVal selector|
-
-    "
-     This is just a demonstration - of how complex constants can be folded.
-     This was inspired by some discussion in c.l.s about enhancing the language - I prefer
-     enhancing the compiler ....
-     The following optimization will convert '#(...) with:#(...) collect:[...]' into an array constant,
-     allowing a constant arrays of complex objects.
-
-     Notice: this method is normally disabled - its just a demo after all.
-    "
-    folding ifTrue:[
-	"do constant folding ..."
-	(recNode isConstant and:[argNode1 isConstant]) ifTrue:[
-	    "check if we can do it ..."
-	    selector := selectorString asSymbolIfInterned.
-	    selector notNil ifTrue:[
-		recVal := recNode evaluate.
-		(recVal respondsTo:selector) ifTrue:[
-		    "
-		     we could do much more here - but then, we need a dependency from
-		     the folded selectors method to the method we generate code for ...
-		     limit optimizations to those that will never change
-		     (or - if you change them - you will crash so bad ...)
-		    "
-		    argVal := argNode1 evaluate.
-		    ((recVal isMemberOf:Array) and:[argVal isMemberOf:Array]) ifTrue:[
-			(selector == #with:collect:) ifTrue:[
-			    (argNode2 isMemberOf:BlockNode) ifTrue:[
-				(SignalSet anySignal catch:[
-				    result := recVal perform:selector with:argVal with:(argNode2 evaluate).
-				]) ifTrue:[
-				    ^ 'error in constant expression'
-				].
-				^ ConstantNode type:(ConstantNode typeOfConstant:result) value:result
-			    ]
-			]
-		    ]
-		]
-	    ]
-	]
-    ].
-    ^ (self basicNew) receiver:recNode selector:selectorString args:(Array with:argNode1 with:argNode2) lineno:0
-!
-
 receiver:recNode selector:selectorString args:anArray
     ^ self receiver:recNode selector:selectorString args:anArray fold:true
 !
@@ -205,45 +205,6 @@
     "Modified: 3.9.1995 / 16:41:39 / claus"
 ! !
 
-!MessageNode methodsFor:'accessing'!
-
-receiver:r selector:s args:a lineno:l
-    receiver := r.
-    selector := s asSymbol.
-    argArray := a.
-    lineNr := l
-!
-
-receiver
-    ^ receiver
-!
-
-selector
-    ^ selector
-!
-
-args
-    ^ argArray
-!
-
-arg1
-    ^ argArray at:1
-!
-
-lineNumber
-     ^ lineNr
-!
-
-lineNumber:num
-     lineNr := num
-! !
-
-!MessageNode methodsFor:'queries'!
-
-isMessage
-    ^ true
-! !
-
 !MessageNode class methodsFor:'queries'!
 
 hasLineNumber:sel
@@ -257,6 +218,27 @@
     ^ true
 !
 
+isBuiltIn1ArgSelector:sel
+    "return true, if selector sel is built-in.
+     (i.e. there is a single bytecode for it)"
+
+    (sel == #at:) ifTrue:[^ true].
+    (sel == #value:) ifTrue:[^ true].
+    (sel == #bitAnd:) ifTrue:[^ true].
+    (sel == #bitOr:) ifTrue:[^ true].
+    (sel == #new:) ifTrue:[^ true].
+    (sel == #basicNew:) ifTrue:[^ true].
+    ^ false
+!
+
+isBuiltIn2ArgSelector:sel
+    "return true, if selector sel is built-in.
+     (i.e. there is a single bytecode for it)"
+
+    (sel == #at:put:) ifTrue:[^ true].
+    ^ false
+!
+
 isBuiltInUnarySelector:sel
     "return true, if unary selector sel is built-in. 
      (i.e. there is a single bytecode for it)"
@@ -280,115 +262,39 @@
     (sel == #new) ifTrue:[^ true].
     (sel == #basicNew) ifTrue:[^ true].
     ^ false
-!
-
-isBuiltIn1ArgSelector:sel
-    "return true, if selector sel is built-in.
-     (i.e. there is a single bytecode for it)"
-
-    (sel == #at:) ifTrue:[^ true].
-    (sel == #value:) ifTrue:[^ true].
-    (sel == #bitAnd:) ifTrue:[^ true].
-    (sel == #bitOr:) ifTrue:[^ true].
-    (sel == #new:) ifTrue:[^ true].
-    (sel == #basicNew:) ifTrue:[^ true].
-    ^ false
-!
-
-isBuiltIn2ArgSelector:sel
-    "return true, if selector sel is built-in.
-     (i.e. there is a single bytecode for it)"
-
-    (sel == #at:put:) ifTrue:[^ true].
-    ^ false
 ! !
 
-!MessageNode methodsFor:'printing'!
-
-printOn:aStream indent:i
-    |needParen selectorParts index index2 arg|
-
-    (#(whileTrue: whileFalse:) includes:selector) ifTrue:[
-	receiver isBlock ifTrue:[
-	    ^ self printWhileOn:aStream indent:i
-	].
-    ].
+!MessageNode methodsFor:'accessing'!
 
-    index := 1.
-    selectorParts := OrderedCollection new.
-    [index == 0] whileFalse:[
-	index2 := selector indexOf:$: startingAt:index.
-	index2 ~~ 0 ifTrue:[
-	    selectorParts add:(selector copyFrom:index to:index2).
-	    index2 := index2 + 1
-	].
-	index := index2
-    ].
+arg1
+    ^ argArray at:1
+!
 
-    needParen := false.
-    receiver isMessage ifTrue:[
-	receiver isUnaryMessage ifFalse:[
-	    receiver isBinaryMessage ifFalse:[
-		needParen := true
-	    ].
-	].
-    ].
-    needParen ifTrue:[
-	aStream nextPutAll:'('
-    ].
-    receiver printOn:aStream indent:i.
-    needParen ifTrue:[
-	aStream nextPutAll:')'
-    ].
+args
+    ^ argArray
+!
 
-    1 to:(argArray size) do:[:argIndex |
-	aStream space.
-	(selectorParts at:argIndex) printOn:aStream.
-	aStream space.
-	arg := argArray at:argIndex.
-	needParen := false.
-	arg isMessage ifTrue:[
-	    arg isBinaryMessage ifFalse:[
-		arg isUnaryMessage ifFalse:[
-		    needParen := true
-		]
-	    ].
-	].
-	needParen ifTrue:[
-	    aStream nextPutAll:'('
-	].
-	arg printOn:aStream indent:i.
-	needParen ifTrue:[
-	    aStream nextPutAll:') '
-	].
-    ]
+lineNumber
+     ^ lineNr
 !
 
-printWhileOn:aStream indent:i
-    |needParen arg|
+lineNumber:num
+     lineNr := num
+!
 
-    "special handling of whileTrue/whileFalse"
-
-    aStream nextPutAll:'['.
-    receiver statements printOn:aStream indent:i.
-    aStream nextPutAll:'] whileTrue: '.
+receiver
+    ^ receiver
+!
 
-    arg := argArray at:1.
-    needParen := false.
-    arg isMessage ifTrue:[
-	arg isBinaryMessage ifFalse:[
-	    arg isUnaryMessage ifFalse:[
-		needParen := true
-	    ]
-	].
-    ].
-    needParen ifTrue:[
-	aStream nextPutAll:'('
-    ].
-    arg printOn:aStream indent:i.
-    needParen ifTrue:[
-	aStream nextPutAll:') '
-    ].
+receiver:r selector:s args:a lineno:l
+    receiver := r.
+    selector := s asSymbol.
+    argArray := a.
+    lineNr := l
+!
+
+selector
+    ^ selector
 ! !
 
 !MessageNode methodsFor:'checks'!
@@ -481,238 +387,8 @@
     ^ nil
 ! !
 
-!MessageNode methodsFor:'evaluating'!
-
-evaluate
-    |r nargs argValueArray class|
-
-    receiver isSuper ifTrue:[
-	r := receiver value.
-	receiver isHere ifTrue:[
-	    class := receiver definingClass.
-	] ifFalse:[
-	    class := receiver definingClass superclass.
-	].
-	argArray notNil ifTrue:[
-	    argValueArray := argArray collect:[:arg | arg evaluate].
-	] ifFalse:[
-	    argValueArray := #()
-	].
-	^ r perform:selector inClass:class withArguments:argValueArray
-    ].
-
-
-    argArray isNil ifTrue:[
-	^ (receiver evaluate) perform:selector
-    ].
-    nargs := argArray size.
-    (nargs == 1) ifTrue:[
-	^ (receiver evaluate) perform:selector with:(argArray at:1) evaluate
-    ].
-    (nargs == 2) ifTrue:[
-	^ (receiver evaluate) perform:selector
-				 with:(argArray at:1) evaluate
-				 with:(argArray at:2) evaluate
-    ].
-    (nargs == 3) ifTrue:[
-	^ (receiver evaluate) perform:selector
-				 with:(argArray at:1) evaluate
-				 with:(argArray at:2) evaluate
-				 with:(argArray at:3) evaluate
-    ].
-    r := receiver evaluate.
-    argValueArray := argArray collect:[:arg | arg evaluate].
-    ^ r perform:selector withArguments:argValueArray
-!
-
-evaluateForCascade
-    |r nargs argValueArray class|
-
-    receiver isSuper ifTrue:[
-	r := receiver value.
-	class := receiver definingClass.
-	receiver isHere ifFalse:[
-	    class := class superclass.
-	].
-	argArray notNil ifTrue:[
-	    argValueArray := argArray collect:[:arg | arg evaluate].
-	] ifFalse:[
-	    argValueArray := #()
-	].
-	r perform:selector inClass:class withArguments:argValueArray.
-	^ r
-    ].
-
-    r := receiver evaluate.
-    argArray isNil ifTrue:[
-	r perform:selector.
-	^ r
-    ].
-    nargs := argArray size.
-    (nargs == 1) ifTrue:[
-	r perform:selector with:(argArray at:1) evaluate.
-	^ r
-    ].
-    (nargs == 2) ifTrue:[
-	r perform:selector with:(argArray at:1) evaluate
-			   with:(argArray at:2) evaluate.
-	^ r
-    ].
-    (nargs == 3) ifTrue:[
-	r perform:selector with:(argArray at:1) evaluate
-			   with:(argArray at:2) evaluate
-			   with:(argArray at:3) evaluate.
-	^ r
-    ].
-    argValueArray := argArray collect:[:arg | arg evaluate].
-    r perform:selector withArguments:argValueArray.
-    ^ r
-! !
-
 !MessageNode methodsFor:'code generation'!
 
-codeForSideEffectOn:aStream inBlock:b for:aCompiler
-    self codeOn:aStream inBlock:b valueNeeded:false for:aCompiler
-!
-
-codeOn:aStream inBlock:b for:aCompiler
-    self codeOn:aStream inBlock:b valueNeeded:true for:aCompiler
-!
-
-optimizedConditionFor:aReceiver with:aByteCode
-    |rec sel|
-
-    rec := aReceiver.
-    (rec isBlock) ifTrue:[
-	rec statements nextStatement isNil ifTrue:[
-	    rec := rec statements expression
-	]
-    ].
-    (rec isUnaryMessage) ifTrue:[
-	sel := rec selector.
-	(sel == #isNil) ifTrue:[
-	    "/
-	    "/ isNil trueJmp  -> nilJump
-	    "/ isNil falseJmp -> notNilJump
-	    "/
-	    (aByteCode == #trueJump) ifTrue:[^ #nilJump].
-	    (aByteCode == #falseJump) ifTrue:[^ #notNilJump]
-	].
-	(sel == #notNil) ifTrue:[
-	    "/
-	    "/ notNil trueJmp  -> notNilJump
-	    "/ notNil falseJmp -> nilJump
-	    "/
-	    (aByteCode == #trueJump) ifTrue:[^ #notNilJump].
-	    (aByteCode == #falseJump) ifTrue:[^ #nilJump]
-	].
-	(sel == #not) ifTrue:[
-	    "/
-	    "/ not trueJmp  -> falseJump
-	    "/ not falseJmp -> trueJump
-	    "/
-	    (aByteCode == #trueJump) ifTrue:[^ #falseJump].
-	    (aByteCode == #falseJump) ifTrue:[^ #trueJump]
-	].
-	^ nil
-    ].
-    (rec isBinaryMessage) ifTrue:[
-	sel := rec selector.
-	rec arg1 isConstant ifTrue:[
-	    (rec arg1 value == 0) ifTrue:[
-		"/
-		"/ ==0 trueJmp  -> zeroJump
-		"/ ==0 falseJmp -> notZeroJump
-		"/
-		(sel == #==) ifTrue:[
-		    (aByteCode == #trueJump) ifTrue:[^ #zeroJump].
-		    (aByteCode == #falseJump) ifTrue:[^ #notZeroJump]
-		].
-		"/
-		"/ ~~0 trueJmp  -> notZeroJump
-		"/ ~~0 falseJmp -> zeroJump
-		"/
-		(sel == #~~) ifTrue:[
-		    (aByteCode == #falseJump) ifTrue:[^ #zeroJump].
-		    (aByteCode == #trueJump) ifTrue:[^ #notZeroJump]
-		].
-		^ nil
-	    ]
-	].
-	(sel == #==) ifTrue:[
-	    "/
-	    "/ == trueJmp  -> eqJump
-	    "/ == falseJmp -> notEqJump
-	    "/
-	    (aByteCode == #trueJump) ifTrue:[^ #eqJump].
-	    (aByteCode == #falseJump) ifTrue:[^ #notEqJump]
-	].
-	(sel == #~~) ifTrue:[
-	    "/
-	    "/ ~~ trueJmp  -> notEqJump
-	    "/ ~~ falseJmp -> eqJump
-	    "/
-	    (aByteCode == #falseJump) ifTrue:[^ #eqJump].
-	    (aByteCode == #trueJump) ifTrue:[^ #notEqJump]
-	]
-    ].
-    ^ nil
-!
-
-codeWhileOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler
-    "generate code for [...] whilexxx:[ ... ]"
-
-    |pos pos2 theReceiver theArg theByteCode optByteCode|
-
-    (selector == #whileTrue:) ifTrue:[
-	theByteCode := #falseJump
-    ] ifFalse:[
-	theByteCode := #trueJump
-    ].
-
-    theReceiver := receiver.
-    optByteCode := self optimizedConditionFor:theReceiver with:theByteCode.
-    optByteCode notNil ifTrue:[
-	((optByteCode == #eqJump) or:[optByteCode == #notEqJump]) ifTrue:[
-	    theArg := receiver statements expression arg1
-	].
-	theReceiver := receiver statements expression receiver.
-	theByteCode := optByteCode
-    ].
-
-"/ OLD:
-"/    valueNeeded ifTrue:[aStream nextPut:#pushNil].
-"/
-    pos := aStream position.
-    optByteCode notNil ifTrue:[
-	theReceiver codeOn:aStream inBlock:b for:aCompiler.
-	theArg notNil ifTrue:[
-	    theArg codeOn:aStream inBlock:b for:aCompiler
-	]
-    ] ifFalse:[
-	theReceiver codeInlineOn:aStream inBlock:b for:aCompiler
-    ].
-
-    (lineNr between:1 and:255) ifTrue:[
-	aStream nextPut:#lineno; nextPut:lineNr.
-    ].
-
-    aStream nextPut:theByteCode.
-    pos2 := aStream position.
-    aStream nextPut:0.
-"/ OLD:
-"/    valueNeeded ifTrue:[aStream nextPut:#drop].
-"/
-"/ OLD:
-"/    (argArray at:1) codeInlineOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler.
-"/ NEW:
-    (argArray at:1) codeInlineOn:aStream inBlock:b valueNeeded:false for:aCompiler.
-    aStream nextPut:#jump; nextPut:pos.
-    (aStream contents) at:pos2 put:(aStream position).
-"/ NEW:
-    valueNeeded ifTrue:[aStream nextPut:#pushNil].
-!
-
 XXcodeWhileOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler
     "generate code for [...] whilexxx:[ ... ]"
 
@@ -758,27 +434,182 @@
     (aStream contents) at:pos2 put:(aStream position).
 !
 
-codeTimesRepeatOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler
-    "generate code for n timesRepeat:[ ... ]"
+codeAndIfOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler
+    "generate code for (x and:[y]) ifxxx:[ ... ]"
+
+    |theByteCode optByteCode theReceiver theArg pos1 pos2 pos3 code here jmp|
+
+
+    theByteCode := #falseJump.
+    theReceiver := receiver receiver.
 
-    |pos pos2 theReceiver|
-
-    theReceiver := receiver.
+    optByteCode := self optimizedConditionFor:theReceiver
+					 with:theByteCode.
+    optByteCode notNil ifTrue:[
+	((optByteCode == #eqJump) or:[optByteCode == #notEqJump]) ifTrue:[
+	    theArg := theReceiver arg1
+	].
+	theReceiver := theReceiver receiver.
+	theByteCode := optByteCode
+    ].
     theReceiver codeOn:aStream inBlock:b for:aCompiler.
-    valueNeeded ifTrue:[aStream nextPut:#dup].
+    theArg notNil ifTrue:[
+	theArg codeOn:aStream inBlock:b for:aCompiler
+    ].
+    aStream nextPut:theByteCode.
+    pos1 := aStream position.
+    aStream nextPut:0.
 
-    pos := aStream position.
-"/    aStream nextPut:#dup; nextPut:#push0; nextPut:#>; nextPut:lineNr; nextPut:#falseJump.
-"/    aStream nextPut:#dup; nextPut:#gt0; nextPut:lineNr; nextPut:#falseJump.
-    aStream nextPut:#pushgt0; nextPut:lineNr; nextPut:#falseJump.
+    theReceiver := receiver arg1.
+    theReceiver codeInlineOn:aStream inBlock:b for:aCompiler.
+    (selector == #ifTrue:) ifTrue:[
+	jmp := #falseJump
+    ] ifFalse:[
+	jmp := #trueJump
+    ].
+    aStream nextPut:jmp.
     pos2 := aStream position.
     aStream nextPut:0.
 
-    (argArray at:1) codeInlineOn:aStream inBlock:b valueNeeded:false for:aCompiler.
-    aStream nextPut:#minus1; nextPut:lineNr; nextPut:#jump; nextPut:pos.
+    code := aStream contents.
+    (selector == #ifFalse:) ifTrue:[
+	code at:pos1 put:(aStream position)
+    ].
+    (argArray at: 1) codeInlineOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler.
+
+    valueNeeded ifTrue:[
+	aStream nextPut:#jump.
+	pos3 := aStream position.
+	aStream nextPut:0.
+	here := aStream position.
+	(selector == #ifTrue:) ifTrue:[
+	    code at:pos1 put:here
+	].
+	code at:pos2 put:here.
+	aStream nextPut:#pushNil.
+	code at:pos3 put:(aStream position)
+    ] ifFalse:[
+	here := aStream position.
+	(selector == #ifTrue:) ifTrue:[
+	    code at:pos1 put:here
+	].
+	code at:pos2 put:here
+    ]
+!
+
+codeAndOrOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler
+    "generate code for x and/or:[y] - but not in an if"
+
+    |pos theReceiver theByteCode|
+
+self halt.
+    theReceiver := receiver.
+    (selector == #and:) ifTrue:[
+	theByteCode := #falseJump
+    ] ifFalse:[
+	theByteCode := #trueJump
+    ].
+"
+    (self canOptimizeConditionFor:receiver) ifTrue:[
+	theByteCode := self optimizedConditionFor:theReceiver
+					     with:theByteCode.
+	theReceiver := theReceiver receiver
+    ].
+"
+    theReceiver codeOn:aStream inBlock:b for:aCompiler.
+    aStream nextPut:theByteCode.
+    pos := aStream position.
+    aStream nextPut:0.
+    (argArray at: 1) codeInlineOn:aStream inBlock:b for:aCompiler.
+    (aStream contents) at:pos put:(aStream position).
+    valueNeeded ifFalse:[aStream nextPut:#drop]
+!
+
+codeForCascadeOn:aStream inBlock:b for:aCompiler
+    "like codeOn, but always leave the receiver instead of the result"
+
+    |nargs isBuiltIn code litIndex|
+
+    argArray isNil ifTrue:[
+	nargs := 0
+    ] ifFalse:[
+	nargs := argArray size
+    ].
+
+    isBuiltIn := false.
 
-    (aStream contents) at:pos2 put:(aStream position).
-    aStream nextPut:#drop.
+    (nargs == 0) ifTrue:[
+	isBuiltIn := self class isBuiltInUnarySelector:selector
+    ].
+    (nargs == 1) ifTrue:[
+	isBuiltIn := self class isBuiltIn1ArgSelector:selector
+    ].
+    (nargs == 2) ifTrue:[
+	isBuiltIn := self class isBuiltIn2ArgSelector:selector
+    ].
+
+    receiver codeOn:aStream inBlock:b for:aCompiler.
+    aStream nextPut:#dup.
+
+    "can we use a send-bytecode ?"
+    isBuiltIn ifTrue:[
+	receiver isSuper ifFalse:[
+	    (nargs > 0) ifTrue:[
+		(argArray at:1) codeOn:aStream inBlock:b for:aCompiler.
+		(nargs > 1) ifTrue:[
+		    (argArray at:2) codeOn:aStream inBlock:b for:aCompiler
+		]
+	    ].
+	    aStream nextPut:selector.
+	    (self class hasLineNumber:selector) ifTrue:[
+		aStream nextPut:lineNr.
+	    ].
+	    aStream nextPut:#drop.
+	    ^ self
+	]
+    ].
+
+    "no - generate a send"
+    argArray notNil ifTrue:[
+	argArray do:[:arg |
+	    arg codeOn:aStream inBlock:b for:aCompiler
+	]
+    ].
+    litIndex := aCompiler addLiteral:selector.
+    litIndex <= 255 ifTrue:[
+	receiver isSuper ifTrue:[
+	    receiver isHere ifTrue:[
+		code := #hereSend
+	    ] ifFalse:[
+		code := #superSend.
+	    ].
+	    aStream nextPut:code; nextPut:lineNr; nextPut:litIndex; nextPut:nargs; nextPut:nil; nextPut:#drop.
+	    ^ self
+	].
+	(nargs <= 3) ifTrue:[
+	    code := #(sendDrop0 sendDrop1 sendDrop2 sendDrop3) at:(nargs+1).
+	    aStream nextPut:code; nextPut:lineNr; nextPut:litIndex.
+	    ^ self
+	].
+
+	aStream nextPut:#sendDrop; nextPut:lineNr; nextPut:litIndex; nextPut:nargs.
+	^ self
+    ].
+    "need 16bit litIndex"
+    receiver isSuper ifTrue:[
+	receiver isHere ifTrue:[
+	    code := #hereSendL
+	] ifFalse:[
+	    code := #superSendL.
+	].
+	aStream nextPut:code; nextPut:lineNr; nextPut:litIndex; nextPut:0; nextPut:nargs; nextPut:nil; nextPut:#drop.
+	^ self
+    ].
+    aStream nextPut:#sendDropL; nextPut:lineNr; nextPut:litIndex; nextPut:0; nextPut:nargs
+!
+
+codeForSideEffectOn:aStream inBlock:b for:aCompiler
+    self codeOn:aStream inBlock:b valueNeeded:false for:aCompiler
 !
 
 codeIfElseOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler
@@ -915,183 +746,8 @@
     ]
 !
 
-codeAndIfOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler
-    "generate code for (x and:[y]) ifxxx:[ ... ]"
-
-    |theByteCode optByteCode theReceiver theArg pos1 pos2 pos3 code here jmp|
-
-
-    theByteCode := #falseJump.
-    theReceiver := receiver receiver.
-
-    optByteCode := self optimizedConditionFor:theReceiver
-					 with:theByteCode.
-    optByteCode notNil ifTrue:[
-	((optByteCode == #eqJump) or:[optByteCode == #notEqJump]) ifTrue:[
-	    theArg := theReceiver arg1
-	].
-	theReceiver := theReceiver receiver.
-	theByteCode := optByteCode
-    ].
-    theReceiver codeOn:aStream inBlock:b for:aCompiler.
-    theArg notNil ifTrue:[
-	theArg codeOn:aStream inBlock:b for:aCompiler
-    ].
-    aStream nextPut:theByteCode.
-    pos1 := aStream position.
-    aStream nextPut:0.
-
-    theReceiver := receiver arg1.
-    theReceiver codeInlineOn:aStream inBlock:b for:aCompiler.
-    (selector == #ifTrue:) ifTrue:[
-	jmp := #falseJump
-    ] ifFalse:[
-	jmp := #trueJump
-    ].
-    aStream nextPut:jmp.
-    pos2 := aStream position.
-    aStream nextPut:0.
-
-    code := aStream contents.
-    (selector == #ifFalse:) ifTrue:[
-	code at:pos1 put:(aStream position)
-    ].
-    (argArray at: 1) codeInlineOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler.
-
-    valueNeeded ifTrue:[
-	aStream nextPut:#jump.
-	pos3 := aStream position.
-	aStream nextPut:0.
-	here := aStream position.
-	(selector == #ifTrue:) ifTrue:[
-	    code at:pos1 put:here
-	].
-	code at:pos2 put:here.
-	aStream nextPut:#pushNil.
-	code at:pos3 put:(aStream position)
-    ] ifFalse:[
-	here := aStream position.
-	(selector == #ifTrue:) ifTrue:[
-	    code at:pos1 put:here
-	].
-	code at:pos2 put:here
-    ]
-!
-
-codeOrIfOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler
-    "generate code for (x or:[y]) ifxxx:[ ... ]"
-
-    |theByteCode optByteCode theReceiver theArg pos1 pos2 pos3 code here jmp|
-
-    theByteCode := #trueJump.
-    theReceiver := receiver receiver.
-
-    optByteCode := self optimizedConditionFor:theReceiver with:theByteCode.
-    optByteCode notNil ifTrue:[
-	((optByteCode == #eqJump) or:[optByteCode == #notEqJump]) ifTrue:[
-	    theArg := theReceiver arg1
-	].
-	theReceiver := theReceiver receiver.
-	theByteCode := optByteCode
-    ].
-    theReceiver codeOn:aStream inBlock:b for:aCompiler.
-    theArg notNil ifTrue:[
-	theArg codeOn:aStream inBlock:b for:aCompiler
-    ].
-    aStream nextPut:theByteCode.
-    pos1 := aStream position.
-    aStream nextPut:0.
-
-
-    theReceiver := receiver arg1.
-
-"new:"
-    (selector == #ifTrue:) ifTrue:[
-	theByteCode := #falseJump
-    ] ifFalse:[
-	theByteCode := #trueJump
-    ].
-    optByteCode := self optimizedConditionFor:theReceiver with:theByteCode.
-    optByteCode notNil ifTrue:[
-	theReceiver isBlock ifTrue:[
-	    theReceiver := theReceiver statements expression
-	].
-	((optByteCode == #eqJump) or:[optByteCode == #notEqJump]) ifTrue:[
-	    theArg := theReceiver arg1
-	].
-	theReceiver := theReceiver receiver.
-	theByteCode := optByteCode.
-
-	theReceiver codeOn:aStream inBlock:b for:aCompiler.
-	theArg notNil ifTrue:[
-	    theArg codeOn:aStream inBlock:b for:aCompiler
-	].
-	aStream nextPut:theByteCode.
-
-    ] ifFalse:[
-"org"
-	theReceiver codeInlineOn:aStream inBlock:b for:aCompiler.
-	(selector == #ifTrue:) ifTrue:[
-	    jmp := #falseJump
-	] ifFalse:[
-	    jmp := #trueJump
-	].
-	aStream nextPut:jmp
-    ].
-    pos2 := aStream position.
-    aStream nextPut:0.
-    (selector == #ifTrue:) ifTrue:[
-	(aStream contents) at:pos1 put:(aStream position)
-    ].
-    (argArray at: 1) codeInlineOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler.
-
-    code := aStream contents.
-    valueNeeded ifTrue:[
-	aStream nextPut:#jump.
-	pos3 := aStream position.
-	aStream nextPut:0.
-	here := aStream position.
-	(selector == #ifFalse:) ifTrue:[
-	    code at:pos1 put:here
-	].
-	code at:pos2 put:here.
-	aStream nextPut:#pushNil.
-	code at:pos3 put:(aStream position)
-    ] ifFalse:[
-	here := aStream position.
-	(selector == #ifFalse:) ifTrue:[
-	    code at:pos1 put:here
-	].
-	code at:pos2 put:here
-    ]
-!
-
-codeAndOrOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler
-    "generate code for x and/or:[y] - but not in an if"
-
-    |pos theReceiver theByteCode|
-
-self halt.
-    theReceiver := receiver.
-    (selector == #and:) ifTrue:[
-	theByteCode := #falseJump
-    ] ifFalse:[
-	theByteCode := #trueJump
-    ].
-"
-    (self canOptimizeConditionFor:receiver) ifTrue:[
-	theByteCode := self optimizedConditionFor:theReceiver
-					     with:theByteCode.
-	theReceiver := theReceiver receiver
-    ].
-"
-    theReceiver codeOn:aStream inBlock:b for:aCompiler.
-    aStream nextPut:theByteCode.
-    pos := aStream position.
-    aStream nextPut:0.
-    (argArray at: 1) codeInlineOn:aStream inBlock:b for:aCompiler.
-    (aStream contents) at:pos put:(aStream position).
-    valueNeeded ifFalse:[aStream nextPut:#drop]
+codeOn:aStream inBlock:b for:aCompiler
+    self codeOn:aStream inBlock:b valueNeeded:true for:aCompiler
 !
 
 codeOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler
@@ -1328,6 +984,94 @@
     "Modified: 3.9.1995 / 12:55:42 / claus"
 !
 
+codeOrIfOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler
+    "generate code for (x or:[y]) ifxxx:[ ... ]"
+
+    |theByteCode optByteCode theReceiver theArg pos1 pos2 pos3 code here jmp|
+
+    theByteCode := #trueJump.
+    theReceiver := receiver receiver.
+
+    optByteCode := self optimizedConditionFor:theReceiver with:theByteCode.
+    optByteCode notNil ifTrue:[
+	((optByteCode == #eqJump) or:[optByteCode == #notEqJump]) ifTrue:[
+	    theArg := theReceiver arg1
+	].
+	theReceiver := theReceiver receiver.
+	theByteCode := optByteCode
+    ].
+    theReceiver codeOn:aStream inBlock:b for:aCompiler.
+    theArg notNil ifTrue:[
+	theArg codeOn:aStream inBlock:b for:aCompiler
+    ].
+    aStream nextPut:theByteCode.
+    pos1 := aStream position.
+    aStream nextPut:0.
+
+
+    theReceiver := receiver arg1.
+
+"new:"
+    (selector == #ifTrue:) ifTrue:[
+	theByteCode := #falseJump
+    ] ifFalse:[
+	theByteCode := #trueJump
+    ].
+    optByteCode := self optimizedConditionFor:theReceiver with:theByteCode.
+    optByteCode notNil ifTrue:[
+	theReceiver isBlock ifTrue:[
+	    theReceiver := theReceiver statements expression
+	].
+	((optByteCode == #eqJump) or:[optByteCode == #notEqJump]) ifTrue:[
+	    theArg := theReceiver arg1
+	].
+	theReceiver := theReceiver receiver.
+	theByteCode := optByteCode.
+
+	theReceiver codeOn:aStream inBlock:b for:aCompiler.
+	theArg notNil ifTrue:[
+	    theArg codeOn:aStream inBlock:b for:aCompiler
+	].
+	aStream nextPut:theByteCode.
+
+    ] ifFalse:[
+"org"
+	theReceiver codeInlineOn:aStream inBlock:b for:aCompiler.
+	(selector == #ifTrue:) ifTrue:[
+	    jmp := #falseJump
+	] ifFalse:[
+	    jmp := #trueJump
+	].
+	aStream nextPut:jmp
+    ].
+    pos2 := aStream position.
+    aStream nextPut:0.
+    (selector == #ifTrue:) ifTrue:[
+	(aStream contents) at:pos1 put:(aStream position)
+    ].
+    (argArray at: 1) codeInlineOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler.
+
+    code := aStream contents.
+    valueNeeded ifTrue:[
+	aStream nextPut:#jump.
+	pos3 := aStream position.
+	aStream nextPut:0.
+	here := aStream position.
+	(selector == #ifFalse:) ifTrue:[
+	    code at:pos1 put:here
+	].
+	code at:pos2 put:here.
+	aStream nextPut:#pushNil.
+	code at:pos3 put:(aStream position)
+    ] ifFalse:[
+	here := aStream position.
+	(selector == #ifFalse:) ifTrue:[
+	    code at:pos1 put:here
+	].
+	code at:pos2 put:here
+    ]
+!
+
 codeSendOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler
     "like code on, but assumes that receiver has already been
      coded onto stack - needed for cascade"
@@ -1441,85 +1185,342 @@
     aStream nextPut:code; nextPut:lineNr; nextPut:litIndex; nextPut:0; nextPut:nargs
 !
 
-codeForCascadeOn:aStream inBlock:b for:aCompiler
-    "like codeOn, but always leave the receiver instead of the result"
+codeTimesRepeatOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler
+    "generate code for n timesRepeat:[ ... ]"
+
+    |pos pos2 theReceiver|
+
+    theReceiver := receiver.
+    theReceiver codeOn:aStream inBlock:b for:aCompiler.
+    valueNeeded ifTrue:[aStream nextPut:#dup].
 
-    |nargs isBuiltIn code litIndex|
+    pos := aStream position.
+"/    aStream nextPut:#dup; nextPut:#push0; nextPut:#>; nextPut:lineNr; nextPut:#falseJump.
+"/    aStream nextPut:#dup; nextPut:#gt0; nextPut:lineNr; nextPut:#falseJump.
+    aStream nextPut:#pushgt0; nextPut:lineNr; nextPut:#falseJump.
+    pos2 := aStream position.
+    aStream nextPut:0.
+
+    (argArray at:1) codeInlineOn:aStream inBlock:b valueNeeded:false for:aCompiler.
+    aStream nextPut:#minus1; nextPut:lineNr; nextPut:#jump; nextPut:pos.
+
+    (aStream contents) at:pos2 put:(aStream position).
+    aStream nextPut:#drop.
+!
+
+codeWhileOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler
+    "generate code for [...] whilexxx:[ ... ]"
+
+    |pos pos2 theReceiver theArg theByteCode optByteCode|
 
-    argArray isNil ifTrue:[
-	nargs := 0
+    (selector == #whileTrue:) ifTrue:[
+	theByteCode := #falseJump
     ] ifFalse:[
-	nargs := argArray size
+	theByteCode := #trueJump
+    ].
+
+    theReceiver := receiver.
+    optByteCode := self optimizedConditionFor:theReceiver with:theByteCode.
+    optByteCode notNil ifTrue:[
+	((optByteCode == #eqJump) or:[optByteCode == #notEqJump]) ifTrue:[
+	    theArg := receiver statements expression arg1
+	].
+	theReceiver := receiver statements expression receiver.
+	theByteCode := optByteCode
+    ].
+
+"/ OLD:
+"/    valueNeeded ifTrue:[aStream nextPut:#pushNil].
+"/
+    pos := aStream position.
+    optByteCode notNil ifTrue:[
+	theReceiver codeOn:aStream inBlock:b for:aCompiler.
+	theArg notNil ifTrue:[
+	    theArg codeOn:aStream inBlock:b for:aCompiler
+	]
+    ] ifFalse:[
+	theReceiver codeInlineOn:aStream inBlock:b for:aCompiler
+    ].
+
+    (lineNr between:1 and:255) ifTrue:[
+	aStream nextPut:#lineno; nextPut:lineNr.
     ].
 
-    isBuiltIn := false.
+    aStream nextPut:theByteCode.
+    pos2 := aStream position.
+    aStream nextPut:0.
+"/ OLD:
+"/    valueNeeded ifTrue:[aStream nextPut:#drop].
+"/
+"/ OLD:
+"/    (argArray at:1) codeInlineOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler.
+"/ NEW:
+    (argArray at:1) codeInlineOn:aStream inBlock:b valueNeeded:false for:aCompiler.
+    aStream nextPut:#jump; nextPut:pos.
+    (aStream contents) at:pos2 put:(aStream position).
+"/ NEW:
+    valueNeeded ifTrue:[aStream nextPut:#pushNil].
+!
+
+optimizedConditionFor:aReceiver with:aByteCode
+    |rec sel|
 
-    (nargs == 0) ifTrue:[
-	isBuiltIn := self class isBuiltInUnarySelector:selector
+    rec := aReceiver.
+    (rec isBlock) ifTrue:[
+	rec statements nextStatement isNil ifTrue:[
+	    rec := rec statements expression
+	]
+    ].
+    (rec isUnaryMessage) ifTrue:[
+	sel := rec selector.
+	(sel == #isNil) ifTrue:[
+	    "/
+	    "/ isNil trueJmp  -> nilJump
+	    "/ isNil falseJmp -> notNilJump
+	    "/
+	    (aByteCode == #trueJump) ifTrue:[^ #nilJump].
+	    (aByteCode == #falseJump) ifTrue:[^ #notNilJump]
+	].
+	(sel == #notNil) ifTrue:[
+	    "/
+	    "/ notNil trueJmp  -> notNilJump
+	    "/ notNil falseJmp -> nilJump
+	    "/
+	    (aByteCode == #trueJump) ifTrue:[^ #notNilJump].
+	    (aByteCode == #falseJump) ifTrue:[^ #nilJump]
+	].
+	(sel == #not) ifTrue:[
+	    "/
+	    "/ not trueJmp  -> falseJump
+	    "/ not falseJmp -> trueJump
+	    "/
+	    (aByteCode == #trueJump) ifTrue:[^ #falseJump].
+	    (aByteCode == #falseJump) ifTrue:[^ #trueJump]
+	].
+	^ nil
     ].
+    (rec isBinaryMessage) ifTrue:[
+	sel := rec selector.
+	rec arg1 isConstant ifTrue:[
+	    (rec arg1 value == 0) ifTrue:[
+		"/
+		"/ ==0 trueJmp  -> zeroJump
+		"/ ==0 falseJmp -> notZeroJump
+		"/
+		(sel == #==) ifTrue:[
+		    (aByteCode == #trueJump) ifTrue:[^ #zeroJump].
+		    (aByteCode == #falseJump) ifTrue:[^ #notZeroJump]
+		].
+		"/
+		"/ ~~0 trueJmp  -> notZeroJump
+		"/ ~~0 falseJmp -> zeroJump
+		"/
+		(sel == #~~) ifTrue:[
+		    (aByteCode == #falseJump) ifTrue:[^ #zeroJump].
+		    (aByteCode == #trueJump) ifTrue:[^ #notZeroJump]
+		].
+		^ nil
+	    ]
+	].
+	(sel == #==) ifTrue:[
+	    "/
+	    "/ == trueJmp  -> eqJump
+	    "/ == falseJmp -> notEqJump
+	    "/
+	    (aByteCode == #trueJump) ifTrue:[^ #eqJump].
+	    (aByteCode == #falseJump) ifTrue:[^ #notEqJump]
+	].
+	(sel == #~~) ifTrue:[
+	    "/
+	    "/ ~~ trueJmp  -> notEqJump
+	    "/ ~~ falseJmp -> eqJump
+	    "/
+	    (aByteCode == #falseJump) ifTrue:[^ #eqJump].
+	    (aByteCode == #trueJump) ifTrue:[^ #notEqJump]
+	]
+    ].
+    ^ nil
+! !
+
+!MessageNode methodsFor:'evaluating'!
+
+evaluate
+    |r nargs argValueArray class|
+
+    receiver isSuper ifTrue:[
+	r := receiver value.
+	receiver isHere ifTrue:[
+	    class := receiver definingClass.
+	] ifFalse:[
+	    class := receiver definingClass superclass.
+	].
+	argArray notNil ifTrue:[
+	    argValueArray := argArray collect:[:arg | arg evaluate].
+	] ifFalse:[
+	    argValueArray := #()
+	].
+	^ r perform:selector inClass:class withArguments:argValueArray
+    ].
+
+
+    argArray isNil ifTrue:[
+	^ (receiver evaluate) perform:selector
+    ].
+    nargs := argArray size.
     (nargs == 1) ifTrue:[
-	isBuiltIn := self class isBuiltIn1ArgSelector:selector
+	^ (receiver evaluate) perform:selector with:(argArray at:1) evaluate
     ].
     (nargs == 2) ifTrue:[
-	isBuiltIn := self class isBuiltIn2ArgSelector:selector
+	^ (receiver evaluate) perform:selector
+				 with:(argArray at:1) evaluate
+				 with:(argArray at:2) evaluate
+    ].
+    (nargs == 3) ifTrue:[
+	^ (receiver evaluate) perform:selector
+				 with:(argArray at:1) evaluate
+				 with:(argArray at:2) evaluate
+				 with:(argArray at:3) evaluate
+    ].
+    r := receiver evaluate.
+    argValueArray := argArray collect:[:arg | arg evaluate].
+    ^ r perform:selector withArguments:argValueArray
+!
+
+evaluateForCascade
+    |r nargs argValueArray class|
+
+    receiver isSuper ifTrue:[
+	r := receiver value.
+	class := receiver definingClass.
+	receiver isHere ifFalse:[
+	    class := class superclass.
+	].
+	argArray notNil ifTrue:[
+	    argValueArray := argArray collect:[:arg | arg evaluate].
+	] ifFalse:[
+	    argValueArray := #()
+	].
+	r perform:selector inClass:class withArguments:argValueArray.
+	^ r
     ].
 
-    receiver codeOn:aStream inBlock:b for:aCompiler.
-    aStream nextPut:#dup.
+    r := receiver evaluate.
+    argArray isNil ifTrue:[
+	r perform:selector.
+	^ r
+    ].
+    nargs := argArray size.
+    (nargs == 1) ifTrue:[
+	r perform:selector with:(argArray at:1) evaluate.
+	^ r
+    ].
+    (nargs == 2) ifTrue:[
+	r perform:selector with:(argArray at:1) evaluate
+			   with:(argArray at:2) evaluate.
+	^ r
+    ].
+    (nargs == 3) ifTrue:[
+	r perform:selector with:(argArray at:1) evaluate
+			   with:(argArray at:2) evaluate
+			   with:(argArray at:3) evaluate.
+	^ r
+    ].
+    argValueArray := argArray collect:[:arg | arg evaluate].
+    r perform:selector withArguments:argValueArray.
+    ^ r
+! !
+
+!MessageNode methodsFor:'printing'!
+
+printOn:aStream indent:i
+    |needParen selectorParts index index2 arg|
+
+    (#(whileTrue: whileFalse:) includes:selector) ifTrue:[
+	receiver isBlock ifTrue:[
+	    ^ self printWhileOn:aStream indent:i
+	].
+    ].
 
-    "can we use a send-bytecode ?"
-    isBuiltIn ifTrue:[
-	receiver isSuper ifFalse:[
-	    (nargs > 0) ifTrue:[
-		(argArray at:1) codeOn:aStream inBlock:b for:aCompiler.
-		(nargs > 1) ifTrue:[
-		    (argArray at:2) codeOn:aStream inBlock:b for:aCompiler
+    index := 1.
+    selectorParts := OrderedCollection new.
+    [index == 0] whileFalse:[
+	index2 := selector indexOf:$: startingAt:index.
+	index2 ~~ 0 ifTrue:[
+	    selectorParts add:(selector copyFrom:index to:index2).
+	    index2 := index2 + 1
+	].
+	index := index2
+    ].
+
+    needParen := false.
+    receiver isMessage ifTrue:[
+	receiver isUnaryMessage ifFalse:[
+	    receiver isBinaryMessage ifFalse:[
+		needParen := true
+	    ].
+	].
+    ].
+    needParen ifTrue:[
+	aStream nextPutAll:'('
+    ].
+    receiver printOn:aStream indent:i.
+    needParen ifTrue:[
+	aStream nextPutAll:')'
+    ].
+
+    1 to:(argArray size) do:[:argIndex |
+	aStream space.
+	(selectorParts at:argIndex) printOn:aStream.
+	aStream space.
+	arg := argArray at:argIndex.
+	needParen := false.
+	arg isMessage ifTrue:[
+	    arg isBinaryMessage ifFalse:[
+		arg isUnaryMessage ifFalse:[
+		    needParen := true
 		]
 	    ].
-	    aStream nextPut:selector.
-	    (self class hasLineNumber:selector) ifTrue:[
-		aStream nextPut:lineNr.
-	    ].
-	    aStream nextPut:#drop.
-	    ^ self
-	]
-    ].
+	].
+	needParen ifTrue:[
+	    aStream nextPutAll:'('
+	].
+	arg printOn:aStream indent:i.
+	needParen ifTrue:[
+	    aStream nextPutAll:') '
+	].
+    ]
+!
+
+printWhileOn:aStream indent:i
+    |needParen arg|
 
-    "no - generate a send"
-    argArray notNil ifTrue:[
-	argArray do:[:arg |
-	    arg codeOn:aStream inBlock:b for:aCompiler
-	]
+    "special handling of whileTrue/whileFalse"
+
+    aStream nextPutAll:'['.
+    receiver statements printOn:aStream indent:i.
+    aStream nextPutAll:'] whileTrue: '.
+
+    arg := argArray at:1.
+    needParen := false.
+    arg isMessage ifTrue:[
+	arg isBinaryMessage ifFalse:[
+	    arg isUnaryMessage ifFalse:[
+		needParen := true
+	    ]
+	].
     ].
-    litIndex := aCompiler addLiteral:selector.
-    litIndex <= 255 ifTrue:[
-	receiver isSuper ifTrue:[
-	    receiver isHere ifTrue:[
-		code := #hereSend
-	    ] ifFalse:[
-		code := #superSend.
-	    ].
-	    aStream nextPut:code; nextPut:lineNr; nextPut:litIndex; nextPut:nargs; nextPut:nil; nextPut:#drop.
-	    ^ self
-	].
-	(nargs <= 3) ifTrue:[
-	    code := #(sendDrop0 sendDrop1 sendDrop2 sendDrop3) at:(nargs+1).
-	    aStream nextPut:code; nextPut:lineNr; nextPut:litIndex.
-	    ^ self
-	].
+    needParen ifTrue:[
+	aStream nextPutAll:'('
+    ].
+    arg printOn:aStream indent:i.
+    needParen ifTrue:[
+	aStream nextPutAll:') '
+    ].
+! !
 
-	aStream nextPut:#sendDrop; nextPut:lineNr; nextPut:litIndex; nextPut:nargs.
-	^ self
-    ].
-    "need 16bit litIndex"
-    receiver isSuper ifTrue:[
-	receiver isHere ifTrue:[
-	    code := #hereSendL
-	] ifFalse:[
-	    code := #superSendL.
-	].
-	aStream nextPut:code; nextPut:lineNr; nextPut:litIndex; nextPut:0; nextPut:nargs; nextPut:nil; nextPut:#drop.
-	^ self
-    ].
-    aStream nextPut:#sendDropL; nextPut:lineNr; nextPut:litIndex; nextPut:0; nextPut:nargs
+!MessageNode methodsFor:'queries'!
+
+isMessage
+    ^ true
 ! !
+