about summary refs log tree commit diff stats
path: root/cpp/012run
blob: f4dd6390eeb852c3883fc83bfe30810bb74a97e5 (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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
:(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")
// Book-keeping while running a recipe.
//: Later layers will change this.
struct routine {
  recipe_number running_recipe;
  size_t running_at;
  routine(recipe_number r) :running_recipe(r), running_at(0) {}
};

:(code)
void run(recipe_number r) {
  run(routine(r));
}

void run(routine rr) {
  while (!done(rr)) {
    vector<instruction>& instructions = steps(rr);
    size_t& pc = running_at(rr);
    // Running one instruction.
    if (instructions[pc].is_label) { ++pc; continue; }
    trace("run") << "instruction " << recipe_name(rr) << '/' << 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;
  }
}

//: Some helpers.
//: We'll need to override these later as we change the definition of routine.
//: Important that they return referrences into the routine.
inline size_t& running_at(routine& rr) {
  return rr.running_at;
}

inline string recipe_name(routine& rr) {
  return Recipe[rr.running_recipe].name;
}

inline vector<instruction>& steps(routine& rr) {
  return Recipe[rr.running_recipe].steps;
}

inline bool done(routine& rr) {
  return running_at(rr) >= steps(rr).size();
}

:(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();
}

//: helper for tests

:(before "End Globals")
// track recipes added so that we can cleanup after each test
vector<recipe_number> recipes_added_by_test;

:(code)
void run(string form) {
  vector<recipe_number> tmp = add_recipes(form);
  recipes_added_by_test.insert(recipes_added_by_test.end(), tmp.begin(), tmp.end());
  run(recipes_added_by_test.front());
}

:(before "End Setup")
for (size_t i = 0; i < recipes_added_by_test.size(); ++i) {
  Recipe_number.erase(Recipe[recipes_added_by_test[i]].name);
  Recipe.erase(recipes_added_by_test[i]);
}
recipes_added_by_test.clear();

:(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(x.value);
    return result;
  }
  int base = x.value;
  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)
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
}

:(scenario run_label)
recipe main [
  +foo
  1:integer <- copy 23:literal
  2:integer <- copy 1:integer
]
+run: instruction main/1
+run: instruction main/2