commit 6779fab30939b61a427f0934f068539f1e6717c1
parent 73c5481ef5b2d36af642a3cb715b6247c632b82d
Author: Drew DeVault <sir@cmpwn.com>
Date: Thu, 2 Sep 2021 12:20:43 +0200
hare::unit: partially implement compound exprs
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
9 files changed, 67 insertions(+), 11 deletions(-)
diff --git a/cmd/harec/gen.ha b/cmd/harec/gen.ha
@@ -79,8 +79,8 @@ fn gen_func(ctx: *context, decl: *unit::decl) void = {
fn gen_expr(ctx: *context, expr: *unit::expr) value = {
match (expr.expr) {
+ unit::compound_expr => abort(), // TODO
unit::constant_expr => return gen_expr_const(ctx, expr),
- * => abort(), // TODO
};
};
diff --git a/hare/unit/check.ha b/hare/unit/check.ha
@@ -1,11 +1,6 @@
use hare::ast;
use hare::types;
-type context = struct {
- store: *types::typestore,
- scope: *scope,
-};
-
// Type checks a set of [[hare::ast::subunit]]s and determines if it is
// logically consistent, then returns the corresponding [[unit]], which from
// then on is guaranteed to be compilable.
@@ -16,7 +11,7 @@ export fn check(
) (unit | error) = {
let ctx = context {
store = store,
- scope = alloc(scope { ... }),
+ scope = alloc(scope { class = scope_class::UNIT, ... }),
};
scan(&ctx, subunits)?;
return process(&ctx, subunits);
diff --git a/hare/unit/context.ha b/hare/unit/context.ha
@@ -0,0 +1,6 @@
+use hare::types;
+
+type context = struct {
+ store: *types::typestore,
+ scope: *scope,
+};
diff --git a/hare/unit/expr.ha b/hare/unit/expr.ha
@@ -8,8 +8,11 @@ export type expr = struct {
end: lex::location,
result: const *types::_type,
terminates: bool,
- expr: (constant_expr | void),
+ expr: (compound_expr | constant_expr | void),
};
+// A compound expression, i.e. { ... }
+export type compound_expr = []*expr;
+
// The value of a constant expression.
export type constant_expr = ast::value; // TODO: composite types
diff --git a/hare/unit/process.ha b/hare/unit/process.ha
@@ -82,7 +82,7 @@ fn process_expr(
ast::break_expr => abort(), // TODO
ast::call_expr => abort(), // TODO
ast::cast_expr => abort(), // TODO
- ast::compound_expr => abort(), // TODO
+ ast::compound_expr => process_compound(ctx, expr),
ast::constant_expr => process_constant(ctx, expr),
ast::continue_expr => abort(), // TODO
ast::defer_expr => abort(), // TODO
@@ -101,6 +101,36 @@ fn process_expr(
ast::unarithm_expr => abort(), // TODO
};
+fn process_compound(ctx: *context, aexpr: *ast::expr) (*expr | error) = {
+ const compound = aexpr.expr as ast::compound_expr;
+ const scope = scope_push(ctx, scope_class::COMPOUND);
+
+ let exprs: compound_expr = [];
+ for (let i = 0z; i < len(compound.exprs); i += 1) {
+ append(exprs, process_expr(ctx, compound.exprs[i])?);
+ };
+
+ scope_pop(ctx);
+ return alloc(expr {
+ start = aexpr.start,
+ end = aexpr.end,
+ result = &types::builtin_void, // TODO: Pick result type
+ expr = exprs,
+ });
+};
+
+@test fn compound() void = {
+ const ctx = mktestctx();
+ defer freetestctx(&ctx);
+ const aexpr = parse_expr("{ void; void; void; }");
+ defer ast::expr_free(aexpr);
+ const expr = process_compound(&ctx, aexpr)!;
+ assert(expr.result.repr as types::builtin == types::builtin::VOID);
+ const compound = expr.expr as compound_expr;
+ assert(len(compound) == 3);
+ // TODO: test yields
+};
+
fn process_constant(ctx: *context, aexpr: *ast::expr) (*expr | error) = {
const constexpr = aexpr.expr as ast::constant_expr;
// TODO: Tuple unpacking
diff --git a/hare/unit/scan.ha b/hare/unit/scan.ha
@@ -8,7 +8,7 @@ fn scan(ctx: *context, subunits: const []ast::subunit) (void | error) = {
let subunit = &subunits[i];
assert(len(subunit.imports) == 0); // TODO
- // TODO: Allocate scope
+ scope_push(ctx, scope_class::SUBUNIT);
for (let j = 0z; j < len(subunit.decls); j += 1) {
let decl = &subunit.decls[j];
match (scan_decl(ctx, decl)) {
@@ -17,6 +17,7 @@ fn scan(ctx: *context, subunits: const []ast::subunit) (void | error) = {
error => abort(), // TODO
};
};
+ scope_pop(ctx);
};
};
diff --git a/hare/unit/scope.ha b/hare/unit/scope.ha
@@ -26,14 +26,26 @@ export type object = struct {
export def SCOPE_BUCKETS: size = 4096;
+export type scope_class = enum {
+ COMPOUND,
+ ENUM,
+ FUNC,
+ LOOP,
+ MATCH,
+ SUBUNIT,
+ UNIT,
+};
+
export type scope = struct {
+ class: scope_class,
parent: nullable *scope,
objects: []object,
hashmap: [SCOPE_BUCKETS][]*object,
};
-fn scope_push(ctx: *context) *scope = {
+fn scope_push(ctx: *context, class: scope_class) *scope = {
let new = alloc(scope {
+ class = class,
parent = ctx.scope,
...
});
@@ -41,6 +53,12 @@ fn scope_push(ctx: *context) *scope = {
return new;
};
+fn scope_pop(ctx: *context) *scope = {
+ const scope = ctx.scope;
+ ctx.scope = ctx.scope.parent: *scope; // TODO: as *scope
+ return scope;
+};
+
fn scope_insert(ctx: *context, obj: object) void = {
const scope = ctx.scope;
append(scope.objects, obj);
diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib
@@ -383,6 +383,7 @@ hare_types() {
gensrcs_hare_unit() {
gen_srcs hare::unit \
check.ha \
+ context.ha \
errors.ha \
expr.ha \
process.ha \
diff --git a/stdlib.mk b/stdlib.mk
@@ -698,6 +698,7 @@ $(HARECACHE)/hare/types/hare_types.ssa: $(stdlib_hare_types_srcs) $(stdlib_rt) $
# hare::unit
stdlib_hare_unit_srcs= \
$(STDLIB)/hare/unit/check.ha \
+ $(STDLIB)/hare/unit/context.ha \
$(STDLIB)/hare/unit/errors.ha \
$(STDLIB)/hare/unit/expr.ha \
$(STDLIB)/hare/unit/process.ha \
@@ -1926,6 +1927,7 @@ $(TESTCACHE)/hare/types/hare_types.ssa: $(testlib_hare_types_srcs) $(testlib_rt)
# hare::unit
testlib_hare_unit_srcs= \
$(STDLIB)/hare/unit/check.ha \
+ $(STDLIB)/hare/unit/context.ha \
$(STDLIB)/hare/unit/errors.ha \
$(STDLIB)/hare/unit/expr.ha \
$(STDLIB)/hare/unit/process.ha \