]> ocean-lang.org Git - ocean/commitdiff
oceani: add "and then" and "or else"
authorNeilBrown <neil@brown.name>
Wed, 8 May 2019 10:50:30 +0000 (20:50 +1000)
committerNeilBrown <neil@brown.name>
Wed, 8 May 2019 10:50:30 +0000 (20:50 +1000)
"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 <neil@brown.name>
csrc/oceani-tests.mdc
csrc/oceani.mdc

index f5f097a1b4ac0a77c648552fb0f00658fa710084..b2c2e1b75f5f282ebb126c9e29ec93e0396ca8a6 100644 (file)
@@ -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
 
index dd02e81ab89e7b01855e145973bf0def5252b6d3..123fffc46ccad91e5b8849de22a8a0adaa3177d7 100644 (file)
@@ -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