diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/formatter.h | 11 | ||||
| -rw-r--r-- | src/formatter/args.c | 55 | ||||
| -rw-r--r-- | src/formatter/args.h | 15 | ||||
| -rw-r--r-- | src/formatter/enums.c | 45 | ||||
| -rw-r--r-- | src/formatter/enums.h | 11 | ||||
| -rw-r--r-- | src/formatter/formatter.c (renamed from src/formatter.c) | 142 | ||||
| -rw-r--r-- | src/formatter/formatter.h | 26 | ||||
| -rw-r--r-- | src/formatter/types.c | 30 | ||||
| -rw-r--r-- | src/formatter/types.h | 9 | ||||
| -rw-r--r-- | src/tomo.c | 2 |
10 files changed, 207 insertions, 139 deletions
diff --git a/src/formatter.h b/src/formatter.h deleted file mode 100644 index bead52ec..00000000 --- a/src/formatter.h +++ /dev/null @@ -1,11 +0,0 @@ -// This code defines functions for transforming ASTs back into Tomo source text - -#pragma once - -#include "ast.h" -#include "stdlib/datatypes.h" - -Text_t format_file(const char *path); -Text_t format_code(ast_t *ast, Table_t comments, Text_t indentation); -OptionalText_t format_inline_code(ast_t *ast, Table_t comments); -OptionalText_t next_comment(Table_t comments, const char **pos, const char *end); diff --git a/src/formatter/args.c b/src/formatter/args.c new file mode 100644 index 00000000..9467c9fe --- /dev/null +++ b/src/formatter/args.c @@ -0,0 +1,55 @@ +// Logic for formatting arguments and argument lists + +#include "../ast.h" +#include "../stdlib/datatypes.h" +#include "../stdlib/optionals.h" +#include "../stdlib/text.h" +#include "formatter.h" +#include "types.h" + +OptionalText_t format_inline_arg(arg_ast_t *arg, Table_t comments) { + if (range_has_comment(arg->start, arg->end, comments)) return NONE_TEXT; + if (arg->name == NULL && arg->value) return must(format_inline_code(arg->value, comments)); + Text_t code = Text$from_str(arg->name); + if (arg->type) code = Texts(code, ":", must(format_inline_type(arg->type, comments))); + if (arg->value) code = Texts(code, " = ", must(format_inline_code(arg->value, comments))); + return code; +} + +Text_t format_arg(arg_ast_t *arg, Table_t comments, Text_t indent) { + OptionalText_t inline_arg = format_inline_arg(arg, comments); + if (inline_arg.length >= 0 && inline_arg.length <= MAX_WIDTH) return inline_arg; + if (arg->name == NULL && arg->value) return format_code(arg->value, comments, indent); + 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)); + return code; +} + +OptionalText_t format_inline_args(arg_ast_t *args, Table_t comments) { + Text_t code = EMPTY_TEXT; + for (; args; args = args->next) { + if (args->name && args->next && args->type == args->next->type && args->value == args->next->value) { + code = Texts(code, Text$from_str(args->name), ","); + } else { + code = Texts(code, must(format_inline_arg(args, comments))); + if (args->next) code = Texts(code, ", "); + } + if (args->next && range_has_comment(args->end, args->next->start, comments)) return NONE_TEXT; + } + return code; +} + +Text_t format_args(arg_ast_t *args, Table_t comments, Text_t indent) { + OptionalText_t inline_args = format_inline_args(args, comments); + if (inline_args.length >= 0 && inline_args.length <= MAX_WIDTH) return inline_args; + Text_t code = EMPTY_TEXT; + for (; args; args = args->next) { + if (args->name && args->next && args->type == args->next->type && args->value == args->next->value) { + code = Texts(code, Text$from_str(args->name), ","); + } else { + add_line(&code, Texts(format_arg(args, comments, indent), ","), indent); + } + } + return code; +} diff --git a/src/formatter/args.h b/src/formatter/args.h new file mode 100644 index 00000000..815069a4 --- /dev/null +++ b/src/formatter/args.h @@ -0,0 +1,15 @@ +// Logic for formatting arguments and argument lists + +#pragma once + +#include "../ast.h" +#include "../stdlib/datatypes.h" + +OptionalText_t format_inline_arg(arg_ast_t *arg, Table_t comments); +Text_t format_arg(arg_ast_t *arg, Table_t comments, Text_t indent); +OptionalText_t format_inline_args(arg_ast_t *args, Table_t comments); +Text_t format_args(arg_ast_t *args, Table_t comments, Text_t indent); +OptionalText_t format_inline_tag(tag_ast_t *tag, Table_t comments); +Text_t format_tag(tag_ast_t *tag, Table_t comments, Text_t indent); +OptionalText_t format_inline_tags(tag_ast_t *tags, Table_t comments); +Text_t format_tags(tag_ast_t *tags, Table_t comments, Text_t indent); diff --git a/src/formatter/enums.c b/src/formatter/enums.c new file mode 100644 index 00000000..430e72ea --- /dev/null +++ b/src/formatter/enums.c @@ -0,0 +1,45 @@ +// Logic for formatting enums and enum tags + +#include "../ast.h" +#include "../stdlib/datatypes.h" +#include "../stdlib/optionals.h" +#include "../stdlib/text.h" +#include "args.h" +#include "formatter.h" +#include "types.h" + +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, ")"); +} + +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, ")"); +} + +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; +} + +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; +} diff --git a/src/formatter/enums.h b/src/formatter/enums.h new file mode 100644 index 00000000..e7233df4 --- /dev/null +++ b/src/formatter/enums.h @@ -0,0 +1,11 @@ +// Logic for formatting enums and enum tags + +#pragma once + +#include "../ast.h" +#include "../stdlib/datatypes.h" + +OptionalText_t format_inline_tag(tag_ast_t *tag, Table_t comments); +Text_t format_tag(tag_ast_t *tag, Table_t comments, Text_t indent); +OptionalText_t format_inline_tags(tag_ast_t *tags, Table_t comments); +Text_t format_tags(tag_ast_t *tags, Table_t comments, Text_t indent); diff --git a/src/formatter.c b/src/formatter/formatter.c index 51155015..d2168231 100644 --- a/src/formatter.c +++ b/src/formatter/formatter.c @@ -3,30 +3,24 @@ #include <assert.h> #include <setjmp.h> -#include "ast.h" +#include "../ast.h" +#include "../parse/context.h" +#include "../parse/files.h" +#include "../parse/utils.h" +#include "../stdlib/datatypes.h" +#include "../stdlib/integers.h" +#include "../stdlib/optionals.h" +#include "../stdlib/stdlib.h" +#include "../stdlib/tables.h" +#include "../stdlib/text.h" +#include "args.h" +#include "enums.h" #include "formatter.h" -#include "parse/context.h" -#include "parse/files.h" -#include "parse/utils.h" -#include "stdlib/datatypes.h" -#include "stdlib/integers.h" -#include "stdlib/optionals.h" -#include "stdlib/stdlib.h" -#include "stdlib/tables.h" -#include "stdlib/text.h" - -#define MAX_WIDTH 100 - -#define must(expr) \ - ({ \ - OptionalText_t _expr = expr; \ - if (_expr.length < 0) return NONE_TEXT; \ - (Text_t) _expr; \ - }) +#include "types.h" const Text_t single_indent = Text(" "); -static void add_line(Text_t *code, Text_t line, Text_t indent) { +void add_line(Text_t *code, Text_t line, Text_t indent) { if (code->length == 0) { *code = line; } else { @@ -46,7 +40,7 @@ OptionalText_t next_comment(Table_t comments, const char **pos, const char *end) return NONE_TEXT; } -static bool range_has_comment(const char *start, const char *end, Table_t comments) { +bool range_has_comment(const char *start, const char *end, Table_t comments) { OptionalText_t comment = next_comment(comments, &start, end); return (comment.length >= 0); } @@ -79,112 +73,6 @@ static Text_t parenthesize(Text_t code, Text_t indent) { else return Texts("(", code, ")"); } -static OptionalText_t format_inline_type(type_ast_t *type, Table_t comments) { - if (range_has_comment(type->start, type->end, comments)) return NONE_TEXT; - switch (type->tag) { - default: { - Text_t code = Text$from_strn(type->start, (int64_t)(type->end - type->start)); - if (Text$has(code, Text("\n"))) return NONE_TEXT; - return Text$replace(code, Text("\t"), single_indent); - } - } -} - -static Text_t format_type(type_ast_t *type, Table_t comments, Text_t indent) { - (void)comments, (void)indent; - switch (type->tag) { - default: { - OptionalText_t inline_type = format_inline_type(type, comments); - if (inline_type.length >= 0) return inline_type; - Text_t code = Text$from_strn(type->start, (int64_t)(type->end - type->start)); - return Text$replace(code, Text("\t"), single_indent); - } - } -} - -static OptionalText_t format_inline_arg(arg_ast_t *arg, Table_t comments) { - if (range_has_comment(arg->start, arg->end, comments)) return NONE_TEXT; - if (arg->name == NULL && arg->value) return must(format_inline_code(arg->value, comments)); - Text_t code = Text$from_str(arg->name); - if (arg->type) code = Texts(code, ":", must(format_inline_type(arg->type, comments))); - if (arg->value) code = Texts(code, " = ", must(format_inline_code(arg->value, comments))); - return code; -} - -static Text_t format_arg(arg_ast_t *arg, Table_t comments, Text_t indent) { - OptionalText_t inline_arg = format_inline_arg(arg, comments); - if (inline_arg.length >= 0 && inline_arg.length <= MAX_WIDTH) return inline_arg; - if (arg->name == NULL && arg->value) return format_code(arg->value, comments, indent); - 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)); - return code; -} - -static OptionalText_t format_inline_args(arg_ast_t *args, Table_t comments) { - Text_t code = EMPTY_TEXT; - for (; args; args = args->next) { - if (args->name && args->next && args->type == args->next->type && args->value == args->next->value) { - code = Texts(code, Text$from_str(args->name), ","); - } else { - code = Texts(code, must(format_inline_arg(args, comments))); - if (args->next) code = Texts(code, ", "); - } - if (args->next && range_has_comment(args->end, args->next->start, comments)) return NONE_TEXT; - } - return code; -} - -static Text_t format_args(arg_ast_t *args, Table_t comments, Text_t indent) { - OptionalText_t inline_args = format_inline_args(args, comments); - if (inline_args.length >= 0 && inline_args.length <= MAX_WIDTH) return inline_args; - Text_t code = EMPTY_TEXT; - for (; args; args = args->next) { - if (args->name && args->next && args->type == args->next->type && args->value == args->next->value) { - code = Texts(code, Text$from_str(args->name), ","); - } else { - add_line(&code, Texts(format_arg(args, comments, indent), ","), indent); - } - } - return code; -} - -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) { diff --git a/src/formatter/formatter.h b/src/formatter/formatter.h new file mode 100644 index 00000000..83bb9e56 --- /dev/null +++ b/src/formatter/formatter.h @@ -0,0 +1,26 @@ +// This code defines functions for transforming ASTs back into Tomo source text + +#pragma once + +#include "../ast.h" +#include "../stdlib/datatypes.h" + +#define MAX_WIDTH 100 + +#define must(expr) \ + ({ \ + OptionalText_t _expr = expr; \ + if (_expr.length < 0) return NONE_TEXT; \ + (Text_t) _expr; \ + }) + +extern const Text_t single_indent; + +Text_t format_file(const char *path); +Text_t format_code(ast_t *ast, Table_t comments, Text_t indentation); +OptionalText_t format_inline_code(ast_t *ast, Table_t comments); + +OptionalText_t next_comment(Table_t comments, const char **pos, const char *end); +bool range_has_comment(const char *start, const char *end, Table_t comments); +OptionalText_t next_comment(Table_t comments, const char **pos, const char *end); +void add_line(Text_t *code, Text_t line, Text_t indent); diff --git a/src/formatter/types.c b/src/formatter/types.c new file mode 100644 index 00000000..282a299f --- /dev/null +++ b/src/formatter/types.c @@ -0,0 +1,30 @@ +// Logic for formatting types + +#include "../ast.h" +#include "../stdlib/datatypes.h" +#include "../stdlib/optionals.h" +#include "../stdlib/text.h" +#include "formatter.h" + +OptionalText_t format_inline_type(type_ast_t *type, Table_t comments) { + if (range_has_comment(type->start, type->end, comments)) return NONE_TEXT; + switch (type->tag) { + default: { + Text_t code = Text$from_strn(type->start, (int64_t)(type->end - type->start)); + if (Text$has(code, Text("\n"))) return NONE_TEXT; + return Text$replace(code, Text("\t"), single_indent); + } + } +} + +Text_t format_type(type_ast_t *type, Table_t comments, Text_t indent) { + (void)comments, (void)indent; + switch (type->tag) { + default: { + OptionalText_t inline_type = format_inline_type(type, comments); + if (inline_type.length >= 0) return inline_type; + Text_t code = Text$from_strn(type->start, (int64_t)(type->end - type->start)); + return Text$replace(code, Text("\t"), single_indent); + } + } +} diff --git a/src/formatter/types.h b/src/formatter/types.h new file mode 100644 index 00000000..1f0698b3 --- /dev/null +++ b/src/formatter/types.h @@ -0,0 +1,9 @@ +// Logic for formatting types + +#pragma once + +#include "../ast.h" +#include "../stdlib/datatypes.h" + +OptionalText_t format_inline_type(type_ast_t *type, Table_t comments); +Text_t format_type(type_ast_t *type, Table_t comments, Text_t indent); @@ -19,7 +19,7 @@ #include "compile/files.h" #include "compile/headers.h" #include "config.h" -#include "formatter.h" +#include "formatter/formatter.h" #include "modules.h" #include "naming.h" #include "parse/files.h" |
