aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-08-26 14:39:11 -0400
committerBruce Hill <bruce@bruce-hill.com>2025-08-26 14:39:11 -0400
commitd25d5642392f93623d1eb4d11156d293fe6df546 (patch)
treeb14e5422d459a62ec086e06d23a81f93c478bd60
parent4715487a4be9f03ad58cb3199e95573e262f6387 (diff)
Formatting for min/max and cleanup for ints/nums
-rw-r--r--src/ast.c17
-rw-r--r--src/ast.h2
-rw-r--r--src/compile/expressions.c2
-rw-r--r--src/formatter/formatter.c37
-rw-r--r--src/formatter/utils.h1
-rw-r--r--src/parse/binops.c2
6 files changed, 43 insertions, 18 deletions
diff --git a/src/ast.c b/src/ast.c
index 314ff998..3b58b919 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -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;
}
diff --git a/src/ast.h b/src/ast.h
index bdccb704..3ac24635 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -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 =