From 2208b7c7f457bbba9bf030e25de7c27f67901d48 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 8 May 2019 20:50:30 +1000 Subject: [PATCH] oceani: add "and then" and "or else" "and then" and "or else" are short-circuit versions of "and" and "or" - they only evaluate second arg if it is needed. Signed-off-by: NeilBrown --- csrc/oceani-tests.mdc | 14 +++++++++++++ csrc/oceani.mdc | 46 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/csrc/oceani-tests.mdc b/csrc/oceani-tests.mdc index f5f097a..b2c2e1b 100644 --- a/csrc/oceani-tests.mdc +++ b/csrc/oceani-tests.mdc @@ -157,6 +157,15 @@ Now we need to test if/else and some different loops count = count + 1 print "error is ", target - guess * guess + for j:=0; then j = j+3 ; while j < 10: + if j != 0 and then 20 / j > 3: + print "20 /", j," =", 20 / j + else: + print "I won't calculate 20 /", j + pi ::= 3.1415926535897 + if 355/113 == pi or else +(pi - 355/113) < 0.001: + print "Close enough" + ###### output: cond_loop Success 1 2 4 8 16 32 64 @@ -165,6 +174,11 @@ Now we need to test if/else and some different loops 2 1.41422 3 1.41421 error is -4.51095e-12 + I won't calculate 20 / 0 + 20 / 3 = 6.66667 + 20 / 6 = 3.33333 + I won't calculate 20 / 9 + Close enough ## Say Hello diff --git a/csrc/oceani.mdc b/csrc/oceani.mdc index dd02e81..123fffc 100644 --- a/csrc/oceani.mdc +++ b/csrc/oceani.mdc @@ -1867,12 +1867,16 @@ Our first user of the `binode` will be expressions, and particularly Boolean expressions. As I haven't implemented precedence in the parser generator yet, we need different names for each precedence level used by expressions. The outer most or lowest level precedence -are Boolean `or` `and`, and `not` which form an `Expression` out of `BTerm`s -and `BFact`s. +are Boolean operators which form an `Expression` out of `BTerm`s and +`BFact`s. As well as `or` `and`, and `not` we have `and then` and `or +else` which only evaluate the second operand if the result would make +a difference. ###### Binode types And, + AndThen, Or, + OrElse, Not, ###### Grammar @@ -1885,6 +1889,13 @@ and `BFact`s. b->right = $<3; $0 = b; } }$ + | Expression or else BTerm ${ { + struct binode *b = new(binode); + b->op = OrElse; + b->left = $<1; + b->right = $<4; + $0 = b; + } }$ | BTerm ${ $0 = $<1; }$ BTerm -> BTerm and BFact ${ { @@ -1894,6 +1905,13 @@ and `BFact`s. b->right = $<3; $0 = b; } }$ + | BTerm and then BFact ${ { + struct binode *b = new(binode); + b->op = AndThen; + b->left = $<1; + b->right = $<4; + $0 = b; + } }$ | BFact ${ $0 = $<1; }$ BFact -> not BFact ${ { @@ -1910,11 +1928,21 @@ and `BFact`s. printf(" and "); print_exec(b->right, -1, 0); break; + case AndThen: + print_exec(b->left, -1, 0); + printf(" and then "); + print_exec(b->right, -1, 0); + break; case Or: print_exec(b->left, -1, 0); printf(" or "); print_exec(b->right, -1, 0); break; + case OrElse: + print_exec(b->left, -1, 0); + printf(" or else "); + print_exec(b->right, -1, 0); + break; case Not: printf("not "); print_exec(b->right, -1, 0); @@ -1922,7 +1950,9 @@ and `BFact`s. ###### propagate binode cases case And: + case AndThen: case Or: + case OrElse: case Not: /* both must be Tbool, result is Tbool */ propagate_types(b->left, c, ok, Tbool, 0); @@ -1940,11 +1970,21 @@ and `BFact`s. right = interp_exec(b->right); rv.bool = rv.bool && right.bool; break; + case AndThen: + rv = interp_exec(b->left); + if (rv.bool) + rv = interp_exec(b->right); + break; case Or: rv = interp_exec(b->left); right = interp_exec(b->right); rv.bool = rv.bool || right.bool; break; + case OrElse: + rv = interp_exec(b->left); + if (!rv.bool) + rv = interp_exec(b->right); + break; case Not: rv = interp_exec(b->right); rv.bool = !rv.bool; @@ -3587,7 +3627,7 @@ Fibonacci, and performs a binary search for a number. a : number a = A; b:number = B - if a > 0 and b > 0: + if a > 0 and then b > 0: while a != b: if a < b: b = b - a -- 2.43.0