commit 746bf5fbf39a71158ce936ad8434df61cfde55a4
parent f3cba36f7dd88255d3a0730de472522fb6ef54ba
Author: Drew DeVault <sir@cmpwn.com>
Date: Sun, 30 Apr 2023 11:55:37 +0200
hare::ast, hare::parse: def/let/const w/o type
This implements AST and parse support for:
def x = 10;
let x = 10;
const x = 10;
i.e. without a type. Also updates haredoc accordingly.
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
7 files changed, 94 insertions(+), 31 deletions(-)
diff --git a/cmd/haredoc/hare.ha b/cmd/haredoc/hare.ha
@@ -135,8 +135,13 @@ fn unparse_hare(out: io::handle, d: ast::decl) (size | io::error) = {
"@symbol(\"{}\") ", g[i].symbol)?;
};
n += unparse::ident(out, g[i].ident)?;
- n += fmt::fprint(out, ": ")?;
- n += unparse::_type(out, 0, g[i]._type)?;
+ match (g[i]._type) {
+ case null =>
+ yield;
+ case let ty: *ast::_type =>
+ n += fmt::fprint(out, ": ")?;
+ n += unparse::_type(out, 0, *ty)?;
+ };
if (i + 1 < len(g)) {
n += fmt::fprint(out, ", ")?;
};
@@ -156,7 +161,13 @@ fn unparse_hare(out: io::handle, d: ast::decl) (size | io::error) = {
for (let i = 0z; i < len(c); i += 1) {
n += unparse::ident(out, c[i].ident)?;
n += fmt::fprint(out, ": ")?;
- n += unparse::_type(out, 0, c[i]._type)?;
+ match (c[i]._type) {
+ case null =>
+ yield;
+ case let ty: *ast::_type =>
+ n += fmt::fprint(out, ": ")?;
+ n += unparse::_type(out, 0, *ty)?;
+ };
if (i + 1 < len(c)) {
n += fmt::fprint(out, ", ")?;
};
diff --git a/cmd/haredoc/html.ha b/cmd/haredoc/html.ha
@@ -271,12 +271,22 @@ fn tocentry(out: io::handle, decl: ast::decl) (void | error) = {
case let t: []ast::decl_type => void;
case let g: []ast::decl_global =>
let g = g[0];
- fmt::fprint(out, ": ")?;
- type_html(out, 0, g._type, true)?;
+ match (g._type) {
+ case null =>
+ yield;
+ case let ty: *ast::_type =>
+ fmt::fprint(out, ": ")?;
+ type_html(out, 0, *ty, true)?;
+ };
case let c: []ast::decl_const =>
let c = c[0];
- fmt::fprint(out, ": ")?;
- type_html(out, 0, c._type, true)?;
+ match (c._type) {
+ case null =>
+ yield;
+ case let ty: *ast::_type =>
+ fmt::fprint(out, ": ")?;
+ type_html(out, 0, *ty, true)?;
+ };
case let f: ast::decl_func =>
prototype_html(out, 0,
f.prototype.repr as ast::func_type,
@@ -444,8 +454,13 @@ fn unparse_html(out: io::handle, d: ast::decl) (size | io::error) = {
n += fmt::fprintf(out, "<span class='keyword'>def</span> ")?;
for (let i = 0z; i < len(c); i += 1) {
n += unparse::ident(out, c[i].ident)?;
- n += fmt::fprint(out, ": ")?;
- n += type_html(out, 0, c[i]._type, false)?;
+ match (c[i]._type) {
+ case null =>
+ yield;
+ case let ty: *ast::_type =>
+ n += fmt::fprint(out, ": ")?;
+ n += type_html(out, 0, *ty, false)?;
+ };
if (i + 1 < len(c)) {
n += fmt::fprint(out, ", ")?;
};
@@ -455,8 +470,13 @@ fn unparse_html(out: io::handle, d: ast::decl) (size | io::error) = {
if (g[0].is_const) "const " else "let ")?;
for (let i = 0z; i < len(g); i += 1) {
n += unparse::ident(out, g[i].ident)?;
- n += fmt::fprint(out, ": ")?;
- n += type_html(out, 0, g[i]._type, false)?;
+ match (g[i]._type) {
+ case null =>
+ yield;
+ case let ty: *ast::_type =>
+ n += fmt::fprint(out, ": ")?;
+ n += type_html(out, 0, *ty, false)?;
+ };
if (i + 1 < len(g)) {
n += fmt::fprint(out, ", ")?;
};
diff --git a/cmd/haredoc/tty.ha b/cmd/haredoc/tty.ha
@@ -159,9 +159,14 @@ fn unparse_tty(out: io::handle, d: ast::decl) (size | io::error) = {
};
n += render(out, syn::GLOBAL)?;
n += unparse::ident(out, g[i].ident)?;
- n += render(out, syn::PUNCTUATION)?;
- n += fmt::fprint(out, ": ")?;
- n += type_tty(out, 0, g[i]._type)?;
+ match (g[i]._type) {
+ case null =>
+ yield;
+ case let ty: *ast::_type =>
+ n += render(out, syn::PUNCTUATION)?;
+ n += fmt::fprint(out, ": ")?;
+ n += type_html(out, 0, *ty, false)?;
+ };
if (i + 1 < len(g)) {
n += render(out, syn::PUNCTUATION)?;
n += fmt::fprint(out, ", ")?;
@@ -175,8 +180,14 @@ fn unparse_tty(out: io::handle, d: ast::decl) (size | io::error) = {
n += render(out, syn::CONSTANT)?;
n += unparse::ident(out, c[i].ident)?;
n += render(out, syn::PUNCTUATION)?;
- n += fmt::fprint(out, ": ")?;
- n += type_tty(out, 0, c[i]._type)?;
+ match (c[i]._type) {
+ case null =>
+ yield;
+ case let ty: *ast::_type =>
+ n += render(out, syn::PUNCTUATION)?;
+ n += fmt::fprint(out, ": ")?;
+ n += type_html(out, 0, *ty, false)?;
+ };
if (i + 1 < len(c)) {
n += render(out, syn::PUNCTUATION)?;
n += fmt::fprint(out, ", ")?;
diff --git a/hare/ast/decl.ha b/hare/ast/decl.ha
@@ -8,7 +8,7 @@ use hare::lex;
// def foo: int = 0;
export type decl_const = struct {
ident: ident,
- _type: _type,
+ _type: nullable *_type,
init: *expr,
};
@@ -21,7 +21,7 @@ export type decl_global = struct {
is_threadlocal: bool,
symbol: str,
ident: ident,
- _type: _type,
+ _type: nullable *_type,
init: nullable *expr,
};
diff --git a/hare/parse/+test/unit.ha b/hare/parse/+test/unit.ha
@@ -121,8 +121,9 @@ fn tup_to_import(tup: import_tuple) ast::import = ast::import {
roundtrip("export type foo::bar = *int, baz = const void;\n\n"
"type foo = ...bar;\n\n"
"type foo = nullable *fn(x: rune, _: int) void;\n\n"
- "export let @symbol(\"_\") foo::bar: int = void, baz: int = void;\n\n"
+ "export let @symbol(\"_\") foo::bar: int = void, baz: int = void, bat = void;\n\n"
"def foo::bar: int = void;\n\n"
+ "def foo::bar = void;\n\n"
"@symbol(\".f9$oo\") fn foo(bar: int, baz: int...) void;\n\n"
"@test fn foo(_: int, ...) void;\n\n"
"export fn main() void = void;\n\n"
diff --git a/hare/parse/decl.ha b/hare/parse/decl.ha
@@ -36,8 +36,13 @@ fn decl_const(
let decl: []ast::decl_const = [];
for (true) {
const ident = ident(lexer)?;
- want(lexer, ltok::COLON)?;
- const _type = _type(lexer)?;
+ const _type: nullable *ast::_type =
+ match (try(lexer, ltok::COLON)?) {
+ case lex::token =>
+ yield alloc(_type(lexer)?);
+ case void =>
+ yield null;
+ };
want(lexer, ltok::EQUAL)?;
const init: *ast::expr = alloc(expr(lexer)?);
append(decl, ast::decl_const {
@@ -72,8 +77,13 @@ fn decl_global(
};
};
const ident = ident(lexer)?;
- want(lexer, ltok::COLON)?;
- const _type = _type(lexer)?;
+ const _type: nullable *ast::_type =
+ match (try(lexer, ltok::COLON)?) {
+ case lex::token =>
+ yield alloc(_type(lexer)?);
+ case void =>
+ yield null;
+ };
const init: nullable *ast::expr =
match (try(lexer, ltok::EQUAL)?) {
case lex::token =>
diff --git a/hare/unparse/decl.ha b/hare/unparse/decl.ha
@@ -24,8 +24,13 @@ export fn decl(out: io::handle, d: ast::decl) (size | io::error) = {
n += fmt::fprint(out, "def ")?;
for (let i = 0z; i < len(c); i += 1) {
n += ident(out, c[i].ident)?;
- n += fmt::fprint(out, ": ")?;
- n += _type(out, 0, c[i]._type)?;
+ match (c[i]._type) {
+ case null =>
+ yield;
+ case let ty: *ast::_type =>
+ n += fmt::fprint(out, ": ")?;
+ n += _type(out, 0, *ty)?;
+ };
n += fmt::fprint(out, " = ")?;
n += expr(out, 0, *c[i].init)?;
if (i + 1 < len(c)) {
@@ -43,8 +48,13 @@ export fn decl(out: io::handle, d: ast::decl) (size | io::error) = {
n += fmt::fprintf(out, "@threadlocal ")?;
};
n += ident(out, g[i].ident)?;
- n += fmt::fprint(out, ": ")?;
- n += _type(out, 0, g[i]._type)?;
+ match (g[i]._type) {
+ case null =>
+ yield;
+ case let ty: *ast::_type =>
+ n += fmt::fprint(out, ": ")?;
+ n += _type(out, 0, *ty)?;
+ };
match (g[i].init) {
case null => void;
case let ex: *ast::expr =>
@@ -171,7 +181,7 @@ fn decl_test(d: ast::decl, expected: str) bool = {
is_threadlocal = false,
symbol = "",
ident = ["foo", "bar"],
- _type = type_int,
+ _type = &type_int,
init = alloc(expr_void),
},
ast::decl_global {
@@ -179,7 +189,7 @@ fn decl_test(d: ast::decl, expected: str) bool = {
is_threadlocal = true,
symbol = "",
ident = ["boo"],
- _type = type_int,
+ _type = &type_int,
init = alloc(expr_void),
},
ast::decl_global {
@@ -187,7 +197,7 @@ fn decl_test(d: ast::decl, expected: str) bool = {
is_threadlocal = false,
symbol = "foobar",
ident = ["baz"],
- _type = type_int,
+ _type = &type_int,
init = alloc(expr_void),
},
],
@@ -199,7 +209,7 @@ fn decl_test(d: ast::decl, expected: str) bool = {
d.decl = [
ast::decl_const {
ident = ["foo"],
- _type = type_int,
+ _type = &type_int,
init = alloc(expr_void),
},
];