about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-05-11 15:21:12 -0700
committerKartik K. Agaram <vc@akkartik.com>2016-05-11 15:21:12 -0700
commitbf3c3d30246c4e955f418f7b34cd29b1c2e8bec4 (patch)
tree977a1650cad677d6c98f9811a74bef6a06cd075e
parentc18f6e98a3ad89dd9fcf871924a4caa1099e52a2 (diff)
downloadmu-bf3c3d30246c4e955f418f7b34cd29b1c2e8bec4.tar.gz
2952 - multi-ary min/max
-rw-r--r--025compare.cc78
-rw-r--r--070text.mu22
2 files changed, 78 insertions, 22 deletions
diff --git a/025compare.cc b/025compare.cc
index c80fcc85..57f2b10c 100644
--- a/025compare.cc
+++ b/025compare.cc
@@ -357,3 +357,81 @@ def main [
   1:boolean <- lesser-or-equal 34, 35, 34
 ]
 +mem: storing 0 in location 1
+
+:(before "End Primitive Recipe Declarations")
+MAX,
+:(before "End Primitive Recipe Numbers")
+put(Recipe_ordinal, "max", MAX);
+:(before "End Primitive Recipe Checks")
+case MAX: {
+  if (SIZE(inst.ingredients) <= 1) {
+    raise << maybe(get(Recipe, r).name) << "'max' needs at least two ingredients to compare in '" << to_original_string(inst) << "'\n" << end();
+    break;
+  }
+  for (int i = 0; i < SIZE(inst.ingredients); ++i) {
+    if (!is_mu_number(inst.ingredients.at(i))) {
+      raise << maybe(get(Recipe, r).name) << "'max' can only compare numbers; got " << inst.ingredients.at(i).original_string << '\n' << end();
+      goto finish_checking_instruction;
+    }
+  }
+  if (SIZE(inst.products) > 1) {
+    raise << maybe(get(Recipe, r).name) << "'max' yields exactly one product in '" << to_original_string(inst) << "'\n" << end();
+    break;
+  }
+  if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_number(inst.products.at(0))) {
+    raise << maybe(get(Recipe, r).name) << "'max' should yield a number, but got " << inst.products.at(0).original_string << '\n' << end();
+    break;
+  }
+  break;
+}
+:(before "End Primitive Recipe Implementations")
+case MAX: {
+  int result = ingredients.at(0).at(0);
+  for (int i = /**/1; i < SIZE(ingredients); ++i) {
+    if (ingredients.at(i).at(0) > result) {
+      result = ingredients.at(i).at(0);
+    }
+  }
+  products.resize(1);
+  products.at(0).push_back(result);
+  break;
+}
+
+:(before "End Primitive Recipe Declarations")
+MIN,
+:(before "End Primitive Recipe Numbers")
+put(Recipe_ordinal, "min", MIN);
+:(before "End Primitive Recipe Checks")
+case MIN: {
+  if (SIZE(inst.ingredients) <= 1) {
+    raise << maybe(get(Recipe, r).name) << "'min' needs at least two ingredients to compare in '" << to_original_string(inst) << "'\n" << end();
+    break;
+  }
+  for (int i = 0; i < SIZE(inst.ingredients); ++i) {
+    if (!is_mu_number(inst.ingredients.at(i))) {
+      raise << maybe(get(Recipe, r).name) << "'min' can only compare numbers; got " << inst.ingredients.at(i).original_string << '\n' << end();
+      goto finish_checking_instruction;
+    }
+  }
+  if (SIZE(inst.products) > 1) {
+    raise << maybe(get(Recipe, r).name) << "'min' yields exactly one product in '" << to_original_string(inst) << "'\n" << end();
+    break;
+  }
+  if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_number(inst.products.at(0))) {
+    raise << maybe(get(Recipe, r).name) << "'min' should yield a number, but got " << inst.products.at(0).original_string << '\n' << end();
+    break;
+  }
+  break;
+}
+:(before "End Primitive Recipe Implementations")
+case MIN: {
+  int result = ingredients.at(0).at(0);
+  for (int i = /**/1; i < SIZE(ingredients); ++i) {
+    if (ingredients.at(i).at(0) < result) {
+      result = ingredients.at(i).at(0);
+    }
+  }
+  products.resize(1);
+  products.at(0).push_back(result);
+  break;
+}
diff --git a/070text.mu b/070text.mu
index 49317557..f7d5897b 100644
--- a/070text.mu
+++ b/070text.mu
@@ -1300,25 +1300,3 @@ scenario text-copy-out-of-bounds-2 [
     3:array:character <- []
   ]
 ]
-
-def min x:number, y:number -> z:number [
-  local-scope
-  load-ingredients
-  {
-    return-x?:boolean <- lesser-than x, y
-    break-if return-x?
-    return y
-  }
-  return x
-]
-
-def max x:number, y:number -> z:number [
-  local-scope
-  load-ingredients
-  {
-    return-x?:boolean <- greater-than x, y
-    break-if return-x?
-    return y
-  }
-  return x
-]