hare

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

commit 24c7a700cc30f1a9fa27d82483efc5a5585d9607
parent 2621ec2fcb906c4363a4f750b6b5ca5248ff0997
Author: Drew DeVault <sir@cmpwn.com>
Date:   Thu, 15 Apr 2021 11:53:15 -0400

hare::parse: parse constant expressions

Diffstat:
Mhare/ast/expr.ha | 5++++-
Mhare/parse/+test/expr.ha | 4++++
Mhare/parse/expr.ha | 29++++++++++++++++++++++++++---
Mhare/unparse/expr.ha | 26+++++++++++++++++++++-----
4 files changed, 55 insertions(+), 9 deletions(-)

diff --git a/hare/ast/expr.ha b/hare/ast/expr.ha @@ -137,8 +137,11 @@ export type struct_constant = struct { // (foo, bar, ...) export type tuple_constant = []*expr; +// The value "null". +export type _null = void; + // A constant -export type constant_expr = (void | lex::value | array_constant | +export type constant_expr = (void | bool | _null | lex::value | array_constant | struct_constant | tuple_constant); // continue :label diff --git a/hare/parse/+test/expr.ha b/hare/parse/+test/expr.ha @@ -2,6 +2,10 @@ roundtrip("export fn main() void = void + void * void / void;\n"); }; +@test fn constant() void = { + roundtrip("export fn main() void = 2 + -4 + void + true;\n"); +}; + @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 @@ -65,8 +65,31 @@ fn cast(lexer: *lex::lexer, lvalue: (ast::expr | void)) (ast::expr | error) = { }; fn constant(lexer: *lex::lexer) (ast::expr | error) = { - want(lexer, ltok::VOID)?; - return void; + let tok = want(lexer)?; + return switch (tok.0) { + ltok::LIT_U8, + ltok::LIT_U16, + ltok::LIT_U32, + ltok::LIT_U64, + ltok::LIT_UINT, + ltok::LIT_SIZE, + ltok::LIT_I8, + ltok::LIT_I16, + ltok::LIT_I32, + ltok::LIT_I64, + ltok::LIT_INT, + ltok::LIT_ICONST, + ltok::LIT_F32, + ltok::LIT_F64, + ltok::LIT_FCONST, + ltok::LIT_RUNE, + ltok::LIT_STR => tok.1, + ltok::VOID => void, + ltok::TRUE => true, + ltok::FALSE => false, + ltok::NULL => ast::_null, + * => syntaxerr(mkloc(lexer), "Expected constant expression"), + }; }; fn control_statement(lexer: *lex::lexer) (ast::expr | error) = { @@ -79,7 +102,7 @@ fn objsel(lexer: *lex::lexer) (ast::expr | error) = { fn plain_expression(lexer: *lex::lexer) (ast::expr | error) = { let tok = peek(lexer)? as lex::token; - if (tok.0 > ltok::LAST_BTOK && tok.0 >= ltok::LAST_LITERAL) { + if (tok.0 >= ltok::LIT_U8 && tok.0 <= ltok::LAST_LITERAL) { return constant(lexer); }; return switch (tok.0) { diff --git a/hare/unparse/expr.ha b/hare/unparse/expr.ha @@ -1,8 +1,8 @@ use io; use fmt; use hare::ast; +use hare::lex; -// TODO export fn expr( out: *io::stream, indent: size, @@ -54,10 +54,7 @@ export fn expr( z += _type(out, indent, *e._type)?; z; }, - e: ast::constant_expr => { - assert(e is void); - fmt::fprint(out, "void")?; - }, + e: ast::constant_expr => constant(out, indent, e)?, e: ast::continue_expr => abort(), e: ast::defer_expr => abort(), e: ast::delete_expr => abort(), @@ -87,3 +84,22 @@ export fn expr( }, }; }; + +fn constant( + out: *io::stream, + indent: size, + e: ast::constant_expr, +) (size | io::error) = { + return match (e) { + void => fmt::fprint(out, "void"), + ast::_null => fmt::fprint(out, "null"), + b: bool => fmt::fprint(out, b), + v: lex::value => fmt::fprint(out, match (v) { + v: (str | rune | i64 | u64 | f64) => v, + void => abort(), + }), + ast::array_constant => abort(), // TODO + ast::struct_constant => abort(), // TODO + ast::tuple_constant => abort(), // TODO + }; +};