hare

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

commit da96a44882f7fa364273245be61783fbb4748df1
parent 4730e0d18cbcc0bdab83c38f1ec9b4e1c8ca3b32
Author: Drew DeVault <sir@cmpwn.com>
Date:   Fri, 16 Apr 2021 08:26:39 -0400

hare::parse: implement call expressions

Diffstat:
Mhare/parse/+test/expr.ha | 8++++++++
Mhare/parse/expr.ha | 42++++++++++++++++++++++++++++++++++++++++--
Mhare/unparse/expr.ha | 23+++++++++++++++++++++--
3 files changed, 69 insertions(+), 4 deletions(-)

diff --git a/hare/parse/+test/expr.ha b/hare/parse/+test/expr.ha @@ -6,6 +6,14 @@ roundtrip("export fn main() void = 2 + -4 + void + true + \"hello\" + '?';\n"); }; +@test fn call() void = { + roundtrip("export fn main() void = test(); +export fn main() void = test(void, void, void); +export fn main() void = test(void, void, void...); +export fn main() void = test()()(void); +"); +}; + @test fn cast() void = { roundtrip("export fn main() void = void: int;\n" "export fn main() void = void as int;\n" diff --git a/hare/parse/expr.ha b/hare/parse/expr.ha @@ -59,6 +59,44 @@ fn builtin(lexer: *lex::lexer) (ast::expr | error) = { return postfix(lexer, void); }; +fn call(lexer: *lex::lexer, lvalue: ast::expr) (ast::expr | error) = { + let args: []*ast::expr = []; + let variadic = false; + + for (true) { + match (try(lexer, ltok::RPAREN)?) { + lex::token => break, + void => void, + }; + + append(args, alloc(expression(lexer)?)); + + match (try(lexer, ltok::ELLIPSIS)?) { + lex::token => { + variadic = true; + try(lexer, ltok::COMMA)?; + want(lexer, ltok::RPAREN)?; + break; + }, + void => void, + }; + + match (try(lexer, ltok::COMMA)?) { + lex::token => void, + void => { + want(lexer, ltok::RPAREN)?; + break; + }, + }; + }; + + return ast::call_expr { + lvalue = alloc(lvalue), + variadic = variadic, + args = args, + }; +}; + fn cast(lexer: *lex::lexer, lvalue: (ast::expr | void)) (ast::expr | error) = { const lvalue = match (lvalue) { void => unarithm(lexer)?, @@ -169,10 +207,10 @@ fn postfix(lexer: *lex::lexer, lvalue: (ast::expr | void)) (ast::expr | error) = ex: ast::expr => ex, }; - match (try(lexer, ltok::LPAREN, ltok::DOT, ltok::LBRACKET, + lvalue = match (try(lexer, ltok::LPAREN, ltok::DOT, ltok::LBRACKET, ltok::QUESTION)) { tok: lex::token => switch (tok.0) { - ltok::LPAREN => abort(), // TODO: Calls + ltok::LPAREN => call(lexer, lvalue)?, ltok::DOT => abort(), // TODO: Field access ltok::LBRACKET => abort(), // TODO: Indexing ltok::QUESTION => abort(), // TODO: Propagation diff --git a/hare/unparse/expr.ha b/hare/unparse/expr.ha @@ -9,7 +9,12 @@ export fn expr( t: ast::expr ) (size | io::error) = { return match (t) { - e: ast::access_expr => abort(), + e: ast::access_expr => match (e) { + id: ast::access_identifier => ident(out, id), + ix: ast::access_index => abort(), + fl: ast::access_field => abort(), + tp: ast::access_tuple => abort(), + }, e: ast::alloc_expr => abort(), e: ast::append_expr => abort(), e: ast::assert_expr => abort(), @@ -42,7 +47,21 @@ export fn expr( }, e: []ast::binding_expr => abort(), e: ast::break_expr => abort(), - e: ast::call_expr => abort(), + e: ast::call_expr => { + let z = expr(out, indent, *e.lvalue)?; + z += fmt::fprintf(out, "(")?; + for (let i = 0z; i < len(e.args); i += 1) { + z += expr(out, indent, *e.args[i])?; + if (i + 1 < len(e.args)) { + z += fmt::fprintf(out, ", ")?; + }; + }; + if (e.variadic) { + z += fmt::fprintf(out, "...")?; + }; + z += fmt::fprintf(out, ")")?; + z; + }, e: ast::cast_expr => { let z = expr(out, indent, *e.value)?; const op = switch (e.kind) {