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:
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;
+};