diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/formatter.c | 72 | ||||
| -rw-r--r-- | src/formatter.h | 6 | ||||
| -rw-r--r-- | src/parse/context.c | 2 | ||||
| -rw-r--r-- | src/parse/context.h | 2 | ||||
| -rw-r--r-- | src/tomo.c | 62 |
5 files changed, 116 insertions, 28 deletions
diff --git a/src/formatter.c b/src/formatter.c index 81a5e126..83d1b7a0 100644 --- a/src/formatter.c +++ b/src/formatter.c @@ -1,23 +1,87 @@ // This code defines functions for transforming ASTs back into Tomo source text +#include <gc.h> +#include <setjmp.h> +#include <string.h> + #include "ast.h" +#include "formatter.h" +#include "parse/context.h" +#include "parse/files.h" +#include "parse/utils.h" #include "stdlib/datatypes.h" #include "stdlib/optionals.h" +#include "stdlib/tables.h" #include "stdlib/text.h" -Text_t code_format(ast_t *ast, Table_t *comments) { +OptionalText_t next_comment(Table_t comments, const char **pos, const char *end) { + for (const char *p = *pos; p < end; p++) { + const char **comment_end = Table$get(comments, &p, parse_comments_info); + if (comment_end) { + *pos = *comment_end; + return Text$from_strn(p, (int64_t)(*comment_end - p)); + } + } + return NONE_TEXT; +} + +Text_t format_code(ast_t *ast, Table_t comments) { (void)comments; switch (ast->tag) { - default: return Text$from_strn(ast->start, (int64_t)(ast->end - ast->start)); + default: { + Text_t code = Text$from_strn(ast->start, (int64_t)(ast->end - ast->start)); + return Text$replace(code, Text("\t"), Text(" ")); + } } } -OptionalText_t code_format_inline(ast_t *ast, Table_t *comments) { - (void)comments; +OptionalText_t format_inline_code(ast_t *ast, Table_t comments) { for (const char *p = ast->start; p < ast->end; p++) { if (*p == '\n' || *p == '\r') return NONE_TEXT; } + const char *pos = ast->start; + OptionalText_t comment = next_comment(comments, &pos, ast->end); + if (comment.length >= 0) return NONE_TEXT; switch (ast->tag) { default: return Text$from_strn(ast->start, (int64_t)(ast->end - ast->start)); } } + +Text_t format_file(const char *path) { + file_t *file = load_file(path); + if (!file) return EMPTY_TEXT; + + jmp_buf on_err; + if (setjmp(on_err) != 0) { + return Text$from_str(file->text); + } + parse_ctx_t ctx = { + .file = file, + .on_err = &on_err, + .comments = {}, + }; + + const char *pos = file->text; + if (match(&pos, "#!")) // shebang + some_not(&pos, "\r\n"); + + whitespace(&ctx, &pos); + ast_t *ast = parse_file_body(&ctx, pos); + if (!ast) return Text$from_str(file->text); + pos = ast->end; + whitespace(&ctx, &pos); + if (pos < file->text + file->len && *pos != '\0') { + return Text$from_str(file->text); + } + + const char *fmt_pos = file->text; + Text_t code = EMPTY_TEXT; + for (OptionalText_t comment; (comment = next_comment(ctx.comments, &fmt_pos, ast->start)).length > 0;) { + code = Texts(code, comment, "\n"); + } + code = Texts(code, format_code(ast, ctx.comments)); + for (OptionalText_t comment; (comment = next_comment(ctx.comments, &fmt_pos, ast->start)).length > 0;) { + code = Texts(code, comment, "\n"); + } + return code; +} diff --git a/src/formatter.h b/src/formatter.h index c3941de9..dd4c7815 100644 --- a/src/formatter.h +++ b/src/formatter.h @@ -5,5 +5,7 @@ #include "ast.h" #include "stdlib/datatypes.h" -Text_t code_format(ast_t *ast, Table_t *comments); -OptionalText_t code_format_inline(ast_t *ast, Table_t *comments); +Text_t format_file(const char *path); +Text_t format_code(ast_t *ast, Table_t comments); +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/parse/context.c b/src/parse/context.c index 689fa1a4..cd8d16bc 100644 --- a/src/parse/context.c +++ b/src/parse/context.c @@ -5,4 +5,4 @@ #include "../stdlib/tables.h" #include "../stdlib/types.h" -TypeInfo_t *parse_comments_info = Table$info(Pointer$info("@", &Memory$info), Pointer$info("@", &Memory$info)); +const TypeInfo_t *parse_comments_info = Table$info(Pointer$info("@", &Memory$info), Pointer$info("@", &Memory$info)); diff --git a/src/parse/context.h b/src/parse/context.h index 4d519a83..f1e3be2f 100644 --- a/src/parse/context.h +++ b/src/parse/context.h @@ -8,7 +8,7 @@ #include "../stdlib/files.h" #include "../stdlib/types.h" -const TypeInfo_t *parse_comments_info; +extern const TypeInfo_t *parse_comments_info; typedef struct { file_t *file; @@ -19,6 +19,7 @@ #include "compile/files.h" #include "compile/headers.h" #include "config.h" +#include "formatter.h" #include "modules.h" #include "naming.h" #include "parse/files.h" @@ -74,9 +75,9 @@ static const char *paths_str(List_t paths) { static OptionalList_t files = NONE_LIST, args = NONE_LIST, uninstall = NONE_LIST, libraries = NONE_LIST; static OptionalBool_t verbose = false, quiet = false, show_version = false, show_parse_tree = false, - show_prefix = false, stop_at_transpile = false, stop_at_obj_compilation = false, - compile_exe = false, should_install = false, clean_build = false, source_mapping = true, - show_changelog = false; + do_format_code = false, show_prefix = false, stop_at_transpile = false, + stop_at_obj_compilation = false, compile_exe = false, should_install = false, clean_build = false, + source_mapping = true, show_changelog = false; static OptionalText_t show_codegen = NONE_TEXT, cflags = Text("-Werror -fdollars-in-identifiers -std=c2x -Wno-trigraphs " @@ -185,23 +186,38 @@ int main(int argc, char *argv[]) { " --optimization|-O <level>: set optimization level\n" " --run|-r: run a program from " TOMO_PREFIX "/share/tomo_" TOMO_VERSION "/installed\n"); Text_t help = Texts(Text("\x1b[1mtomo\x1b[m: a compiler for the Tomo programming language"), Text("\n\n"), usage); - tomo_parse_args( - argc, argv, usage, help, TOMO_VERSION, {"files", true, List$info(&Path$info), &files}, - {"args", true, List$info(&Text$info), &args}, {"verbose", false, &Bool$info, &verbose}, - {"v", false, &Bool$info, &verbose}, {"version", false, &Bool$info, &show_version}, - {"parse", false, &Bool$info, &show_parse_tree}, {"p", false, &Bool$info, &show_parse_tree}, - {"prefix", false, &Bool$info, &show_prefix}, {"quiet", false, &Bool$info, &quiet}, - {"q", false, &Bool$info, &quiet}, {"transpile", false, &Bool$info, &stop_at_transpile}, - {"t", false, &Bool$info, &stop_at_transpile}, {"compile-obj", false, &Bool$info, &stop_at_obj_compilation}, - {"c", false, &Bool$info, &stop_at_obj_compilation}, {"compile-exe", false, &Bool$info, &compile_exe}, - {"e", false, &Bool$info, &compile_exe}, {"uninstall", false, List$info(&Text$info), &uninstall}, - {"u", false, List$info(&Text$info), &uninstall}, {"library", false, List$info(&Path$info), &libraries}, - {"L", false, List$info(&Path$info), &libraries}, {"show-codegen", false, &Text$info, &show_codegen}, - {"C", false, &Text$info, &show_codegen}, {"install", false, &Bool$info, &should_install}, - {"I", false, &Bool$info, &should_install}, {"optimization", false, &Text$info, &optimization}, - {"O", false, &Text$info, &optimization}, {"force-rebuild", false, &Bool$info, &clean_build}, - {"f", false, &Bool$info, &clean_build}, {"source-mapping", false, &Bool$info, &source_mapping}, - {"m", false, &Bool$info, &source_mapping}, {"changelog", false, &Bool$info, &show_changelog}, ); + tomo_parse_args(argc, argv, usage, help, TOMO_VERSION, // + {"files", true, List$info(&Path$info), &files}, // + {"args", true, List$info(&Text$info), &args}, // + {"verbose", false, &Bool$info, &verbose}, // + {"v", false, &Bool$info, &verbose}, // + {"version", false, &Bool$info, &show_version}, // + {"parse", false, &Bool$info, &show_parse_tree}, // + {"p", false, &Bool$info, &show_parse_tree}, // + {"format", false, &Bool$info, &do_format_code}, // + {"prefix", false, &Bool$info, &show_prefix}, // + {"quiet", false, &Bool$info, &quiet}, // + {"q", false, &Bool$info, &quiet}, // + {"transpile", false, &Bool$info, &stop_at_transpile}, // + {"t", false, &Bool$info, &stop_at_transpile}, // + {"compile-obj", false, &Bool$info, &stop_at_obj_compilation}, // + {"c", false, &Bool$info, &stop_at_obj_compilation}, // + {"compile-exe", false, &Bool$info, &compile_exe}, // + {"e", false, &Bool$info, &compile_exe}, // + {"uninstall", false, List$info(&Text$info), &uninstall}, // + {"u", false, List$info(&Text$info), &uninstall}, // + {"library", false, List$info(&Path$info), &libraries}, // + {"L", false, List$info(&Path$info), &libraries}, // + {"show-codegen", false, &Text$info, &show_codegen}, // + {"C", false, &Text$info, &show_codegen}, // + {"install", false, &Bool$info, &should_install}, // + {"I", false, &Bool$info, &should_install}, // + {"optimization", false, &Text$info, &optimization}, // + {"O", false, &Text$info, &optimization}, // + {"force-rebuild", false, &Bool$info, &clean_build}, {"f", false, &Bool$info, &clean_build}, // + {"source-mapping", false, &Bool$info, &source_mapping}, + {"m", false, &Bool$info, &source_mapping}, // + {"changelog", false, &Bool$info, &show_changelog}, ); if (show_prefix) { print(TOMO_PREFIX); @@ -299,6 +315,12 @@ int main(int argc, char *argv[]) { continue; } + if (do_format_code) { + Text_t formatted = format_file(Path$as_c_string(path)); + print(formatted); + continue; + } + Path_t exe_path = compile_exe ? Path$with_extension(path, Text(""), true) : build_file(Path$with_extension(path, Text(""), true), ""); |
