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:
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 \