###### 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,
###### 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;