hare

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

commit 06c599619fc71d3363b753f83900029c2ec40f30
parent 12611ccff5cba70b0763c6f2cac90fbd0d9059b3
Author: Drew DeVault <sir@cmpwn.com>
Date:   Wed,  1 Sep 2021 11:46:31 +0200

all: yield WIP

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

Diffstat:
Mascii/ctype.ha | 4++--
Mbufio/buffered.ha | 2+-
Mbufio/memstream.ha | 4++--
Mcmd/hare/schedule.ha | 4++--
Mcmd/harec/gen.ha | 1-
Mcmd/haredoc/html.ha | 6+++---
Mcmd/haredoc/sort.ha | 12++++++------
Mcmd/haredoc/tty.ha | 6+++---
Mcompress/flate/inflate.ha | 4++--
Mcompress/zlib/reader.ha | 2+-
Mcrypto/sha256/sha256.ha | 2+-
Mfmt/fmt.ha | 10+++++-----
Mformat/xml/parser.ha | 18+++++++++---------
Mfs/fs.ha | 2+-
Mhare/lex/lex.ha | 14+++++++-------
Mhare/module/context.ha | 2+-
Mhare/parse/decl.ha | 4++--
Mhare/parse/expr.ha | 42+++++++++++++++++++++---------------------
Mhare/parse/parse.ha | 6+++---
Mhare/parse/type.ha | 10+++++-----
Mhare/types/store.ha | 58+++++++++++++++++++++++++++++-----------------------------
Mhare/unit/process.ha | 2+-
Mhare/unit/scan.ha | 2+-
Mhare/unparse/expr.ha | 72++++++++++++++++++++++++++++++++++++++++++------------------------------
Mhare/unparse/type.ha | 6+++---
Mhash/crc16/crc16.ha | 4++--
Mhash/crc32/crc32.ha | 4++--
Mhash/crc64/crc64.ha | 4++--
Mio/limit.ha | 4++--
Mlinux/io_uring/cqe.ha | 2+-
Mlinux/io_uring/setup.ha | 2+-
Mnet/dial/resolve.ha | 2+-
Mnet/dns/error.ha | 2+-
Mnet/ip/+test.ha | 2+-
Mnet/ip/ip.ha | 11++++++-----
Mrt/+linux/segmalloc.ha | 2+-
Mrt/+linux/syscalls.ha | 10+++++-----
Mrt/malloc.ha | 2+-
Mstrconv/ftos.ha | 6+++---
Mstrconv/stof.ha | 2+-
Mstrconv/utos.ha | 2+-
Munix/tty/+linux/winsize.ha | 10++++------
42 files changed, 188 insertions(+), 178 deletions(-)

