hare

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

commit 038db64a25f09c70eba2ee347da754e89bfed527
parent 0559b7754e59e4aa7d402cca52caddee2511e43f
Author: Sebastian <sebastian@sebsite.pw>
Date:   Thu, 17 Feb 2022 20:18:42 -0500

unparse: more accurately format switch/match expressions

This commit adds two exceptions to adding a newline after the `=>`
token in a case:

    case foo => abort();
    case foo => void;

In all other scenarios, a newline and extra level of indentation is
placed prior to the case body (the status quo).

    case foo =>
        yield bar;

Signed-off-by: Sebastian <sebastian@sebsite.pw>

Diffstat:
Mhare/parse/+test/expr.ha | 18++++++++----------
Mhare/unparse/expr.ha | 61++++++++++++++++++++++++++++++++++++++++++-------------------
2 files changed, 50 insertions(+), 29 deletions(-)

diff --git a/hare/parse/+test/expr.ha b/hare/parse/+test/expr.ha @@ -218,12 +218,12 @@ @test fn switch_expr() void = { roundtrip("export fn main() void = { switch (x) { - case 1234, 4321 => - return y; - case 1337 => - return z; - case => - return q; + case 1234, 4321 => + return y; + case 1337 => + return z; + case => + return q; }; }; "); @@ -240,10 +240,8 @@ return bar; case foo::bar => return baz; - case null => - void; - case *int => - void; + case null => void; + case *int => void; }; match (x) { case let s: matchdata => diff --git a/hare/unparse/expr.ha b/hare/unparse/expr.ha @@ -301,8 +301,7 @@ export fn expr( 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.exprs[i])?; - z += fmt::fprintf(out, ";")?; + z += stmt(out, indent + 1, *e.exprs[i])?; }; z += newline(out, indent)?; z += fmt::fprintf(out, "}}")?; @@ -388,6 +387,17 @@ export fn expr( }; }; +fn stmt( + out: io::handle, + indent: size, + e: ast::expr +) (size | io::error) = { + let n = 0z; + n += expr(out, indent, e)?; + n += fmt::fprint(out, ";")?; + return n; +}; + fn constant( out: io::handle, indent: size, @@ -512,7 +522,6 @@ fn switch_expr( let z = fmt::fprint(out, "switch (")?; z += expr(out, indent, *e.value)?; z += fmt::fprint(out, ") {")?; - indent += 1; for (let i = 0z; i < len(e.cases); i += 1) { z += newline(out, indent)?; @@ -530,14 +539,9 @@ fn switch_expr( }; z += fmt::fprint(out, " =>")?; }; - for (let j = 0z; j < len(item.exprs); j += 1) { - z += newline(out, indent + 1)?; - z += expr(out, indent + 1, *item.exprs[j])?; - z += fmt::fprint(out, ";")?; - }; + z += case_exprs(out, indent + 1, item.exprs)?; }; - indent -= 1; z += newline(out, indent)?; z += fmt::fprint(out, "}")?; return z; @@ -569,24 +573,43 @@ fn match_expr( case null => void; }; z += fmt::fprint(out, " =>")?; - for (let i = 0z; i < len(item.exprs); i += 1) { - z += newline(out, indent + 1)?; - z += expr(out, indent + 1, *item.exprs[i])?; - z += fmt::fprint(out, ";")?; - }; + z += case_exprs(out, indent + 1, item.exprs)?; }; if (len(e.default) != 0) { z += newline(out, indent)?; z += fmt::fprint(out, "case =>")?; - for (let i = 0z; i < len(e.default); i += 1) { - z += newline(out, indent + 1)?; - z += expr(out, indent + 1, *e.default[i])?; - z += fmt::fprint(out, ";")?; - }; + z += case_exprs(out, indent + 1, e.default)!; }; z += newline(out, indent)?; z += fmt::fprint(out, "}")?; return z; }; + +fn case_exprs( + out: io::handle, + indent: size, + exprs: []*ast::expr, +) (size | io::error) = { + let z = 0z; + + if (len(exprs) == 1) match (exprs[0].expr) { + case let e: ast::assert_expr => + if (e.cond == null) { + // abort() expression + z += fmt::fprint(out, " ")?; + z += stmt(out, indent, *exprs[0])?; + return z; + }; + case let e: ast::value => + if (e is void) return fmt::fprint(out, " void;")?; + case => void; + }; + for (let j = 0z; j < len(exprs); j += 1) { + z += newline(out, indent)?; + z += stmt(out, indent, *exprs[j])?; + }; + + return z; +};