about summary refs log tree commit diff stats
path: root/cpp/012run
blob: 3f02c7b9653e15ba1e118e70fee7a28833262716 (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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
:(scenarios run)
:(scenario copy_literal)
recipe main [
  1:integer <- copy 23:literal
]
+run: instruction main/0
+run: ingredient 0 is 23
+mem: storing in location 1

:(scenario copy)
recipe main [
  1:integer <- copy 23:literal
  2:integer <- copy 1:integer
]
+run: instruction main/1
+run: ingredient 0 is 1
+mem: location 1 is 23
+mem: storing in location 2

:(before "End Types")
// Each recipe can be 'called' many many times in a program. Each call needs a
// little extra information. TODO: move this into the call layer somehow
struct call {
  recipe_number running_recipe;
  size_t pc;
  // End Call Fields
  call(recipe_number r) :running_recipe(r), pc(0) {}
};
typedef stack<call> call_stack;

// TODO: move this into the scheduler layer somehow
struct routine {
  size_t alloc;
  size_t alloc_max;
  call_stack calls;
  size_t limit;
  size_t running_since;
  // todo: sleep conditions
};

:(code)
void run(string form) {
  run(add_recipes(form));
}

void run(recipe_number r) {
  routine rr;
  rr.calls.push(call(r));
  run(rr);
}

void run(routine rr) {
  while (!rr.calls.empty()) {
    vector<instruction>& instructions = Recipe[rr.calls.top().running_recipe].steps;
    // TODO: move this into the call layer somehow
    while (rr.calls.top().pc >= instructions.size()) {
      rr.calls.pop();
      if (rr.calls.empty()) return;
      // todo: no results returned warning
      ++rr.calls.top().pc;
    }
    size_t& pc = rr.calls.top().pc;
    trace("run") << "instruction " << Recipe[rr.calls.top().running_recipe].name << '/' << pc;
    switch (instructions[pc].operation) {
      // Primitive Recipe Implementations.
      case COPY: {
        trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name;
        vector<int> data = read_memory(instructions[pc].ingredients[0]);
        write_memory(instructions[pc].products[0], data);
        break;
      }
      // End Primitive Recipe Implementations.
      default: {
        cout << "not a primitive op: " << instructions[pc].operation << '\n';
      }
    }
    ++pc;
  }
}

:(before "End Main")
if (argc > 1) {
  setup();
  for (int i = 1; i < argc; ++i) {
    ifstream fin(argv[i]);
    while (!fin.eof()) add_recipe(fin);
    fin.close();
  }

  recipe_number r = Recipe_number[string("main")];
  if (r) run(r);
  dump_memory();
}

:(code)
vector<int> read_memory(reagent x) {
//?   cout << "read_memory: " << x.to_string() << '\n'; //? 1
  vector<int> result;
  if (x.types[0] == 0) {  // literal
    result.push_back(to_int(x.name));
    return result;
  }
  int base = to_int(x.name);
  for (size_t offset = 0; offset < Type[x.types[0]].size; ++offset) {
    int val = Memory[base+offset];
    trace("mem") << "location " << base+offset << " is " << val;
    result.push_back(val);
  }
  return result;
}

void write_memory(reagent x, vector<int> data) {
  int base = to_int(x.name);
  size_t size = size_of(x);
  if (size != data.size()) raise << "size mismatch in storing to " << x.to_string();
  for (size_t offset = 0; offset < size; ++offset) {
    trace("mem") << "storing in location " << base+offset;
    Memory[base+offset] = data[offset];
  }
}

:(code)
int to_int(string n) {
  char* end = NULL;
  int result = strtol(n.c_str(), &end, /*any base*/0);
  assert(*end == '\0');
  return result;
}

size_t size_of(reagent r) {
  type_info t = Type[r.types[0]];
  if (!t.is_record && !t.is_array) return t.size;
  return t.size;  // TODO
}