commit 696aefd5b69e84fef0dd837a3aa2aece46c7044f
parent df58525ba5493bd23d74902555a2cb25257b5105
Author: Sebastian <sebastian@sebsite.pw>
Date: Sun, 1 Oct 2023 00:57:30 -0400
hare::ast: pass around pointers
We won't see much benefit from this until matching on pointers is
implemented, but this at least updates the interface.
References: https://todo.sr.ht/~sircmpwn/hare/378
Signed-off-by: Sebastian <sebastian@sebsite.pw>
Diffstat:
7 files changed, 167 insertions(+), 112 deletions(-)
diff --git a/cmd/hare/build/types.ha b/cmd/hare/build/types.ha
@@ -95,7 +95,9 @@ export fn ctx_finish(ctx: *context) void = {
for (let i = 0z; i < len(ctx.defines); i += 1) {
ast::ident_free(ctx.defines[i].ident);
ast::type_finish(ctx.defines[i]._type);
+ free(ctx.defines[i]._type);
ast::expr_finish(ctx.defines[i].init);
+ free(ctx.defines[i].init);
};
free(ctx.defines);
free(ctx.libdirs);
diff --git a/cmd/haretype/main.ha b/cmd/haretype/main.ha
@@ -27,7 +27,7 @@ fn typeinfo(
const lexer = lex::init(&stream, "-");
defer lex::finish(&lexer);
const atype = parse::_type(&lexer)?;
- defer ast::type_finish(atype);
+ defer ast::type_finish(&atype);
const typ = types::lookup(store, &atype)?;
unparse::_type(os::stdout, &unparse::syn_nowrap, atype)?;
fmt::println()?;
diff --git a/hare/ast/decl.ha b/hare/ast/decl.ha
@@ -72,25 +72,33 @@ export fn decl_finish(d: decl) void = {
free(g[i].symbol);
ident_free(g[i].ident);
type_finish(g[i]._type);
+ free(g[i]._type);
expr_finish(g[i].init);
+ free(g[i].init);
};
free(g);
case let t: []decl_type =>
for (let i = 0z; i < len(t); i += 1) {
ident_free(t[i].ident);
- type_finish(t[i]._type);
+ type_finish(&t[i]._type);
};
free(t);
case let f: decl_func =>
free(f.symbol);
ident_free(f.ident);
- type_finish(f.prototype);
- if (f.body is expr) expr_finish(f.body as expr);
+ type_finish(&f.prototype);
+ match (f.body) {
+ case let e: expr =>
+ expr_finish(&e);
+ case void => void;
+ };
case let c: []decl_const =>
for (let i = 0z; i < len(c); i += 1) {
ident_free(c[i].ident);
type_finish(c[i]._type);
+ free(c[i]._type);
expr_finish(c[i].init);
+ free(c[i].init);
};
free(c);
};
diff --git a/hare/ast/expr.ha b/hare/ast/expr.ha
@@ -433,15 +433,9 @@ export type expr = struct {
};
// Frees resources associated with a Hare [[expr]]ession.
-export fn expr_finish(e: (expr | nullable *expr)) void = match (e) {
-case let e: nullable *expr =>
- match (e) {
- case null => void;
- case let e: *expr =>
- expr_finish(*e);
- free(e);
- };
-case let e: expr =>
+export fn expr_finish(e: nullable *expr) void = match (e) {
+case null => void;
+case let e: *expr =>
match (e.expr) {
case let a: access_expr =>
match (a) {
@@ -449,32 +443,49 @@ case let e: expr =>
ident_free(i);
case let i: access_index =>
expr_finish(i.object);
+ free(i.object);
expr_finish(i.index);
+ free(i.index);
case let f: access_field =>
expr_finish(f.object);
+ free(f.object);
free(f.field);
case let t: access_tuple =>
expr_finish(t.object);
+ free(t.object);
expr_finish(t.value);
+ free(t.value);
};
case let a: align_expr =>
- type_finish(a: *_type);
+ type_finish(a);
+ free(a);
case let a: alloc_expr =>
expr_finish(a.init);
+ free(a.init);
expr_finish(a.capacity);
+ free(a.capacity);
case let a: append_expr =>
expr_finish(a.object);
+ free(a.object);
expr_finish(a.value);
+ free(a.value);
expr_finish(a.length);
+ free(a.length);
case let a: assert_expr =>
expr_finish(a.cond);
+ free(a.cond);
expr_finish(a.message);
+ free(a.message);
case let a: assign_expr =>
expr_finish(a.object);
+ free(a.object);
expr_finish(a.value);
+ free(a.value);
case let b: binarithm_expr =>
expr_finish(b.lvalue);
+ free(b.lvalue);
expr_finish(b.rvalue);
+ free(b.rvalue);
case let b: binding_expr =>
for (let i = 0z; i < len(b.bindings); i += 1) {
match (b.bindings[i].name) {
@@ -491,23 +502,30 @@ case let e: expr =>
free(u);
};
type_finish(b.bindings[i]._type);
+ free(b.bindings[i]._type);
expr_finish(b.bindings[i].init);
+ free(b.bindings[i].init);
};
free(b.bindings);
case let b: break_expr =>
free(b);
case let c: call_expr =>
expr_finish(c.lvalue);
+ free(c.lvalue);
for (let i = 0z; i < len(c.args); i += 1) {
expr_finish(c.args[i]);
+ free(c.args[i]);
};
free(c.args);
case let c: cast_expr =>
expr_finish(c.value);
+ free(c.value);
type_finish(c._type);
+ free(c._type);
case let c: compound_expr =>
for (let i = 0z; i < len(c.exprs); i += 1) {
expr_finish(c.exprs[i]);
+ free(c.exprs[i]);
};
free(c.exprs);
free(c.label);
@@ -516,13 +534,15 @@ case let e: expr =>
case let a: array_constant =>
for (let i = 0z; i < len(a.values); i += 1) {
expr_finish(a.values[i]);
+ free(a.values[i]);
};
free(a.values);
case let s: struct_constant =>
- struct_constant_finish(s);
+ struct_constant_finish(&s);
case let t: tuple_constant =>
for (let i = 0z; i < len(t); i += 1) {
expr_finish(t[i]);
+ free(t[i]);
};
free(t);
case (value | number_constant) => void;
@@ -530,94 +550,128 @@ case let e: expr =>
case let c: continue_expr =>
free(c);
case let d: defer_expr =>
- expr_finish(d: *expr);
+ expr_finish(d);
+ free(d);
case let d: delete_expr =>
expr_finish(d.object);
+ free(d.object);
case let e: error_assert_expr =>
expr_finish(e);
+ free(e);
case let f: for_expr =>
expr_finish(f.bindings);
+ free(f.bindings);
expr_finish(f.cond);
+ free(f.cond);
expr_finish(f.afterthought);
+ free(f.afterthought);
expr_finish(f.body);
+ free(f.body);
case let f: free_expr =>
- expr_finish(f: *expr);
+ expr_finish(f);
+ free(f);
case let i: if_expr =>
expr_finish(i.cond);
+ free(i.cond);
expr_finish(i.tbranch);
+ free(i.tbranch);
expr_finish(i.fbranch);
+ free(i.fbranch);
case let e: insert_expr =>
expr_finish(e.object);
+ free(e.object);
expr_finish(e.value);
+ free(e.value);
expr_finish(e.length);
+ free(e.length);
case let l: len_expr =>
- expr_finish(l: *expr);
+ expr_finish(l);
+ free(l);
case let m: match_expr =>
expr_finish(m.value);
+ free(m.value);
for (let i = 0z; i < len(m.cases); i += 1) {
free(m.cases[i].name);
type_finish(m.cases[i]._type);
+ free(m.cases[i]._type);
const exprs = m.cases[i].exprs;
for (let i = 0z; i < len(exprs); i += 1) {
expr_finish(exprs[i]);
+ free(exprs[i]);
};
free(exprs);
};
free(m.cases);
case let o: offset_expr =>
- expr_finish(o: *expr);
+ expr_finish(o);
+ free(o);
case let p: propagate_expr =>
expr_finish(p);
+ free(p);
case let r: return_expr =>
- expr_finish(r: *expr);
+ expr_finish(r);
+ free(r);
case let s: size_expr =>
- type_finish(s: *_type);
+ type_finish(s);
+ free(s);
case let s: slice_expr =>
expr_finish(s.object);
+ free(s.object);
expr_finish(s.start);
+ free(s.start);
expr_finish(s.end);
+ free(s.end);
case let s: switch_expr =>
expr_finish(s.value);
+ free(s.value);
for (let i = 0z; i < len(s.cases); i += 1) {
let opts = s.cases[i].options;
for (let j = 0z; j < len(opts); j += 1) {
expr_finish(opts[j]);
+ free(opts[j]);
};
free(opts);
let exprs = s.cases[i].exprs;
for (let j = 0z; j < len(exprs); j += 1) {
expr_finish(exprs[j]);
+ free(exprs[j]);
};
free(exprs);
};
free(s.cases);
case let u: unarithm_expr =>
expr_finish(u.operand);
+ free(u.operand);
case let v: variadic_expr =>
match (v) {
case vastart_expr => void;
case let v: vaarg_expr =>
expr_finish(v);
+ free(v);
case let v: vaend_expr =>
expr_finish(v);
+ free(v);
};
case let y: yield_expr =>
free(y.label);
expr_finish(y.value);
+ free(y.value);
};
};
-fn struct_constant_finish(s: struct_constant) void = {
+fn struct_constant_finish(s: *struct_constant) void = {
ident_free(s.alias);
for (let i = 0z; i < len(s.fields); i += 1) {
match (s.fields[i]) {
case let v: struct_value =>
free(v.name);
type_finish(v._type);
+ free(v._type);
expr_finish(v.init);
+ free(v.init);
case let c: *struct_constant =>
- struct_constant_finish(*c);
+ struct_constant_finish(c);
free(c);
};
};
diff --git a/hare/ast/type.ha b/hare/ast/type.ha
@@ -133,26 +133,19 @@ export type _type = struct {
tagged_type | tuple_type),
};
-fn struct_type_finish(t: (struct_type | union_type)) void = {
- let membs = match (t) {
- case let s: struct_type =>
- yield s.members: []struct_member;
- case let u: union_type =>
- yield u: []struct_member;
- };
+fn struct_members_free(membs: []struct_member) void = {
for (let i = 0z; i < len(membs); i += 1) {
free(membs[i].docs);
- match (membs[i]._offset) {
- case null => void;
- case let e: *expr =>
- expr_finish(e);
- };
+ expr_finish(membs[i]._offset);
+ free(membs[i]._offset);
match (membs[i].member) {
case let f: struct_field =>
free(f.name);
type_finish(f._type);
+ free(f._type);
case let e: struct_embedded =>
- type_finish(e: *_type);
+ type_finish(e);
+ free(e);
case let a: struct_alias =>
ident_free(a);
};
@@ -161,58 +154,56 @@ fn struct_type_finish(t: (struct_type | union_type)) void = {
};
// Frees resources associated with a [[_type]].
-export fn type_finish(t: (_type | nullable *_type)) void = {
- match (t) {
- case let t: nullable *_type =>
- match (t) {
- case null => void;
- case let t: *_type =>
- type_finish(*t);
- free(t);
+export fn type_finish(t: nullable *_type) void = match (t) {
+case null => void;
+case let t: *_type =>
+ match (t.repr) {
+ case let a: alias_type =>
+ ident_free(a.ident);
+ case builtin_type => void;
+ case let e: enum_type =>
+ for (let i = 0z; i < len(e.values); i += 1) {
+ free(e.values[i].name);
+ expr_finish(e.values[i].value);
+ free(e.values[i].value);
};
- case let t: _type =>
- match (t.repr) {
- case let a: alias_type =>
- ident_free(a.ident);
- case builtin_type => void;
- case let e: enum_type =>
- for (let i = 0z; i < len(e.values); i += 1) {
- free(e.values[i].name);
- match (e.values[i].value) {
- case null => void;
- case let v: *expr =>
- expr_finish(v);
- };
- };
- free(e.values);
- case let f: func_type =>
- type_finish(f.result);
- for (let i = 0z; i < len(f.params); i += 1) {
- free(f.params[i].name);
- type_finish(f.params[i]._type);
- };
- free(f.params);
- case let l: list_type =>
- match (l.length) {
- case let e: *expr =>
- expr_finish(e);
- case => void;
- };
- type_finish(l.members);
- case let p: pointer_type =>
- type_finish(p.referent);
- case let s: (struct_type | union_type) =>
- struct_type_finish(s);
- case let t: tagged_type =>
- for (let i = 0z; i < len(t); i += 1) {
- type_finish(t[i]);
- };
- free(t);
- case let t: tuple_type =>
- for (let i = 0z; i < len(t); i += 1) {
- type_finish(t[i]);
- };
- free(t);
+ free(e.values);
+ case let f: func_type =>
+ type_finish(f.result);
+ free(f.result);
+ for (let i = 0z; i < len(f.params); i += 1) {
+ free(f.params[i].name);
+ type_finish(f.params[i]._type);
+ free(f.params[i]._type);
};
+ free(f.params);
+ case let l: list_type =>
+ match (l.length) {
+ case let e: *expr =>
+ expr_finish(e);
+ free(e);
+ case => void;
+ };
+ type_finish(l.members);
+ free(l.members);
+ case let p: pointer_type =>
+ type_finish(p.referent);
+ free(p.referent);
+ case let s: struct_type =>
+ struct_members_free(s.members);
+ case let t: tagged_type =>
+ for (let i = 0z; i < len(t); i += 1) {
+ type_finish(t[i]);
+ free(t[i]);
+ };
+ free(t);
+ case let t: tuple_type =>
+ for (let i = 0z; i < len(t); i += 1) {
+ type_finish(t[i]);
+ free(t[i]);
+ };
+ free(t);
+ case let u: union_type =>
+ struct_members_free(u);
};
};
diff --git a/hare/parse/+test/loc.ha b/hare/parse/+test/loc.ha
@@ -21,7 +21,7 @@ fn expr_testloc(srcs: str...) void = for (let i = 0z; i < len(srcs); i += 1) {
fmt::errorfln("{}: {}", srcs[i], strerror(err))!;
abort();
};
- defer ast::expr_finish(exp);
+ defer ast::expr_finish(&exp);
let runes = 0z;
let d = utf8::decode(srcs[i]);
for (true) match (utf8::next(&d)!) {
@@ -86,7 +86,7 @@ fn expr_testloc(srcs: str...) void = for (let i = 0z; i < len(srcs); i += 1) {
fmt::errorln(strerror(err))!;
abort();
};
- defer ast::expr_finish(exp);
+ defer ast::expr_finish(&exp);
assert(exp.start.line == 1 && exp.start.col == 1);
assert(exp.end.line == 1 && exp.end.col == 13);
let c = exp.expr as ast::cast_expr;
@@ -110,7 +110,7 @@ fn type_testloc(srcs: str...) void = for (let i = 0z; i < len(srcs); i += 1) {
fmt::errorln(strerror(err))!;
abort();
};
- defer ast::type_finish(typ);
+ defer ast::type_finish(&typ);
let runes = 0z;
let d = utf8::decode(srcs[i]);
for (true) match (utf8::next(&d)!) {
diff --git a/hare/types/+test.ha b/hare/types/+test.ha
@@ -21,7 +21,7 @@ fn parse_type(in: str) ast::_type = {
defer store_free(st);
let atype = parse_type("int");
- defer ast::type_finish(atype);
+ defer ast::type_finish(&atype);
let htype = lookup(st, &atype)!;
assert(htype.repr as builtin == builtin::INT);
assert(htype.sz == x86_64._int && htype._align == x86_64._int);
@@ -30,7 +30,7 @@ fn parse_type(in: str) ast::_type = {
assert(htype == type2, "types should be singletons");
let atype = parse_type("*int");
- defer ast::type_finish(atype);
+ defer ast::type_finish(&atype);
let htype = lookup(st, &atype)!;
assert(htype.sz == x86_64._pointer && htype._align == x86_64._pointer);
let htype = htype.repr as pointer;
@@ -55,7 +55,7 @@ fn resolve(
// Basic struct
let atype = parse_type("struct { x: int, y: int }");
- defer ast::type_finish(atype);
+ defer ast::type_finish(&atype);
let htype = lookup(st, &atype)!;
assert(htype.sz == 8);
assert(htype._align == 4);
@@ -75,7 +75,7 @@ fn resolve(
// Basic union
let atype = parse_type("union { x: int, y: int }");
- defer ast::type_finish(atype);
+ defer ast::type_finish(&atype);
let htype = lookup(st, &atype)!;
assert(htype.sz == 4);
assert(htype._align == 4);
@@ -95,7 +95,7 @@ fn resolve(
// Padding
let atype = parse_type("struct { w: u8, x: u32, y: u8, z: u64 }");
- defer ast::type_finish(atype);
+ defer ast::type_finish(&atype);
let htype = lookup(st, &atype)!;
assert(htype.sz == 24);
assert(htype._align == 8);
@@ -112,13 +112,13 @@ fn resolve(
assert(z.offs == 16);
let atype = parse_type("struct { x: u8, y: size, z: u8 }");
- defer ast::type_finish(atype);
+ defer ast::type_finish(&atype);
let htype = lookup(st, &atype)!;
assert(htype.sz == 24);
// Sort order
let atype = parse_type("struct { z: u8, y: u8, x: u8, q: u8 }");
- defer ast::type_finish(atype);
+ defer ast::type_finish(&atype);
let htype = lookup(st, &atype)!;
let stype = htype.repr as _struct;
assert(stype.fields[0].name == "q");
@@ -136,7 +136,7 @@ fn resolve(
},
p: int,
}");
- defer ast::type_finish(atype);
+ defer ast::type_finish(&atype);
let htype = lookup(st, &atype)!;
assert(htype.sz == 20);
assert(htype._align == 4);
@@ -162,7 +162,7 @@ fn resolve(
},
p: int,
}");
- defer ast::type_finish(atype);
+ defer ast::type_finish(&atype);
let htype = lookup(st, &atype)!;
assert(htype.sz == 16);
assert(htype._align == 4);
@@ -190,7 +190,7 @@ fn resolve(
@offset(16) y: int,
@offset(32) z: int,
}");
- defer ast::type_finish(atype);
+ defer ast::type_finish(&atype);
let htype = lookup(st, &atype)!;
assert(htype.sz == 36);
assert(htype._align == 4);
@@ -209,7 +209,7 @@ fn resolve(
// Basic case
let atype = parse_type("(int, int)");
- defer ast::type_finish(atype);
+ defer ast::type_finish(&atype);
let htype = lookup(st, &atype)!;
assert(htype.sz == 8);
assert(htype._align == 4);
@@ -223,7 +223,7 @@ fn resolve(
// Padding
let atype = parse_type("(i8, i32, i8, i64)");
- defer ast::type_finish(atype);
+ defer ast::type_finish(&atype);
let htype = lookup(st, &atype)!;
assert(htype.sz == 24);
assert(htype._align == 8);
@@ -241,7 +241,7 @@ fn resolve(
// Slice
let atype = parse_type("[]int");
- defer ast::type_finish(atype);
+ defer ast::type_finish(&atype);
let htype = lookup(st, &atype)!;
assert(htype.sz == 24);
assert(htype._align == 8);
@@ -250,7 +250,7 @@ fn resolve(
// Normal array
let atype = parse_type("[5]i32");
- defer ast::type_finish(atype);
+ defer ast::type_finish(&atype);
let htype = lookup(st, &atype)!;
assert(htype.sz == 4 * 5);
assert(htype._align == 4);
@@ -260,7 +260,7 @@ fn resolve(
// Unbounded array
let atype = parse_type("[*]i32");
- defer ast::type_finish(atype);
+ defer ast::type_finish(&atype);
let htype = lookup(st, &atype)!;
assert(htype.sz == SIZE_UNDEFINED);
assert(htype._align == 4);
@@ -270,7 +270,7 @@ fn resolve(
// Contextual array (equivalent to unbounded at this compilation stage)
let atype = parse_type("[_]i32");
- defer ast::type_finish(atype);
+ defer ast::type_finish(&atype);
let htype = lookup(st, &atype)!;
assert(htype.sz == SIZE_UNDEFINED);
assert(htype._align == 4);
@@ -284,7 +284,7 @@ fn resolve(
defer store_free(st);
let atype = parse_type("fn() never");
- defer ast::type_finish(atype);
+ defer ast::type_finish(&atype);
let htype = lookup(st, &atype)!;
assert(htype.sz == SIZE_UNDEFINED);
assert(htype._align == SIZE_UNDEFINED);
@@ -294,7 +294,7 @@ fn resolve(
assert(len(f.params) == 0);
let atype = parse_type("fn(foo: int, bar: str...) int");
- defer ast::type_finish(atype);
+ defer ast::type_finish(&atype);
let htype = lookup(st, &atype)!;
assert(htype.sz == SIZE_UNDEFINED);
assert(htype._align == SIZE_UNDEFINED);
@@ -311,7 +311,7 @@ fn resolve(
defer store_free(st);
let atype = parse_type("(int | int | void)");
- defer ast::type_finish(atype);
+ defer ast::type_finish(&atype);
let htype = lookup(st, &atype)!;
assert(htype.sz == st.arch._int * 2);
assert(htype._align == st.arch._int);
@@ -321,7 +321,7 @@ fn resolve(
assert(t[1].repr as builtin == builtin::VOID);
let atype = parse_type("(int | (int | str | void))");
- defer ast::type_finish(atype);
+ defer ast::type_finish(&atype);
let htype = lookup(st, &atype)!;
assert(htype.sz == 32);
assert(htype._align == 8);
@@ -344,7 +344,7 @@ fn resolve(
assert((al.repr as alias).secondary == of);
const atype = parse_type("myalias");
- defer ast::type_finish(atype);
+ defer ast::type_finish(&atype);
const htype = lookup(st, &atype)!;
assert(htype == al);
};
@@ -354,7 +354,7 @@ fn resolve(
defer store_free(st);
const atype = parse_type("myalias");
- defer ast::type_finish(atype);
+ defer ast::type_finish(&atype);
const htype = lookup(st, &atype)!;
assert((htype.repr as alias).secondary == null);