diff options
-rw-r--r-- | 002test.cc | 1 | ||||
-rw-r--r-- | 003trace.cc | 2 | ||||
-rw-r--r-- | 012transform.cc | 2 | ||||
-rw-r--r-- | 020run.cc | 24 | ||||
-rw-r--r-- | 021arithmetic.cc | 227 | ||||
-rw-r--r-- | 022boolean.cc | 6 | ||||
-rw-r--r-- | 023jump.cc | 6 | ||||
-rw-r--r-- | 024compare.cc | 30 | ||||
-rw-r--r-- | 027debug.cc | 2 | ||||
-rw-r--r-- | 030container.cc | 10 | ||||
-rw-r--r-- | 031address.cc | 2 | ||||
-rw-r--r-- | 032array.cc | 21 | ||||
-rw-r--r-- | 033length.cc | 4 | ||||
-rw-r--r-- | 034exclusive_container.cc | 7 | ||||
-rw-r--r-- | 036call_ingredient.cc | 4 | ||||
-rw-r--r-- | 038scheduler.cc | 4 | ||||
-rw-r--r-- | 039wait.cc | 12 | ||||
-rw-r--r-- | 040brace.cc | 31 | ||||
-rw-r--r-- | 041name.cc | 8 | ||||
-rw-r--r-- | 042new.cc | 11 | ||||
-rw-r--r-- | 043space.cc | 8 | ||||
-rw-r--r-- | 044space_surround.cc | 4 | ||||
-rw-r--r-- | 047jump_label.cc | 2 | ||||
-rw-r--r-- | 050scenario.cc | 20 | ||||
-rw-r--r-- | 060string.mu | 16 | ||||
-rw-r--r-- | 070display.cc | 6 | ||||
-rw-r--r-- | 071print.mu | 2 | ||||
-rw-r--r-- | 072scenario_screen.cc | 31 | ||||
-rw-r--r-- | 075scenario_keyboard.cc | 6 |
29 files changed, 316 insertions, 193 deletions
diff --git a/002test.cc b/002test.cc index 0b445526..9a6765d1 100644 --- a/002test.cc +++ b/002test.cc @@ -54,6 +54,7 @@ if (Run_tests) { time_t t; time(&t); cerr << "C tests: " << ctime(&t); for (index_t i=0; i < sizeof(Tests)/sizeof(Tests[0]); ++i) { +//? cerr << "===\n"; //? 1 run_test(i); } // End Tests diff --git a/003trace.cc b/003trace.cc index 6fb6dfa7..85779092 100644 --- a/003trace.cc +++ b/003trace.cc @@ -205,7 +205,7 @@ struct lease_tracer { #define START_TRACING_UNTIL_END_OF_SCOPE lease_tracer leased_tracer; :(before "End Test Setup") START_TRACING_UNTIL_END_OF_SCOPE -//? Trace_stream->dump_layer = "all"; //? 1 +//? Trace_stream->dump_layer = "all"; //? 2 :(before "End Tracing") void trace_all(const string& label, const list<string>& in) { diff --git a/012transform.cc b/012transform.cc index 7b2b58e8..1ec8d6e4 100644 --- a/012transform.cc +++ b/012transform.cc @@ -48,5 +48,5 @@ void parse_int_reagents() { void populate_value(reagent& r) { if (r.initialized) return; if (!is_number(r.name)) return; - r.set_value(to_number(r.name)); + r.set_value(mu_integer(to_number(r.name))); } diff --git a/020run.cc b/020run.cc index 3f3237e8..ff23200e 100644 --- a/020run.cc +++ b/020run.cc @@ -78,7 +78,11 @@ void run_current_routine() switch (current_instruction().operation) { // Primitive Recipe Implementations case COPY: { - copy(ingredients.begin(), ingredients.end(), inserter(products, products.begin())); + products.resize(ingredients.size()); + for (index_t i = 0; i < ingredients.size(); ++i) { + copy(ingredients.at(i).begin(), ingredients.at(i).end(), inserter(products.at(i), products.at(i).begin())); + } +//? copy(ingredients.begin(), ingredients.end(), inserter(products, products.begin())); break; } // End Primitive Recipe Implementations @@ -121,6 +125,7 @@ inline bool routine::completed() const { } :(before "End Commandline Parsing") +// Loading Commandline Files if (argc > 1) { for (int i = 1; i < argc; ++i) { load_permanently(argv[i]); @@ -183,10 +188,14 @@ vector<long long int> read_memory(reagent x) { return result; } index_t base = x.value; +//? cerr << "AAA " << base << '\n'; //? 1 + assert(!is_negative(base)); + base = value(base); size_t size = size_of(x); for (index_t offset = 0; offset < size; ++offset) { long long int val = Memory[base+offset]; - trace("mem") << "location " << base+offset << " is " << val; +//? cerr << "AAA2 " << val << '\n'; //? 1 + trace("mem") << "location " << base+offset << " is " << value(val); result.push_back(val); } return result; @@ -194,11 +203,20 @@ vector<long long int> read_memory(reagent x) { void write_memory(reagent x, vector<long long int> data) { if (is_dummy(x)) return; + // Preprocess x. + // End Preprocess x. index_t base = x.value; + assert(!is_negative(base)); + base = value(base); if (size_of(x) != data.size()) raise << "size mismatch in storing to " << x.to_string() << '\n'; +//? cerr << "BBB " << base << '\n'; //? 1 for (index_t offset = 0; offset < data.size(); ++offset) { - trace("mem") << "storing " << data.at(offset) << " in location " << base+offset; + trace("mem") << "storing " << value(data.at(offset)) << " in location " << base+offset; +//? if (base+offset > 99999) { //? 1 +//? raise << "AAAAAAAAAAAAAAAAAAAAA\n"; //? 1 +//? Trace_stream->newline(), exit(0); //? 1 +//? } //? 1 Memory[base+offset] = data.at(offset); } } diff --git a/021arithmetic.cc b/021arithmetic.cc index d36b15f3..ed852b9e 100644 --- a/021arithmetic.cc +++ b/021arithmetic.cc @@ -6,13 +6,13 @@ ADD, Recipe_number["add"] = ADD; :(before "End Primitive Recipe Implementations") case ADD: { - long long int result = 0; + double result = 0; for (index_t i = 0; i < ingredients.size(); ++i) { assert(ingredients.at(i).size() == 1); // scalar - result += ingredients.at(i).at(0); + result += value(ingredients.at(i).at(0)); } products.resize(1); - products.at(0).push_back(result); + products.at(0).push_back(mu_noninteger(result)); break; } @@ -53,13 +53,13 @@ Recipe_number["subtract"] = SUBTRACT; :(before "End Primitive Recipe Implementations") case SUBTRACT: { assert(ingredients.at(0).size() == 1); // scalar - long long int result = ingredients.at(0).at(0); + double result = value(ingredients.at(0).at(0)); for (index_t i = 1; i < ingredients.size(); ++i) { assert(ingredients.at(i).size() == 1); // scalar - result -= ingredients.at(i).at(0); + result -= value(ingredients.at(i).at(0)); } products.resize(1); - products.at(0).push_back(result); + products.at(0).push_back(mu_noninteger(result)); break; } @@ -99,13 +99,13 @@ MULTIPLY, Recipe_number["multiply"] = MULTIPLY; :(before "End Primitive Recipe Implementations") case MULTIPLY: { - long long int result = 1; + double result = 1; for (index_t i = 0; i < ingredients.size(); ++i) { assert(ingredients.at(i).size() == 1); // scalar - result *= ingredients.at(i).at(0); + result *= value(ingredients.at(i).at(0)); } products.resize(1); - products.at(0).push_back(result); + products.at(0).push_back(mu_noninteger(result)); break; } @@ -146,13 +146,13 @@ Recipe_number["divide"] = DIVIDE; :(before "End Primitive Recipe Implementations") case DIVIDE: { assert(ingredients.at(0).size() == 1); // scalar - long long int result = ingredients.at(0).at(0); + double result = value(ingredients.at(0).at(0)); for (index_t i = 1; i < ingredients.size(); ++i) { assert(ingredients.at(i).size() == 1); // scalar - result /= ingredients.at(i).at(0); + result /= value(ingredients.at(i).at(0)); } products.resize(1); - products.at(0).push_back(result); + products.at(0).push_back(mu_noninteger(result)); break; } @@ -192,11 +192,15 @@ DIVIDE_WITH_REMAINDER, Recipe_number["divide-with-remainder"] = DIVIDE_WITH_REMAINDER; :(before "End Primitive Recipe Implementations") case DIVIDE_WITH_REMAINDER: { - long long int quotient = ingredients.at(0).at(0) / ingredients.at(1).at(0); - long long int remainder = ingredients.at(0).at(0) % ingredients.at(1).at(0); + assert(ingredients.at(0).size() == 1); // scalar + long long int a = value(ingredients.at(0).at(0)); + assert(ingredients.at(1).size() == 1); // scalar + long long int b = value(ingredients.at(1).at(0)); + long long int quotient = a / b; + long long int remainder = a % b; products.resize(2); - products.at(0).push_back(quotient); - products.at(1).push_back(remainder); + products.at(0).push_back(mu_integer(quotient)); + products.at(1).push_back(mu_integer(remainder)); break; } @@ -230,6 +234,13 @@ recipe main [ //:: Support for non-integer numbers. +:(scenario divide_with_decimal_point) +recipe main [ + # todo: literal floats? + 1:integer <- divide 5:literal, 2:literal +] ++mem: storing 2.5 in location 1 + //: Supporting non-integers is hopefully the only place where we need to think //: about the size of each location of memory. :(after "int main") @@ -240,129 +251,181 @@ assert(sizeof(double) == 8); //: Conventional hardware uses the most significant bit to represent the sign //: in both (2's complement) integers, and so-called floating-point numbers //: (with sign, exponent and fraction regions: https://en.wikipedia.org/wiki/Double-precision_floating-point_format) -static const long long int HOST_SET_NEGATIVE = 0x8000000000000000LL; -//: Floating-point numbers store the sign of the exponent in the second-most -//: significant bit. -static const long long int HOST_SET_FLOAT_NEGATIVE_EXPONENT = 0x4000000000000000LL; + +//: Watch out: perform bitwise operations only on unsigned values to avoid +//: undefined behavior. +//: For similar reasons, don't coerce between signed and unsigned, instead +//: manually interpret the bit-pattern + +const unsigned long long int HOST_SET_NEGATIVE = (0x1ULL << 63ULL); //: As an experiment, we'd like to not have to distinguish between the two in //: mu. So we'll use the most-significant bit to represent whether a number is //: an integer (MSB 0) or a float (MSB 1). This will halve the set of numbers //: we can represent, whether integers or non-integers, but that price seems //: reasonable right now. -const long long int MU_NUMBER_TYPE_MASK = 0x8000000000000000LL; +const unsigned long long int MU_NUMBER_NONINTEGER_MASK = (0x1ULL << 63ULL); //: As a result, the sign bit is now pushed to the second-most significant //: bit.. -const long long int MU_NUMBER_SIGN_MASK = 0x4000000000000000LL; -//: ..and the sign of the exponent for floating-point is pushed to the -//: third-most significant bit. -const long long int MU_FLOAT_EXPONENT_SIGN_MASK = 0x2000000000000000LL; - -//: One nice side-effect of this mergek +const unsigned long long int MU_NUMBER_SIGN_MASK = (0x1ULL << 62ULL); :(after "int main") -assert(MU_NUMBER_TYPE_MASK == HOST_SET_NEGATIVE); -assert(MU_NUMBER_SIGN_MASK == HOST_SET_FLOAT_NEGATIVE_EXPONENT); +assert(MU_NUMBER_NONINTEGER_MASK == HOST_SET_NEGATIVE); :(code) inline bool is_float(long long int number) { - return number & MU_NUMBER_TYPE_MASK; + unsigned long long int tmp = *reinterpret_cast<unsigned long long int*>(&number); + return tmp & MU_NUMBER_NONINTEGER_MASK; } inline bool is_integer(long long int number) { return !is_float(number); } -// both floats and integers use the most significant bit for the sign inline bool is_negative(long long int number) { - return number & MU_NUMBER_SIGN_MASK; + unsigned long long int tmp = *reinterpret_cast<unsigned long long int*>(&number); + return tmp & MU_NUMBER_SIGN_MASK; } -inline bool float_has_negative_exponent(long long int number) { - return number & MU_FLOAT_EXPONENT_SIGN_MASK; +inline double value(long long int number) { + return is_integer(number) ? to_int(number) : to_float(number); } -long long int to_integer(long long int number) { +// convert a mu integer to host representation +long long int to_int(long long int number) { assert(is_integer(number)); - if (is_negative(number)) { - // slide the sign over by one bit - number = number | HOST_SET_NEGATIVE; - // clear the old sign bit - number = number & (~MU_NUMBER_SIGN_MASK); - } - return number; + if (!is_negative(number)) return number; + // negative number + unsigned long long int tmp = *reinterpret_cast<unsigned long long int*>(&number); + // slide the sign over by one bit + tmp = tmp | HOST_SET_NEGATIVE; +//? // clear the old sign bit +//? // so the range of numbers we can represent shrinks by half +//? tmp = tmp & (~MU_NUMBER_SIGN_MASK); + // reinterpret back as signed + long long int result = *reinterpret_cast<long long int*>(&tmp); + return result; +} + +// convert an integer from host representation to mu representation +long long int mu_integer(long long int n) { + unsigned long long int tmp = *reinterpret_cast<unsigned long long int*>(&n); + // slide the sign to the right + if (tmp & HOST_SET_NEGATIVE) tmp = tmp | MU_NUMBER_SIGN_MASK; + // clear the old sign bit + tmp = tmp & (~HOST_SET_NEGATIVE); + // reinterpret back as signed + long long int result = *reinterpret_cast<long long int*>(&tmp); + assert(is_integer(result)); +//? printf("%llx\n", result); //? 1 + return result; } +// convert a mu non-integer to host representation double to_float(long long int number) { assert(is_float(number)); -//? cerr << "0: " << std::hex << number << std::dec << ' ' << *reinterpret_cast<double*>(&number) << '\n'; //? 1 - if (is_negative(number)) { - // slide the sign over by one bit - number = number | HOST_SET_NEGATIVE; -//? cerr << "1: " << std::hex << number << std::dec << ' ' << *reinterpret_cast<double*>(&number) << '\n'; //? 1 - // clear the old sign bit - number = number & (~MU_NUMBER_SIGN_MASK); -//? cerr << "2: " << std::hex << number << std::dec << ' ' << *reinterpret_cast<double*>(&number) << '\n'; //? 1 - } - if (float_has_negative_exponent(number)) { - // slide the sign of the exponent over by one bit - number = number | HOST_SET_FLOAT_NEGATIVE_EXPONENT; -//? cerr << "3: " << std::hex << number << std::dec << ' ' << *reinterpret_cast<double*>(&number) << '\n'; //? 1 -//? // clear the old exponent sign bit -//? number = number & (~MU_FLOAT_EXPONENT_SIGN_MASK); -//? cerr << "4: " << std::hex << number << std::dec << ' ' << *reinterpret_cast<double*>(&number) << '\n'; - } - double result = *reinterpret_cast<double*>(&number); + unsigned long long int tmp = *reinterpret_cast<unsigned long long int*>(&number); + // slide the entire number over the most significant bit + // so the precision of numbers we can represent shrinks by 1 bit + tmp = (tmp << 1); + double result = *reinterpret_cast<double*>(&tmp); + return result; +} + +// convert a float from host representation to mu representation +long long int mu_noninteger(double n) { + unsigned long long int tmp = *reinterpret_cast<unsigned long long int*>(&n); + tmp = (tmp >> 1); + tmp = (tmp | MU_NUMBER_NONINTEGER_MASK); + long long int result = *reinterpret_cast<long long int*>(&tmp); + assert(is_float(result)); return result; } +// Spot-check some bit-patterns and make sure they convert back to themselves. void test_integer_representation() { // Assuming long long int is 8 bytes: - static const long long int nbits = 64; + static const int nbits = 64; //? cerr << '\n'; //? 1 //? cerr << nbits << " iterations\n"; //? 1 //? cerr << std::hex; //? 1 -//? cerr << "type mask: " << MU_NUMBER_TYPE_MASK << '\n'; //? 1 +//? cerr << "type mask: " << MU_NUMBER_NONINTEGER_MASK << '\n'; //? 1 //? cerr << "sign mask: " << MU_NUMBER_SIGN_MASK << '\n'; //? 1 //? cerr << std::dec; //? 1 // until the last 2 bits all integers retain their value for (int i = 0; i < nbits-2; ++i) { - long long int n = (0x1LL << i); -//? cerr << i << ": " << "0x" << std::hex << n << std::dec << ' ' << n << " => " << to_integer(n) << '\n'; //? 1 + unsigned long long int x = (0x1ULL << i); + long long int n = *reinterpret_cast<long long int*>(&x); +//? cerr << i << ": " << "0x" << std::hex << n << std::dec << ' ' << n << " => " << to_int(n) << '\n'; //? 2 CHECK(is_integer(n)); - CHECK(n == to_integer(n)); + CHECK_EQ(n, to_int(n)); +//? printf("0x%llx\n", mu_integer(to_int(n))); //? 1 + CHECK_EQ(n, mu_integer(to_int(n))); } - long long int n = (0x1LL << (nbits-2)); + // second-last bit + unsigned long long int x = (0x1ULL << (nbits-2)); + long long int n = *reinterpret_cast<long long int*>(&x); CHECK(is_integer(n)); -//? cerr << nbits-2 << ": " << "0x" << std::hex << n << std::dec << ' ' << n << " => " << to_integer(n) << '\n'; //? 1 +//? cerr << nbits-2 << ": " << "0x" << std::hex << n << std::dec << ' ' << n << " => " << to_int(n) << '\n'; //? 1 CHECK(is_negative(n)); + CHECK_EQ(n, mu_integer(to_int(n))); + // most significant bit is for non-integers below +} + +// Now go the other way; spot-check a few mu integers and make sure they +// convert back to themselves. +void test_small_integers() { + for (long long int n = -1000; n < 1000; ++n) { +//? printf("0x%llx vs 0x%llx\n", n, to_int(mu_integer(n))); //? 1 + CHECK_EQ(n, to_int(mu_integer(n))); + } } +// Spot-check some bit-patterns and make sure they convert back to themselves. void test_noninteger_representation() { // Assuming long long int is 8 bytes: - static const long long int nbits = 64; - static const long long int FLOAT_MASK = (0x1LL << (nbits-1)); - double f = -2.0; - printf("0x%llx\n", *(long long int*)&f); - cout << '\n'; + static const int nbits = 64; + static const long long int FLOAT_MASK = (0x1ULL << (nbits-1)); +//? double f = -2.0; //? 1 +//? printf("0x%llx\n", *(long long int*)&f); //? 1 +//? printf("\n"); //? 1 for (int fraction = 0; fraction < 52; ++fraction) { for (int exponent = 52; exponent < 63; ++exponent) { - long long int n = (0x1LL << fraction) | (0x1LL << exponent) | FLOAT_MASK; + long long int n = (0x1ULL << fraction) | (0x1ULL << exponent) | FLOAT_MASK; CHECK(is_float(n)); - double result_on_host = *reinterpret_cast<double*>(&n); double result = to_float(n); - printf("%02d %d: 0x%llx %.30e\n", fraction, exponent, n, result_on_host); - printf("=> %.30e\n", result); +//? double result_on_host = *reinterpret_cast<double*>(&n); //? 1 +//? printf("%02d %d: 0x%llx %.30e\n", fraction, exponent, n, result_on_host); //? 1 +//? printf("=> %.30e\n", result); //? 1 +//? printf("=> 0x%llx\n", mu_noninteger(result)); //? 1 + CHECK_EQ(n, mu_noninteger(result)); } + int exponent = 63; + long long int n = ((0x1ULL << 62) | (0x1ULL << exponent) | FLOAT_MASK); + CHECK(is_float(n)); + double result = to_float(n); +//? double result_on_host = *reinterpret_cast<double*>(&n); //? 1 +//? printf("%02d %d: 0x%llx %.30e\n", fraction, nbits-1, n, result_on_host); //? 1 +//? printf("=> %.30e\n", result); //? 1 +//? printf("=> 0x%llx\n", mu_noninteger(result)); //? 1 + CHECK_EQ(n, mu_noninteger(result)); } -//? long long int n = ((0x1LL << (nbits-2)) | FLOAT_MASK); -//? CHECK(is_float(n)); -//? double result_on_host = *reinterpret_cast<double*>(&n); -//? double result = to_float(n); -//? cout << nbits-2 << ": " << "0x" << std::hex << n << std::dec << ' ' << result_on_host -//? << " => " << result << '\n'; } +:(code) +// Now go the other way; spot-check a few mu non-integers and make sure they +// convert back to themselves. +void test_small_nonintegers() { + for (double n = -1000.0; n < 1000.0; n += 0.001) { +//? printf("%.30e vs %.30e\n", n, to_float(mu_noninteger(n))); //? 1 + CHECK(fabs(n - to_float(mu_noninteger(n))) < epsilon); + } +} + +:(before "End Globals") +const double epsilon = 1e-13; + :(before "End Includes") #include<iomanip> #include<limits> +#include<math.h> diff --git a/022boolean.cc b/022boolean.cc index e91dc209..bca425b0 100644 --- a/022boolean.cc +++ b/022boolean.cc @@ -12,7 +12,7 @@ case AND: { result = result && ingredients.at(i).at(0); } products.resize(1); - products.at(0).push_back(result); + products.at(0).push_back(result); // boolean must be a positive integer break; } @@ -60,7 +60,7 @@ case OR: { result = result || ingredients.at(i).at(0); } products.resize(1); - products.at(0).push_back(result); + products.at(0).push_back(result); // boolean must be a positive integer break; } @@ -105,7 +105,7 @@ case NOT: { products.resize(ingredients.size()); for (index_t i = 0; i < ingredients.size(); ++i) { assert(ingredients.at(i).size() == 1); // must be a scalar - products.at(i).push_back(!ingredients.at(i).at(0)); + products.at(i).push_back(!ingredients.at(i).at(0)); // boolean must be a positive integer } break; } diff --git a/023jump.cc b/023jump.cc index 807113f3..4252b36e 100644 --- a/023jump.cc +++ b/023jump.cc @@ -9,7 +9,7 @@ case JUMP: { assert(current_instruction().ingredients.at(0).initialized); assert(ingredients.size() == 1); assert(ingredients.at(0).size() == 1); // scalar - instruction_counter += ingredients.at(0).at(0); + instruction_counter += value(ingredients.at(0).at(0)); trace("run") << "jumping to instruction " << instruction_counter+1; break; } @@ -49,7 +49,7 @@ case JUMP_IF: { break; } assert(ingredients.at(1).size() == 1); // scalar - instruction_counter += ingredients.at(1).at(0); + instruction_counter += value(ingredients.at(1).at(0)); trace("run") << "jumping to instruction " << instruction_counter+1; break; } @@ -89,7 +89,7 @@ case JUMP_UNLESS: { break; } assert(ingredients.at(1).size() == 1); // scalar - instruction_counter += ingredients.at(1).at(0); + instruction_counter += value(ingredients.at(1).at(0)); trace("run") << "jumping to instruction " << instruction_counter+1; break; } diff --git a/024compare.cc b/024compare.cc index 92d87e5c..c9d73170 100644 --- a/024compare.cc +++ b/024compare.cc @@ -9,13 +9,23 @@ case EQUAL: { vector<long long int>& exemplar = ingredients.at(0); bool result = true; for (index_t i = 1; i < ingredients.size(); ++i) { - if (!equal(ingredients.at(i).begin(), ingredients.at(i).end(), exemplar.begin())) { +//? cerr << ingredients.at(i).at(0) << " <=> " << exemplar.at(0) << '\n'; //? 1 +//? cerr << value(ingredients.at(i).at(0)) << " <=> " << value(exemplar.at(0)) << '\n'; //? 1 + if (ingredients.at(i).size() != exemplar.size()) { result = false; break; } +//? if (!equal(ingredients.at(i).begin(), ingredients.at(i).end(), exemplar.begin())) + for (index_t j = 0; j < exemplar.size(); ++j) { + if (value(ingredients.at(i).at(j)) != value(exemplar.at(j))) { + result = false; + goto finish; + } + } } + finish: products.resize(1); - products.at(0).push_back(result); + products.at(0).push_back(result); // boolean must be a positive integer break; } @@ -70,12 +80,12 @@ case GREATER_THAN: { assert(ingredients.at(i).size() == 1); // scalar } for (index_t i = /**/1; i < ingredients.size(); ++i) { - if (ingredients.at(i-1).at(0) <= ingredients.at(i).at(0)) { + if (value(ingredients.at(i-1).at(0)) <= value(ingredients.at(i).at(0))) { result = false; } } products.resize(1); - products.at(0).push_back(result); + products.at(0).push_back(result); // boolean must be a positive integer break; } @@ -130,12 +140,12 @@ case LESSER_THAN: { assert(ingredients.at(i).size() == 1); // scalar } for (index_t i = /**/1; i < ingredients.size(); ++i) { - if (ingredients.at(i-1).at(0) >= ingredients.at(i).at(0)) { + if (value(ingredients.at(i-1).at(0)) >= value(ingredients.at(i).at(0))) { result = false; } } products.resize(1); - products.at(0).push_back(result); + products.at(0).push_back(result); // boolean must be a positive integer break; } @@ -190,12 +200,12 @@ case GREATER_OR_EQUAL: { assert(ingredients.at(i).size() == 1); // scalar } for (index_t i = /**/1; i < ingredients.size(); ++i) { - if (ingredients.at(i-1).at(0) < ingredients.at(i).at(0)) { + if (value(ingredients.at(i-1).at(0)) < value(ingredients.at(i).at(0))) { result = false; } } products.resize(1); - products.at(0).push_back(result); + products.at(0).push_back(result); // boolean must be a positive integer break; } @@ -264,12 +274,12 @@ case LESSER_OR_EQUAL: { assert(ingredients.at(i).size() == 1); // scalar } for (index_t i = /**/1; i < ingredients.size(); ++i) { - if (ingredients.at(i-1).at(0) > ingredients.at(i).at(0)) { + if (value(ingredients.at(i-1).at(0)) > value(ingredients.at(i).at(0))) { result = false; } } products.resize(1); - products.at(0).push_back(result); + products.at(0).push_back(result); // boolean must be a positive integer break; } diff --git a/027debug.cc b/027debug.cc index bbce5d6e..004dd68d 100644 --- a/027debug.cc +++ b/027debug.cc @@ -15,7 +15,7 @@ case _PRINT: { for (index_t j = 0; j < ingredients.at(i).size(); ++j) { trace("run") << "$print: " << ingredients.at(i).at(j); if (j > 0) cout << " "; - cout << ingredients.at(i).at(j); + cout << value(ingredients.at(i).at(j)); } } } diff --git a/030container.cc b/030container.cc index edde3395..042c0b5a 100644 --- a/030container.cc +++ b/030container.cc @@ -110,7 +110,8 @@ Recipe_number["get"] = GET; :(before "End Primitive Recipe Implementations") case GET: { reagent base = current_instruction().ingredients.at(0); - index_t base_address = base.value; + assert(!is_negative(base.value)); + index_t base_address = value(base.value); type_number base_type = base.types.at(0); assert(Type[base_type].kind == container); assert(isa_literal(current_instruction().ingredients.at(1))); @@ -126,7 +127,7 @@ case GET: { type_number src_type = Type[base_type].elements.at(offset).at(0); trace("run") << "its type is " << src_type; reagent tmp; - tmp.set_value(src); + tmp.set_value(mu_integer(src)); tmp.types.push_back(src_type); products.push_back(read_memory(tmp)); break; @@ -174,7 +175,8 @@ Recipe_number["get-address"] = GET_ADDRESS; :(before "End Primitive Recipe Implementations") case GET_ADDRESS: { reagent base = current_instruction().ingredients.at(0); - index_t base_address = base.value; + assert(!is_negative(base.value)); + index_t base_address = value(base.value); type_number base_type = base.types.at(0); assert(Type[base_type].kind == container); assert(isa_literal(current_instruction().ingredients.at(1))); @@ -186,6 +188,6 @@ case GET_ADDRESS: { } trace("run") << "address to copy is " << result; products.resize(1); - products.at(0).push_back(result); + products.at(0).push_back(mu_integer(result)); // address must be a positive integer break; } diff --git a/031address.cc b/031address.cc index 58d93466..259ea976 100644 --- a/031address.cc +++ b/031address.cc @@ -48,7 +48,7 @@ reagent deref(reagent x) { assert(x.types.at(0) == ADDRESS); // compute value - result.set_value(Memory[x.value]); + result.set_value(mu_integer(value(Memory[x.value]))); // address must be a positive integer trace("mem") << "location " << x.value << " is " << result.value; // populate types diff --git a/032array.cc b/032array.cc index 67b03293..19a4ac50 100644 --- a/032array.cc +++ b/032array.cc @@ -53,7 +53,7 @@ if (x.types.at(0) != Type_number["array"] && size_of(x) != data.size()) if (r.types.at(0) == Type_number["array"]) { assert(r.types.size() > 1); // skip the 'array' type to get at the element type - return 1 + Memory[r.value]*size_of(array_element(r.types)); + return 1 + value(Memory[r.value])*size_of(array_element(r.types)); } //:: To access elements of an array, use 'index' @@ -98,7 +98,8 @@ case INDEX: { //? if (Trace_stream) Trace_stream->dump_layer = "run"; //? 1 reagent base = canonize(current_instruction().ingredients.at(0)); //? trace("run") << "ingredient 0 after canonize: " << base.to_string(); //? 1 - index_t base_address = base.value; + assert(!is_negative(base.value)); + index_t base_address = value(base.value); assert(base.types.at(0) == Type_number["array"]); reagent offset = canonize(current_instruction().ingredients.at(1)); //? trace("run") << "ingredient 1 after canonize: " << offset.to_string(); //? 1 @@ -106,11 +107,12 @@ case INDEX: { vector<type_number> element_type = array_element(base.types); //? trace("run") << "offset: " << offset_val.at(0); //? 1 //? trace("run") << "size of elements: " << size_of(element_type); //? 1 - index_t src = base_address + 1 + offset_val.at(0)*size_of(element_type); + assert(offset_val.size() == 1); // scalar + index_t src = base_address + 1 + value(offset_val.at(0))*size_of(element_type); trace("run") << "address to copy is " << src; trace("run") << "its type is " << element_type.at(0); reagent tmp; - tmp.set_value(src); + tmp.set_value(mu_integer(src)); copy(element_type.begin(), element_type.end(), inserter(tmp.types, tmp.types.begin())); products.push_back(read_memory(tmp)); break; @@ -153,13 +155,14 @@ Recipe_number["index-address"] = INDEX_ADDRESS; :(before "End Primitive Recipe Implementations") case INDEX_ADDRESS: { reagent base = canonize(current_instruction().ingredients.at(0)); - index_t base_address = base.value; + assert(!is_negative(base.value)); + index_t base_address = value(base.value); assert(base.types.at(0) == Type_number["array"]); - reagent offset = canonize(current_instruction().ingredients.at(1)); - vector<long long int> offset_val(read_memory(offset)); + vector<long long int>& offset_val = ingredients.at(1); + assert(offset_val.size() == 1); vector<type_number> element_type = array_element(base.types); - index_t result = base_address + 1 + offset_val.at(0)*size_of(element_type); + index_t result = base_address + 1 + value(offset_val.at(0))*size_of(element_type); products.resize(1); - products.at(0).push_back(result); + products.at(0).push_back(mu_integer(result)); // address must be a positive integer break; } diff --git a/033length.cc b/033length.cc index 2268611a..8f18180e 100644 --- a/033length.cc +++ b/033length.cc @@ -23,6 +23,8 @@ case LENGTH: { break; } products.resize(1); - products.at(0).push_back(Memory[x.value]); + assert(is_integer(Memory[x.value])); + assert(!is_negative(Memory[x.value])); + products.at(0).push_back(Memory[x.value]); // length must be a positive integer break; } diff --git a/034exclusive_container.cc b/034exclusive_container.cc index b2855f79..5b849916 100644 --- a/034exclusive_container.cc +++ b/034exclusive_container.cc @@ -89,19 +89,20 @@ Recipe_number["maybe-convert"] = MAYBE_CONVERT; :(before "End Primitive Recipe Implementations") case MAYBE_CONVERT: { reagent base = canonize(current_instruction().ingredients.at(0)); - index_t base_address = base.value; + assert(!is_negative(base.value)); + index_t base_address = value(base.value); type_number base_type = base.types.at(0); assert(Type[base_type].kind == exclusive_container); assert(isa_literal(current_instruction().ingredients.at(1))); index_t tag = current_instruction().ingredients.at(1).value; long long int result; - if (tag == static_cast<index_t>(Memory[base_address])) { + if (tag == static_cast<index_t>(value(Memory[base_address]))) { result = base_address+1; } else { result = 0; } products.resize(1); - products.at(0).push_back(result); + products.at(0).push_back(mu_integer(result)); // address must be a positive integer break; } diff --git a/036call_ingredient.cc b/036call_ingredient.cc index 5c321ef9..f5964e4b 100644 --- a/036call_ingredient.cc +++ b/036call_ingredient.cc @@ -105,14 +105,14 @@ case INGREDIENT: { products.push_back( Current_routine->calls.top().ingredient_atoms.at(Current_routine->calls.top().next_ingredient_to_process)); assert(products.size() == 1); products.resize(2); // push a new vector - products.at(1).push_back(1); + products.at(1).push_back(1); // non-negative integer ++Current_routine->calls.top().next_ingredient_to_process; } else { if (current_instruction().products.size() > 1) { products.resize(2); products.at(0).push_back(0); // todo: will fail noisily if we try to read a compound value - products.at(1).push_back(0); + products.at(1).push_back(0); // non-negative integer } } break; diff --git a/038scheduler.cc b/038scheduler.cc index 99ced920..64889f31 100644 --- a/038scheduler.cc +++ b/038scheduler.cc @@ -135,7 +135,7 @@ case START_RUNNING: { new_routine->calls.top().ingredient_atoms.push_back(ingredients.at(i)); Routines.push_back(new_routine); products.resize(1); - products.at(0).push_back(new_routine->id); + products.at(0).push_back(new_routine->id); // routine ids are positive integers break; } @@ -301,7 +301,7 @@ case ROUTINE_STATE: { } } products.resize(1); - products.at(0).push_back(result); + products.at(0).push_back(result); // routine states are positive integers break; } diff --git a/039wait.cc b/039wait.cc index 82354a53..a674ad25 100644 --- a/039wait.cc +++ b/039wait.cc @@ -24,7 +24,7 @@ WAITING, :(before "End routine Fields") // only if state == WAITING index_t waiting_on_location; -int old_value_of_waiting_location; +double old_value_of_waiting_location; :(before "End routine Constructor") waiting_on_location = old_value_of_waiting_location = 0; @@ -39,9 +39,9 @@ case WAIT_FOR_LOCATION: { reagent loc = canonize(current_instruction().ingredients.at(0)); Current_routine->state = WAITING; Current_routine->waiting_on_location = loc.value; - Current_routine->old_value_of_waiting_location = Memory[loc.value]; - trace("run") << "waiting for location " << loc.value << " to change from " << Memory[loc.value]; -//? trace("schedule") << Current_routine->id << ": waiting for location " << loc.value << " to change from " << Memory[loc.value]; //? 2 + Current_routine->old_value_of_waiting_location = value(Memory[loc.value]); + trace("run") << "waiting for location " << loc.value << " to change from " << value(Memory[loc.value]); +//? trace("schedule") << Current_routine->id << ": waiting for location " << loc.value << " to change from " << value(Memory[loc.value]); //? 2 break; } @@ -54,9 +54,9 @@ for (index_t i = 0; i < Routines.size(); ++i) { //? trace("schedule") << "waiting on location: " << Routines.at(i)->waiting_on_location; //? 1 //? if (Routines.at(i)->waiting_on_location) //? 2 //? trace("schedule") << "checking routine " << Routines.at(i)->id << " waiting on location " //? 2 -//? << Routines.at(i)->waiting_on_location << ": " << Memory[Routines.at(i)->waiting_on_location] << " vs " << Routines.at(i)->old_value_of_waiting_location; //? 2 +//? << Routines.at(i)->waiting_on_location << ": " << value(Memory[Routines.at(i)->waiting_on_location]) << " vs " << Routines.at(i)->old_value_of_waiting_location; //? 2 if (Routines.at(i)->waiting_on_location && - Memory[Routines.at(i)->waiting_on_location] != Routines.at(i)->old_value_of_waiting_location) { + value(Memory[Routines.at(i)->waiting_on_location]) != Routines.at(i)->old_value_of_waiting_location) { trace("schedule") << "waking up routine\n"; Routines.at(i)->state = RUNNING; Routines.at(i)->waiting_on_location = Routines.at(i)->old_value_of_waiting_location = 0; diff --git a/040brace.cc b/040brace.cc index 224dbf96..f4c493c9 100644 --- a/040brace.cc +++ b/040brace.cc @@ -69,10 +69,10 @@ void transform_braces(const recipe_number r) { } else { reagent ing; - ing.set_value(open_braces.top()-index); + ing.set_value(mu_integer(open_braces.top()-index)); ing.types.push_back(Type_number["offset"]); inst.ingredients.push_back(ing); - trace("after-brace") << "jump " << ing.value << ":offset"; + trace("after-brace") << "jump " << to_int(ing.value) << ":offset"; trace("after-brace") << index << ": " << ing.to_string(); trace("after-brace") << index << ": " << Recipe[r].steps.at(index).ingredients.at(0).to_string(); } @@ -85,10 +85,10 @@ void transform_braces(const recipe_number r) { } else { reagent ing; - ing.set_value(matching_brace(open_braces.top(), braces) - index - 1); + ing.set_value(mu_integer(matching_brace(open_braces.top(), braces) - index - 1)); ing.types.push_back(Type_number["offset"]); inst.ingredients.push_back(ing); - trace("after-brace") << "jump " << ing.value << ":offset"; + trace("after-brace") << "jump " << to_int(ing.value) << ":offset"; } } else if (inst.operation == Recipe_number["loop-if"]) { @@ -99,10 +99,10 @@ void transform_braces(const recipe_number r) { } else { reagent ing; - ing.set_value(open_braces.top()-index); + ing.set_value(mu_integer(open_braces.top()-index)); ing.types.push_back(Type_number["offset"]); inst.ingredients.push_back(ing); - trace("after-brace") << "jump-if " << inst.ingredients.at(0).name << ", " << ing.value << ":offset"; + trace("after-brace") << "jump-if " << inst.ingredients.at(0).name << ", " << to_int(ing.value) << ":offset"; } } else if (inst.operation == Recipe_number["break-if"]) { @@ -113,10 +113,10 @@ void transform_braces(const recipe_number r) { } else { reagent ing; - ing.set_value(matching_brace(open_braces.top(), braces) - index - 1); + ing.set_value(mu_integer(matching_brace(open_braces.top(), braces) - index - 1)); ing.types.push_back(Type_number["offset"]); inst.ingredients.push_back(ing); - trace("after-brace") << "jump-if " << inst.ingredients.at(0).name << ", " << ing.value << ":offset"; + trace("after-brace") << "jump-if " << inst.ingredients.at(0).name << ", " << to_int(ing.value) << ":offset"; } } else if (inst.operation == Recipe_number["loop-unless"]) { @@ -127,10 +127,10 @@ void transform_braces(const recipe_number r) { } else { reagent ing; - ing.set_value(open_braces.top()-index); + ing.set_value(mu_integer(open_braces.top()-index)); ing.types.push_back(Type_number["offset"]); inst.ingredients.push_back(ing); - trace("after-brace") << "jump-unless " << inst.ingredients.at(0).name << ", " << ing.value << ":offset"; + trace("after-brace") << "jump-unless " << inst.ingredients.at(0).name << ", " << to_int(ing.value) << ":offset"; } } else if (inst.operation == Recipe_number["break-unless"]) { @@ -142,10 +142,10 @@ void transform_braces(const recipe_number r) { } else { reagent ing; - ing.set_value(matching_brace(open_braces.top(), braces) - index - 1); + ing.set_value(mu_integer(matching_brace(open_braces.top(), braces) - index - 1)); ing.types.push_back(Type_number["offset"]); inst.ingredients.push_back(ing); - trace("after-brace") << "jump-unless " << inst.ingredients.at(0).name << ", " << ing.value << ":offset"; + trace("after-brace") << "jump-unless " << inst.ingredients.at(0).name << ", " << to_int(ing.value) << ":offset"; } } else { @@ -380,13 +380,14 @@ recipe test-factorial [ 1:integer <- copy 5:literal 2:integer <- copy 1:literal { - 3:boolean <- equal 1:integer 1:literal + 3:boolean <- equal 1:integer, 1:literal break-if 3:boolean +#? $print 1:integer, [ ], 2:integer, [ +#? ] # $print 1:integer 2:integer <- multiply 2:integer, 1:integer 1:integer <- subtract 1:integer, 1:literal loop } - 4:integer <- copy 2:integer # trigger a read ] -+mem: location 2 is 120 ++mem: storing 120 in location 2 diff --git a/041name.cc b/041name.cc index e5e9449b..ff2b811c 100644 --- a/041name.cc +++ b/041name.cc @@ -46,7 +46,7 @@ void transform_names(const recipe_number r) { if (!already_transformed(inst.ingredients.at(in), names)) { raise << "use before set: " << inst.ingredients.at(in).name << " in " << Recipe[r].name << '\n'; } - inst.ingredients.at(in).set_value(lookup_name(inst.ingredients.at(in), r)); + inst.ingredients.at(in).set_value(mu_integer(lookup_name(inst.ingredients.at(in), r))); // must be a positive integer } for (index_t out = 0; out < inst.products.size(); ++out) { if (is_numeric_location(inst.products.at(out))) numeric_locations_used = true; @@ -57,7 +57,7 @@ void transform_names(const recipe_number r) { names[inst.products.at(out).name] = curr_idx; curr_idx += size_of(inst.products.at(out)); } - inst.products.at(out).set_value(lookup_name(inst.products.at(out), r)); + inst.products.at(out).set_value(mu_integer(lookup_name(inst.products.at(out), r))); // must be a positive integer } } if (names_used && numeric_locations_used) @@ -220,7 +220,7 @@ if (inst.operation == Recipe_number["get"] if (inst.ingredients.at(1).name.find_first_not_of("0123456789") == string::npos) continue; // since first non-address in base type must be a container, we don't have to canonize type_number base_type = skip_addresses(inst.ingredients.at(0).types); - inst.ingredients.at(1).set_value(find_element_name(base_type, inst.ingredients.at(1).name)); + inst.ingredients.at(1).set_value(mu_integer(find_element_name(base_type, inst.ingredients.at(1).name))); // must be a positive integer trace("name") << "element " << inst.ingredients.at(1).name << " of type " << Type[base_type].name << " is at offset " << inst.ingredients.at(1).value; } @@ -256,6 +256,6 @@ if (inst.operation == Recipe_number["maybe-convert"]) { if (inst.ingredients.at(1).name.find_first_not_of("0123456789") == string::npos) continue; // since first non-address in base type must be an exclusive container, we don't have to canonize type_number base_type = skip_addresses(inst.ingredients.at(0).types); - inst.ingredients.at(1).set_value(find_element_name(base_type, inst.ingredients.at(1).name)); + inst.ingredients.at(1).set_value(mu_integer(find_element_name(base_type, inst.ingredients.at(1).name))); // must be a positive integer trace("name") << "variant " << inst.ingredients.at(1).name << " of type " << Type[base_type].name << " has tag " << inst.ingredients.at(1).value; } diff --git a/042new.cc b/042new.cc index 754091c8..c960210b 100644 --- a/042new.cc +++ b/042new.cc @@ -37,7 +37,7 @@ if (inst.operation == Recipe_number["new"]) { //? cout << inst.ingredients.at(0).to_string() << '\n'; //? 1 assert(isa_literal(inst.ingredients.at(0))); if (inst.ingredients.at(0).properties.at(0).second.at(0) == "type") { - inst.ingredients.at(0).set_value(Type_number[inst.ingredients.at(0).name]); + inst.ingredients.at(0).set_value(mu_integer(Type_number[inst.ingredients.at(0).name])); // type numbers must be positive integers } trace("new") << inst.ingredients.at(0).name << " -> " << inst.ingredients.at(0).value; } @@ -51,15 +51,16 @@ Recipe_number["new"] = NEW; :(before "End Primitive Recipe Implementations") case NEW: { // compute the space we need +//? cerr << current_instruction().to_string() << '\n'; //? 1 size_t size = 0; size_t array_length = 0; { vector<type_number> type; assert(isa_literal(current_instruction().ingredients.at(0))); - type.push_back(current_instruction().ingredients.at(0).value); + type.push_back(value(current_instruction().ingredients.at(0).value)); // type numbers must be positive integers if (current_instruction().ingredients.size() > 1) { // array - array_length = ingredients.at(1).at(0); + array_length = value(ingredients.at(1).at(0)); trace("mem") << "array size is " << array_length; size = array_length*size_of(type) + /*space for length*/1; } @@ -78,7 +79,7 @@ case NEW: { products.at(0).push_back(result); // initialize array if necessary if (current_instruction().ingredients.size() > 1) { - Memory[result] = array_length; + Memory[result] = mu_integer(array_length); // array lengths must be positive integers } // bump Current_routine->alloc += size; @@ -89,6 +90,7 @@ case NEW: { :(code) void ensure_space(size_t size) { +//? cerr << size << '\n'; //? 1 assert(size <= Initial_memory_per_routine); //? cout << Current_routine->alloc << " " << Current_routine->alloc_max << " " << size << '\n'; //? 1 if (Current_routine->alloc + size > Current_routine->alloc_max) { @@ -158,6 +160,7 @@ if (isa_literal(current_instruction().ingredients.at(0)) // allocate an array just large enough for it size_t string_length = current_instruction().ingredients.at(0).name.size(); //? cout << "string_length is " << string_length << '\n'; //? 1 +//? cerr << "AAA\n"; //? 1 ensure_space(string_length+1); // don't forget the extra location for array size products.resize(1); products.at(0).push_back(Current_routine->alloc); diff --git a/043space.cc b/043space.cc index b0ee7f85..24d63505 100644 --- a/043space.cc +++ b/043space.cc @@ -42,7 +42,7 @@ reagent absolutize(reagent x) { //? cout << "not raw: " << x.to_string() << '\n'; //? 1 assert(x.initialized); reagent r = x; - r.set_value(address(r.value, space_base(r))); + r.set_value(mu_integer(address(r.value, space_base(r)))); // must be a positive integer //? cout << "after absolutize: " << r.value << '\n'; //? 1 r.properties.push_back(pair<string, vector<string> >("raw", vector<string>())); assert(is_raw(r)); @@ -100,11 +100,11 @@ index_t space_base(const reagent& x) { index_t address(index_t offset, index_t base) { if (base == 0) return offset; // raw //? cout << base << '\n'; //? 2 - if (offset >= static_cast<index_t>(Memory[base])) { + if (value(offset) >= value(Memory[base])) { // todo: test - raise << "location " << offset << " is out of bounds " << Memory[base] << '\n'; + raise << "location " << value(offset) << " is out of bounds " << value(Memory[base]) << '\n'; } - return base+1 + offset; + return value(base)+1 + value(offset); } :(after "void write_memory(reagent x, vector<long long int> data)") diff --git a/044space_surround.cc b/044space_surround.cc index b1e4c5e7..30d4c3f2 100644 --- a/044space_surround.cc +++ b/044space_surround.cc @@ -36,8 +36,8 @@ index_t space_base(const reagent& x, index_t space_index, index_t base) { //? trace("foo") << "base of space " << space_index << " is " << base << '\n'; //? 1 return base; } -//? trace("foo") << "base of space " << space_index << " is " << Memory[base+1] << '\n'; //? 1 - index_t result = space_base(x, space_index-1, Memory[base+1]); +//? trace("foo") << "base of space " << space_index << " is " << value(Memory[base+1]) << '\n'; //? 1 + index_t result = space_base(x, space_index-1, value(Memory[base+1])); return result; } diff --git a/047jump_label.cc b/047jump_label.cc index c9dcb4f5..b03d8b73 100644 --- a/047jump_label.cc +++ b/047jump_label.cc @@ -52,7 +52,7 @@ void replace_offset(reagent& x, /*const*/ map<string, index_t>& offset, const in //? cerr << "DDD " << x.to_string() << '\n'; //? 1 if (offset.find(x.name) == offset.end()) raise << "can't find label " << x.name << " in routine " << Recipe[r].name << '\n'; - x.set_value(offset[x.name]-current_offset); + x.set_value(mu_integer(offset[x.name]-current_offset)); } :(scenario break_to_label) diff --git a/050scenario.cc b/050scenario.cc index c5ff2765..3aa34089 100644 --- a/050scenario.cc +++ b/050scenario.cc @@ -88,7 +88,7 @@ time_t mu_time; time(&mu_time); cerr << "\nMu tests: " << ctime(&mu_time); for (index_t i = 0; i < Scenarios.size(); ++i) { //? cerr << Passed << '\n'; //? 1 -//? cerr << i << ": " << Scenarios.at(i).name << '\n'; //? 2 +//? cerr << i << ": " << Scenarios.at(i).name << '\n'; //? 3 run_mu_scenario(Scenarios.at(i)); if (Passed) cerr << "."; } @@ -215,15 +215,15 @@ void check_memory(const string& s) { skip_whitespace_and_comments(in); string _assign; in >> _assign; assert(_assign == "<-"); skip_whitespace_and_comments(in); - int value = 0; in >> value; + int expected_value = 0; in >> expected_value; if (locations_checked.find(address) != locations_checked.end()) raise << "duplicate expectation for location " << address << '\n'; trace("run") << "checking location " << address; - if (Memory[address] != value) { + if (value(Memory[address]) != expected_value) { if (Current_scenario) - raise << "\nF - " << Current_scenario->name << ": expected location " << address << " to contain " << value << " but saw " << Memory[address] << '\n'; + raise << "\nF - " << Current_scenario->name << ": expected location " << address << " to contain " << expected_value << " but saw " << value(Memory[address]) << '\n'; else - raise << "expected location " << address << " to contain " << value << " but saw " << Memory[address] << '\n'; + raise << "expected location " << address << " to contain " << expected_value << " but saw " << value(Memory[address]) << '\n'; Passed = false; return; } @@ -234,7 +234,7 @@ void check_memory(const string& s) { void check_type(const string& lhs, istream& in) { reagent x(lhs); if (x.properties.at(0).second.at(0) == "string") { - x.set_value(to_number(x.name)); + x.set_value(mu_integer(to_number(x.name))); // address must be a positive integer skip_whitespace_and_comments(in); string _assign = next_word(in); assert(_assign == "<-"); @@ -252,13 +252,13 @@ void check_type(const string& lhs, istream& in) { void check_string(index_t address, const string& literal) { trace("run") << "checking string length at " << address; - if (Memory[address] != static_cast<signed>(literal.size())) - raise << "expected location " << address << " to contain length " << literal.size() << " of string [" << literal << "] but saw " << Memory[address] << '\n'; + if (value(Memory[address]) != static_cast<signed>(literal.size())) + raise << "expected location " << address << " to contain length " << literal.size() << " of string [" << literal << "] but saw " << value(Memory[address]) << '\n'; ++address; // now skip length for (index_t i = 0; i < literal.size(); ++i) { trace("run") << "checking location " << address+i; - if (Memory[address+i] != literal.at(i)) - raise << "expected location " << (address+i) << " to contain " << literal.at(i) << " but saw " << Memory[address+i] << '\n'; + if (value(Memory[address+i]) != literal.at(i)) + raise << "expected location " << (address+i) << " to contain " << literal.at(i) << " but saw " << value(Memory[address+i]) << '\n'; } } diff --git a/060string.mu b/060string.mu index 6b38803b..c2b4e356 100644 --- a/060string.mu +++ b/060string.mu @@ -156,6 +156,8 @@ recipe buffer-append [ default-space:address:array:location <- new location:type, 30:literal in:address:buffer <- next-ingredient c:character <- next-ingredient +#? $print c:character, [ #? 1 +#? ] #? 1 { # grow buffer if necessary full?:boolean <- buffer-full? in:address:buffer @@ -175,8 +177,12 @@ scenario buffer-append-works [ default-space:address:array:location <- new location:type, 30:literal x:address:buffer <- init-buffer 3:literal s1:address:array:character <- get x:address:buffer/deref, data:offset +#? $start-tracing #? 1 x:address:buffer <- buffer-append x:address:buffer, 97:literal # 'a' +#? $exit #? 1 +#? $start-tracing #? 1 x:address:buffer <- buffer-append x:address:buffer, 98:literal # 'b' +#? $exit #? 1 x:address:buffer <- buffer-append x:address:buffer, 99:literal # 'c' s2:address:array:character <- get x:address:buffer/deref, data:offset 1:boolean/raw <- equal s1:address:array:character, s2:address:array:character @@ -194,7 +200,9 @@ scenario buffer-append-works [ #? ] #? $print 1065:integer/raw, [ #? ] +#? $start-tracing #? 1 2:array:character/raw <- copy s2:address:array:character/deref +#? $exit #? 1 +buffer-filled x:address:buffer <- buffer-append x:address:buffer, 100:literal # 'd' s3:address:array:character <- get x:address:buffer/deref, data:offset @@ -261,6 +269,8 @@ recipe integer-to-decimal-string [ buf:address:array:character <- get tmp:address:buffer/deref, data:offset result:address:array:character <- new character:type, len:integer i:integer <- subtract len:integer, 1:literal +#? $print len:integer, [ - 1 = ], i:integer, [ #? 1 +#? ] #? 1 j:integer <- copy 0:literal { # while i >= 0 @@ -271,7 +281,11 @@ recipe integer-to-decimal-string [ dest:address:character <- index-address result:address:array:character/deref, j:integer dest:address:character/deref <- copy src:character # ++i +#? $print [aaa: ], i:integer, [ #? 1 +#? ] #? 1 i:integer <- subtract i:integer, 1:literal +#? $print [bbb: ], i:integer, [ #? 1 +#? ] #? 1 # --j j:integer <- add j:integer, 1:literal loop @@ -290,6 +304,7 @@ scenario integer-to-decimal-digit-zero [ ] scenario integer-to-decimal-digit-positive [ +#? $start-tracing #? 1 run [ 1:address:array:character/raw <- integer-to-decimal-string 234:literal 2:array:character/raw <- copy 1:address:array:character/deref/raw @@ -300,6 +315,7 @@ scenario integer-to-decimal-digit-positive [ ] scenario integer-to-decimal-digit-negative [ +#? $start-tracing #? 1 run [ 1:address:array:character/raw <- integer-to-decimal-string -1:literal 2:array:character/raw <- copy 1:address:array:character/deref/raw diff --git a/070display.cc b/070display.cc index 8a782f87..7c850ef8 100644 --- a/070display.cc +++ b/070display.cc @@ -70,7 +70,7 @@ case PRINT_CHARACTER_TO_DISPLAY: { size_t height = (h >= 0) ? h : 0; size_t width = (w >= 0) ? w : 0; assert(ingredients.at(0).size() == 1); // scalar - long long int c = ingredients.at(0).at(0); + long long int c = value(ingredients.at(0).at(0)); // unicode code-point will probably always be a positive integer if (c == '\n' || c == '\r') { if (Display_row < height-1) { Display_column = 0; @@ -117,9 +117,9 @@ Recipe_number["move-cursor-on-display"] = MOVE_CURSOR_ON_DISPLAY; :(before "End Primitive Recipe Implementations") case MOVE_CURSOR_ON_DISPLAY: { assert(ingredients.at(0).size() == 1); // scalar - Display_row = ingredients.at(0).at(0); + Display_row = ingredients.at(0).at(0); // screen coordinate will always be a non-negative integer assert(ingredients.at(1).size() == 1); // scalar - Display_column = ingredients.at(1).at(0); + Display_column = ingredients.at(1).at(0); // screen coordinate will always be a non-negative integer tb_set_cursor(Display_column, Display_row); tb_present(); break; diff --git a/071print.mu b/071print.mu index d6c72b32..487608a2 100644 --- a/071print.mu +++ b/071print.mu @@ -41,7 +41,7 @@ recipe clear-screen [ done?:boolean <- greater-or-equal i:integer, max:integer break-if done?:boolean c:address:character <- index-address buf:address:array:character/deref, i:integer - c:address:character/deref <- copy [ ] + c:address:character/deref <- copy [ ] # hack: can't copy any literal string except a single space i:integer <- add i:integer, 1:literal loop } diff --git a/072scenario_screen.cc b/072scenario_screen.cc index 2e563b82..5d57c199 100644 --- a/072scenario_screen.cc +++ b/072scenario_screen.cc @@ -6,7 +6,7 @@ :(scenarios run_mu_scenario) :(scenario screen_in_scenario) scenario screen-in-scenario [ -#? $start-tracing +#? $start-tracing #? 3 assume-screen 5:literal/width, 3:literal/height run [ screen:address <- print-character screen:address, 97:literal # 'a' @@ -35,6 +35,7 @@ scenario screen-in-scenario-error [ . . ] ] +# manual test: modifying the trace line below should cause a failure +warn: expected screen location (0, 0) to contain 'b' instead of 'a' :(before "End Globals") @@ -66,7 +67,7 @@ if (curr.name == "assume-screen") { curr.operation = Recipe_number["init-fake-screen"]; assert(curr.products.empty()); curr.products.push_back(reagent("screen:address")); - curr.products.at(0).set_value(SCREEN); + curr.products.at(0).set_value(mu_integer(SCREEN)); // address must be a positive integer //? cout << "after: " << curr.to_string() << '\n'; //? 1 //? cout << "AAA " << Recipe_number["init-fake-screen"] << '\n'; //? 1 } @@ -86,15 +87,15 @@ case SCREEN_SHOULD_CONTAIN: { :(code) void check_screen(const string& contents) { assert(!Current_routine->calls.top().default_space); // not supported - index_t screen_location = Memory[SCREEN]; + index_t screen_location = value(Memory[SCREEN]); int data_offset = find_element_name(Type_number["screen"], "data"); assert(data_offset >= 0); index_t screen_data_location = screen_location+data_offset; // type: address:array:character - index_t screen_data_start = Memory[screen_data_location]; // type: array:character + index_t screen_data_start = value(Memory[screen_data_location]); // type: array:character int width_offset = find_element_name(Type_number["screen"], "num-columns"); - size_t screen_width = Memory[screen_location+width_offset]; + size_t screen_width = value(Memory[screen_location+width_offset]); int height_offset = find_element_name(Type_number["screen"], "num-rows"); - size_t screen_height = Memory[screen_location+height_offset]; + size_t screen_height = value(Memory[screen_location+height_offset]); string expected_contents; istringstream in(contents); in >> std::noskipws; @@ -112,19 +113,21 @@ void check_screen(const string& contents) { //? assert(in.get() == ']'); trace("run") << "checking screen size at " << screen_data_start; //? cout << expected_contents.size() << '\n'; //? 1 - if (Memory[screen_data_start] > static_cast<signed>(expected_contents.size())) - raise << "expected contents are larger than screen size " << Memory[screen_data_start] << '\n'; + if (value(Memory[screen_data_start]) > static_cast<signed>(expected_contents.size())) + raise << "expected contents are larger than screen size " << value(Memory[screen_data_start]) << '\n'; ++screen_data_start; // now skip length for (index_t i = 0; i < expected_contents.size(); ++i) { trace("run") << "checking location " << screen_data_start+i; -//? cerr << "comparing " << i/screen_width << ", " << i%screen_width << ": " << Memory[screen_data_start+i] << " vs " << (int)expected_contents.at(i) << '\n'; //? 1 - if ((!Memory[screen_data_start+i] && !isspace(expected_contents.at(i))) // uninitialized memory => spaces - || (Memory[screen_data_start+i] && Memory[screen_data_start+i] != expected_contents.at(i))) { +//? cerr << "comparing " << i/screen_width << ", " << i%screen_width << ": " << value(Memory[screen_data_start+i]) << " vs " << (int)expected_contents.at(i) << '\n'; //? 1 + long long int curr = value(Memory[screen_data_start+i]); +//? cerr << curr << " <= " << expected_contents.at(i) << '\n'; //? 1 + if ((!curr && !isspace(expected_contents.at(i))) // uninitialized memory => spaces + || (curr && value(Memory[screen_data_start+i]) != expected_contents.at(i))) { //? cerr << "CCC " << Trace_stream << " " << Hide_warnings << '\n'; //? 1 - if (Current_scenario) - raise << "\nF - " << Current_scenario->name << ": expected screen location (" << i/screen_width << ", " << i%screen_width << ") to contain '" << expected_contents.at(i) << "' instead of '" << static_cast<char>(Memory[screen_data_start+i]) << "'\n"; + if (Current_scenario && !Hide_warnings) // Hide_warnings indicates we're checking for the warning at the C++ level rather than raising a test failure at the mu level + raise << "\nF - " << Current_scenario->name << ": expected screen location (" << i/screen_width << ", " << i%screen_width << ") to contain '" << expected_contents.at(i) << "' instead of '" << static_cast<char>(value(Memory[screen_data_start+i])) << "'\n"; else - raise << "expected screen location (" << i/screen_width << ", " << i%screen_width << ") to contain '" << expected_contents.at(i) << "' instead of '" << static_cast<char>(Memory[screen_data_start+i]) << "'\n"; + raise << "expected screen location (" << i/screen_width << ", " << i%screen_width << ") to contain '" << expected_contents.at(i) << "' instead of '" << static_cast<char>(value(Memory[screen_data_start+i])) << "'\n"; Passed = false; return; } diff --git a/075scenario_keyboard.cc b/075scenario_keyboard.cc index 0de6a2eb..3d816c2a 100644 --- a/075scenario_keyboard.cc +++ b/075scenario_keyboard.cc @@ -41,15 +41,15 @@ if (curr.name == "assume-keyboard") { curr.operation = Recipe_number["new"]; assert(curr.products.empty()); curr.products.push_back(reagent("keyboard:address")); - curr.products.at(0).set_value(KEYBOARD); + curr.products.at(0).set_value(mu_integer(KEYBOARD)); // address must be a positive integer result.steps.push_back(curr); // hacky that "Rewrite Instruction" is converting to multiple instructions // leave second instruction in curr curr.clear(); curr.operation = Recipe_number["init-fake-keyboard"]; assert(curr.ingredients.empty()); curr.ingredients.push_back(reagent("keyboard:address")); - curr.ingredients.at(0).set_value(KEYBOARD); + curr.ingredients.at(0).set_value(mu_integer(KEYBOARD)); // address must be a positive integer assert(curr.products.empty()); curr.products.push_back(reagent("keyboard:address")); - curr.products.at(0).set_value(KEYBOARD); + curr.products.at(0).set_value(mu_integer(KEYBOARD)); // address must be a positive integer } |