diff --git a/ascii/ctype.ha b/ascii/ctype.ha @@ -79,7 +79,7 @@ export fn isascii(c: rune) bool = c: u32 <= 0o177; // if it was not a lowercase letter (or was not ASCII). export fn toupper(c: rune) rune = { return if (islower(c)) { - (c: u32 - ('a': u32) + ('A': u32)): rune; + yield (c: u32 - ('a': u32) + ('A': u32)): rune; } else c; }; @@ -87,7 +87,7 @@ export fn toupper(c: rune) rune = { // if it was not an uppercase letter (or was not ASCII). export fn tolower(c: rune) rune = { return if (isupper(c)) { - (c: u32 - ('A': u32) + ('a': u32)): rune; + yield (c: u32 - ('A': u32) + ('a': u32)): rune; } else c; }; diff --git a/bufio/buffered.ha b/bufio/buffered.ha @@ -167,7 +167,7 @@ fn buffered_read(s: *io::stream, buf: []u8) (size | io::EOF | io::error) = { if (s.ravail == 0) { return io::EOF; }; - 0z; + yield 0z; }, z: size => z, }; diff --git a/bufio/memstream.ha b/bufio/memstream.ha @@ -145,9 +145,9 @@ fn read(s: *io::stream, buf: []u8) (size | io::EOF | io::error) = { return io::EOF; }; const n = if (len(s.buf) - s.pos < len(buf)) { - len(s.buf) - s.pos; + yield len(s.buf) - s.pos; } else { - len(buf); + yield len(buf); }; assert(s.pos + n <= len(s.buf)); buf[..n] = s.buf[s.pos..s.pos + n]; diff --git a/cmd/hare/schedule.ha b/cmd/hare/schedule.ha @@ -205,7 +205,7 @@ fn sched_hare_object( path, fs::strerror(err)), }; append(harec.cmd, "-t", path::join(path, td)); - path::join(path, name); + yield path::join(path, name); } else { // XXX: This is probably kind of dumb // It would be better to apply any defines which affect this @@ -214,7 +214,7 @@ fn sched_hare_object( append(harec.cmd, "-D", plan.context.defines[i]); }; - mkfile(plan, "o"); // TODO: Should exes go in the cache? + yield mkfile(plan, "o"); // TODO: Should exes go in the cache? }; for (let i = 0z; i < len(ver.inputs); i += 1) { diff --git a/cmd/harec/gen.ha b/cmd/harec/gen.ha @@ -75,7 +75,6 @@ fn gen_expr(ctx: *context, expr: *unit::expr) value = { unit::constant_expr => return gen_expr_const(ctx, expr), * => abort(), // TODO }; - abort(); // Unreachable }; fn gen_expr_const(ctx: *context, expr: *unit::expr) value = { diff --git a/cmd/haredoc/html.ha b/cmd/haredoc/html.ha @@ -478,11 +478,11 @@ fn struct_union_html( let members = match (t.repr) { t: ast::struct_type => { z += fmt::fprint(out, "<span class='keyword'>struct</span> {")?; - t: []ast::struct_member; + yield t: []ast::struct_member; }, t: ast::union_type => { z += fmt::fprint(out, "<span class='keyword'>union</span> {")?; - t: []ast::struct_member; + yield t: []ast::struct_member; }, }; @@ -634,7 +634,7 @@ fn type_html( t: ast::union_type => z += struct_union_html(out, indent, _type, brief)?, }; - z; + return z; }; fn prototype_html( diff --git a/cmd/haredoc/sort.ha b/cmd/haredoc/sort.ha @@ -38,7 +38,7 @@ fn sort_decls(decls: []ast::decl) summary = { // XXX: Kind of bad let new: []ast::decl_type = []; append(new, t[j]); - new; + yield new; }, docs = decl.docs, }); @@ -52,7 +52,7 @@ fn sort_decls(decls: []ast::decl) summary = { // XXX: Kind of bad let new: []ast::decl_const = []; append(new, c[j]); - new; + yield new; }, docs = decl.docs, }); @@ -66,7 +66,7 @@ fn sort_decls(decls: []ast::decl) summary = { // XXX: Kind of bad let new: []ast::decl_global = []; append(new, g[j]); - new; + yield new; }, docs = decl.docs, }); @@ -98,14 +98,14 @@ fn decl_ident(decl: ast::decl) ast::ident = match (decl.decl) { f: ast::decl_func => f.ident, t: []ast::decl_type => { assert(len(t) == 1); - t[0].ident; + yield t[0].ident; }, c: []ast::decl_const => { assert(len(c) == 1); - c[0].ident; + yield c[0].ident; }, g: []ast::decl_global => { assert(len(g) == 1); - g[0].ident; + yield g[0].ident; }, }; diff --git a/cmd/haredoc/tty.ha b/cmd/haredoc/tty.ha @@ -166,12 +166,12 @@ fn struct_union_type_tty( st: ast::struct_type => { z += fmt::fprint(out, "\x1b[36m" "struct" "\x1b[0m" " {")?; - st: []ast::struct_member; + yield st: []ast::struct_member; }, ut: ast::union_type => { z += fmt::fprint(out, "\x1b[36m" "union" "\x1b[0m" " {")?; - ut: []ast::struct_member; + yield ut: []ast::struct_member; }, }; @@ -190,7 +190,7 @@ fn struct_union_type_tty( se: ast::struct_embedded => type_tty(out, indent, *se)?, sa: ast::struct_alias => unparse::ident(out, sa)?, sf: ast::struct_field => { - fmt::fprintf(out, "{}: ", sf.name)? + yield fmt::fprintf(out, "{}: ", sf.name)? + type_tty(out, indent, *sf._type)?; }, }; diff --git a/compress/flate/inflate.ha b/compress/flate/inflate.ha @@ -233,7 +233,7 @@ fn uncompressed_read(d: *decompressor) (void | io::EOF | io::error) = { let z = match (io::read(d.in, buf)?) { z: size => { d.left -= z; - z; + yield z; }, io::EOF => return wraperror(inflate_err::EOF), }; @@ -294,7 +294,7 @@ fn dynamic(d: *decompressor) (void | io::EOF | io::error) = { return wraperror(inflate_err::TABLE); }; n = lens[len(lens) - 1]; - 3 + bits(d, 2)?; + yield 3 + bits(d, 2)?; }, 17 => 3 + bits(d, 3)?, 18 => 11 + bits(d, 7)?, diff --git a/compress/zlib/reader.ha b/compress/zlib/reader.ha @@ -67,7 +67,7 @@ fn read(s: *io::stream, buf: []u8) (size | io::EOF | io::error) = { io::EOF => return verifysum(s), z: size => buf = buf[..z], }; - hash::write(s.hash, buf); + return hash::write(s.hash, buf); }; fn close(s: *io::stream) void = { diff --git a/crypto/sha256/sha256.ha b/crypto/sha256/sha256.ha @@ -80,7 +80,7 @@ fn write(st: *io::stream, buf: const []u8) (size | io::error) = { h.ln += n; if (h.nx > 0) { let n = if (len(b) > len(h.x) - h.nx) { - len(h.x) - h.nx; + yield len(h.x) - h.nx; } else len(b); h.x[h.nx..] = b[..n]; h.nx += n; diff --git a/fmt/fmt.ha b/fmt/fmt.ha @@ -175,11 +175,11 @@ export fn fprintf( continue; } else if (ascii::isdigit(r)) { strings::push(&iter, r); - args[scan_uint(&iter)]; + yield args[scan_uint(&iter)]; } else { strings::push(&iter, r); i += 1; - args[i - 1]; + yield args[i - 1]; }; let mod = modifiers { base = strconv::base::DEC, ... }; @@ -245,11 +245,11 @@ fn format_raw( b: bool => io::write(out, strings::toutf8(if (b) "true" else "false")), n: types::numeric => { let s = strconv::numerictosb(n, mod.base); - io::write(out, strings::toutf8(s)); + yield io::write(out, strings::toutf8(s)); }, p: uintptr => { let s = strconv::uptrtosb(p, mod.base); - io::write(out, strings::toutf8(s)); + yield io::write(out, strings::toutf8(s)); }, v: nullable *void => match (v) { v: *void => { @@ -257,7 +257,7 @@ fn format_raw( strconv::base::HEX_LOWER); let n = io::write(out, strings::toutf8("0x"))?; n += io::write(out, strings::toutf8(s))?; - n; + yield n; }, null => format(out, "(null)", mod), }, diff --git a/format/xml/parser.ha b/format/xml/parser.ha @@ -73,7 +73,7 @@ export fn scan(par: *parser) (token | void | error) = { io::EOF => return syntaxerr, rn: rune => { bufio::unreadrune(par.in, rn); - rn; + yield rn; }, }; bufio::unreadrune(par.in, rn); @@ -84,14 +84,14 @@ export fn scan(par: *parser) (token | void | error) = { }; let el = scan_element(par)?; par.state = state::ATTRS; - el; + yield el; }, * => { if (par.state == state::ROOT) { return syntaxerr; }; bufio::unreadrune(par.in, rn); - scan_content(par)?; + yield scan_content(par)?; }, }, state::ATTRS => { @@ -106,7 +106,7 @@ export fn scan(par: *parser) (token | void | error) = { return syntaxerr; }; bufio::unreadrune(par.in, rn); - scan_attr(par)?; + yield scan_attr(par)?; }, }; }; @@ -138,7 +138,7 @@ fn scan_attr(par: *parser) (token | error) = { '<' => return syntaxerr, '&' => { bufio::unreadrune(par.in, rn); - scan_entity(par)?; + yield scan_entity(par)?; }, * => rn, }; @@ -228,7 +228,7 @@ fn scan_content(par: *parser) (text | error) = { }, '&', '%' => { bufio::unreadrune(par.in, rn); - scan_entity(par)?; + yield scan_entity(par)?; }, * => rn, }; @@ -269,7 +269,7 @@ fn scan_entity(par: *parser) (rune | error) = { '%' => syntaxerr, // XXX: Deliberate omission: PEReference * => { bufio::unreadrune(par.in, rn); - scan_namedent(par); + yield scan_namedent(par); }, }; }; @@ -378,7 +378,7 @@ fn prolog(par: *parser) (void | error) = { io::EOF => false, rn: rune => { bufio::unreadrune(par.in, rn); - hadws && rn == 'e'; + yield hadws && rn == 'e'; }, }; if (encoding) { @@ -398,7 +398,7 @@ fn prolog(par: *parser) (void | error) = { io::EOF => false, rn: rune => { bufio::unreadrune(par.in, rn); - hadws && rn == 's'; + yield hadws && rn == 's'; }, }; if (standalone) { diff --git a/fs/fs.ha b/fs/fs.ha @@ -167,7 +167,7 @@ export fn mksubdir(fs: *fs, path: str) (*fs | error) = { return match (fs.mksubdir) { null => { mkdir(fs, path)?; - subdir(fs, path); + yield subdir(fs, path); }, f: *mksubdirfunc => f(fs, path), }; diff --git a/hare/lex/lex.ha b/hare/lex/lex.ha @@ -271,7 +271,7 @@ fn lex_name(lex: *lexer, loc: location, label: bool) (token | error) = { defer free(n); let tok = v: uintptr - &bmap[0]: uintptr; tok /= size(str): uintptr; - (tok: ltok, void, loc); + yield (tok: ltok, void, loc); }, }; }; @@ -410,7 +410,7 @@ fn lex_literal(lex: *lexer) (token | error) = { void => len(chars), suff: size => suff, }; - strings::fromutf8(chars[exp..end]); + yield strings::fromutf8(chars[exp..end]); }, }; let exp = match (strconv::stoi(exp)) { @@ -460,14 +460,14 @@ fn lex_literal(lex: *lexer) (token | error) = { strconv::invalid => abort(), strconv::overflow => if (chars[0] != '-': u32: u8) { suff = ltok::LIT_U64; - strconv::stou64b(val, base); + yield strconv::stou64b(val, base); } else strconv::overflow, }, ltok::LIT_I8, ltok::LIT_I16, ltok::LIT_I32, ltok::LIT_I64, ltok::LIT_INT => strconv::stoi64b(val, base), ltok::LIT_F32, ltok::LIT_F64, ltok::LIT_FCONST => { val = strings::fromutf8(chars[..floatend]); - strconv::stof64(val); + yield strconv::stof64(val); }, }; let val = match (val) { @@ -475,13 +475,13 @@ fn lex_literal(lex: *lexer) (token | error) = { for (let i = 0z; i < exp; i += 1) { val *= 10; }; - val; + yield val; }, val: i64 => { for (let i = 0z; i < exp; i += 1) { val *= 10; }; - val; + yield val; }, val: f64 => val, strconv::invalid => abort(), // Shouldn't be lexed in @@ -529,7 +529,7 @@ fn lex2(lex: *lexer) (token | error) = { * => { unget(lex, r); return if (is_name(r.0, false)) { - lex_name(lex, first.1, true)?; + yield lex_name(lex, first.1, true)?; } else (ltok::COLON, void, first.1); }, }, diff --git a/hare/module/context.ha b/hare/module/context.ha @@ -45,7 +45,7 @@ export fn context_init(tags: []tag, defs: []str, harepath: str) context = { }; append(path, strings::dup(".")); free(sl); - path; + yield path; }, }, cache: str = match (os::getenv("HARECACHE")) { diff --git a/hare/parse/decl.ha b/hare/parse/decl.ha @@ -143,7 +143,7 @@ fn decl_func(lexer: *lex::lexer) (ast::decl_func | error) = { len(params[i].name) > 0, "Expected parameter name in function declaration")?; }; - expression(lexer)?; + yield expression(lexer)?; }, ltok::SEMICOLON => lex::unlex(lexer, tok), }; @@ -172,7 +172,7 @@ export fn decls(lexer: *lex::lexer) ([]ast::decl | error) = { void => false, lex::token => { comment = strings::dup(lex::comment(lexer)); - true; + yield true; }, }; const toks = [ltok::CONST, ltok::LET, ltok::DEF, ltok::TYPE]; diff --git a/hare/parse/expr.ha b/hare/parse/expr.ha @@ -25,8 +25,8 @@ export fn expression(lexer: *lex::lexer) (ast::expr | error) = { // * unary-expression assignment-op expression // and // binary-expression - if (peek(lexer, atoks...)? is lex::token) { - expr; + yield if (peek(lexer, atoks...)? is lex::token) { + yield expr; } else return binarithm(lexer, ast::expr { start = loc, end = lex::prevloc(lexer), @@ -99,11 +99,11 @@ fn assert_expr(lexer: *lex::lexer, is_static: bool) (ast::expr | error) = { want(lexer, ltok::LPAREN)?; const msg: nullable *ast::expr = if (peek(lexer, ltok::RPAREN)? is lex::token) { - null; + yield null; } else alloc(expression(lexer)?); want(lexer, ltok::RPAREN)?; - ast::assert_expr { + yield ast::assert_expr { cond = null, message = msg, is_static = is_static, @@ -115,11 +115,11 @@ fn assert_expr(lexer: *lex::lexer, is_static: bool) (ast::expr | error) = { alloc(expression(lexer)?); const msg: nullable *ast::expr = if (try(lexer, ltok::COMMA)? is lex::token) { - alloc(expression(lexer)?); + yield alloc(expression(lexer)?); } else null; want(lexer, ltok::RPAREN)?; - ast::assert_expr { + yield ast::assert_expr { cond = cond, message = msg, is_static = is_static, @@ -142,7 +142,7 @@ fn alloc_expr(lexer: *lex::lexer) (ast::expr | error) = { const init = expression(lexer)?; const cap: nullable *ast::expr = if (try(lexer, ltok::COMMA)? is lex::token) { - alloc(expression(lexer)?); + yield alloc(expression(lexer)?); } else null; want(lexer, ltok::RPAREN)?; @@ -210,14 +210,14 @@ fn measurement(lexer: *lex::lexer) (ast::expr | error) = { let e = expression(lexer)?; want(lexer, ltok::RPAREN)?; - alloc(e): ast::len_expr; + yield alloc(e): ast::len_expr; }, ltok::SIZE => { want(lexer, ltok::LPAREN)?; let ty = _type(lexer)?; want(lexer, ltok::RPAREN)?; - alloc(ty): ast::size_expr; + yield alloc(ty): ast::size_expr; }, ltok::OFFSET => abort(), // TODO }; @@ -282,7 +282,7 @@ fn binding(lexer: *lex::lexer, is_static: bool) (ast::expr | error) = { const name = want(lexer, ltok::NAME)?.1 as str; const btype: nullable *ast::_type = if (try(lexer, ltok::COLON)? is lex::token) { - alloc(_type(lexer)?); + yield alloc(_type(lexer)?); } else null; want(lexer, ltok::EQUAL)?; const init = alloc(expression(lexer)?); @@ -330,7 +330,7 @@ fn builtin(lexer: *lex::lexer) (ast::expr | error) = { void => return syntaxerr(tok.2, "Expected let, const, or assert"), }; - switch (tok.0) { + yield switch (tok.0) { ltok::LET, ltok::CONST => binding(lexer, true), ltok::ABORT, ltok::ASSERT => assert_expr(lexer, true), @@ -341,7 +341,7 @@ fn builtin(lexer: *lex::lexer) (ast::expr | error) = { ltok::DEFER => { want(lexer, ltok::DEFER)?; let expr = alloc(expression(lexer)?); - ast::expr { + yield ast::expr { start = tok.2, end = lex::prevloc(lexer), expr = expr: ast::defer_expr, @@ -442,7 +442,7 @@ fn constant(lexer: *lex::lexer) (ast::expr | error) = { fn control(lexer: *lex::lexer) (ast::expr | error) = { let tok = want(lexer, ltok::BREAK, ltok::CONTINUE, ltok::RETURN)?; let label = if (tok.0 == ltok::BREAK || tok.0 == ltok::CONTINUE) { - match (try(lexer, ltok::LABEL)?) { + yield match (try(lexer, ltok::LABEL)?) { tok: lex::token => tok.1 as str, void => "", }; @@ -482,7 +482,7 @@ fn compound_expr(lexer: *lex::lexer) (ast::expr | error) = { const label = switch (start.0) { ltok::LABEL => { want(lexer, ltok::LBRACE)?; - start.1 as str; + yield start.1 as str; }, * => "", }; @@ -517,7 +517,7 @@ fn for_expr(lexer: *lex::lexer) (ast::expr | error) = { lex::token => { const bindings = alloc(binding(lexer, false)?); want(lexer, ltok::SEMICOLON)?; - bindings; + yield bindings; }, }; @@ -528,7 +528,7 @@ fn for_expr(lexer: *lex::lexer) (ast::expr | error) = { void => null, lex::token => { want(lexer, ltok::SEMICOLON)?; - alloc(expression(lexer)?); + yield alloc(expression(lexer)?); }, }; @@ -610,7 +610,7 @@ fn indexing(lexer: *lex::lexer, lvalue: ast::expr) (ast::expr | error) = { object = alloc(lvalue), index = { assert(start != null && end == null); - start: *ast::expr; + yield start: *ast::expr; }, }, }; @@ -659,7 +659,7 @@ fn plain_expression(lexer: *lex::lexer) (ast::expr | error) = { }, lex::token => { let s = plain_struct(lexer, id)?; - ast::expr { + yield ast::expr { start = tok.2, end = lex::prevloc(lexer), expr = s, @@ -779,7 +779,7 @@ fn struct_field( const _type = alloc(_type(lexer)?); want(lexer, ltok::EQUAL)?; const init = alloc(expression(lexer)?); - ast::struct_value { + yield ast::struct_value { name = name, _type = _type, init = init, @@ -894,7 +894,7 @@ fn postfix_dot( let val = val as lex::value; synassert(lex::mkloc(lexer), val is i64, "Expected integer constant")?; - ast::expr { + yield ast::expr { start = lvalue.start, end = lex::prevloc(lexer), expr = ast::access_tuple { @@ -965,7 +965,7 @@ fn match_case(lexer: *lex::lexer) (ast::match_case | error) = { let nt = switch (tok.0) { ltok::NULL => { want(lexer, ltok::NULL)?; - ("", ast::_type { + yield ("", ast::_type { start = loc, end = lex::prevloc(lexer), flags = 0, diff --git a/hare/parse/parse.ha b/hare/parse/parse.ha @@ -96,16 +96,16 @@ fn nametype(lexer: *lex::lexer) ((str, ast::_type) | error) = { let name = tok.1 as str; want(lexer, ltok::NAME)?; tok = peek(lexer)? as lex::token; - switch (tok.0) { + yield switch (tok.0) { ltok::COLON => { want(lexer, ltok::COLON)?; - (name, _type(lexer)?); + yield (name, _type(lexer)?); }, ltok::DOUBLE_COLON => { want(lexer, ltok::DOUBLE_COLON)?; let id = ident(lexer)?; insert(id[0], name); - ("", ast::_type { + yield ("", ast::_type { start = start, end = lex::prevloc(lexer), flags = 0, diff --git a/hare/parse/type.ha b/hare/parse/type.ha @@ -85,7 +85,7 @@ fn primitive_type(lexer: *lex::lexer) (ast::_type | error) = { ltok::U32, ltok::U64, ltok::U64, ltok::U8, ltok::UINT, ltok::UINTPTR => { lex::unlex(lexer, tok); - integer_type(lexer)?; + yield integer_type(lexer)?; }, ltok::RUNE => builtin_type::RUNE, ltok::STR => builtin_type::STR, @@ -227,7 +227,7 @@ fn struct_union_type(lexer: *lex::lexer) (ast::_type | error) = { want(lexer, ltok::LPAREN)?; let ex = expression(lexer)?; want(lexer, ltok::RPAREN)?; - alloc(ex); + yield alloc(ex); }, }; @@ -299,7 +299,7 @@ fn struct_embed_or_field( ltok::DOUBLE_COLON => { let id = ident(lexer)?; insert(id[0], name.1 as str); - id; + yield id; }, * => abort(), }, @@ -348,7 +348,7 @@ fn enum_type(lexer: *lex::lexer) (ast::_type | error) = { void => { let storage = integer_type(lexer)?; want(lexer, ltok::LBRACE)?; - storage; + yield storage; }, lex::token => builtin_type::INT, }; @@ -416,7 +416,7 @@ export fn _type(lexer: *lex::lexer) (ast::_type | error) = { ltok::LPAREN => { want(lexer, ltok::LPAREN)?; let t = _type(lexer)?; - switch (want(lexer, ltok::BOR, + yield switch (want(lexer, ltok::BOR, ltok::COMMA)?.0) { ltok::BOR => tagged_type(lexer, t, tok.2)?, ltok::COMMA => tuple_type(lexer, t, tok.2)?, diff --git a/hare/types/store.ha b/hare/types/store.ha @@ -107,7 +107,7 @@ fn fromast(store: *typestore, atype: *ast::_type) (_type | deferred | error) = { a: ast::alias_type => { // TODO: This is incomplete assert(!a.unwrap); - alias { + yield alias { id = ast::ident_dup(a.ident), secondary = null, }; @@ -117,49 +117,49 @@ fn fromast(store: *typestore, atype: *ast::_type) (_type | deferred | error) = { ast::builtin_type::BOOL => { sz = store.arch._int; align = store.arch._int; - builtin::BOOL; + yield builtin::BOOL; }, ast::builtin_type::CHAR => { sz = 1; align = 1; - builtin::CHAR; + yield builtin::CHAR; }, ast::builtin_type::F32 => { sz = 4; align = 4; - builtin::F32; + yield builtin::F32; }, ast::builtin_type::F64 => { sz = 8; align = 8; - builtin::F64; + yield builtin::F64; }, ast::builtin_type::I16 => { sz = 2; align = 2; - builtin::I16; + yield builtin::I16; }, ast::builtin_type::I32 => { sz = 4; align = 4; - builtin::I32; + yield builtin::I32; }, ast::builtin_type::I64 => { sz = 8; align = 8; - builtin::I64; + yield builtin::I64; }, ast::builtin_type::I8 => { sz = 1; align = 1; - builtin::I8; + yield builtin::I8; }, ast::builtin_type::INT => { sz = store.arch._int; align = store.arch._int; - builtin::INT; + yield builtin::INT; }, ast::builtin_type::RUNE => { sz = 4; align = 4; - builtin::RUNE; + yield builtin::RUNE; }, ast::builtin_type::SIZE => { sz = store.arch._size; align = store.arch._size; - builtin::SIZE; + yield builtin::SIZE; }, ast::builtin_type::STR => { sz = store.arch._pointer; @@ -169,37 +169,37 @@ fn fromast(store: *typestore, atype: *ast::_type) (_type | deferred | error) = { store.arch._size else store.arch._pointer; - builtin::STR; + yield builtin::STR; }, ast::builtin_type::U16 => { sz = 2; align = 2; - builtin::U16; + yield builtin::U16; }, ast::builtin_type::U32 => { sz = 4; align = 4; - builtin::U32; + yield builtin::U32; }, ast::builtin_type::U64 => { sz = 8; align = 8; - builtin::U64; + yield builtin::U64; }, ast::builtin_type::U8 => { sz = 1; align = 1; - builtin::U8; + yield builtin::U8; }, ast::builtin_type::UINT => { sz = store.arch._int; align = store.arch._int; - builtin::UINT; + yield builtin::UINT; }, ast::builtin_type::UINTPTR => { sz = store.arch._pointer; align = store.arch._pointer; - builtin::UINTPTR; + yield builtin::UINTPTR; }, ast::builtin_type::VOID => { sz = 0; align = 0; - builtin::VOID; + yield builtin::VOID; }, ast::builtin_type::NULL => builtin::NULL, ast::builtin_type::ICONST, @@ -209,7 +209,7 @@ fn fromast(store: *typestore, atype: *ast::_type) (_type | deferred | error) = { p: ast::pointer_type => { sz = store.arch._pointer; align = store.arch._pointer; - pointer { + yield pointer { referent = lookup(store, p.referent)?, flags = p.flags: pointer_flags, }; @@ -226,7 +226,7 @@ fn fromast(store: *typestore, atype: *ast::_type) (_type | deferred | error) = { align = field._type.align; }; }; - st; + yield st; }, un: ast::union_type => { let st = struct_from_ast(store, un, true)?; @@ -240,7 +240,7 @@ fn fromast(store: *typestore, atype: *ast::_type) (_type | deferred | error) = { align = field._type.align; }; }; - st; + yield st; }, ta: ast::tagged_type => { let ta = tagged_from_ast(store, ta)?; @@ -257,7 +257,7 @@ fn fromast(store: *typestore, atype: *ast::_type) (_type | deferred | error) = { align = store.arch._int; }; sz += store.arch._int % align + store.arch._int; - ta; + yield ta; }, tu: ast::tuple_type => { let tu = tuple_from_ast(store, tu)?; @@ -271,13 +271,13 @@ fn fromast(store: *typestore, atype: *ast::_type) (_type | deferred | error) = { align = value._type.align; }; }; - tu; + yield tu; }, lt: ast::list_type => { let r = list_from_ast(store, &lt)?; sz = r.0; align = r.1; - r.2; + yield r.2; }, et: ast::enum_type => abort(), // TODO }; @@ -331,14 +331,14 @@ fn list_from_ast( align = if (store.arch._pointer > store.arch._size) store.arch._pointer else store.arch._size; - memb: slice; + yield memb: slice; }, // Note: contextual length is handled by hare::unit when // initializing bindings. We treat it like unbounded here and // it's fixed up later on. (ast::len_unbounded | ast::len_contextual) => { align = memb.align; - array { + yield array { length = SIZE_UNDEFINED, member = memb, }; @@ -352,7 +352,7 @@ fn list_from_ast( sz = memb.sz * length; assert(sz / length == memb.sz, "overflow"); align = memb.align; - array { + yield array { length = length, member = memb, }; diff --git a/hare/unit/process.ha b/hare/unit/process.ha @@ -28,7 +28,7 @@ fn process_decl( decl: *ast::decl, ) (decl | error) = { // TODO: match on &decl.decl - match (decl.decl) { + return match (decl.decl) { co: []ast::decl_const => abort(), // TODO gl: []ast::decl_global => abort(), // TODO ty: []ast::decl_type => abort(), // TODO diff --git a/hare/unit/scan.ha b/hare/unit/scan.ha @@ -25,7 +25,7 @@ fn scan_decl( decl: *ast::decl, ) (void | types::deferred | error) = { // TODO: match on &decl.decl - match (decl.decl) { + return match (decl.decl) { co: []ast::decl_const => abort(), // TODO gl: []ast::decl_global => abort(), // TODO ty: []ast::decl_type => abort(), // TODO diff --git a/hare/unparse/expr.ha b/hare/unparse/expr.ha @@ -21,16 +21,18 @@ export fn expr( z += fmt::fprintf(out, "[")?; z += expr(out, indent, *ix.index)?; z += fmt::fprintf(out, "]")?; - z; + yield z; }, fi: ast::access_field => { let z = expr(out, indent, *fi.object)?; - z + fmt::fprintf(out, ".{}", fi.field)?; + z += fmt::fprintf(out, ".{}", fi.field)?; + yield z; }, tp: ast::access_tuple => { let z = expr(out, indent, *tp.object)?; z += fmt::fprintf(out, ".")?; - z + expr(out, indent, *tp.value)?; + z += expr(out, indent, *tp.value)?; + yield z; }, }, e: ast::alloc_expr => { @@ -44,7 +46,7 @@ export fn expr( }, }; z += fmt::fprint(out, ")")?; - z; + yield z; }, e: ast::append_expr => { let z = fmt::fprint(out, "append(")?; @@ -65,7 +67,8 @@ export fn expr( z += fmt::fprint(out, "...")?; }, }; - z + fmt::fprint(out, ")")?; + z += fmt::fprint(out, ")")?; + yield z; }, e: ast::assert_expr => { let z = fmt::fprint( @@ -73,7 +76,7 @@ export fn expr( // assert without a condition = abort z += match (e.cond) { e: *ast::expr => { - fmt::fprint(out, "assert(")? + + yield fmt::fprint(out, "assert(")? + expr(out, indent, *e)?; }, null => fmt::fprint(out, "abort(")?, @@ -87,11 +90,13 @@ export fn expr( }, null => void, }; - z + expr(out, indent, *m)?; + z += expr(out, indent, *m)?; + yield z; }, null => 0, }; - z + fmt::fprint(out, ")")?; + z += fmt::fprint(out, ")")?; + yield z; }, e: ast::assign_expr => { let z = 0z; @@ -120,7 +125,7 @@ export fn expr( }; z += fmt::fprintf(out, " {} ", op)?; z += expr(out, indent, *e.value)?; - z; + yield z; }, e: ast::binarithm_expr => { let z = expr(out, indent, *e.lvalue)?; @@ -146,7 +151,7 @@ export fn expr( ast::binarithm_op::BXOR => "^", })?; z += expr(out, indent, *e.rvalue)?; - z; + yield z; }, e: ast::binding_expr => { let z = fmt::fprintf(out, "{}{}", @@ -157,9 +162,11 @@ export fn expr( z += match (binding._type) { null => fmt::fprint(out, binding.name)?, t: *ast::_type => { - fmt::fprintf(out, "{}: ", - binding.name)? - + _type(out, indent, *t)?; + let z = 0z; + z += fmt::fprintf(out, "{}: ", + binding.name)?; + z += _type(out, indent, *t)?; + yield z; }, }; z += fmt::fprint(out, " = ")?; @@ -168,14 +175,14 @@ export fn expr( z += fmt::fprint(out, ", ")?; }; }; - z; + yield z; }, e: ast::break_expr => { let z = fmt::fprint(out, "break")?; if (e != "") { z += fmt::fprintf(out, " :{}", e)?; }; - z; + yield z; }, e: ast::call_expr => { let z = expr(out, indent, *e.lvalue)?; @@ -190,7 +197,7 @@ export fn expr( z += fmt::fprintf(out, "...")?; }; z += fmt::fprintf(out, ")")?; - z; + yield z; }, e: ast::cast_expr => { let z = expr(out, indent, *e.value)?; @@ -201,7 +208,7 @@ export fn expr( }; z += fmt::fprintf(out, "{}", op)?; z += _type(out, indent, *e._type)?; - z; + yield z; }, e: ast::constant_expr => constant(out, indent, e)?, e: ast::continue_expr => { @@ -209,7 +216,7 @@ export fn expr( if (e != "") { z += fmt::fprintf(out, " :{}", e)?; }; - z; + yield z; }, e: ast::defer_expr => fmt::fprint(out, "defer ")? + expr(out, indent, *e)?, @@ -234,7 +241,7 @@ export fn expr( z += expr(out, indent, *e)?; }, }; - z; + yield z; }, e: ast::compound_expr => { let z = 0z; @@ -249,23 +256,26 @@ export fn expr( }; z += newline(out, indent)?; z += fmt::fprintf(out, "}}")?; - z; + yield z; }, e: ast::match_expr => match_expr(out, indent, e)?, e: ast::len_expr => { let z = fmt::fprint(out, "len(")?; z += expr(out, indent, *e)?; - z + fmt::fprint(out, ")")?; + z += fmt::fprint(out, ")")?; + yield z; }, e: ast::size_expr => { let z = fmt::fprint(out, "size(")?; z += _type(out, indent, *e)?; - z + fmt::fprint(out, ")")?; + z += fmt::fprint(out, ")")?; + yield z; }, ast::offset_expr => abort(), e: ast::propagate_expr => { let z = expr(out, indent, *e.expr)?; - z + fmt::fprintf(out, if (e.is_abort) "!" else "?")?; + z += fmt::fprintf(out, if (e.is_abort) "!" else "?")?; + yield z; }, e: ast::return_expr => { let z = fmt::fprint(out, "return")?; @@ -276,7 +286,7 @@ export fn expr( z += expr(out, indent, *e)?; }, }; - z; + yield z; }, e: ast::slice_expr => { let z = expr(out, indent, *e.object)?; @@ -291,7 +301,7 @@ export fn expr( e: *ast::expr => expr(out, indent, *e)?, }; z += fmt::fprint(out, "]")?; - z; + yield z; }, e: ast::switch_expr => switch_expr(out, indent, e)?, e: ast::unarithm_expr => { @@ -304,7 +314,7 @@ export fn expr( ast::unarithm_op::PLUS => "+", })?; z += expr(out, indent, *e.operand)?; - z; + yield z; }, }; }; @@ -333,8 +343,9 @@ fn constant( z += fmt::fprint(out, ", ")?; }; }; - z + fmt::fprintf(out, "{}]", + z += fmt::fprintf(out, "{}]", if (ac.expand) "..." else "")?; + yield z; }, sc: ast::struct_constant => struct_constant(out, indent, sc)?, tu: ast::tuple_constant => { @@ -345,7 +356,8 @@ fn constant( z += fmt::fprint(out, ", ")?; }; }; - z + fmt::fprint(out, ")")?; + z += fmt::fprint(out, ")")?; + yield z; }, }; }; @@ -357,9 +369,9 @@ fn struct_constant( ) (size | io::error) = { let z = 0z; z += if (len(sc.alias) != 0) { - ident(out, sc.alias)?; + yield ident(out, sc.alias)?; } else { - fmt::fprint(out, "struct")?; + yield fmt::fprint(out, "struct")?; }; z += fmt::fprint(out, " {")?; indent += 1; diff --git a/hare/unparse/type.ha b/hare/unparse/type.ha @@ -66,11 +66,11 @@ fn struct_union_type( let membs = match (t.repr) { st: ast::struct_type => { z += fmt::fprint(out, "struct {")?; - st: []ast::struct_member; + yield st: []ast::struct_member; }, ut: ast::union_type => { z += fmt::fprint(out, "union {")?; - ut: []ast::struct_member; + yield ut: []ast::struct_member; }, }; @@ -89,7 +89,7 @@ fn struct_union_type( se: ast::struct_embedded => _type(out, indent, *se)?, sa: ast::struct_alias => ident(out, sa)?, sf: ast::struct_field => { - fmt::fprintf(out, "{}: ", sf.name)? + yield fmt::fprintf(out, "{}: ", sf.name)? + _type(out, indent, *sf._type)?; }, }; diff --git a/hash/crc16/crc16.ha b/hash/crc16/crc16.ha @@ -162,9 +162,9 @@ export fn memoize(polynomial: u16, buf: *[256]u16) void = { let value = i: u16; for (let z = 0z; z < 8; z += 1) { value = if (value & 0x1 == 1) { - (value >> 1) ^ polynomial; + yield (value >> 1) ^ polynomial; } else { - value >> 1; + yield value >> 1; }; }; buf[i] = value; diff --git a/hash/crc32/crc32.ha b/hash/crc32/crc32.ha @@ -169,9 +169,9 @@ export fn memoize(polynomial: u32, buf: *[256]u32) void = { let value = i: u32; for (let z = 0z; z < 8; z += 1) { value = if (value & 0x1 == 1) { - (value >> 1) ^ polynomial; + yield (value >> 1) ^ polynomial; } else { - value >> 1; + yield value >> 1; }; }; buf[i] = value; diff --git a/hash/crc64/crc64.ha b/hash/crc64/crc64.ha @@ -201,9 +201,9 @@ export fn memoize(polynomial: u64, buf: *[256]u64) void = { let value = i: u64; for (let z = 0z; z < 8; z += 1) { value = if (value & 0x1 == 1) { - (value >> 1) ^ polynomial; + yield (value >> 1) ^ polynomial; } else { - value >> 1; + yield value >> 1; }; }; buf[i] = value; diff --git a/io/limit.ha b/io/limit.ha @@ -49,9 +49,9 @@ fn limited_read(s: *stream, buf: []u8) (size | EOF | error) = { fn limited_write(s: *stream, buf: const []u8) (size | error) = { let stream = s: *limited_stream; let slice = if (len(buf) > stream.limit) { - buf[..stream.limit]; + yield buf[..stream.limit]; } else { - buf[..]; + yield buf[..]; }; stream.limit -= len(slice); return write(stream.source, slice); diff --git a/linux/io_uring/cqe.ha b/linux/io_uring/cqe.ha @@ -17,7 +17,7 @@ export fn wait(ring: *io_uring) (*cqe | error) = { err: error => err, cq: nullable *cqe => { assert(cq != null); // XXX: Correct? - cq: *cqe; + yield cq: *cqe; }, }; }; diff --git a/linux/io_uring/setup.ha b/linux/io_uring/setup.ha @@ -39,7 +39,7 @@ export fn setup(entries: u32, params: *params) (io_uring | error) = { }; cq.ring_ptr = if (uring.features & features::SINGLE_MMAP == features::SINGLE_MMAP) { - sq.ring_ptr; + yield sq.ring_ptr; } else match (rt::mmap(null, cq.ring_sz, rt::PROT_READ | rt::PROT_WRITE, rt::MAP_SHARED | rt::MAP_POPULATE, diff --git a/net/dial/resolve.ha b/net/dial/resolve.ha @@ -23,7 +23,7 @@ export fn resolve( i: size => { const sub = strings::sub(addr, i + 1, strings::end); addr = strings::sub(addr, 0, i); - match (strconv::stou16(sub)) { + yield match (strconv::stou16(sub)) { u: u16 => u, * => return invalid_address, }; diff --git a/net/dns/error.ha b/net/dns/error.ha @@ -30,7 +30,7 @@ export type error = !(format | server_failure | name_error export fn strerror(err: error) const str = { static let buf: [64]u8 = [0...]; - match (err) { + return match (err) { format => "The DNS message was poorly formatted", server_failure => "The name server was unable to process this query due to a problem with the name server", name_error => "The domain name referenced in the query does not exist", diff --git a/net/ip/+test.ha b/net/ip/+test.ha @@ -9,7 +9,7 @@ fn ip_test(s: str, expected: (addr|invalid)) void = { } else { assert(expected is addr); assert(equal(pr as addr, expected as addr)); - pr as addr; + yield pr as addr; }; let fmted = string(ip); let iprp = parse(fmted); diff --git a/net/ip/ip.ha b/net/ip/ip.ha @@ -40,14 +40,14 @@ export fn equal(l: addr, r: addr) bool = { return false; }; let r = r as addr4; - bytes::equal(l, r); + yield bytes::equal(l, r); }, l: addr6 => { if (!(r is addr6)) { return false; }; let r = r as addr6; - bytes::equal(l, r); + yield bytes::equal(l, r); }, }; }; @@ -113,7 +113,6 @@ fn parsev6(st: str) (addr6 | invalid) = { i += 4; break; }; - return invalid; }; if (!(strings::next_token(&tok) is void)) { return invalid; @@ -137,11 +136,13 @@ fn parsev6(st: str) (addr6 | invalid) = { // Parses an IP address. export fn parse(s: str) (addr | invalid) = { - match(parsev4(s)) { + match (parsev4(s)) { v4: addr4 => return v4, + invalid => void, }; - match(parsev6(s)) { + match (parsev6(s)) { v6: addr6 => return v6, + invalid => void, }; return invalid; }; diff --git a/rt/+linux/segmalloc.ha b/rt/+linux/segmalloc.ha @@ -5,7 +5,7 @@ fn segmalloc(n: size) nullable *void = { MAP_PRIVATE | MAP_ANON, -1, 0)) { err: errno => { assert(err == ENOMEM: errno); - null; + yield null; }, p: *void => p, }; diff --git a/rt/+linux/syscalls.ha b/rt/+linux/syscalls.ha @@ -19,7 +19,7 @@ fn copy_kpath(path: path, buf: []u8) (*const char | errno) = { length: size, capacity: size, }; - ptr.buf[..ptr.length]; + yield ptr.buf[..ptr.length]; }, b: []u8 => b, }; @@ -240,7 +240,7 @@ export fn mmap( ) (*void | errno) = { let r = syscall6(SYS_mmap, addr: uintptr: u64, length: u64, prot: u64, flags: u64, fd: u64, offs: u64); - match (wrap_return(r)) { + return match (wrap_return(r)) { err: errno => { // XXX: Type promotion would simplify this return if (r: int == -EPERM @@ -248,7 +248,7 @@ export fn mmap( && (flags & MAP_ANON) > 0 && (flags & MAP_FIXED) == 0) { // Fix up incorrect EPERM from kernel: - wrap_errno(ENOMEM); + yield wrap_errno(ENOMEM); } else err; }, n: u64 => n: uintptr: *void, @@ -283,7 +283,7 @@ fn faccessat1(dirfd: int, path: *const char, mode: int) (bool | errno) = { }, n: u64 => { assert(n == 0); - true; + yield true; }, }; }; @@ -309,7 +309,7 @@ export fn faccessat( }, n: u64 => { assert(n == 0); - true; + yield true; }, }; }; diff --git a/rt/malloc.ha b/rt/malloc.ha @@ -74,7 +74,7 @@ fn malloc_small(n: size) nullable *void = { return if (p != null) { let q = *(p: **void); bins[b] = q; - p; + yield p; } else null; }; diff --git a/strconv/ftos.ha b/strconv/ftos.ha @@ -96,7 +96,7 @@ fn mulshiftall64(m: u64, mul: (u64, u64), j: i32, mm_shift: u32) (u64, u64, u64) const lo3 = lo - mul.0; const mid3 = mid - mul.1 - ibool(lo3 > lo); const hi3 = hi - ibool(mid3 > mid); - u128rshift(mid3, hi3, (j - 64 - 1): u32); + yield u128rshift(mid3, hi3, (j - 64 - 1): u32); } else { const lo3 = lo + lo; const mid3 = mid + mid + ibool(lo3 < lo); @@ -104,7 +104,7 @@ fn mulshiftall64(m: u64, mul: (u64, u64), j: i32, mm_shift: u32) (u64, u64, u64) const lo4 = lo3 - mul.0; const mid4 = mid3 - mul.1 - ibool(lo4 > lo3); const hi4 = hi3 - ibool(mid4 > mid3); - u128rshift(mid4, hi4, (j - 64): u32); + yield u128rshift(mid4, hi4, (j - 64): u32); }; const v_rounded = u128rshift(mid, hi, (j - 64 - 1): u32); return (v_plus, v_rounded, v_minus); @@ -593,7 +593,7 @@ fn encode_base10(buf: []u8, mantissa: u64, exponent: i32, digits: i32) size = { let ex = if (exp < 0) { buf[h] = '-': u32: u8; h += 1; - -exp; + yield -exp; } else exp; const elen = declen(ex: u64); let k = h + elen: i32 - 1; diff --git a/strconv/stof.ha b/strconv/stof.ha @@ -437,7 +437,7 @@ fn floatbits(d: *decimal, f: *math::floatinfo) (u64 | overflow) = { for (d.decimal_point <= 0) { const n: int = if (d.decimal_point == 0) { if (d.digits[0] >= 5) break; - if (d.digits[0] < 2) 2 else 1; + yield if (d.digits[0] < 2) 2 else 1; } else if (-d.decimal_point >= len(powtab): i32) maxshift: int else powtab[-d.decimal_point]; diff --git a/strconv/utos.ha b/strconv/utos.ha @@ -17,7 +17,7 @@ export fn u64tosb(u: u64, b: base) const str = { ]; const lut = if (b != base::HEX_LOWER) &lut_upper else { b = base::HEX_UPPER; - &lut_lower; + yield &lut_lower; }; let s = types::string { data = &buf, ... }; diff --git a/unix/tty/+linux/winsize.ha b/unix/tty/+linux/winsize.ha @@ -11,12 +11,10 @@ export fn winsize(tty: *io::stream) (ttysize | error) = { }; let wsz = rt::winsize { ... }; return match (rt::ioctl(fd, rt::TIOCGWINSZ, &wsz: *void)) { - e: rt::errno => { - switch (e: int) { - rt::EBADFD => errors::invalid, - rt::ENOTTY => errors::unsupported, - * => abort("unreachable"), - }; + e: rt::errno => switch (e: int) { + rt::EBADFD => errors::invalid, + rt::ENOTTY => errors::unsupported, + * => abort("unreachable"), }, int => ttysize { rows = wsz.ws_row,