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:
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;
+};