about summary refs log tree commit diff stats
path: root/022arithmetic.cc
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-02-03 23:10:11 -0800
committerKartik K. Agaram <vc@akkartik.com>2016-02-03 23:10:11 -0800
commit8bd4d8dd7c1241b73a7473cd35fae00b664bda05 (patch)
treee0e408f2e4932d03c41a3e3f0ee750d2eed6aa70 /022arithmetic.cc
parentb2566a847948ba808d4ca93d02bcc62ee6487255 (diff)
downloadmu-8bd4d8dd7c1241b73a7473cd35fae00b664bda05.tar.gz
2626
Diffstat (limited to '022arithmetic.cc')
-rw-r--r--022arithmetic.cc80
1 files changed, 80 insertions, 0 deletions
diff --git a/022arithmetic.cc b/022arithmetic.cc
index dc191efa..badd298a 100644
--- a/022arithmetic.cc
+++ b/022arithmetic.cc
@@ -321,3 +321,83 @@ recipe main [
 ]
 # integer division can't return floating-point infinity
 +error: main: divide by zero in '1:number <- divide-with-remainder 4, 0'
+
+//: Bitwise shifts
+
+:(before "End Primitive Recipe Declarations")
+SHIFT_LEFT,
+:(before "End Primitive Recipe Numbers")
+put(Recipe_ordinal, "shift-left", SHIFT_LEFT);
+:(before "End Primitive Recipe Checks")
+case SHIFT_LEFT: {
+  if (SIZE(inst.ingredients) != 2) {
+    raise_error << maybe(get(Recipe, r).name) << "'shift-left' requires exactly two ingredients, but got '" << inst.to_string() << "'\n" << end();
+    break;
+  }
+  if (!is_mu_number(inst.ingredients.at(0)) || !is_mu_number(inst.ingredients.at(1))) {
+    raise_error << maybe(get(Recipe, r).name) << "'shift-left' requires number ingredients, but got '" << inst.to_string() << "'\n" << end();
+    break;
+  }
+  if (SIZE(inst.products) > 1) {
+    raise_error << maybe(get(Recipe, r).name) << "'shift-left' yields one product in '" << inst.to_string() << "'\n" << end();
+    break;
+  }
+  if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_number(inst.products.at(0))) {
+    raise_error << maybe(get(Recipe, r).name) << "'shift-left' should yield a number, but got " << inst.products.at(0).original_string << '\n' << end();
+    goto finish_checking_instruction;
+  }
+  break;
+}
+:(before "End Primitive Recipe Implementations")
+case SHIFT_LEFT: {
+  // ingredients must be integers
+  long long int a = static_cast<long long int>(ingredients.at(0).at(0));
+  long long int b = static_cast<long long int>(ingredients.at(1).at(0));
+  products.resize(1);
+  if (b < 0) {
+    raise_error << maybe(current_recipe_name()) << "second ingredient can't be negative in '" << current_instruction().to_string() << "'\n" << end();
+    products.at(0).push_back(0);
+    break;
+  }
+  products.at(0).push_back(a<<b);
+  break;
+}
+
+:(before "End Primitive Recipe Declarations")
+SHIFT_RIGHT,
+:(before "End Primitive Recipe Numbers")
+put(Recipe_ordinal, "shift-right", SHIFT_RIGHT);
+:(before "End Primitive Recipe Checks")
+case SHIFT_RIGHT: {
+  if (SIZE(inst.ingredients) != 2) {
+    raise_error << maybe(get(Recipe, r).name) << "'shift-right' requires exactly two ingredients, but got '" << inst.to_string() << "'\n" << end();
+    break;
+  }
+  if (!is_mu_number(inst.ingredients.at(0)) || !is_mu_number(inst.ingredients.at(1))) {
+    raise_error << maybe(get(Recipe, r).name) << "'shift-right' requires number ingredients, but got '" << inst.to_string() << "'\n" << end();
+    break;
+  }
+  if (SIZE(inst.products) > 1) {
+    raise_error << maybe(get(Recipe, r).name) << "'shift-right' yields one product in '" << inst.to_string() << "'\n" << end();
+    break;
+  }
+  if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_number(inst.products.at(0))) {
+    raise_error << maybe(get(Recipe, r).name) << "'shift-right' should yield a number, but got " << inst.products.at(0).original_string << '\n' << end();
+    goto finish_checking_instruction;
+  }
+  break;
+}
+:(before "End Primitive Recipe Implementations")
+case SHIFT_RIGHT: {
+  // ingredients must be integers
+  long long int a = static_cast<long long int>(ingredients.at(0).at(0));
+  long long int b = static_cast<long long int>(ingredients.at(1).at(0));
+  products.resize(1);
+  if (b < 0) {
+    raise_error << maybe(current_recipe_name()) << "second ingredient can't be negative in '" << current_instruction().to_string() << "'\n" << end();
+    products.at(0).push_back(0);
+    break;
+  }
+  products.at(0).push_back(a>>b);
+  break;
+}