RE: [Sablevm-developer] Continuations (Part 1)
Brought to you by:
egagnon
From: Brent F. <bre...@xp...> - 2000-07-20 21:15:19
|
> In fact, can you write for me a simple example that requires > continuation? > Here goes: I took this example from http://www.nightmare.com/schintro-v14/schintro_127.html which I need to read through -- it seems to have lots of useful information. ------------------------------------------- (define some-flag #t) (define (my-abortable-proc escape-proc) (display "in my-abortable-proc") (if some-flag (escape-proc "ABORTED")) (display "still in my-abortable-proc") "NOT ABORTED") (define (my-resumable-proc) (do-something) (display (call-with-current-continuation my-abortable-proc)) (do-some-more)) (define (do-something) (display "Doing something.")) (define (do-some-more) (display "Doing some more.")) (my-resumable-proc) ------------------------------------------------- The result of this is: Doing something. in my-abortable-proc still in my-abortable-proc ABORTED Doing some more. The "ABORTED" shows that the call-with-current-continuation was used to jump back to its calling point. A neat Scheme-on-java implementation (SILK) http://www.cs.brandeis.edu/silk/silkweb/doc/resources/HOWTO.html#class allows you to compile Scheme to Java. Running this test.scm through that yields this: ------------------------------------------------------------------ // no package name; /** * this file is automatically generated by the silk->javac compiler Compiler.scm. * Modify at your own risk! */ import silk.*; import java.lang.reflect.*; import java.util.*; public class test extends silk.Procedure implements silk.Function, Runnable { public int whichcode=0; // corresponds to a numbering of the toplevel procedures of the program public int whichtype=0; // 0 = user defined procedure, 1 = java literal public static final int USER_DEF=0, JAVA_LIT=1; public Pair frame; public test() { super();} public test(int t, int n, Pair f) { whichtype = t; whichcode = n; frame = f; } private Boolean addImport(String s) { silk.Import.addImport(s); return Boolean.TRUE; } public void run() { this.invoke(null); } public Object apply(Object[] args) { return invoke((Pair)args[0]); } public Object apply(Pair args) { return invoke(args); } public Object invoke(Pair args) { return LCO.eval(invoke1(args)); } static Object tmp; public static void load() { new test().init(); } public static void load(String shellArgs[]) { silk.Symbol.intern("shellArgs").setGlobalValue(shellArgs); load(); } public static void main(String shellArgs[]) { Symbol main = silk.Symbol.intern("main"); load(shellArgs); if (main.isDefined()) ((silk.Procedure) main.getGlobalValue()).apply(new Pair(shellArgs,Pair.EMPTY)); } public Object invoke1(Pair args) { if (whichtype == USER_DEF) { switch (whichcode) { case 0: return(_L0(args)); case 1: return(_L1(args)); case 2: return(_L2(args)); case 3: return(_L3(args)); default: System.exit(0); break; }} else { switch (whichcode) { default: System.exit(0); break; }} return null; } public void init() { Pair Args = null; Symbol.intern("this").setGlobalValue(this); Class _p = Primitive.class; // this loads the primitives Symbol.intern("some-flag").setGlobalValue(_C0); Symbol.intern("my-abortable-proc").setGlobalValue(new test(USER_DEF, 0, new Pair( Args, this.frame))); Symbol.intern("my-resumable-proc").setGlobalValue(new test(USER_DEF, 1, new Pair( Args, this.frame))); Symbol.intern("do-something").setGlobalValue(new test(USER_DEF, 2, new Pair( Args, this.frame))); Symbol.intern("do-some-more").setGlobalValue(new test(USER_DEF, 3, new Pair( Args, this.frame))); ((silk.Procedure) ((Symbol)my_45_resumable_45_proc).getGlobalValue()).apply(Pair.EMPTY); } // definitions of global variables public static Object some_45_flag = Symbol.intern("some-flag"); public static Object my_45_abortable_45_proc = Symbol.intern("my-abortable-proc"); public static Object my_45_resumable_45_proc = Symbol.intern("my-resumable-proc"); // definitions of Scheme variables defined externally static Object display= Symbol.intern("display"); static Object do_45_something= Symbol.intern("do-something"); static Object call_45_with_45_current_45_continuation= Symbol.intern("call-with-current-continuation"); static Object do_45_some_45_more= Symbol.intern("do-some-more"); // definitions of quoted terms static Object _C0=Boolean.FALSE; static Object _C1="in my-abortable-proc"; static Object _C2="ABORTED"; static Object _C3=Boolean.TRUE; static Object _C4="still in my-abortable-proc"; static Object _C5="NOT ABORTED"; static Object _C6="Doing something."; static Object _C7="Doing some more."; // definitions of embedded lambdas Object _L0(Pair Args){ Object tmp; tmp = ((silk.Procedure) ((Symbol)display).getGlobalValue()).apply(new Pair(_C1, Pair.EMPTY)); tmp = (Boolean.FALSE.equals(((Symbol)some_45_flag).getGlobalValue()) ? _C3 : ((silk.Procedure) (( Pair) Args).getEltNover2(1)).apply(new Pair(_C2, Pair.EMPTY)) ); tmp = ((silk.Procedure) ((Symbol)display).getGlobalValue()).apply(new Pair(_C4, Pair.EMPTY)); tmp = _C5; return tmp; } Object _L1(Pair Args){ Object tmp; tmp = ((silk.Procedure) ((Symbol)do_45_something).getGlobalValue()).apply(Pair.EMPTY); tmp = ((silk.Procedure) ((Symbol)display).getGlobalValue()).apply(new Pair(((silk.Procedure) ((Symbol)call_45_with_45_current_45_continuation).getGlobalValue()).apply(ne w Pair(((Symbol)my_45_abortable_45_proc).getGlobalValue(), Pair.EMPTY)), Pair.EMPTY)); tmp = new LCO(((Symbol)do_45_some_45_more).getGlobalValue(),Pair.EMPTY); return tmp; } Object _L2(Pair Args){ Object tmp; tmp = new LCO(((Symbol)display).getGlobalValue(),new Pair(_C6, Pair.EMPTY)); return tmp; } Object _L3(Pair Args){ Object tmp; tmp = new LCO(((Symbol)display).getGlobalValue(),new Pair(_C7, Pair.EMPTY)); return tmp; } ------------------------------- This class obviously relies on the Silk interpreter code. I tried creating a stand-alone version (in a *.class file) under Kawa, but couldn't get it to work right under Windows (damn pathnames!). Thanks, -Brent |