about summary refs log tree commit diff stats
path: root/048continuation.cc
blob: 80c9293d8302605297ab0066e969dfe31b2c20a3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
//: Continuations are a powerful primitive for constructing advanced kinds of
//: control *policies* like back-tracking. They're usually provided using a
//: primitive called 'call-cc': http://en.wikipedia.org/wiki/Call-with-current-continuation)
//: But in mu 'call-cc' is constructed out of a combination of two primitives:
//:   'current-continuation', which returns a continuation, and
//:   'continue-from', which takes a continuation to switch to.

//: todo: implement continuations in mu's memory
:(before "End Globals")
map<index_t, call_stack> Continuation;
index_t Next_continuation_id = 0;
:(before "End Setup")
Continuation.clear();
Next_continuation_id = 0;

:(before "End Mu Types Initialization")
type_number continuation = Type_number["continuation"] = Next_type_number++;
Type[continuation].name = "continuation";

:(before "End Primitive Recipe Declarations")
CURRENT_CONTINUATION,
:(before "End Primitive Recipe Numbers")
Recipe_number["current-continuation"] = CURRENT_CONTINUATION;
:(before "End Primitive Recipe Implementations")
case CURRENT_CONTINUATION: {
  Continuation[Next_continuation_id] = Current_routine->calls;  // deep copy because calls have no pointers
  products.resize(1);
  products.at(0).push_back(Next_continuation_id);
  ++Next_continuation_id;
  break;
}

:(before "End Primitive Recipe Declarations")
CONTINUE_FROM,
:(before "End Primitive Recipe Numbers")
Recipe_number["continue-from"] = CONTINUE_FROM;
:(before "End Primitive Recipe Implementations")
case CONTINUE_FROM: {
  assert(ingredients.at(0).size() == 1);  // scalar
  index_t c = ingredients.at(0).at(0);
  Current_routine->calls = Continuation[c];  // deep copy because calls have no pointers
  // refresh instruction_counter to next instruction after current-continuation
  instruction_counter = current_step_index()+1;
  continue;  // skip the rest of this instruction
}

:(scenario continuation)
# simulate a loop using continuations
recipe main [
  1:number <- copy 0:literal
  2:continuation <- current-continuation
  {
#?     $print 1:number
    3:boolean <- greater-or-equal 1:number, 3:literal
    break-if 3:boolean
    1:number <- add 1:number, 1:literal
    continue-from 2:continuation  # loop
  }
]
+mem: storing 1 in location 1
+mem: storing 2 in location 1
+mem: storing 3 in location 1
-mem: storing 4 in location 1

:(scenario continuation_inside_caller)
recipe main [
  1:number <- copy 0:literal
  2:continuation <- loop-body
  {
    3:boolean <- greater-or-equal 1:number, 3:literal
    break-if 3:boolean
    continue-from 2:continuation  # loop
  }
]

recipe loop-body [
  4:continuation <- current-continuation
  1:number <- add 1:number, 1:literal
]
+mem: storing 1 in location 1
+mem: storing 2 in location 1
+mem: storing 3 in location 1
-mem: storing 4 in location 1