An annoying thing with C and languages with C-like syntax is the
distinction between statements and expressions. Specifically, that you
lose some expressiveness in expression contexts since declarations and
statements like for/while/switch etc can't be used in there.
Gcc has an extension to allow blocks inside statements: One just puts
a block inside parenthesis and writes statements there. E.g:
({ int y = foo (); int z;
if (y > 0) z = y;
else z = - y;
z; })
The result of the expression is the last statement.
It occurred to me that it would be really simple to add this to pike
too. We already have gauge and catch which can open up statement
blocks inside expressions, so we only need a variety that returns the
value of the last statement expression.
The gcc syntax doesn't work since ({ }) means arrays, so among the
existing keywords I picked "inline":
werror ("%d\n", inline {
int s = 1;
for (int i = 2; i < 7; i++) s *= i;
s;
});
Type checking of the last statement etc works just fine since the
statement/expression distinction doesn't exist on the abstract syntax
tree level anyway. If the last statement isn't an expression then the
inline block will be of void type, so this gives "assigning a void
expression":
mixed c = inline {
for (int i = 0; i < 10; i++)
werror (" %O\n", i);
};
This construct is different from lambdas (implicit or not) since the
block is not a function of its own, but rather just another nested
block. I.e. it's possible to exit it using "break" and "continue", and
"return" will return from the surrounding function.
I only made this for fun and haven't committed it yet. Here's the
patch if someone wants to play around with it:
--- src/language.yacc 30 May 2008 11:20:41 -0000 1.426
+++ src/language.yacc 31 May 2008 13:59:55 -0000
@@ -3674,6 +3674,10 @@
free_node ($3);
}
| expr4 TOK_ARROW line_number_info error {$$=$1; free_node ($3);}
+ | TOK_INLINE '{' statements comma_expr2 expected_semicolon end_block
+ { $$ = mknode (F_COMMA_EXPR, $3, $4); }
+ | TOK_INLINE '{' statements end_block
+ { $$ = $3; }
;
idents2: idents
The syntax is still open for discussion, of course. It would work to
use e.g. "block {...}" instead; the new "block" keyword would not
conflict with identifiers.