guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] 53/99: Implement Winding & Unwinding


From: Christopher Allan Webber
Subject: [Guile-commits] 53/99: Implement Winding & Unwinding
Date: Sun, 10 Oct 2021 21:50:59 -0400 (EDT)

cwebber pushed a commit to branch compile-to-js-merge
in repository guile.

commit 479294fc056b5c0e8cb0ca20a1bdf760f02898fb
Author: Ian Price <ianprice90@googlemail.com>
AuthorDate: Wed Jun 28 15:03:03 2017 +0100

    Implement Winding & Unwinding
    
    * module/language/js-il/runtime.js
      (wind, unwind): Implement.
      (callcc): Wind when invoking continuation.
---
 module/language/js-il/runtime.js | 71 ++++++++++++++++++++++++++++++++++++----
 1 file changed, 65 insertions(+), 6 deletions(-)

diff --git a/module/language/js-il/runtime.js b/module/language/js-il/runtime.js
index 5a2afa2..5fc10c2 100644
--- a/module/language/js-il/runtime.js
+++ b/module/language/js-il/runtime.js
@@ -380,7 +380,7 @@ var abort_to_prompt = function(self, k, prompt) {
         kont = new scheme.Closure(f, 0);
     };
 
-    unwind(idx);
+    unwind(scheme.dynstack, idx); // FIXME:
 
     var handler = frame.handler;
     args.unshift(kont);
@@ -396,8 +396,17 @@ var call_with_values = function (self, k, producer, 
consumer) {
 };
 
 var callcc = function (self, k, closure) {
+    var dynstack = scheme.dynstack.slice();
+
     var f = function (self, k2) {
         var args = Array.prototype.slice.call(arguments, 2);
+
+        var i = shared_stack_length(dynstack, scheme.dynstack);
+
+        unwind(scheme.dynstack, i);
+        wind(dynstack, i);
+        scheme.dynstack = dynstack;
+
         return k.apply(k,args);
     };
     return closure.fun(closure, k, new scheme.Closure(f, 0));
@@ -461,8 +470,17 @@ scheme.primitives["fluid-ref"] = function (fluid) {
 scheme.primitives["variable?"] = not_implemented_yet;
 
 // Dynamic Wind
-scheme.primitives["wind"] = not_implemented_yet;
-scheme.primitives["unwind"] = not_implemented_yet;
+scheme.primitives["wind"] = function(enter, leave) {
+    var frame = new scheme.frame.DynWind(enter, leave);
+    scheme.dynstack.unshift(frame);
+};
+
+scheme.primitives["unwind"] = function () {
+    var frame = scheme.dynstack.shift();
+    if (!(frame instanceof scheme.frame.DynWind)) {
+        throw "not a dynamic wind frame";
+    };
+};
 
 // Misc
 scheme.primitives["prompt"] = function(escape_only, tag, handler){
@@ -470,9 +488,45 @@ scheme.primitives["prompt"] = function(escape_only, tag, 
handler){
     scheme.dynstack.unshift(frame);
 };
 
-var unwind = function (idx) {
-    // TODO: call winders
-    scheme.dynstack = scheme.dynstack.slice(idx+1);
+var shared_stack_length = function (dynstack1, dynstack2) {
+    // Assumes that if it matches at i then it matches for all x<i,
+    // which will be fine given that we don't reuse frames
+    var size1 = dynstack1.length;
+    var size2 = dynstack2.length;
+    var last = Math.min(size1, size2);
+
+    var i = last-1;
+    for (; i >= 0; i--) {
+        if (dynstack1[i] === dynstack2[i]) {
+            break;
+        }
+    };
+
+    return i + 1;
+};
+
+var wind = function (dynstack, idx) {
+    for (var i = idx; i < dynstack.length; i++) {
+        var frame = dynstack[i];
+        if (frame instanceof scheme.frame.DynWind) {
+            // TODO: how to handle continuations and errors in this?
+            frame.wind.fun(frame.wind, scheme.initial_cont);
+        } else {
+            throw "unsupported frame type -- wind";
+        }
+    }
+};
+
+var unwind = function (dynstack, idx) {
+    for (var i = dynstack.length - 1; i >= idx; i--) {
+        var frame = dynstack[i];
+        if (frame instanceof scheme.frame.DynWind) {
+            // TODO: how to handle continuations and errors in this?
+            frame.unwind.fun(frame.unwind, scheme.initial_cont);
+        } else {
+            throw "unsupported frame type -- unwind";
+        }
+    }
 };
 
 var find_prompt = function(prompt) {
@@ -509,6 +563,11 @@ scheme.frame.Fluid = function(fluid, old_value) {
     this.old_value = old_value;
 };
 
+scheme.frame.DynWind = function(wind, unwind) {
+    this.wind = wind;
+    this.unwind = unwind;
+};
+
 // Module Cache
 scheme.module_cache["guile"] = scheme.env;
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]