]> ocean-lang.org Git - ocean/commitdiff
oceani: add conditional expression
authorNeilBrown <neil@brown.name>
Thu, 9 May 2019 11:13:16 +0000 (21:13 +1000)
committerNeilBrown <neil@brown.name>
Thu, 9 May 2019 11:38:18 +0000 (21:38 +1000)
[value] if [condition] else [alternate value]

is a conditional expression which will only evaluate and return one of
the two values, depending on the condition.
This has lowest precedence of all expressions.

Signed-off-by: NeilBrown <neil@brown.name>
csrc/oceani-tests.mdc
csrc/oceani.mdc

index b2c2e1b75f5f282ebb126c9e29ec93e0396ca8a6..d5e60b739236ab9417b19fa11e329d49e1032a22 100644 (file)
@@ -165,6 +165,7 @@ Now we need to test if/else and some different loops
                pi ::= 3.1415926535897
                if 355/113 == pi or else +(pi - 355/113) < 0.001:
                        print "Close enough"
+               print "lower" if 355/113 < pi else "higher"
 
 ###### output: cond_loop
        Success
@@ -179,6 +180,7 @@ Now we need to test if/else and some different loops
        20 / 6  = 3.33333
        I won't calculate 20 / 9
        Close enough
+       higher
 
 ## Say Hello
 
index 123fffc46ccad91e5b8849de22a8a0adaa3177d7..07caefafca523bf1014752bf1cc228f0f7689a72 100644 (file)
@@ -1861,16 +1861,86 @@ link to find the primary instance.
 ###### free exec cases
        case Xvar: free_var(cast(var, e)); break;
 
+### Expressions: Conditional
+
+Our first user of the `binode` will be conditional expressions, which
+is a bit odd as they actually have three components.  That will be
+handled by having 2 binodes for each expression.  The conditional
+expression is the lowest precedence operatior, so it gets to define
+what an "Expression" is.  The next level up is "BoolExpr", which
+comes next.
+
+Conditional expressions are of the form "value `if` condition `else`
+other_value".  There is no associativite with this operator: the
+values and conditions can only be other conditional expressions if
+they are enclosed in parentheses.  Allowing nesting without
+parentheses would be too confusing.
+
+###### Binode types
+       CondExpr,
+
+###### Grammar
+
+       $*exec
+       Expression -> BoolExpr if BoolExpr else BoolExpr ${ {
+                       struct binode *b1 = new(binode);
+                       struct binode *b2 = new(binode);
+                       b1->op = CondExpr;
+                       b1->left = $<3;
+                       b1->right = b2;
+                       b2->op = CondExpr;
+                       b2->left = $<1;
+                       b2->right = $<5;
+                       $0 = b1;
+               } }$
+               | BoolExpr ${ $0 = $<1; }$
+
+###### print binode cases
+
+       case CondExpr:
+               b2 = cast(binode, b->right);
+               print_exec(b2->left, -1, 0);
+               printf(" if ");
+               print_exec(b->left, -1, 0);
+               printf(" else ");
+               print_exec(b2->right, -1, 0);
+               break;
+
+###### propagate binode cases
+
+       case CondExpr: {
+               /* cond must be Tbool, others must match */
+               struct binode *b2 = cast(binode, b->right);
+               struct type *t2;
+
+               propagate_types(b->left, c, ok, Tbool, 0);
+               t = propagate_types(b2->left, c, ok, type, Rnolabel);
+               t2 = propagate_types(b2->right, c, ok, type ?: t, Rnolabel);
+               return t ?: t2;
+       }
+
+###### interp binode cases
+
+       case CondExpr: {
+               struct binode *b2 = cast(binode, b->right);
+               left = interp_exec(b->left);
+               if (left.bool)
+                       rv = interp_exec(b2->left);
+               else
+                       rv = interp_exec(b2->right);
+               }
+               break;
+
 ### Expressions: Boolean
 
-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 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.
+The next class of expressions to use the `binode` will be 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
+conditional expressions are Boolean operators which form an `BoolExpr`
+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,
@@ -1882,14 +1952,14 @@ a difference.
 ###### Grammar
 
        $*exec
-       Expression -> Expression or BTerm ${ {
+       BoolExpr -> BoolExpr or BTerm ${ {
                        struct binode *b = new(binode);
                        b->op = Or;
                        b->left = $<1;
                        b->right = $<3;
                        $0 = b;
                } }$
-               | Expression or else BTerm ${ {
+               | BoolExpr or else BTerm ${ {
                        struct binode *b = new(binode);
                        b->op = OrElse;
                        b->left = $<1;