'From Squeak 1.21 of July 17, 1997 on 5 August 1997 at 6:02:56 pm'! "Change Set: continuations Date: 5 August 1997 Author: Ian Piumarta A simple implementation of continuations for Squeak"! Object subclass: #Continuation instanceVariableNames: 'stack ' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Methods'! !Continuation methodsFor: 'private'! stack ^stack! ! !Continuation methodsFor: 'private'! stack: s stack := s! ! !Continuation methodsFor: 'invocation'! oneShotValue thisContext sender: stack. ^nil! ! !Continuation methodsFor: 'invocation'! oneShotValue: v "escape to the original continuation with v as the result, discarding the stack on the way" thisContext sender: stack. ^v! ! !Continuation methodsFor: 'invocation'! value thisContext sender: stack copyStack. ^nil! ! !Continuation methodsFor: 'invocation' stamp: 'ikp 8/5/97 17:56'! value: v "return to the original continuation, copying the stack to allow another activation" thisContext swapSender: stack copyStack. ^v! ! !Continuation methodsFor: 'invocation'! valueWithArguments: v "with one argument, just invoke the usual value mechanism" v size == 1 ifFalse: [^self error: 'continuations can only be resumed with one argument']. ^self value: (v at: 1)! ! !Continuation class methodsFor: 'instance creation'! fromContext: aStack ^super new stack: aStack copyStack! ! !Continuation class methodsFor: 'examples' stamp: 'ikp 8/5/97 17:52'! factorialExample: x "Modified from the example given in Dybvig p. 81 (the example is explained adequately there). Evaluate each of the following expressions in turn (and be prepared for a slight surprise in the current selection!!). Undeclared is used to hold a `global' temporary to avoid cluttering your namespace." "Transcript cr; show: (Continuation factorialExample: 4) printString; cr" "(Undeclared at: #RetryCC) value: 2" "(Undeclared at: #RetryCC) value: 5" "Undeclared removeKey: #RetryCC" ^x == 0 ifTrue: [ [:continuation | Undeclared at: #RetryCC put: continuation. 1] callCC] ifFalse: [x * (self factorialExample: x - 1)]! ! !InstructionStream methodsFor: 'private' stamp: 'ikp 8/5/97 18:00'! setSender: aContext sender _ aContext! ! !ContextPart methodsFor: 'copying' stamp: 'ikp 8/5/97 18:00'! copyStack ^sender == nil ifTrue: [self copy] ifFalse: [self copy setSender: sender copyStack]! ! !BlockContext methodsFor: 'continuations'! callCC ^self value: (Continuation fromContext: thisContext sender)! !