hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

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:
Mhare/ast/expr.ha | 14+++++++++++++-
Mhare/lex/token.ha | 4+++-
Mhare/parse/+test/expr.ha | 7+++++++
Mhare/parse/expr.ha | 28+++++++++++++++++++++++++++-
Mhare/unparse/expr.ha | 15+++++++++++++++
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; + }, }; };