X-Git-Url: https://ocean-lang.org/code/?a=blobdiff_plain;f=csrc%2Foceani.mdc;h=07caefafca523bf1014752bf1cc228f0f7689a72;hb=6f3c6db8d0e5c5bf244f9a101e72e5e498b5fb6d;hp=dd02e81ab89e7b01855e145973bf0def5252b6d3;hpb=89377f910b5d607fdcdb2d7152ca3a58668a3de0;p=ocean diff --git a/csrc/oceani.mdc b/csrc/oceani.mdc index dd02e81..07caefa 100644 --- a/csrc/oceani.mdc +++ b/csrc/oceani.mdc @@ -1861,30 +1861,111 @@ 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 `or` `and`, and `not` which form an `Expression` out of `BTerm`s -and `BFact`s. +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, + AndThen, Or, + OrElse, Not, ###### 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; } }$ + | BoolExpr 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 +1975,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 +1998,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 +2020,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 +2040,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 +3697,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