aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-08-25 14:36:51 -0400
committerBruce Hill <bruce@bruce-hill.com>2025-08-25 14:36:51 -0400
commit6c134dd340e24e6247a9ca5a03a7c47c27c3d34f (patch)
tree108fb3a41159c55bbf245d0e524f4b4b0f98a14d /src
parent15f3227ae693b6b9c07f8a89909faaff297ceb9a (diff)
More formatter functionality
Diffstat (limited to 'src')
-rw-r--r--src/ast.h1
-rw-r--r--src/formatter.c77
-rw-r--r--src/parse/typedefs.c4
3 files changed, 77 insertions, 5 deletions
diff --git a/src/ast.h b/src/ast.h
index 43972371..8facc202 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -90,6 +90,7 @@ typedef enum {
} type_ast_e;
typedef struct tag_ast_s {
+ const char *start, *end;
const char *name;
arg_ast_t *fields;
struct tag_ast_s *next;
diff --git a/src/formatter.c b/src/formatter.c
index 9b7439c3..cd3e1463 100644
--- a/src/formatter.c
+++ b/src/formatter.c
@@ -99,7 +99,8 @@ static OptionalText_t format_inline_arg(arg_ast_t *arg, Table_t comments) {
}
static Text_t format_arg(arg_ast_t *arg, Table_t comments, Text_t indent) {
- (void)comments;
+ OptionalText_t inline_arg = format_inline_arg(arg, comments);
+ if (inline_arg.length >= 0) return inline_arg;
Text_t code = Text$from_str(arg->name);
if (arg->type) code = Texts(code, ":", format_type(arg->type, comments, indent));
if (arg->value) code = Texts(code, " = ", format_code(arg->value, comments, indent));
@@ -134,13 +135,55 @@ static Text_t format_args(arg_ast_t *args, Table_t comments, Text_t indent) {
return code;
}
-ast_t *unwrap_block(ast_t *ast) {
+static OptionalText_t format_inline_tag(tag_ast_t *tag, Table_t comments) {
+ if (range_has_comment(tag->start, tag->end, comments)) return NONE_TEXT;
+ Text_t code = Texts(Text$from_str(tag->name), "(", must(format_inline_args(tag->fields, comments)));
+ if (tag->secret) code = Texts(code, "; secret");
+ return Texts(code, ")");
+}
+
+static Text_t format_tag(tag_ast_t *tag, Table_t comments, Text_t indent) {
+ OptionalText_t inline_tag = format_inline_tag(tag, comments);
+ if (inline_tag.length >= 0) return inline_tag;
+ Text_t code =
+ Texts(Text$from_str(tag->name), "(", format_args(tag->fields, comments, Texts(indent, single_indent)));
+ if (tag->secret) code = Texts(code, "; secret");
+ return Texts(code, ")");
+}
+
+static OptionalText_t format_inline_tags(tag_ast_t *tags, Table_t comments) {
+ Text_t code = EMPTY_TEXT;
+ for (; tags; tags = tags->next) {
+ code = Texts(code, must(format_inline_tag(tags, comments)));
+ if (tags->next) code = Texts(code, ", ");
+ if (tags->next && range_has_comment(tags->end, tags->next->start, comments)) return NONE_TEXT;
+ }
+ return code;
+}
+
+static Text_t format_tags(tag_ast_t *tags, Table_t comments, Text_t indent) {
+ OptionalText_t inline_tags = format_inline_tags(tags, comments);
+ if (inline_tags.length >= 0) return inline_tags;
+ Text_t code = EMPTY_TEXT;
+ for (; tags; tags = tags->next) {
+ add_line(&code, Texts(format_tag(tags, comments, indent), ","), indent);
+ }
+ return code;
+}
+
+static CONSTFUNC ast_t *unwrap_block(ast_t *ast) {
+ if (ast == NULL) return NULL;
while (ast->tag == Block && Match(ast, Block)->statements && Match(ast, Block)->statements->next == NULL) {
ast = Match(ast, Block)->statements->ast;
}
return ast;
}
+static Text_t format_namespace(ast_t *namespace, Table_t comments, Text_t indent) {
+ if (unwrap_block(namespace) == NULL) return EMPTY_TEXT;
+ return Texts("\n", indent, single_indent, format_code(namespace, comments, Texts(indent, single_indent)));
+}
+
OptionalText_t format_inline_code(ast_t *ast, Table_t comments) {
if (range_has_comment(ast->start, ast->end, comments)) return NONE_TEXT;
switch (ast->tag) {
@@ -150,6 +193,10 @@ OptionalText_t format_inline_code(ast_t *ast, Table_t comments) {
else if (statements->next == NULL) return format_inline_code(statements->ast, comments);
else return NONE_TEXT;
}
+ case StructDef:
+ case EnumDef:
+ case LangDef:
+ case Extend:
case FunctionDef: return NONE_TEXT;
case If: {
DeclareMatch(if_, ast, If);
@@ -254,8 +301,30 @@ Text_t format_code(ast_t *ast, Table_t comments, Text_t indent) {
code = Texts(code, func->args ? Text(" -> ") : Text("-> "), format_type(func->ret_type, comments, indent));
if (func->cache) code = Texts(code, "; cache=", format_code(func->cache, comments, indent));
if (func->is_inline) code = Texts(code, "; inline");
- code = Texts(code, ")\n", single_indent, format_code(func->body, comments, Texts(indent, single_indent)));
- return Texts(code, "\n");
+ code =
+ Texts(code, ")\n", indent, single_indent, format_code(func->body, comments, Texts(indent, single_indent)));
+ return Texts(code);
+ }
+ case StructDef: {
+ DeclareMatch(def, ast, StructDef);
+ Text_t code = Texts("struct ", Text$from_str(def->name), "(", format_args(def->fields, comments, indent));
+ if (def->secret) code = Texts(code, "; secret");
+ if (def->external) code = Texts(code, "; external");
+ if (def->opaque) code = Texts(code, "; opaque");
+ return Texts(code, ")", format_namespace(def->namespace, comments, indent));
+ }
+ case EnumDef: {
+ DeclareMatch(def, ast, EnumDef);
+ Text_t code = Texts("enum ", Text$from_str(def->name), "(", format_tags(def->tags, comments, indent));
+ return Texts(code, ")", format_namespace(def->namespace, comments, indent));
+ }
+ case LangDef: {
+ DeclareMatch(def, ast, LangDef);
+ return Texts("lang ", Text$from_str(def->name), format_namespace(def->namespace, comments, indent));
+ }
+ case Extend: {
+ DeclareMatch(extend, ast, Extend);
+ return Texts("lang ", Text$from_str(extend->name), format_namespace(extend->body, comments, indent));
}
default: {
if (inlined_fits) return inlined;
diff --git a/src/parse/typedefs.c b/src/parse/typedefs.c
index d5ade767..6e5e40d0 100644
--- a/src/parse/typedefs.c
+++ b/src/parse/typedefs.c
@@ -113,6 +113,7 @@ ast_t *parse_enum_def(parse_ctx_t *ctx, const char *pos) {
whitespace(ctx, &pos);
for (;;) {
spaces(&pos);
+ const char *tag_start = pos;
const char *tag_name = get_id(&pos);
if (!tag_name) break;
@@ -133,7 +134,8 @@ ast_t *parse_enum_def(parse_ctx_t *ctx, const char *pos) {
fields = NULL;
}
- tags = new (tag_ast_t, .name = tag_name, .fields = fields, .secret = secret, .next = tags);
+ tags = new (tag_ast_t, .start = tag_start, .end = pos, .name = tag_name, .fields = fields, .secret = secret,
+ .next = tags);
if (!match_separator(ctx, &pos)) break;
}