//? enum recipe_number { //? // arithmetic //? add = 1, //? subtract, //? multiply, //? divide, //? divide_with_remainder, //? //? // boolean //? conjunction, // 'and' is a keyword //? disjunction, // 'or' is a keyword //? negation, // 'not' is a keyword //? //? // comparison //? equal, //? not_equal, //? less_than, //? greater_than, //? lesser_or_equal, //? greater_or_equal, //? //? // control flow //? jump, //? jump_if, //? jump_unless, //? //? // data management: scalars, arrays, and_records (structs) //? copy, //? get, //? get_address, //? index, //? index_address, //? allocate, //? size, //? length, //? //? // tagged_values require one primitive //? save_type, //? //? // code points for characters //? character_to_integer, //? integer_to_character, //? //? // multiprocessing //? fork, //? fork_helper, //? sleep, //? assert, //? assert_false, //? //? // cursor-based (text mode) interaction //? cursor_mode, //? retro_mode, //? clear_host_screen, //? clear_line_on_host, //? cursor_on_host, //? cursor_on_host_to_next_line, //? cursor_up_on_host, //? cursor_down_on_host, //? cursor_right_on_host, //? cursor_left_on_host, //? print_character_to_host, //? read_key_from_host, //? //? // debugging aides //? _dump_memory, //? _dump_trace, //? _start_tracing, //? _stop_tracing, //? _dump_routine, //? _dump_channel, //? _quit, //? _wait_for_key_from_host, //? _print, //? //? // first-class continuations //? current_continuation, //? continue_from, //? //? // user-defined functions //? next_input, //? input, //? prepare_reply, //? reply, //? //? Max_primitive_recipe, //? }; struct property { vector values; }; typedef int type_number; struct type_info { int size; bool is_address; bool is_record; bool is_array; vector target; // only if is_address vector > elements; // only if is_record or is_array type_info() :size(0) {} }; typedef int type_number; unordered_map Type_number; unordered_map Type; int Next_type_number = 1; unordered_map Memory; struct reagent { string name; vector types; vector > properties; }; const int idle = 0; struct instruction { bool is_label; string label; // only if is_label recipe_number operation; // only if !is_label vector ingredients; // only if !is_label vector products; // only if !is_label instruction() :is_label(false), operation(idle) {} }; struct recipe { vector step; }; typedef int recipe_number; unordered_map Recipe_number; unordered_map Recipe; int Next_recipe_number = 1; void load(string filename) { } void run(string function_name) { } void setup_memory() { Memory.clear(); } void setup_types() { int integer = Type_number["integer"] = Next_type_number++; Type[integer].size = 1; } void compile(string form) { istringstream in(form); in >> std::noskipws; string _recipe = next_word(in); //? cout << _recipe << '\n'; //? 1 if (_recipe != "recipe") raise << "top-level forms must be of the form 'recipe _name_ [ _instruction_ ... ]'\n"; string recipe_name = next_word(in); //? cout << '^' << recipe_name << "$\n"; //? 1 if (recipe_name.empty()) raise << "empty recipe name in " << form << '\n'; int r = Recipe_number[recipe_name] = Next_recipe_number++; //? string foo = next_word(in); //? 1 //? cout << '^' << foo << "$ (" << foo.size() << ")\n"; //? 1 if (next_word(in) != "[") raise << "recipe body must begin with '['\n"; skip_newlines(in); instruction curr; //? while (next_instruction(in, &curr)) { //? 1 //? Recipe[r].step.push_back(curr); //? 1 //? } //? 1 } bool next_instruction(istream& in, instruction* curr) { skip_whitespace(in); skip_newlines(in); return !in.eof(); } string next_word(istream& in) { ostringstream out; //? cout << "1: " << (int)in.peek() << '\n'; //? 1 skip_whitespace(in); //? cout << "2: " << (int)in.peek() << '\n'; //? 1 slurp_word(in, out); //? cout << "3: " << (int)in.peek() << '\n'; //? 1 //? cout << out.str() << '\n'; //? 1 return out.str(); } void slurp_word(istream& in, ostream& out) { char c; while (in >> c) { //? cout << c << '\n'; //? 1 if (isspace(c) || c == ',') { //? cout << " space\n"; //? 1 in.putback(c); break; } out << c; } } void skip_whitespace(istream& in) { while (isspace(in.peek()) && in.peek() != '\n') { //? cout << "skip\n"; //? 1 in.get(); } } void skip_newlines(istream& in) { while (in.peek() == '\n') in.get(); } void skip_comma(istream& in) { skip_whitespace(in); if (in.peek() == ',') in.get(); skip_whitespace(in); } //// test harness void run_tests() { for (unsigned long i=0; i < sizeof(Tests)/sizeof(Tests[0]); ++i) { START_TRACING_UNTIL_END_OF_SCOPE; setup(); CLEAR_TRACE; (*Tests[i])(); verify(); } cerr << '\n'; if (Num_failures > 0) cerr << Num_failures << " failure" << (Num_failures > 1 ? "s" : "") << '\n'; } void verify() { if (!Passed) ; else cerr << "."; } void setup() { setup_memory(); setup_types(); Passed = true; } string time_string() { time_t t; time(&t); char buffer[10]; if (!strftime(buffer, 10, "%H:%M:%S", localtime(&t))) return ""; return buffer; } } // end namespace mu int main(int argc, const char* argv[]) { if (argc == 2 && string(argv[1]) == "test") { mu::run_tests(); return 0; } for (int i = 1; i < argc; ++i) { mu::load(argv[i]); } mu::run("main"); } namespace mu {