hare

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

commit cb4abcbad7c204d2ab84f34970f1ffd57cc786c8
parent bc8d0bf21145131f7ce3cb4d399ecc3cd10213a6
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sat, 21 Aug 2021 11:47:42 +0200

hare::unit: fill in more bones

Signed-off-by: Drew DeVault <sir@cmpwn.com>

Diffstat:
Mhare/unit/check.ha | 11+----------
Ahare/unit/expr.ha | 17+++++++++++++++++
Ahare/unit/process.ha | 103+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mhare/unit/unit.ha | 6+++++-
Mscripts/gen-stdlib | 18++++++++++++++++++
Mstdlib.mk | 40++++++++++++++++++++++++++++++++++++++++
6 files changed, 184 insertions(+), 11 deletions(-)

diff --git a/hare/unit/check.ha b/hare/unit/check.ha @@ -3,7 +3,6 @@ use hare::types; type context = struct { store: *types::typestore, - unit: *unit, scope: *scope, }; @@ -15,18 +14,10 @@ export fn check( ident: ast::ident, subunits: const []ast::subunit, ) (unit | error) = { - let unit = unit { - ident = ident, - decls = [], - }; let ctx = context { store = store, - unit = &unit, scope = alloc(scope { ... }), }; - scan(&ctx, subunits)?; - // TODO: validate - - return unit; + return process(&ctx, subunits); }; diff --git a/hare/unit/expr.ha b/hare/unit/expr.ha @@ -0,0 +1,17 @@ +use hare::lex; +use hare::types; + +// A type-checked and validated Hare expression. +export type expr = struct { + start: lex::location, + end: lex::location, + result: const *types::_type, + terminates: bool, + expr: (constant_expr | void), +}; + +// The value "null". +export type _null = void; + +// The value of a constant expression. +export type constant_expr = (void | bool | _null | lex::value); // TODO: composite types diff --git a/hare/unit/process.ha b/hare/unit/process.ha @@ -0,0 +1,103 @@ +use hare::ast; +use hare::types; + +fn process(ctx: *context, subunits: const []ast::subunit) (unit | error) = { + let unit = unit { + ident = [], // TODO + decls = [], + }; + + for (let i = 0z; i < len(subunits); i += 1) { + let subunit = subunits[i]; + for (let j = 0z; j < len(subunit.decls); j += 1) { + let adecl = &subunit.decls[j]; + let decl = match (process_decl(ctx, adecl)) { + d: decl => d, + error => abort(), // TODO + }; + append(unit.decls, decl); + }; + }; + + return unit; +}; + +fn process_decl( + ctx: *context, + decl: *ast::decl, +) (decl | error) = { + // TODO: match on &decl.decl + match (decl.decl) { + co: []ast::decl_const => abort(), // TODO + gl: []ast::decl_global => abort(), // TODO + ty: []ast::decl_type => abort(), // TODO + fu: ast::decl_func => process_func(ctx, decl, fu), + }; +}; + +fn process_func( + ctx: *context, + adecl: *ast::decl, + func: ast::decl_func, +) (decl | error) = { + assert(func.attrs & ast::fndecl_attrs::TEST == 0); // TODO + const afndecl = adecl.decl as ast::decl_func; + const prototype = types::lookup(ctx.store, &func.prototype)!; + const fntype = prototype._type as types::func; + assert(fntype.variadism == types::variadism::NONE); // TODO + assert(len(fntype.params) == 0); // TODO + + let body: nullable *expr = null; + // TODO: Change the afndecl body field to nullable *ast::expr + if (afndecl.body is ast::expr) { + const abody = afndecl.body as ast::expr; + body = process_expr(ctx, &abody)?; + }; + + return decl { + exported = adecl.exported, + loc = adecl.loc, + decl = decl_func { + symbol = afndecl.symbol, + // TODO: Add namespace to ident + ident = ast::ident_dup(afndecl.ident), + prototype = prototype, + body = body, + // TODO: We should make these enums inherited + attrs = afndecl.attrs: fndecl_attrs, + }, + }; +}; + +fn process_expr( + ctx: *context, + expr: *ast::expr, +) (*expr | error) = match (expr.expr) { + ast::access_expr => abort(), // TODO + ast::alloc_expr => abort(), // TODO + ast::append_expr => abort(), // TODO + ast::assert_expr => abort(), // TODO + ast::assign_expr => abort(), // TODO + ast::binarithm_expr => abort(), // TODO + ast::binding_expr => abort(), // TODO + ast::break_expr => abort(), // TODO + ast::call_expr => abort(), // TODO + ast::cast_expr => abort(), // TODO + ast::constant_expr => abort(), // TODO + ast::continue_expr => abort(), // TODO + ast::defer_expr => abort(), // TODO + ast::delete_expr => abort(), // TODO + ast::for_expr => abort(), // TODO + ast::free_expr => abort(), // TODO + ast::if_expr => abort(), // TODO + ast::list_expr => abort(), // TODO + ast::match_expr => abort(), // TODO + ast::len_expr => abort(), // TODO + ast::size_expr => abort(), // TODO + ast::offset_expr => abort(), // TODO + ast::propagate_expr => abort(), // TODO + ast::return_expr => abort(), // TODO + ast::slice_expr => abort(), // TODO + ast::switch_expr => abort(), // TODO + ast::unarithm_expr => abort(), // TODO +}; diff --git a/hare/unit/unit.ha b/hare/unit/unit.ha @@ -2,6 +2,7 @@ use hare::ast; use hare::lex; use hare::types; +// Attributes applicable to a function declaration. export type fndecl_attrs = enum { NONE, FINI, @@ -9,20 +10,23 @@ export type fndecl_attrs = enum { TEST, }; +// A function declaration. export type decl_func = struct { symbol: str, ident: ast::ident, prototype: const *types::_type, - //body: (expr | void), TODO + body: nullable *expr, attrs: fndecl_attrs, }; +// A declaration within a unit. export type decl = struct { exported: bool, loc: lex::location, decl: (decl_func | void), // TODO: Other decl types }; +// A single compilation unit, representing all of the members of a namespace. export type unit = struct { ident: ast::ident, decls: []decl, diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib @@ -383,6 +383,23 @@ hare_types() { gen_ssa hare::types hare::ast hare::parse hash hash::fnv endian } +gensrcs_hare_unit() { + gen_srcs hare::unit \ + check.ha \ + errors.ha \ + expr.ha \ + process.ha \ + scan.ha \ + scope.ha \ + unit.ha \ + $* +} + +hare_unit() { + gensrcs_hare_unit + gen_ssa hare::unit hare::ast hare::types hash hash::fnv strings hare::lex +} + hare_unparse() { gen_srcs hare::unparse \ expr.ha \ @@ -857,6 +874,7 @@ hare::lex hare::module hare::parse hare::types +hare::unit hare::unparse hash hash::adler32 diff --git a/stdlib.mk b/stdlib.mk @@ -197,6 +197,10 @@ hare_stdlib_deps+=$(stdlib_hare_parse) stdlib_hare_types=$(HARECACHE)/hare/types/hare_types.o hare_stdlib_deps+=$(stdlib_hare_types) +# gen_lib hare::unit +stdlib_hare_unit=$(HARECACHE)/hare/unit/hare_unit.o +hare_stdlib_deps+=$(stdlib_hare_unit) + # gen_lib hare::unparse stdlib_hare_unparse=$(HARECACHE)/hare/unparse/hare_unparse.o hare_stdlib_deps+=$(stdlib_hare_unparse) @@ -702,6 +706,22 @@ $(HARECACHE)/hare/types/hare_types.ssa: $(stdlib_hare_types_srcs) $(stdlib_rt) $ @HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Nhare::types \ -t$(HARECACHE)/hare/types/hare_types.td $(stdlib_hare_types_srcs) +# hare::unit +stdlib_hare_unit_srcs= \ + $(STDLIB)/hare/unit/check.ha \ + $(STDLIB)/hare/unit/errors.ha \ + $(STDLIB)/hare/unit/expr.ha \ + $(STDLIB)/hare/unit/process.ha \ + $(STDLIB)/hare/unit/scan.ha \ + $(STDLIB)/hare/unit/scope.ha \ + $(STDLIB)/hare/unit/unit.ha + +$(HARECACHE)/hare/unit/hare_unit.ssa: $(stdlib_hare_unit_srcs) $(stdlib_rt) $(stdlib_hare_ast) $(stdlib_hare_types) $(stdlib_hash) $(stdlib_hash_fnv) $(stdlib_strings) $(stdlib_hare_lex) + @printf 'HAREC \t$@\n' + @mkdir -p $(HARECACHE)/hare/unit + @HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Nhare::unit \ + -t$(HARECACHE)/hare/unit/hare_unit.td $(stdlib_hare_unit_srcs) + # hare::unparse stdlib_hare_unparse_srcs= \ $(STDLIB)/hare/unparse/expr.ha \ @@ -1396,6 +1416,10 @@ hare_testlib_deps+=$(testlib_hare_parse) testlib_hare_types=$(TESTCACHE)/hare/types/hare_types.o hare_testlib_deps+=$(testlib_hare_types) +# gen_lib hare::unit +testlib_hare_unit=$(TESTCACHE)/hare/unit/hare_unit.o +hare_testlib_deps+=$(testlib_hare_unit) + # gen_lib hare::unparse testlib_hare_unparse=$(TESTCACHE)/hare/unparse/hare_unparse.o hare_testlib_deps+=$(testlib_hare_unparse) @@ -1918,6 +1942,22 @@ $(TESTCACHE)/hare/types/hare_types.ssa: $(testlib_hare_types_srcs) $(testlib_rt) @HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nhare::types \ -t$(TESTCACHE)/hare/types/hare_types.td $(testlib_hare_types_srcs) +# hare::unit +testlib_hare_unit_srcs= \ + $(STDLIB)/hare/unit/check.ha \ + $(STDLIB)/hare/unit/errors.ha \ + $(STDLIB)/hare/unit/expr.ha \ + $(STDLIB)/hare/unit/process.ha \ + $(STDLIB)/hare/unit/scan.ha \ + $(STDLIB)/hare/unit/scope.ha \ + $(STDLIB)/hare/unit/unit.ha + +$(TESTCACHE)/hare/unit/hare_unit.ssa: $(testlib_hare_unit_srcs) $(testlib_rt) $(testlib_hare_ast) $(testlib_hare_types) $(testlib_hash) $(testlib_hash_fnv) $(testlib_strings) $(testlib_hare_lex) + @printf 'HAREC \t$@\n' + @mkdir -p $(TESTCACHE)/hare/unit + @HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nhare::unit \ + -t$(TESTCACHE)/hare/unit/hare_unit.td $(testlib_hare_unit_srcs) + # hare::unparse testlib_hare_unparse_srcs= \ $(STDLIB)/hare/unparse/expr.ha \