hare

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

commit f476566936a2477e30caab1cfbd90257d873a851
parent ce79901bd64e351dc0269f939a3da31367427b03
Author: Sebastian <sebastian@sebsite.pw>
Date:   Fri, 29 Sep 2023 22:19:49 -0400

hare::*: update append/insert parsing

Signed-off-by: Sebastian <sebastian@sebsite.pw>

Diffstat:
Mhare/ast/expr.ha | 42++++++++++++++----------------------------
Mhare/parse/+test/expr_test.ha | 7+++----
Mhare/parse/expr.ha | 41++++++++++++++++-------------------------
Mhare/unparse/expr.ha | 93++++++++++++++++++++++++++++---------------------------------------------------
4 files changed, 66 insertions(+), 117 deletions(-)

diff --git a/hare/ast/expr.ha b/hare/ast/expr.ha @@ -63,11 +63,14 @@ export type alloc_expr = struct { // An append expression. // -// append(foo, bar, (more), baz...) +// append(foo, bar); +// append(foo, bar...); +// append(foo, [0...], bar); export type append_expr = struct { object: *expr, - variadic: nullable *expr, - values: []*expr, + value: *expr, + length: nullable *expr, + variadic: bool, is_static: bool, }; @@ -290,13 +293,10 @@ export type if_expr = struct { // An insert expression. // -// insert(foo[0], bar, (more), baz...) -export type insert_expr = struct { - object: *expr, - variadic: nullable *expr, - values: []*expr, - is_static: bool, -}; +// insert(foo[0], bar); +// insert(foo[0], bar...); +// insert(foo[0], [0...], bar); +export type insert_expr = append_expr; // :label. The ":" character is not included. export type label = str; @@ -466,15 +466,8 @@ case let e: expr => expr_finish(a.capacity); case let a: append_expr => expr_finish(a.object); - match (a.variadic) { - case null => void; - case let v: *expr => - expr_finish(v); - }; - for (let i = 0z; i < len(a.values); i += 1) { - expr_finish(a.values[i]); - }; - free(a.values); + expr_finish(a.value); + expr_finish(a.length); case let a: assert_expr => expr_finish(a.cond); expr_finish(a.message); @@ -557,15 +550,8 @@ case let e: expr => expr_finish(i.fbranch); case let e: insert_expr => expr_finish(e.object); - match (e.variadic) { - case null => void; - case let v: *expr => - expr_finish(v); - }; - for (let i = 0z; i < len(e.values); i += 1) { - expr_finish(e.values[i]); - }; - free(e.values); + expr_finish(e.value); + expr_finish(e.length); case let l: len_expr => expr_finish(l: *expr); case let m: match_expr => diff --git a/hare/parse/+test/expr_test.ha b/hare/parse/+test/expr_test.ha @@ -47,9 +47,8 @@ alloc(1234...); alloc(4321, 1234); append(x, 10); - append(x, 10...); - append(x, 10, 20, 30); - append(x, y, z, q...); + append(x, [10]...); + append(x, [10...], 20); static append(x, 10); abort(); abort("surprize"); @@ -67,7 +66,7 @@ free(x); insert(x[0], foo); insert(x[0], foo...); - insert(x[0], foo, bar...); + insert(x[0], foo, bar); static insert(x[0], foo); len([1, 2, 3, 4]); offset(foo.bar); diff --git a/hare/parse/expr.ha b/hare/parse/expr.ha @@ -208,42 +208,33 @@ fn append_insert_expr( const object = if (tok.0 == ltok::APPEND) objsel(lexer)? else idxexpr(lexer)?; want(lexer, ltok::COMMA)?; + const value = expr(lexer)?; - let variadic: nullable *ast::expr = null; - let values: []*ast::expr = []; - for (true) { - if (try(lexer, ltok::RPAREN)? is lex::token) break; - - const expr = alloc(expr(lexer)?); - switch (want(lexer, ltok::COMMA, ltok::ELLIPSIS, ltok::RPAREN)?.0) { + let length: nullable *ast::expr = null; + let variadic = false; + match (try(lexer, ltok::COMMA, ltok::ELLIPSIS)?) { + case let tok: lex::token => + switch (tok.0) { case ltok::COMMA => - append(values, expr); + length = alloc(expr(lexer)?); case ltok::ELLIPSIS => - variadic = expr; - try(lexer, ltok::COMMA)?; - want(lexer, ltok::RPAREN)?; - break; - case ltok::RPAREN => - append(values, expr); - break; + variadic = true; case => abort(); }; + case void => void; }; + want(lexer, ltok::RPAREN)?; - synassert(lex::mkloc(lexer), variadic != null || len(values) != 0, - "Expected values to append")?; - - const expr = if (tok.0 == ltok::APPEND) ast::append_expr { - object = alloc(object), - variadic = variadic, - values = values, - is_static = is_static, - } else ast::insert_expr { + let expr = ast::append_expr { object = alloc(object), + value = alloc(value), + length = length, variadic = variadic, - values = values, is_static = is_static, }; + const expr = if (tok.0 == ltok::INSERT) { + yield expr: ast::insert_expr; + } else expr; return ast::expr { start = tok.2, diff --git a/hare/unparse/expr.ha b/hare/unparse/expr.ha @@ -107,36 +107,7 @@ fn _expr(ctx: *context, syn: *synfunc, e: ast::expr) (size | io::error) = { z += syn(ctx, ")", synkind::PUNCTUATION)?; return z; case let e: ast::append_expr => - let z = 0z; - if (e.is_static) { - z += syn(ctx, "static", synkind::KEYWORD)?; - z += space(ctx)?; - }; - z += syn(ctx, "append", synkind::KEYWORD)?; - z += syn(ctx, "(", synkind::PUNCTUATION)?; - z += _expr(ctx, syn, *e.object)?; - z += syn(ctx, ",", synkind::PUNCTUATION)?; - z += space(ctx)?; - for (let i = 0z; i < len(e.values); i += 1) { - let val = e.values[i]; - z += _expr(ctx, syn, *val)?; - if (i + 1 < len(e.values)) { - z += syn(ctx, ",", synkind::PUNCTUATION)?; - z += space(ctx)?; - }; - }; - match (e.variadic) { - case null => void; - case let v: *ast::expr => - if (len(e.values) != 0) { - z += syn(ctx, ",", synkind::PUNCTUATION)?; - z += space(ctx)?; - }; - z += _expr(ctx, syn, *v)?; - z += syn(ctx, "...", synkind::OPERATOR)?; - }; - z += syn(ctx, ")", synkind::PUNCTUATION)?; - return z; + return append_insert_expr(ctx, syn, e, false); case let e: ast::assert_expr => let z = 0z; if (e.is_static) { @@ -431,36 +402,7 @@ fn _expr(ctx: *context, syn: *synfunc, e: ast::expr) (size | io::error) = { }; return z; case let e: ast::insert_expr => - let z = 0z; - if (e.is_static) { - z += syn(ctx, "static", synkind::KEYWORD)?; - z += space(ctx)?; - }; - z += syn(ctx, "insert", synkind::KEYWORD)?; - z += syn(ctx, "(", synkind::PUNCTUATION)?; - z += _expr(ctx, syn, *e.object)?; - z += syn(ctx, ",", synkind::PUNCTUATION)?; - z += space(ctx)?; - for (let i = 0z; i < len(e.values); i += 1) { - let val = e.values[i]; - z += _expr(ctx, syn, *val)?; - if (i + 1 < len(e.values)) { - z += syn(ctx, ",", synkind::PUNCTUATION)?; - z += space(ctx)?; - }; - }; - match (e.variadic) { - case null => void; - case let v: *ast::expr => - if (len(e.values) != 0) { - z += syn(ctx, ",", synkind::PUNCTUATION)?; - z += space(ctx)?; - }; - z += _expr(ctx, syn, *v)?; - z += syn(ctx, "...", synkind::OPERATOR)?; - }; - z += syn(ctx, ")", synkind::PUNCTUATION)?; - return z; + return append_insert_expr(ctx, syn, e, true); case let e: ast::compound_expr => let z = 0z; if (e.label != "") { @@ -1067,3 +1009,34 @@ fn is_unary(e: *ast::expr) bool = { fn is_cast(e: *ast::expr) bool = { return is_unary(e) || (e.expr is ast::cast_expr); }; + +fn append_insert_expr( + ctx: *context, + syn: *synfunc, + e: ast::append_expr, + is_insert: bool, +) (size | io::error) = { + let z = 0z; + if (e.is_static) { + z += syn(ctx, "static", synkind::KEYWORD)?; + z += space(ctx)?; + }; + z += syn(ctx, if (is_insert) "insert" else "append", synkind::KEYWORD)?; + z += syn(ctx, "(", synkind::PUNCTUATION)?; + z += _expr(ctx, syn, *e.object)?; + z += syn(ctx, ",", synkind::PUNCTUATION)?; + z += space(ctx)?; + z += _expr(ctx, syn, *e.value)?; + if (e.variadic) { + z += syn(ctx, "...", synkind::OPERATOR)?; + }; + match (e.length) { + case null => void; + case let l: *ast::expr => + z += syn(ctx, ",", synkind::PUNCTUATION)?; + z += space(ctx)?; + z += _expr(ctx, syn, *l)?; + }; + z += syn(ctx, ")", synkind::PUNCTUATION)?; + return z; +};