On Wed, 15 Jul 2015, Richard Sandiford wrote: > Michael Matz <m...@suse.de> writes: > >> >> (switch > >> >> (A) B > >> >> (B) C > >> >> (C) D > >> >> E) > >> > > >> >The lispy way would have been > >> > > >> > (switch > >> > (A) (B) > >> > (C) (D) > >> > (E) (F) > >> > G) > >> > > >> >i.e. parenthesize the result as well, which then would be unambiguously > >> > >> That's just atoms vs. Expressions. > > > > But if the result is no atom, you'd want parentheses. Similar if the > > condition is no expression but an atom, you'd want to leave out > > parentheses as well. My point is, that both condition and result are at > > the same level, and hence should be subject to the same parenthesis rules, > > namely: surrounding parens by default, optional for atoms. > > > >> Like (Plus @0 @1) vs. Plain @1. So you suggest to require ((plus @0 > >> @1)) here to make it unambiguous? > > > > No :) Just look at your example again: > > > > (switch > > (A) B > > ) > > > > Both A and B are at the same level, and are both expressions, but still > > you parenthesize them differently; that can't be right. You also don't > > write > > > > (switch > > ((plus @0 @1)) (@0) > > ) > > > > You write > > > > (switch > > (plus @0 @1) (@0) > > ) > > > > And as syntactic sugar you are allowed to leave out the parens around @0 > > as it's an atom: > > > > (switch > > (plus @0 @1) @0 > > ) > > > > Similar, if the condition is an atom you should be able to leave the > > parens away: > > > > (switch > > cond (minus @0 @1) > > ) > > > > (given a predicate 'cond' defined appropriately). > > Agreed FWIW. The rtx equivalent (unfortunately called "cond", > so the clash with "cond"==COND_EXPR prevents naming consistency) > uses the lispy syntax without any ambiguity.
It also puts an extra pair of [] parens around the if-then cases and leaves a single else case. It's ('cond' [cond1 then1 cond2 then2 ...] else) That's of course also possible to mimic with (switch ( (integer_zerop (@1)) @0 (INTEGRAL_TYPE_P (type)) (plus @1 @2) ) (minus @3 @2)) not sure if that is visually easier to parse than the 'if' keyword. One of the current switch stmts we have is (switch /* x > +Inf is always false, if with ignore sNANs. */ (if (code == GT_EXPR && ! HONOR_SNANS (@0)) { constant_boolean_node (false, type); }) (if (code == LE_EXPR) /* x <= +Inf is always true, if we don't case about NaNs. */ (if (! HONOR_NANS (@0)) { constant_boolean_node (true, type); } /* x <= +Inf is the same as x == x, i.e. isfinite(x). */ (eq @0 @0))) /* x == +Inf and x >= +Inf are always equal to x > DBL_MAX. */ (if (code == EQ_EXPR || code == GE_EXPR) (with { real_maxval (&max, neg, TYPE_MODE (TREE_TYPE (@0))); } (if (neg) (lt @0 { build_real (TREE_TYPE (@0), max); }) (gt @0 { build_real (TREE_TYPE (@0), max); })))) /* x < +Inf is always equal to x <= DBL_MAX. */ (if (code == LT_EXPR) (with { real_maxval (&max, neg, TYPE_MODE (TREE_TYPE (@0))); } (if (neg) (ge @0 { build_real (TREE_TYPE (@0), max); }) (le @0 { build_real (TREE_TYPE (@0), max); })))) /* x != +Inf is always equal to !(x > DBL_MAX). */ (if (code == NE_EXPR) (with { real_maxval (&max, neg, TYPE_MODE (TREE_TYPE (@0))); } (if (! HONOR_NANS (@0)) (if (neg) (ge @0 { build_real (TREE_TYPE (@0), max); }) (le @0 { build_real (TREE_TYPE (@0), max); })) (if (neg) (bit_xor (lt @0 { build_real (TREE_TYPE (@0), max); }) { build_one_cst (type); }) (bit_xor (gt @0 { build_real (TREE_TYPE (@0), max); }) { build_one_cst (type); })))))) (this doesn't have an else clause) Richard.