hare

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

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:
Mcmd/harec/gen.ha | 2+-
Mhare/unit/check.ha | 7+------
Ahare/unit/context.ha | 6++++++
Mhare/unit/expr.ha | 5++++-
Mhare/unit/process.ha | 32+++++++++++++++++++++++++++++++-
Mhare/unit/scan.ha | 3++-
Mhare/unit/scope.ha | 20+++++++++++++++++++-
Mscripts/gen-stdlib | 1+
Mstdlib.mk | 2++
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 \