commit 7f3283f2e743611463be7f1fe7b1bf0d92a78f24
parent 07c4c8efb39a29d5accfdd79a0581930e697104e
Author: Joe Finney <me@spxtr.net>
Date: Sun, 10 Mar 2024 14:23:13 +0000
Update hare::parse for optional function params.
Signed-off-by: Joe Finney <me@spxtr.net>
Diffstat:
5 files changed, 34 insertions(+), 2 deletions(-)
diff --git a/hare/ast/type.ha b/hare/ast/type.ha
@@ -42,6 +42,7 @@ export type func_param = struct {
loc: lex::location,
name: str,
_type: *_type,
+ default_value: (void | expr),
};
// fn(foo: int, baz: int...) int
diff --git a/hare/parse/+test/types.ha b/hare/parse/+test/types.ha
@@ -129,7 +129,7 @@ export type foo = fn(
long_type_name,
blablablabla,
multiple_lines,
- and_stuff,
+ and_stuff = 4,
) void;
export type foo = fn(
diff --git a/hare/parse/type.ha b/hare/parse/type.ha
@@ -28,6 +28,7 @@ fn prototype(lexer: *lex::lexer) (ast::func_type | error) = {
loc = loc,
name = "",
_type = alloc(name_or_type),
+ default_value = void,
});
case lex::token =>
// Bit of a hack because we can't unlex twice.
@@ -39,8 +40,15 @@ fn prototype(lexer: *lex::lexer) (ast::func_type | error) = {
loc = loc,
name = ns[0],
_type = alloc(_type(lexer)?),
+ default_value = void,
});
};
+ match (try(lexer, ltok::EQUAL)?) {
+ case void =>
+ yield void;
+ case lex::token =>
+ params[len(params) - 1].default_value = expr(lexer)?;
+ };
match (try(lexer, ltok::ELLIPSIS)?) {
case lex::token =>
variadism = ast::variadism::HARE;
diff --git a/hare/unparse/decl.ha b/hare/unparse/decl.ha
@@ -181,6 +181,7 @@ fn decl_test(d: *ast::decl, expected: str) bool = {
decl(&buf, &syn_nowrap, d)!;
let s = memio::string(&buf)!;
defer free(s);
+ fmt::println(s)!;
return s == expected;
};
@@ -208,11 +209,13 @@ fn decl_test(d: *ast::decl, expected: str) bool = {
loc = loc,
name = "foo",
_type = &type_int,
+ default_value = void,
},
ast::func_param {
loc = loc,
name = "bar",
_type = &type_int,
+ default_value = void,
},
],
},
@@ -297,6 +300,14 @@ fn decl_test(d: *ast::decl, expected: str) bool = {
loc = loc,
name = "",
_type = &type_int,
+ default_value = ast::expr {
+ expr = ast::number_literal {
+ value = 4u64,
+ sign = false,
+ suff = lex::ltok::LIT_ICONST,
+ },
+ ...
+ },
},
],
};
@@ -307,5 +318,5 @@ fn decl_test(d: *ast::decl, expected: str) bool = {
body = &expr_void,
attrs = 0,
};
- assert(decl_test(&d, "fn foo(int) int = void;"));
+ assert(decl_test(&d, "fn foo(int = 4) int = void;"));
};
diff --git a/hare/unparse/type.ha b/hare/unparse/type.ha
@@ -78,6 +78,15 @@ fn prototype(
n += space(ctx)?;
};
n += __type(ctx, syn, param._type)?;
+ match (param.default_value) {
+ case void =>
+ yield;
+ case let e: ast::expr =>
+ n += space(ctx)?;
+ n += syn(ctx, "=", synkind::PUNCTUATION)?;
+ n += space(ctx)?;
+ n += _expr(ctx, syn, &e)?;
+ };
if (i + 1 < len(t.params) || t.variadism == variadism::C) {
n += syn(ctx, ",", synkind::PUNCTUATION)?;
n += space(ctx)?;
@@ -396,6 +405,7 @@ fn type_test(t: *ast::_type, expected: str) void = {
loc = loc,
name = "",
_type = &type_int,
+ default_value = void,
},
],
};
@@ -408,11 +418,13 @@ fn type_test(t: *ast::_type, expected: str) void = {
loc = loc,
name = "foo",
_type = &type_int,
+ default_value = void,
},
ast::func_param {
loc = loc,
name = "bar",
_type = &type_int,
+ default_value = void,
},
],
};