Add generic label mechanism
[conkeror.git] / modules / coroutine.js
blob456ca80bd30382a17bca3f24e1955f5f15bfa9c5
1 /**
2 * (C) Copyright 2008 Jeremy Maitin-Shepard
4 * Use, modification, and distribution are subject to the terms specified in the
5 * COPYING file.
6 **/
8 function _return_value(x) {
9 this.value = x;
12 function co_return(x) {
13 return new _return_value(x);
16 const CONTINUATION = { toString: function () "[object CONTINUATION]" };
17 const SUSPEND = { toString: function () "[object SUSPEND]" };
19 function is_coroutine(obj) {
20 return obj != null &&
21 typeof(obj) == "object" &&
22 typeof(obj.next) == "function" &&
23 typeof(obj.send) == "function";
26 function _do_call(f) {
27 var cc = yield;
29 var stack = [];
30 var y = undefined;
31 var throw_value = false;
32 while (true) {
33 try {
34 let x;
35 if (throw_value) {
36 throw_value = false;
37 x = f.throw(y);
39 else
40 x = f.send(y);
42 if (x == CONTINUATION) {
43 y = cc;
44 continue;
47 if (x === SUSPEND) {
48 try {
49 x = yield;
50 y = x;
51 } catch (e) {
52 throw_value = true;
53 y = e;
55 continue;
58 if (is_coroutine(x))
60 stack[stack.length] = f;
61 f = x;
62 y = undefined;
63 continue;
66 if (x instanceof _return_value) {
67 if (stack.length == 0)
68 return;
69 f.close();
70 f = stack[stack.length - 1];
71 stack.length--;
72 y = x.value;
73 continue;
76 // Just return the value back to the function
77 y = x;
78 } catch (e) {
79 if (stack.length == 0)
80 return;
81 f = stack[stack.length - 1];
82 stack.length--;
83 if (e instanceof StopIteration)
84 y = undefined;
85 else {
86 y = e;
87 throw_value = true;
93 function co_call(f) {
94 if (!is_coroutine(f))
95 return;
96 var g = _do_call(f);
97 g.next();
98 var cc = function (x) {
99 try {
100 g.send(x);
101 } catch (e if e instanceof StopIteration) {}
102 catch (e) {
103 // Dump this error, because it indicates a programming error
104 dump_error(e);
107 cc.throw = function (x) {
108 try {
109 g.throw(x);
110 } catch (e if e instanceof StopIteration) {}
111 catch (e) {
112 // Dump this error, because it indicates a programming error
113 dump_error(e);
116 try {
117 g.send(cc);
118 } catch (e if e instanceof StopIteration) {}
119 catch (e) {
120 // Dump this error, because it indicates a programming error
121 dump_error(e);
123 return cc;