diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2025-08-26 14:39:11 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2025-08-26 14:39:11 -0400 |
| commit | d25d5642392f93623d1eb4d11156d293fe6df546 (patch) | |
| tree | b14e5422d459a62ec086e06d23a81f93c478bd60 | |
| parent | 4715487a4be9f03ad58cb3199e95573e262f6387 (diff) | |
Formatting for min/max and cleanup for ints/nums
| -rw-r--r-- | src/ast.c | 17 | ||||
| -rw-r--r-- | src/ast.h | 2 | ||||
| -rw-r--r-- | src/compile/expressions.c | 2 | ||||
| -rw-r--r-- | src/formatter/formatter.c | 37 | ||||
| -rw-r--r-- | src/formatter/utils.h | 1 | ||||
| -rw-r--r-- | src/parse/binops.c | 2 |
6 files changed, 43 insertions, 18 deletions
@@ -5,6 +5,7 @@ #include "ast.h" #include "stdlib/datatypes.h" +#include "stdlib/optionals.h" #include "stdlib/tables.h" #include "stdlib/text.h" @@ -202,8 +203,8 @@ Text_t ast_to_sexp(ast_t *ast) { T(None, "(None)"); T(Bool, "(Bool ", data.b ? "yes" : "no", ")"); T(Var, "(Var ", quoted_text(data.name), ")"); - T(Int, "(Int ", quoted_text(ast_source(ast)), ")"); - T(Num, "(Num ", quoted_text(ast_source(ast)), ")"); + T(Int, "(Int ", Text$quoted(ast_source(ast), false, Text("\"")), ")"); + T(Num, "(Num ", Text$quoted(ast_source(ast), false, Text("\"")), ")"); T(TextLiteral, Text$quoted(data.text, false, Text("\""))); T(TextJoin, "(Text", data.lang ? Texts(" :lang ", quoted_text(data.lang)) : EMPTY_TEXT, ast_list_to_sexp(data.children), ")"); @@ -312,13 +313,9 @@ Text_t ast_to_sexp(ast_t *ast) { const char *ast_to_sexp_str(ast_t *ast) { return Text$as_c_string(ast_to_sexp(ast)); } -const char *ast_source(ast_t *ast) { - if (!ast) return NULL; - size_t len = (size_t)(ast->end - ast->start); - char *source = GC_MALLOC_ATOMIC(len + 1); - memcpy(source, ast->start, len); - source[len] = '\0'; - return source; +OptionalText_t ast_source(ast_t *ast) { + if (ast == NULL || ast->start == NULL || ast->end == NULL) return NONE_TEXT; + return Text$from_strn(ast->start, (int64_t)(ast->end - ast->start)); } PUREFUNC bool is_idempotent(ast_t *ast) { @@ -427,6 +424,8 @@ void visit_topologically(ast_list_t *asts, Closure_t fn) { CONSTFUNC bool is_binary_operation(ast_t *ast) { switch (ast->tag) { + case Min: + case Max: case BINOP_CASES: return true; default: return false; } @@ -481,7 +481,7 @@ struct ast_s { extern const int op_tightness[NUM_AST_TAGS]; -const char *ast_source(ast_t *ast); +OptionalText_t ast_source(ast_t *ast); Text_t ast_to_sexp(ast_t *ast); const char *ast_to_sexp_str(ast_t *ast); diff --git a/src/compile/expressions.c b/src/compile/expressions.c index 2320474a..58288c50 100644 --- a/src/compile/expressions.c +++ b/src/compile/expressions.c @@ -152,7 +152,7 @@ Text_t compile(env_t *env, ast_t *ast) { ast_t *key = ast->tag == Min ? Match(ast, Min)->key : Match(ast, Max)->key; ast_t *lhs = ast->tag == Min ? Match(ast, Min)->lhs : Match(ast, Max)->lhs; ast_t *rhs = ast->tag == Min ? Match(ast, Min)->rhs : Match(ast, Max)->rhs; - const char *key_name = "$"; + const char *key_name = ast->tag == Min ? "_min_" : "_max_"; if (key == NULL) key = FakeAST(Var, key_name); env_t *expr_env = fresh_scope(env); diff --git a/src/formatter/formatter.c b/src/formatter/formatter.c index 96bdf632..a48a1f33 100644 --- a/src/formatter/formatter.c +++ b/src/formatter/formatter.c @@ -216,6 +216,7 @@ OptionalText_t format_inline_code(ast_t *ast, Table_t comments) { return Texts(code, quote); } /*inline*/ case TextLiteral: { fail("Something went wrong, we shouldn't be formatting text literals directly"); } + /*inline*/ case Path: { return Texts("(", Text$from_str(Match(ast, Path)->path), ")"); } /*inline*/ case Stop: { const char *target = Match(ast, Stop)->target; return target ? Texts("stop ", Text$from_str(target)) : Text("stop"); @@ -224,15 +225,27 @@ OptionalText_t format_inline_code(ast_t *ast, Table_t comments) { const char *target = Match(ast, Skip)->target; return target ? Texts("skip ", Text$from_str(target)) : Text("skip"); } + /*inline*/ case Min: + /*inline*/ case Max: { + Text_t lhs = fmt_inline(ast->tag == Min ? Match(ast, Min)->lhs : Match(ast, Max)->lhs, comments); + Text_t rhs = fmt_inline(ast->tag == Min ? Match(ast, Min)->rhs : Match(ast, Max)->rhs, comments); + ast_t *key = ast->tag == Min ? Match(ast, Min)->key : Match(ast, Max)->key; + return Texts(lhs, key ? fmt_inline(key, comments) : (ast->tag == Min ? Text(" _min_ ") : Text(" _max_ ")), rhs); + } /*inline*/ case None: + return Text("none"); /*inline*/ case Bool: - /*inline*/ case Int: - /*inline*/ case Num: - /*inline*/ case Var: { - Text_t code = Text$from_strn(ast->start, (int64_t)(ast->end - ast->start)); - if (Text$has(code, Text("\n"))) return NONE_TEXT; - return code; + return Match(ast, Bool)->b ? Text("yes") : Text("no"); + /*inline*/ case Int: { + OptionalText_t source = ast_source(ast); + return source.length > 0 ? source : Text$from_str(Match(ast, Int)->str); + } + /*inline*/ case Num: { + OptionalText_t source = ast_source(ast); + return source.length > 0 ? source : Text$from_str(String(Match(ast, Num)->n)); } + /*inline*/ case Var: + return Text$from_str(Match(ast, Var)->name); /*inline*/ case FunctionCall: { DeclareMatch(call, ast, FunctionCall); return Texts(fmt_inline(call->fn, comments), "(", must(format_inline_args(call->args, comments)), ")"); @@ -566,6 +579,18 @@ Text_t format_code(ast_t *ast, Table_t comments, Text_t indent) { return code; } /*multiline*/ case TextLiteral: { fail("Something went wrong, we shouldn't be formatting text literals directly"); } + /*multiline*/ case Path: { + assert(inlined.length > 0); + return inlined; + } + /*inline*/ case Min: + /*inline*/ case Max: { + Text_t lhs = termify(ast->tag == Min ? Match(ast, Min)->lhs : Match(ast, Max)->lhs, comments, indent); + Text_t rhs = termify(ast->tag == Min ? Match(ast, Min)->rhs : Match(ast, Max)->rhs, comments, indent); + ast_t *key = ast->tag == Min ? Match(ast, Min)->key : Match(ast, Max)->key; + Text_t op = key ? fmt(key, comments, indent) : (ast->tag == Min ? Text("_min_") : Text("_max_")); + return Texts(lhs, " ", op, " ", rhs); + } /*multiline*/ case Stop: /*multiline*/ case Skip: /*multiline*/ case None: diff --git a/src/formatter/utils.h b/src/formatter/utils.h index df9c9b92..9dc230e4 100644 --- a/src/formatter/utils.h +++ b/src/formatter/utils.h @@ -6,6 +6,7 @@ #include "../ast.h" #include "../stdlib/datatypes.h" +#include "../stdlib/optionals.h" #define MAX_WIDTH 100 diff --git a/src/parse/binops.c b/src/parse/binops.c index 80bd7dd5..4676b249 100644 --- a/src/parse/binops.c +++ b/src/parse/binops.c @@ -67,7 +67,7 @@ ast_t *parse_infix_expr(parse_ctx_t *ctx, const char *pos, int min_tightness) { for (ast_e op; (op = match_binary_operator(&pos)) != Unknown && op_tightness[op] >= min_tightness; spaces(&pos)) { ast_t *key = NULL; if (op == Min || op == Max) { - key = NewAST(ctx->file, pos, pos, Var, .name = "$"); + key = NewAST(ctx->file, pos, pos, Var, .name = (op == Min ? "_min_" : "_max_")); for (bool progress = true; progress;) { ast_t *new_term; progress = |
