commit 237fd35a61715e7bb04a91d31e0f84380d5e85c0
parent 06c599619fc71d3363b753f83900029c2ec40f30
Author: Eyal Sawady <ecs@d2evs.net>
Date: Wed, 1 Sep 2021 12:00:03 +0000
hare::{lex,parse}: implement yield
Signed-off-by: Eyal Sawady <ecs@d2evs.net>
Diffstat:
5 files changed, 65 insertions(+), 3 deletions(-)
diff --git a/hare/ast/expr.ha b/hare/ast/expr.ha
@@ -339,6 +339,14 @@ export type unarithm_expr = struct {
operand: *expr,
};
+// A yield expression.
+//
+// yield foo
+export type yield_expr = struct {
+ label: str,
+ value: nullable *expr,
+};
+
// A Hare expression.
export type expr = struct {
start: lex::location,
@@ -349,7 +357,7 @@ export type expr = struct {
defer_expr | delete_expr | for_expr | free_expr | if_expr |
compound_expr | match_expr | len_expr | size_expr | offset_expr |
propagate_expr | return_expr | slice_expr | switch_expr |
- unarithm_expr),
+ unarithm_expr | yield_expr),
};
// Frees resources associated with a Hare [[expr]]ession.
@@ -508,5 +516,9 @@ export fn expr_free(e: (expr | nullable *expr)) void = match (e) {
free(s.cases);
},
u: unarithm_expr => expr_free(u.operand),
+ y: yield_expr => {
+ free(y.label);
+ expr_free(y.value);
+ },
},
};
diff --git a/hare/lex/token.ha b/hare/lex/token.ha
@@ -65,7 +65,8 @@ export type ltok = enum uint {
UNION,
USE,
VOID,
- LAST_KEYWORD = VOID,
+ YIELD,
+ LAST_KEYWORD = YIELD,
// Operators
BAND,
@@ -208,6 +209,7 @@ const bmap: [_]str = [
"union",
"use",
"void",
+ "yield",
"&",
"&=",
"~",
diff --git a/hare/parse/+test/expr.ha b/hare/parse/+test/expr.ha
@@ -252,3 +252,10 @@
"export fn main() void = !void;\n"
"export fn main() void = &x;\n");
};
+
+@test fn yield_expr() void = {
+ roundtrip("export fn main() void = yield;\n"
+ "export fn main() void = yield void;\n"
+ "export fn main() void = yield :foo;\n"
+ "export fn main() void = yield :foo, void;\n");
+};
diff --git a/hare/parse/expr.ha b/hare/parse/expr.ha
@@ -38,7 +38,7 @@ export fn expression(lexer: *lex::lexer) (ast::expr | error) = {
} else match (peek(lexer, ltok::LBRACE, ltok::MATCH,
ltok::SWITCH, ltok::IF, ltok::LABEL, ltok::FOR,
ltok::BREAK, ltok::CONTINUE, ltok::RETURN, ltok::LET,
- ltok::CONST)?) {
+ ltok::CONST, ltok::YIELD)?) {
void => binarithm(lexer, void, 0)?,
tok: lex::token => switch (tok.0) {
ltok::LABEL, ltok::LBRACE => compound_expr(lexer)?,
@@ -50,6 +50,7 @@ export fn expression(lexer: *lex::lexer) (ast::expr | error) = {
ltok::CONTINUE,
ltok::RETURN => control(lexer)?,
ltok::LET, ltok::CONST => binding(lexer, false)?,
+ ltok::YIELD => yield_expr(lexer)?,
* => abort(), // Invariant
},
};
@@ -1070,6 +1071,31 @@ fn unarithm(lexer: *lex::lexer) (ast::expr | error) = {
};
};
+fn yield_expr(lexer: *lex::lexer) (ast::expr | error) = {
+ const start = want(lexer, ltok::YIELD)?;
+ let label = "";
+ let value: nullable *ast::expr = null;
+ match (try(lexer, ltok::SEMICOLON, ltok::LABEL)?) {
+ void => value = alloc(expression(lexer)?),
+ t: lex::token => switch (t.0) {
+ ltok::SEMICOLON => lex::unlex(lexer, t),
+ ltok::LABEL => {
+ label = t.1 as str;
+ if (try(lexer, ltok::COMMA)? is void) yield;
+ value = alloc(expression(lexer)?);
+ },
+ },
+ };
+ return ast::expr {
+ start = start.2,
+ end = lex::prevloc(lexer),
+ expr = ast::yield_expr {
+ label = label,
+ value = value,
+ },
+ };
+};
+
fn binop_for_tok(tok: lex::token) ast::binarithm_op = switch (tok.0) {
ltok::BAND => ast::binarithm_op::BAND,
ltok::BOR => ast::binarithm_op::BOR,
diff --git a/hare/unparse/expr.ha b/hare/unparse/expr.ha
@@ -316,6 +316,21 @@ export fn expr(
z += expr(out, indent, *e.operand)?;
yield z;
},
+ e: ast::yield_expr => {
+ let z = fmt::fprint(out, "yield")?;
+ if (e.label != "") {
+ z += fmt::fprintf(out, " :{}", e.label)?;
+ };
+ match (e.value) {
+ null => void,
+ v: *ast::expr => {
+ z += fmt::fprint(out, if (e.label == "")
+ " " else ", ")?;
+ z += expr(out, indent, *v)?;
+ },
+ };
+ yield z;
+ },
};
};