hare

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

commit f95b8556f86c1758fe3cf5d8b31b22add1f6a45e
parent 2d570e4371baf7ec84884c279171c7eaca759571
Author: Sebastian <sebastian@sebsite.pw>
Date:   Thu, 21 Apr 2022 15:41:01 -0400

ast, lex, parse, unparse: vaargs updates

Implements: https://todo.sr.ht/~sircmpwn/hare/594
Signed-off-by: Sebastian <sebastian@sebsite.pw>

Diffstat:
Mhare/ast/expr.ha | 29++++++++++++++++++++++++++++-
Mhare/ast/type.ha | 2+-
Mhare/lex/token.ha | 8++++++++
Mhare/module/scan.ha | 2+-
Mhare/parse/+test/expr.ha | 3+++
Mhare/parse/+test/loc.ha | 1+
Mhare/parse/expr.ha | 31++++++++++++++++++++++++++++++-
Mhare/parse/type.ha | 4+++-
Mhare/unparse/expr.ha | 15+++++++++++++++
Mhare/unparse/type.ha | 2++
10 files changed, 92 insertions(+), 5 deletions(-)

diff --git a/hare/ast/expr.ha b/hare/ast/expr.ha @@ -382,6 +382,24 @@ export type unarithm_expr = struct { operand: *expr, }; +// A vastart expression. +// +// vastart() +export type vastart_expr = void; + +// A vaarg expression. +// +// vaarg(ap) +export type vaarg_expr = *expr; + +// A vaend expression. +// +// vaend(ap) +export type vaend_expr = *expr; + +// A C-style variadic expression. +export type variadic_expr = (vastart_expr | vaarg_expr | vaend_expr); + // A yield expression. // // yield foo @@ -400,7 +418,8 @@ export type expr = struct { defer_expr | delete_expr | for_expr | free_expr | if_expr | insert_expr | compound_expr | match_expr | len_expr | size_expr | offset_expr | propagate_expr | return_expr | - slice_expr | switch_expr | unarithm_expr | yield_expr), + slice_expr | switch_expr | unarithm_expr | variadic_expr | + yield_expr), }; // Frees resources associated with a Hare [[expr]]ession. @@ -568,6 +587,14 @@ case let e: expr => free(s.cases); case let u: unarithm_expr => expr_free(u.operand); + case let v: variadic_expr => + match (v) { + case vastart_expr => void; + case let v: vaarg_expr => + expr_free(v); + case let v: vaend_expr => + expr_free(v); + }; case let y: yield_expr => free(y.label); expr_free(y.value); diff --git a/hare/ast/type.ha b/hare/ast/type.ha @@ -13,7 +13,7 @@ export type alias_type = struct { // A built-in primitive type (int, bool, str, etc). export type builtin_type = enum { BOOL, CHAR, F32, F64, FCONST, I16, I32, I64, I8, ICONST, INT, NULL, - RUNE, SIZE, STR, U16, U32, U64, U8, UINT, UINTPTR, VOID, + RUNE, SIZE, STR, U16, U32, U64, U8, UINT, UINTPTR, VALIST, VOID, }; // An enumeration field (and optional value). diff --git a/hare/lex/token.ha b/hare/lex/token.ha @@ -71,6 +71,10 @@ export type ltok = enum uint { UINTPTR, UNION, USE, + VAARG, + VAEND, + VALIST, + VASTART, VOID, YIELD, LAST_KEYWORD = YIELD, @@ -216,6 +220,10 @@ const bmap: [_]str = [ "uintptr", "union", "use", + "vaarg", + "vaend", + "valist", + "vastart", "void", "yield", "=>", diff --git a/hare/module/scan.ha b/hare/module/scan.ha @@ -18,7 +18,7 @@ use sort; use strings; use strio; -def ABI_VERSION: u8 = 3; +def ABI_VERSION: u8 = 4; // Scans the files in a directory for eligible build inputs and returns a // [[version]] which includes all applicable files and their dependencies. diff --git a/hare/parse/+test/expr.ha b/hare/parse/+test/expr.ha @@ -73,6 +73,9 @@ len([1, 2, 3, 4]); offset(foo.bar); size(u32); + vastart(); + vaarg(va); + vaend(va); }; `); }; diff --git a/hare/parse/+test/loc.ha b/hare/parse/+test/loc.ha @@ -67,6 +67,7 @@ fn expr_testloc(srcs: str...) void = for (let i = 0z; i < len(srcs); i += 1) { expr_testloc("switch (foo) { case => bar; }"); expr_testloc("foo[bar..baz]"); expr_testloc("&foo"); + expr_testloc("vastart()", "vaarg(ap)", "vaend(ap)"); // We want to check the location of nested expressions, so this can't // use expr_testloc diff --git a/hare/parse/expr.ha b/hare/parse/expr.ha @@ -353,7 +353,7 @@ fn builtin(lexer: *lex::lexer) (ast::expr | error) = { const tok = match (peek(lexer, ltok::ALLOC, ltok::APPEND, ltok::FREE, ltok::DELETE, ltok::ABORT, ltok::ASSERT, ltok::INSERT, ltok::STATIC, ltok::SIZE, ltok::LEN, ltok::OFFSET, - ltok::DEFER)?) { + ltok::DEFER, ltok::VASTART, ltok::VAARG, ltok::VAEND)?) { case let tok: lex::token => yield tok; case void => @@ -402,6 +402,35 @@ fn builtin(lexer: *lex::lexer) (ast::expr | error) = { end = lex::prevloc(lexer), expr = expr: ast::defer_expr, }; + case ltok::VASTART => + want(lexer, ltok::VASTART)?; + want(lexer, ltok::LPAREN)?; + want(lexer, ltok::RPAREN)?; + return ast::expr { + start = tok.2, + end = lex::prevloc(lexer), + expr = void: ast::vastart_expr: ast::variadic_expr, + }; + case ltok::VAARG => + want(lexer, ltok::VAARG)?; + want(lexer, ltok::LPAREN)?; + const expr = alloc(expr(lexer)?); + want(lexer, ltok::RPAREN)?; + return ast::expr { + start = tok.2, + end = lex::prevloc(lexer), + expr = expr: ast::vaarg_expr: ast::variadic_expr, + }; + case ltok::VAEND => + want(lexer, ltok::VAEND)?; + want(lexer, ltok::LPAREN)?; + const expr = alloc(expr(lexer)?); + want(lexer, ltok::RPAREN)?; + return ast::expr { + start = tok.2, + end = lex::prevloc(lexer), + expr = expr: ast::vaend_expr: ast::variadic_expr, + }; case => abort(); // Invariant }; }; diff --git a/hare/parse/type.ha b/hare/parse/type.ha @@ -121,6 +121,8 @@ fn primitive_type(lexer: *lex::lexer) (ast::_type | error) = { yield builtin_type::F64; case ltok::BOOL => yield builtin_type::BOOL; + case ltok::VALIST => + yield builtin_type::VALIST; case ltok::VOID => yield builtin_type::VOID; case => @@ -463,7 +465,7 @@ export fn _type(lexer: *lex::lexer) (ast::_type | error) = { ltok::INT, ltok::SIZE, ltok::U16, ltok::U32, ltok::U64, ltok::U8, ltok::UINT, ltok::UINTPTR, ltok::RUNE, ltok::STR, ltok::F32, ltok::F64, ltok::BOOL, - ltok::VOID, ltok::TYPE => + ltok::VALIST, ltok::VOID, ltok::TYPE => yield primitive_type(lexer)?; case ltok::ENUM => yield enum_type(lexer)?; diff --git a/hare/unparse/expr.ha b/hare/unparse/expr.ha @@ -379,6 +379,21 @@ export fn expr( })?; z += expr(out, indent, *e.operand)?; return z; + case let e: ast::variadic_expr => + match (e) { + case ast::vastart_expr => + return fmt::fprint(out, "vastart()")?; + case let e: ast::vaarg_expr => + let z = fmt::fprint(out, "vaarg(")?; + z += expr(out, indent, *e)?; + z += fmt::fprint(out, ")")?; + return z; + case let e: ast::vaend_expr => + let z = fmt::fprint(out, "vaend(")?; + z += expr(out, indent, *e)?; + z += fmt::fprint(out, ")")?; + return z; + }; case let e: ast::yield_expr => let z = fmt::fprint(out, "yield")?; if (e.label != "") { diff --git a/hare/unparse/type.ha b/hare/unparse/type.ha @@ -52,6 +52,8 @@ case ast::builtin_type::UINT => yield "uint"; case ast::builtin_type::UINTPTR => yield "uintptr"; +case ast::builtin_type::VALIST => + yield "valist"; case ast::builtin_type::VOID => yield "void"; };