hare

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

commit 4c82f02d849e82bfa50fb188cb8d41422a5d8716
parent aba521506ff6c227f02483bcca47bca1f8646b1a
Author: Drew DeVault <sir@cmpwn.com>
Date:   Mon, 23 Aug 2021 16:39:29 +0200

all: move labels to compound exprs

This follows the appropriate changes to harec.

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

Diffstat:
Mcmd/hare/subcmds.ha | 72+++++++++++++++++++++++++++++++++++++-----------------------------------
Mgetopt/getopts.ha | 6+++---
Mhare/ast/expr.ha | 38++++++++++++++++++++------------------
Mhare/parse/+test/expr.ha | 2+-
Mhare/parse/+test/loc.ha | 2+-
Mhare/parse/expr.ha | 34++++++++++++++++++----------------
Mhare/unit/process.ha | 2+-
Mhare/unparse/expr.ha | 18+++++++++---------
8 files changed, 90 insertions(+), 84 deletions(-)

diff --git a/cmd/hare/subcmds.ha b/cmd/hare/subcmds.ha @@ -262,41 +262,43 @@ fn sched_walk(plan: *plan, ident: ast::ident, link: *[]*task) void = { const path = module::identpath(ident); const it = os::iter(path)?; free(path); - :loop for (true) match (fs::next(it)) { - ent: fs::dirent => { - if (ent.name == "." || ent.name == "..") { - continue; - }; - if (ent.ftype & fs::mode::DIR != fs::mode::DIR) { - continue; - }; - const d = utf8::decode(ent.name); - match (utf8::next(&d)) { - void => break, - (utf8::more | utf8::invalid) => continue :loop, - r: rune => if (!ascii::isalpha(r) && r != '_') { - continue :loop; - }, - }; - for (true) match (utf8::next(&d)) { - void => break, - (utf8::more | utf8::invalid) => continue :loop, - r: rune => if (!ascii::isalnum(r) && r != '_') { - continue :loop; - }, - }; - let new = ast::ident_dup(ident); - append(new, strings::dup(ent.name)); - sched_walk(plan, new, link); - - match (module::lookup(plan.context, new)) { - ver: module::version => - if (len(ver.inputs) == 0) continue, - module::error => continue, - }; - sched_module(plan, new, link); - }, - void => break, + for (true) :loop { + match (fs::next(it)) { + ent: fs::dirent => { + if (ent.name == "." || ent.name == "..") { + continue; + }; + if (ent.ftype & fs::mode::DIR != fs::mode::DIR) { + continue; + }; + const d = utf8::decode(ent.name); + match (utf8::next(&d)) { + void => break, + (utf8::more | utf8::invalid) => continue :loop, + r: rune => if (!ascii::isalpha(r) && r != '_') { + continue :loop; + }, + }; + for (true) match (utf8::next(&d)) { + void => break, + (utf8::more | utf8::invalid) => continue :loop, + r: rune => if (!ascii::isalnum(r) && r != '_') { + continue :loop; + }, + }; + let new = ast::ident_dup(ident); + append(new, strings::dup(ent.name)); + sched_walk(plan, new, link); + + match (module::lookup(plan.context, new)) { + ver: module::version => + if (len(ver.inputs) == 0) continue, + module::error => continue, + }; + sched_module(plan, new, link); + }, + void => break, + }; }; }; diff --git a/getopt/getopts.ha b/getopt/getopts.ha @@ -108,7 +108,7 @@ export type help = (cmd_help | flag_help | parameter_help); export fn parse(args: []str, help: help...) command = { let opts: []option = []; let i = 1z; - :arg for (i < len(args); i += 1) { + for (i < len(args); i += 1) :arg { const arg = args[i]; if (len(arg) == 0 || arg == "-" || !strings::has_prefix(arg, "-")) { @@ -122,9 +122,9 @@ export fn parse(args: []str, help: help...) command = { let d = utf8::decode(arg); assert(utf8::next(&d) as rune == '-'); let next = utf8::next(&d); - :flag for (next is rune; next = utf8::next(&d)) { + for (next is rune; next = utf8::next(&d)) :flag { const r = next as rune; - :help for (let j = 0z; j < len(help); j += 1) { + for (let j = 0z; j < len(help); j += 1) :help { let p: parameter_help = match (help[j]) { cmd_help => continue :help, f: flag_help => if (r == f.0) { diff --git a/hare/ast/expr.ha b/hare/ast/expr.ha @@ -156,6 +156,18 @@ export type cast_expr = struct { _type: *_type, }; +// A compound expression. +// +// { +// foo; +// bar; +// // ... +// } +export type compound_expr = struct { + exprs: []*expr, + label: label, +}; + // An array constant. // // [foo, bar, ...] @@ -214,7 +226,6 @@ export type delete_expr = *expr; // // :label for (let foo = 0; foo < bar; baz) quux export type for_expr = struct { - label: label, bindings: nullable *expr, cond: *expr, afterthought: nullable *expr, @@ -243,15 +254,6 @@ export type label = str; // len(foo) export type len_expr = *expr; -// An expression list. -// -// { -// foo; -// bar; -// // ... -// } -export type list_expr = []*expr; - // A match case. // // name: type => expr @@ -345,7 +347,7 @@ export type expr = struct { assign_expr | binarithm_expr | binding_expr | break_expr | call_expr | cast_expr | constant_expr | continue_expr | defer_expr | delete_expr | for_expr | free_expr | if_expr | - list_expr | match_expr | len_expr | size_expr | offset_expr | + compound_expr | match_expr | len_expr | size_expr | offset_expr | propagate_expr | return_expr | slice_expr | switch_expr | unarithm_expr), }; @@ -422,6 +424,13 @@ export fn expr_free(e: (expr | nullable *expr)) void = match (e) { expr_free(c.value); type_free(c._type); }, + c: compound_expr => { + for (let i = 0z; i < len(c.exprs); i += 1) { + expr_free(c.exprs[i]); + }; + free(c.exprs); + free(c.label); + }, c: constant_expr => match(c) { (void | lex::value) => void, a: array_constant => { @@ -456,7 +465,6 @@ export fn expr_free(e: (expr | nullable *expr)) void = match (e) { d: defer_expr => expr_free(d: *expr), d: delete_expr => expr_free(d: *expr), f: for_expr => { - free(f.label); expr_free(f.bindings); expr_free(f.cond); expr_free(f.afterthought); @@ -469,12 +477,6 @@ export fn expr_free(e: (expr | nullable *expr)) void = match (e) { expr_free(i.fbranch); }, l: len_expr => expr_free(l: *expr), - l: list_expr => { - for (let i = 0z; i < len(l); i += 1) { - expr_free(l[i]); - }; - free(l); - }, m: match_expr => { expr_free(m.value); for (let i = 0z; i < len(m.cases); i += 1) { diff --git a/hare/parse/+test/expr.ha b/hare/parse/+test/expr.ha @@ -151,7 +151,7 @@ for (true) { x; }; - :label for (true) { + for (true) :label { x; }; for (let x = 0; x < 10) { diff --git a/hare/parse/+test/loc.ha b/hare/parse/+test/loc.ha @@ -50,7 +50,7 @@ fn expr_testloc(srcs: str...) void = for (let i = 0z; i < len(srcs); i += 1) { expr_testloc("defer foo"); expr_testloc("delete(foo[bar])", "delete(foo[bar..baz])"); expr_testloc("for (let foo = 0; bar; baz) quux", - ":foo for (let bar = 0; baz; quux) quuux"); + "for (let bar = 0; baz; quux) quuux"); expr_testloc("free(foo)"); expr_testloc("if (foo) bar", "if (foo) bar else baz"); expr_testloc("len(foo)"); diff --git a/hare/parse/expr.ha b/hare/parse/expr.ha @@ -41,11 +41,11 @@ export fn expression(lexer: *lex::lexer) (ast::expr | error) = { ltok::CONST)?) { void => binarithm(lexer, void, 0)?, tok: lex::token => switch (tok.0) { - ltok::LBRACE => expression_list(lexer)?, + ltok::LABEL, ltok::LBRACE => compound_expr(lexer)?, ltok::MATCH => match_expr(lexer)?, ltok::SWITCH => switch_expr(lexer)?, ltok::IF => if_expr(lexer)?, - ltok::LABEL, ltok::FOR => for_expr(lexer)?, + ltok::FOR => for_expr(lexer)?, ltok::BREAK, ltok::CONTINUE, ltok::RETURN => control(lexer)?, @@ -475,10 +475,18 @@ fn delete_expr(lexer: *lex::lexer) (ast::expr | error) = { }; }; -fn expression_list(lexer: *lex::lexer) (ast::expr | error) = { - let items: ast::list_expr = []; +fn compound_expr(lexer: *lex::lexer) (ast::expr | error) = { + let items: []*ast::expr = []; + + const start = want(lexer, ltok::LBRACE, ltok::LABEL)?; + const label = switch (start.0) { + ltok::LABEL => { + want(lexer, ltok::LBRACE)?; + start.1 as str; + }, + * => "", + }; - const start = want(lexer, ltok::LBRACE)?; for (let more = true; more) { const item = match (peek(lexer, ltok::RBRACE)?) { lex::token => break, @@ -492,20 +500,15 @@ fn expression_list(lexer: *lex::lexer) (ast::expr | error) = { return ast::expr { start = start.2, end = lex::prevloc(lexer), - expr = items, + expr = ast::compound_expr { + exprs = items, + label = label, + }, }; }; fn for_expr(lexer: *lex::lexer) (ast::expr | error) = { - const tok = want(lexer, ltok::FOR, ltok::LABEL)?; - const label: ast::label = switch (tok.0) { - ltok::LABEL => { - want(lexer, ltok::FOR)?; - tok.1 as str; - }, - * => "", - }; - + const tok = want(lexer, ltok::FOR)?; want(lexer, ltok::LPAREN)?; const bindings: nullable *ast::expr = match (peek( @@ -537,7 +540,6 @@ fn for_expr(lexer: *lex::lexer) (ast::expr | error) = { start = tok.2, end = lex::prevloc(lexer), expr = ast::for_expr { - label = label, bindings = bindings, cond = cond, afterthought = afterthought, diff --git a/hare/unit/process.ha b/hare/unit/process.ha @@ -82,6 +82,7 @@ fn process_expr( ast::break_expr => abort(), // TODO ast::call_expr => abort(), // TODO ast::cast_expr => abort(), // TODO + ast::compound_expr => abort(), // TODO ast::constant_expr => process_constant(ctx, expr), ast::continue_expr => abort(), // TODO ast::defer_expr => abort(), // TODO @@ -89,7 +90,6 @@ fn process_expr( 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 diff --git a/hare/unparse/expr.ha b/hare/unparse/expr.ha @@ -236,11 +236,15 @@ export fn expr( }; z; }, - e: ast::list_expr => { - let z = fmt::fprintf(out, "{{")?; - for (let i = 0z; i < len(e); i += 1) { + e: ast::compound_expr => { + let z = 0z; + if (e.label != "") { + z += fmt::fprintf(out, ":{} ", e.label)?; + }; + z += fmt::fprintf(out, "{{")?; + for (let i = 0z; i < len(e.exprs); i += 1) { z += newline(out, indent + 1)?; - z += expr(out, indent + 1, *e[i])?; + z += expr(out, indent + 1, *e.exprs[i])?; z += fmt::fprintf(out, ";")?; }; z += newline(out, indent)?; @@ -393,11 +397,7 @@ fn for_expr( indent: size, e: ast::for_expr, ) (size | io::error) = { - let z = 0z; - if (e.label != "") { - z += fmt::fprintf(out, ":{} ", e.label)?; - }; - z += fmt::fprintf(out, "for (")?; + let z = fmt::fprintf(out, "for (")?; z += match (e.bindings) { null => 0z, e: *ast::expr => expr(out, indent, *e)?