commit abbddbb92bc983a79d9f23396d6cff90e1f5ceba
parent d5c8418cc83900114ef139ea3d9e24989c371460
Author: Sebastian <sebastian@sebsite.pw>
Date: Tue, 17 Oct 2023 21:07:21 -0400
hare::*: implement local constant definitions
Signed-off-by: Sebastian <sebastian@sebsite.pw>
Diffstat:
5 files changed, 44 insertions(+), 9 deletions(-)
diff --git a/hare/ast/expr.ha b/hare/ast/expr.ha
@@ -144,12 +144,19 @@ export type binding = struct {
// (foo, _, bar)
export type binding_unpack = [](str | void);
+// The kind of binding expression being used.
+export type binding_kind = enum {
+ CONST,
+ DEF,
+ LET,
+};
+
// A variable binding expression.
//
// let foo: int = bar, ...
export type binding_expr = struct {
is_static: bool,
- is_const: bool,
+ kind: binding_kind,
bindings: []binding,
};
diff --git a/hare/parse/+test/expr_test.ha b/hare/parse/+test/expr_test.ha
@@ -40,6 +40,7 @@
const z: int = 42, q: int = 24;
const (foo, bar): (int, bool) = (42, true);
const (foo, _, bar): (int, uint, bool) = (42, 12u, true);
+ def X: int = 1337, y = 7331;
static let p: int = 62893, o = 39826;
static const w: int = 62893, t = 39826;
};
diff --git a/hare/parse/expr.ha b/hare/parse/expr.ha
@@ -320,7 +320,17 @@ fn binding_unpack(lexer: *lex::lexer) (ast::binding_unpack | error) = {
fn binding(lexer: *lex::lexer, is_static: bool) (ast::expr | error) = {
const loc = lex::mkloc(lexer);
- const is_const = want(lexer, ltok::LET, ltok::CONST)?.0 == ltok::CONST;
+ const tok = want(lexer, ltok::DEF, ltok::CONST, ltok::LET)?.0;
+ const kind = switch (tok) {
+ case ltok::DEF =>
+ assert(!is_static);
+ yield ast::binding_kind::DEF;
+ case ltok::CONST =>
+ yield ast::binding_kind::CONST;
+ case ltok::LET =>
+ yield ast::binding_kind::LET;
+ case => abort(); // unreachable
+ };
let bindings: []ast::binding = [];
for (true) {
@@ -329,6 +339,10 @@ fn binding(lexer: *lex::lexer, is_static: bool) (ast::expr | error) = {
case ltok::NAME =>
yield value as str;
case ltok::LPAREN =>
+ if (kind == ast::binding_kind::DEF) {
+ return syntaxerr(lex::mkloc(lexer),
+ "Can't use tuple unpacking with def");
+ };
yield binding_unpack(lexer)?;
case => abort();
};
@@ -354,7 +368,7 @@ fn binding(lexer: *lex::lexer, is_static: bool) (ast::expr | error) = {
end = lex::prevloc(lexer),
expr = ast::binding_expr {
is_static = is_static,
- is_const = is_const,
+ kind = kind,
bindings = bindings,
},
};
@@ -631,7 +645,7 @@ fn compound_expr(lexer: *lex::lexer) (ast::expr | error) = {
};
fn stmt(lexer: *lex::lexer) (ast::expr | error) = {
- const expr = match (try(lexer, ltok::DEFER,
+ const expr = match (try(lexer, ltok::DEFER, ltok::DEF,
ltok::LET, ltok::CONST, ltok::STATIC)?) {
case let tok: lex::token =>
yield switch (tok.0) {
@@ -642,7 +656,7 @@ fn stmt(lexer: *lex::lexer) (ast::expr | error) = {
end = lex::prevloc(lexer),
expr = expr: ast::defer_expr,
};
- case ltok::LET, ltok::CONST =>
+ case ltok::DEF, ltok::CONST, ltok::LET =>
lex::unlex(lexer, tok);
yield binding(lexer, false)?;
case ltok::STATIC =>
@@ -667,12 +681,19 @@ fn for_expr(lexer: *lex::lexer) (ast::expr | error) = {
want(lexer, ltok::LPAREN)?;
const bindings: nullable *ast::expr =
- match (peek(lexer, ltok::LET, ltok::CONST, ltok::STATIC)?) {
+ match (peek(lexer, ltok::DEF, ltok::LET, ltok::CONST,
+ ltok::STATIC)?) {
case void =>
yield null;
case let tok: lex::token =>
let is_static = if (tok.0 == ltok::STATIC) {
want(lexer, ltok::STATIC)?;
+ match (peek(lexer, ltok::LET, ltok::CONST)?) {
+ case lex::token => void;
+ case void =>
+ want(lexer, ltok::LET, ltok::CONST)?;
+ abort(); // unreachable
+ };
yield true;
} else false;
const bindings = alloc(binding(lexer, is_static)?);
diff --git a/hare/unit/process.ha b/hare/unit/process.ha
@@ -174,7 +174,7 @@ fn process_access(ctx: *context, aexpr: *ast::expr) (*expr | error) = {
fn process_binding(ctx: *context, aexpr: *ast::expr) (*expr | error) = {
const bind = aexpr.expr as ast::binding_expr;
- assert(!bind.is_static && !bind.is_const); // TODO
+ assert(!bind.is_static && bind.kind == ast::binding_kind::LET);
let bindings: bindings = [];
for (let i = 0z; i < len(bind.bindings); i += 1) {
diff --git a/hare/unparse/expr.ha b/hare/unparse/expr.ha
@@ -235,8 +235,14 @@ fn _expr(ctx: *context, syn: *synfunc, e: ast::expr) (size | io::error) = {
z += syn(ctx, "static", synkind::KEYWORD)?;
z += space(ctx)?;
};
- z += syn(ctx, if (e.is_const) "const" else "let",
- synkind::KEYWORD)?;
+ switch (e.kind) {
+ case ast::binding_kind::DEF =>
+ z += syn(ctx, "def", synkind::KEYWORD)?;
+ case ast::binding_kind::CONST =>
+ z += syn(ctx, "const", synkind::KEYWORD)?;
+ case ast::binding_kind::LET =>
+ z += syn(ctx, "let", synkind::KEYWORD)?;
+ };
z += space(ctx)?;
for (let i = 0z; i < len(e.bindings); i += 1) {
let binding = e.bindings[i];