commit b418d70857bd7262362b1a48f72f47f79622c03e
parent c475996982ec81275b76cb8b20386aa234cb9f94
Author: Sebastian <sebastian@sebsite.pw>
Date: Wed, 30 Aug 2023 20:25:46 -0400
hare::*: add never and remove @noreturn
Signed-off-by: Sebastian <sebastian@sebsite.pw>
Diffstat:
16 files changed, 47 insertions(+), 92 deletions(-)
diff --git a/cmd/harec/gen.ha b/cmd/harec/gen.ha
@@ -49,7 +49,6 @@ fn gen_func(ctx: *context, decl: *unit::decl) void = {
return; // Prototype
};
const fntype = fndecl.prototype.repr as types::func;
- assert(fntype.flags == 0);
ctx.serial = 0;
const ident = module::identuscore(fndecl.ident);
diff --git a/cmd/haredoc/hare.ha b/cmd/haredoc/hare.ha
@@ -183,9 +183,6 @@ fn unparse_hare(out: io::handle, d: ast::decl) (size | io::error) = {
yield "@test ";
})?;
let p = f.prototype.repr as ast::func_type;
- if (p.attrs & ast::func_attrs::NORETURN != 0) {
- n += fmt::fprint(out, "@noreturn ")?;
- };
if (len(f.symbol) != 0) {
n += fmt::fprintf(out, "@symbol(\"{}\") ",
f.symbol)?;
diff --git a/cmd/haredoc/html.ha b/cmd/haredoc/html.ha
@@ -501,9 +501,6 @@ fn unparse_html(out: io::handle, d: ast::decl) (size | io::error) = {
yield "@test ";
})?;
let p = f.prototype.repr as ast::func_type;
- if (p.attrs & ast::func_attrs::NORETURN != 0) {
- n += fmt::fprint(out, "@noreturn ")?;
- };
n += fmt::fprint(out, "<span class='keyword'>fn</span> ")?;
n += unparse::ident(out, f.ident)?;
n += prototype_html(out, 0,
@@ -718,10 +715,6 @@ fn type_html(
z += fmt::fprint(out, "*")?;
z += type_html(out, indent, *t.referent, brief)?;
case let t: ast::func_type =>
- if (t.attrs & ast::func_attrs::NORETURN == ast::func_attrs::NORETURN) {
- z += fmt::fprint(out, "@noreturn ")?;
- };
-
z += fmt::fprint(out, "<span class='keyword'>fn</span>(")?;
for (let i = 0z; i < len(t.params); i += 1) {
const param = t.params[i];
diff --git a/cmd/haredoc/tty.ha b/cmd/haredoc/tty.ha
@@ -222,11 +222,6 @@ fn unparse_tty(out: io::handle, d: ast::decl) (size | io::error) = {
n += render(out, syn::NORMAL)?;
let p = f.prototype.repr as ast::func_type;
- if (p.attrs & ast::func_attrs::NORETURN != 0) {
- n += render(out, syn::ATTRIBUTE)?;
- n += fmt::fprint(out, "@noreturn ")?;
- n += render(out, syn::NORMAL)?;
- };
if (len(f.symbol) != 0) {
n += render(out, syn::ATTRIBUTE)?;
n += fmt::fprintf(out, "@symbol(")?;
@@ -507,10 +502,6 @@ fn type_tty(
n += render(out, syn::PUNCTUATION)?;
n += fmt::fprint(out, "}")?;
case let f: ast::func_type =>
- if (f.attrs & ast::func_attrs::NORETURN != 0) {
- n += render(out, syn::ATTRIBUTE)?;
- n += fmt::fprint(out, "@noreturn ")?;
- };
n += render(out, syn::TYPE)?;
n += fmt::fprint(out, "fn")?;
n += prototype_tty(out, indent, f)?;
diff --git a/hare/ast/type.ha b/hare/ast/type.ha
@@ -12,8 +12,9 @@ export type alias_type = struct {
// A built-in primitive type (int, bool, str, etc).
export type builtin_type = enum {
- BOOL, F32, F64, FCONST, I16, I32, I64, I8, ICONST, INT, NULL, OPAQUE,
- RCONST, RUNE, SIZE, STR, U16, U32, U64, U8, UINT, UINTPTR, VALIST, VOID,
+ BOOL, F32, F64, FCONST, I16, I32, I64, I8, ICONST, INT, NEVER, NULL,
+ OPAQUE, RCONST, RUNE, SIZE, STR, U16, U32, U64, U8, UINT, UINTPTR,
+ VALIST, VOID,
};
// An enumeration field (and optional value).
@@ -37,12 +38,6 @@ export type variadism = enum {
HARE,
};
-// The attributes associated with a function type.
-export type func_attrs = enum uint {
- NONE = 0,
- NORETURN = 1 << 0,
-};
-
// A parameter to a function type.
export type func_param = struct {
loc: lex::location,
@@ -53,7 +48,6 @@ export type func_param = struct {
// fn(foo: int, baz: int...) int
export type func_type = struct {
result: *_type,
- attrs: func_attrs,
variadism: variadism,
params: []func_param,
};
diff --git a/hare/lex/token.ha b/hare/lex/token.ha
@@ -12,7 +12,6 @@ export type ltok = enum uint {
ATTR_FINI,
ATTR_INIT,
- ATTR_NORETURN,
ATTR_OFFSET,
ATTR_PACKED,
ATTR_SYMBOL,
@@ -53,6 +52,7 @@ export type ltok = enum uint {
LEN,
LET,
MATCH,
+ NEVER,
NULL,
NULLABLE,
OFFSET,
@@ -163,7 +163,6 @@ const bmap: [_]str = [
// Keep ordered with tok
"@fini",
"@init",
- "@noreturn",
"@offset",
"@packed",
"@symbol",
@@ -204,6 +203,7 @@ const bmap: [_]str = [
"len",
"let",
"match",
+ "never",
"null",
"nullable",
"offset",
diff --git a/hare/parse/+test/loc.ha b/hare/parse/+test/loc.ha
@@ -128,7 +128,7 @@ fn type_testloc(srcs: str...) void = for (let i = 0z; i < len(srcs); i += 1) {
type_testloc("foo", "...foo");
type_testloc("int");
type_testloc("enum { FOO = bar }");
- type_testloc("fn(foo: bar) baz", "@noreturn fn(foo: bar) baz");
+ type_testloc("fn(foo: bar) baz");
type_testloc("[foo]bar", "[*]foo", "[]foo", "[_]int");
type_testloc("*foo", "nullable *int");
type_testloc("struct { foo: bar }");
diff --git a/hare/parse/decl.ha b/hare/parse/decl.ha
@@ -126,10 +126,10 @@ fn decl_type(lexer: *lex::lexer) ([]ast::decl_type | error) = {
};
fn decl_func(lexer: *lex::lexer) (ast::decl_func | error) = {
- let attr = ast::fndecl_attrs::NONE, noreturn = false, sym = "";
+ let attr = ast::fndecl_attrs::NONE, sym = "";
const attrs = [
ltok::ATTR_FINI, ltok::ATTR_INIT, ltok::ATTR_TEST,
- ltok::ATTR_NORETURN, ltok::ATTR_SYMBOL
+ ltok::ATTR_SYMBOL
];
for (true) match (try(lexer, attrs...)?) {
case void =>
@@ -142,8 +142,6 @@ fn decl_func(lexer: *lex::lexer) (ast::decl_func | error) = {
attr = ast::fndecl_attrs::INIT;
case ltok::ATTR_TEST =>
attr = ast::fndecl_attrs::TEST;
- case ltok::ATTR_NORETURN =>
- noreturn = true;
case ltok::ATTR_SYMBOL =>
sym = attr_symbol(lexer)?;
case =>
@@ -157,9 +155,6 @@ fn decl_func(lexer: *lex::lexer) (ast::decl_func | error) = {
let proto_start = lex::mkloc(lexer);
let prototype = prototype(lexer)?;
let proto_end = lex::prevloc(lexer);
- if (noreturn) {
- prototype.attrs |= ast::func_attrs::NORETURN;
- };
let tok = want(lexer, ltok::EQUAL, ltok::SEMICOLON)?;
let body = switch (tok.0) {
diff --git a/hare/parse/type.ha b/hare/parse/type.ha
@@ -63,7 +63,6 @@ fn prototype(lexer: *lex::lexer) (ast::func_type | error) = {
let t = _type(lexer)?;
return ast::func_type {
result = alloc(t),
- attrs = ast::func_attrs::NONE,
variadism = variadism,
params = params,
};
@@ -126,6 +125,8 @@ fn primitive_type(lexer: *lex::lexer) (ast::_type | error) = {
yield builtin_type::VOID;
case ltok::OPAQUE =>
yield builtin_type::OPAQUE;
+ case ltok::NEVER =>
+ yield builtin_type::NEVER;
case =>
return syntaxerr(lex::mkloc(lexer),
"Unexected {}, was expecting primitive type",
@@ -221,15 +222,8 @@ fn tuple_type(
fn fn_type(lexer: *lex::lexer) (ast::_type | error) = {
const start = lex::mkloc(lexer);
- let attrs = match (try(lexer, ltok::ATTR_NORETURN)?) {
- case void =>
- yield ast::func_attrs::NONE;
- case =>
- yield ast::func_attrs::NORETURN;
- };
want(lexer, ltok::FN)?;
let proto = prototype(lexer)?;
- proto.attrs |= attrs;
return ast::_type {
start = start,
end = lex::prevloc(lexer),
@@ -482,7 +476,7 @@ export fn _type(lexer: *lex::lexer) (ast::_type | error) = {
ltok::U8, ltok::U16, ltok::U32, ltok::U64,
ltok::INT, ltok::UINT, ltok::UINTPTR, ltok::SIZE,
ltok::F32, ltok::F64,
- ltok::VALIST, ltok::VOID, ltok::OPAQUE =>
+ ltok::VALIST, ltok::VOID, ltok::OPAQUE, ltok::NEVER =>
yield primitive_type(lexer)?;
case ltok::ENUM =>
yield enum_type(lexer)?;
@@ -502,7 +496,7 @@ export fn _type(lexer: *lex::lexer) (ast::_type | error) = {
yield tuple_type(lexer, t, tok.2)?;
case => abort("unreachable");
};
- case ltok::ATTR_NORETURN, ltok::FN =>
+ case ltok::FN =>
yield fn_type(lexer)?;
case ltok::ELLIPSIS, ltok::NAME =>
yield alias_type(lexer)?;
diff --git a/hare/types/+test.ha b/hare/types/+test.ha
@@ -286,15 +286,14 @@ fn resolve(
let st = store(x86_64, &resolve, null);
defer store_free(st);
- let atype = parse_type("@noreturn fn() void");
+ let atype = parse_type("fn() never");
defer ast::type_finish(atype);
let htype = lookup(st, &atype)!;
assert(htype.sz == SIZE_UNDEFINED);
assert(htype._align == SIZE_UNDEFINED);
let f = htype.repr as func;
- assert(f.result.repr as builtin == builtin::VOID);
+ assert(f.result.repr as builtin == builtin::NEVER);
assert(f.variadism == variadism::NONE);
- assert(f.flags == func_flag::NORETURN);
assert(len(f.params) == 0);
let atype = parse_type("fn(foo: int, bar: str...) int");
@@ -305,7 +304,6 @@ fn resolve(
let f = htype.repr as func;
assert(f.result.repr as builtin == builtin::INT);
assert(f.variadism == variadism::HARE);
- assert(f.flags == 0);
assert(len(f.params) == 2);
assert(f.params[0].repr as builtin == builtin::INT);
assert(f.params[1].repr as builtin == builtin::STR);
@@ -322,8 +320,8 @@ fn resolve(
assert(htype._align == st.arch._int);
let t = htype.repr as tagged;
assert(len(t) == 2);
- assert(t[0].repr as builtin == builtin::VOID);
- assert(t[1].repr as builtin == builtin::INT);
+ assert(t[0].repr as builtin == builtin::INT);
+ assert(t[1].repr as builtin == builtin::VOID);
let atype = parse_type("(int | (int | str | void))");
defer ast::type_finish(atype);
@@ -332,9 +330,9 @@ fn resolve(
assert(htype._align == 8);
let t = htype.repr as tagged;
assert(len(t) == 3);
- assert(t[0].repr as builtin == builtin::VOID);
+ assert(t[0].repr as builtin == builtin::STR);
assert(t[1].repr as builtin == builtin::INT);
- assert(t[2].repr as builtin == builtin::STR);
+ assert(t[2].repr as builtin == builtin::VOID);
};
@test fn alias() void = {
diff --git a/hare/types/builtins.ha b/hare/types/builtins.ha
@@ -64,7 +64,15 @@ export const builtin_i64: _type = _type {
export const builtin_opaque: _type = _type {
repr = builtin::OPAQUE,
sz = SIZE_UNDEFINED, _align = SIZE_UNDEFINED,
- id = 461893804,
+ id = 2374983655,
+ ...
+};
+
+// [[_type]] representation of never.
+export const builtin_never: _type = _type {
+ repr = builtin::NEVER,
+ sz = SIZE_UNDEFINED, _align = SIZE_UNDEFINED,
+ id = 2374983655,
...
};
@@ -72,7 +80,7 @@ export const builtin_opaque: _type = _type {
export const builtin_rune: _type = _type {
repr = builtin::RUNE,
sz = 4, _align = 4,
- id = 2374983655,
+ id = 1737287038,
...
};
@@ -80,7 +88,7 @@ export const builtin_rune: _type = _type {
export const builtin_u8: _type = _type {
repr = builtin::U8,
sz = 1, _align = 1,
- id = 1906196061,
+ id = 1268499444,
...
};
@@ -88,7 +96,7 @@ export const builtin_u8: _type = _type {
export const builtin_u16: _type = _type {
repr = builtin::U16,
sz = 2, _align = 2,
- id = 2206074632,
+ id = 4119164483,
...
};
@@ -96,7 +104,7 @@ export const builtin_u16: _type = _type {
export const builtin_u32: _type = _type {
repr = builtin::U32,
sz = 4, _align = 4,
- id = 4119164483,
+ id = 3481467866,
...
};
@@ -104,7 +112,7 @@ export const builtin_u32: _type = _type {
export const builtin_u64: _type = _type {
repr = builtin::U64,
sz = 8, _align = 8,
- id = 3481467866,
+ id = 1906196061,
...
};
@@ -112,6 +120,6 @@ export const builtin_u64: _type = _type {
export const builtin_void: _type = _type {
repr = builtin::VOID,
sz = 0, _align = 0,
- id = 2543892678,
+ id = 3650376889,
...
};
diff --git a/hare/types/hash.ha b/hare/types/hash.ha
@@ -8,7 +8,7 @@ use strings;
// Keep ordered with respect to bootstrap harec:include/types.h
type storage = enum u8 {
- BOOL, F32, F64, I16, I32, I64, I8, INT, NULL, OPAQUE,
+ BOOL, F32, F64, I16, I32, I64, I8, INT, NEVER, NULL, OPAQUE,
RUNE, SIZE, STRING, U16, U32, U64, U8, UINT, UINTPTR, VOID, ALIAS,
ARRAY, ENUM, FUNCTION, POINTER, SLICE, STRUCT, TAGGED, TUPLE, UNION,
};
@@ -31,6 +31,8 @@ fn builtin_storage(b: builtin) u8 = {
return storage::I8;
case builtin::INT =>
return storage::INT;
+ case builtin::NEVER =>
+ return storage::NEVER;
case builtin::NULL =>
return storage::NULL;
case builtin::OPAQUE =>
@@ -132,7 +134,6 @@ export fn hash(t: *_type) u32 = {
case let f: func =>
write32(&id, hash(f.result));
write8(&id, f.variadism: u8);
- write8(&id, f.flags: u8);
for (let i = 0z; i < len(f.params); i += 1) {
write32(&id, hash(f.params[i]));
};
diff --git a/hare/types/store.ha b/hare/types/store.ha
@@ -259,6 +259,10 @@ fn fromast(store: *typestore, atype: *ast::_type) (_type | deferred | error) = {
sz = SIZE_UNDEFINED;
_align = SIZE_UNDEFINED;
yield builtin::OPAQUE;
+ case ast::builtin_type::NEVER =>
+ sz = SIZE_UNDEFINED;
+ _align = SIZE_UNDEFINED;
+ yield builtin::NEVER;
};
case let f: ast::func_type =>
yield func_from_ast(store, &f)?;
@@ -358,12 +362,8 @@ fn func_from_ast(
case ast::variadism::HARE =>
yield variadism::HARE;
},
- flags = 0,
params = alloc([], len(ft.params)),
};
- if (ft.attrs & ast::func_attrs::NORETURN != 0) {
- f.flags |= func_flag::NORETURN;
- };
for (let i = 0z; i < len(ft.params); i += 1) {
append(f.params, lookup(store, ft.params[i]._type)?);
};
diff --git a/hare/types/types.ha b/hare/types/types.ha
@@ -22,8 +22,9 @@ export type array = struct {
export type builtin = enum u8 {
// Keep me consistent with ast::builtin
- BOOL, F32, F64, FCONST, I16, I32, I64, I8, ICONST, INT, NULL, OPAQUE,
- RCONST, RUNE, SIZE, STR, U16, U32, U64, U8, UINT, UINTPTR, VALIST, VOID,
+ BOOL, F32, F64, FCONST, I16, I32, I64, I8, ICONST, INT, NEVER, NULL,
+ OPAQUE, RCONST, RUNE, SIZE, STR, U16, U32, U64, U8, UINT, UINTPTR,
+ VALIST, VOID,
};
// An enum type, e.g. enum { FOO = 0 }
@@ -39,17 +40,10 @@ export type variadism = enum {
HARE,
};
-// Indicats if a [[func]] has the @noreturn attribute
-export type func_flag = enum uint {
- NONE = 0,
- NORETURN = 1 << 0,
-};
-
// A function type, e.g. fn(x: int, y: int) int
export type func = struct {
result: const *_type,
variadism: variadism,
- flags: func_flag,
params: []const *_type,
};
diff --git a/hare/unparse/decl.ha b/hare/unparse/decl.ha
@@ -87,9 +87,6 @@ export fn decl(out: io::handle, d: ast::decl) (size | io::error) = {
yield "@test ";
})?;
let p = f.prototype.repr as ast::func_type;
- if (p.attrs & ast::func_attrs::NORETURN != 0) {
- n += fmt::fprint(out, "@noreturn ")?;
- };
if (len(f.symbol) != 0) {
n += fmt::fprintf(out, "@symbol(\"{}\") ",
f.symbol)?;
@@ -149,7 +146,6 @@ fn decl_test(d: ast::decl, expected: str) bool = {
flags = 0,
repr = ast::func_type {
result = &type_int,
- attrs = ast::func_attrs::NORETURN,
variadism = ast::variadism::HARE,
params = [
ast::func_param {
@@ -235,11 +231,10 @@ fn decl_test(d: ast::decl, expected: str) bool = {
body = void,
attrs = ast::fndecl_attrs::FINI,
};
- assert(decl_test(d, "@fini @noreturn @symbol(\"foo\") fn foo(foo: int, bar: int...) int;"));
+ assert(decl_test(d, "@fini @symbol(\"foo\") fn foo(foo: int, bar: int...) int;"));
type_fn.repr = ast::func_type {
result = &type_int,
- attrs = 0,
variadism = ast::variadism::NONE,
params = [
ast::func_param {
diff --git a/hare/unparse/type.ha b/hare/unparse/type.ha
@@ -31,6 +31,8 @@ case ast::builtin_type::I8 =>
yield "i8";
case ast::builtin_type::INT =>
yield "int";
+case ast::builtin_type::NEVER =>
+ yield "never";
case ast::builtin_type::NULL =>
yield "null";
case ast::builtin_type::OPAQUE =>
@@ -277,9 +279,6 @@ export fn _type(
};
n += fmt::fprint(out, "}")?;
case let f: ast::func_type =>
- if (f.attrs & ast::func_attrs::NORETURN != 0) {
- n += fmt::fprint(out, "@noreturn ")?;
- };
n += fmt::fprint(out, "fn")?;
n += prototype(out, indent, f)?;
case let l: ast::list_type =>
@@ -432,14 +431,12 @@ fn type_test(t: ast::_type, expected: str) void = {
t.repr = ast::func_type {
result = &type_int,
- attrs = 0,
variadism = variadism::NONE,
params = [],
};
type_test(t, "fn() int");
t.repr = ast::func_type {
result = &type_int,
- attrs = ast::func_attrs::NORETURN,
variadism = variadism::C,
params = [
ast::func_param {
@@ -449,10 +446,9 @@ fn type_test(t: ast::_type, expected: str) void = {
},
],
};
- type_test(t, "@noreturn fn(int, ...) int");
+ type_test(t, "fn(int, ...) int");
t.repr = ast::func_type {
result = &type_int,
- attrs = 0,
variadism = variadism::HARE,
params = [
ast::func_param {