1 // This file defines utility functions for autoformatting code
7 #include "../parse/context.h"
8 #include "../stdlib/datatypes.h"
9 #include "../stdlib/optionals.h"
10 #include "../stdlib/tables.h"
11 #include "../stdlib/text.h"
12 #include "formatter.h"
14 const Text_t single_indent = Text(" ");
16 void add_line(Text_t *code, Text_t line, Text_t indent) {
17 if (code->length == 0) {
20 if (line.length > 0) *code = Texts(*code, "\n", indent, line);
21 else *code = Texts(*code, "\n");
25 OptionalText_t next_comment(Table_t comments, const char **pos, const char *end) {
26 for (const char *p = *pos; p < end; p++) {
27 const char **comment_end = Table$get(comments, &p, parse_comments_info);
30 return Text$from_strn(p, (size_t)(*comment_end - p));
36 bool range_has_comment(const char *start, const char *end, Table_t comments) {
37 OptionalText_t comment = next_comment(comments, &start, end);
38 return (comment.tag != TEXT_NONE);
41 CONSTFUNC int suggested_blank_lines(ast_t *first, ast_t *second) {
42 if (second == NULL) return 0;
45 if (first->tag == Declare && Match(first, Declare)->value) {
46 first = Match(first, Declare)->value;
47 } else if (first->tag == DebugLog) {
53 if (second->tag == Declare && Match(second, Declare)->value) {
54 second = Match(second, Declare)->value;
55 } else if (second->tag == DebugLog) {
73 case LangDef: return 1;
75 if (second->tag != Use) return 1;
79 DeclareMatch(decl, first, Declare);
80 if (decl->value) return suggested_blank_lines(decl->value, second);
84 DeclareMatch(assign, first, Assign);
85 for (ast_list_t *val = assign->values; val; val = val->next) {
86 if (suggested_blank_lines(val->ast, second) > 0) return 1;
93 switch (second->tag) {
106 case LangDef: return 1;
112 Text_t indent_code(Text_t code) {
113 if (code.length <= 0) return code;
114 return Texts(single_indent, Text$replace(code, Text("\n"), Texts("\n", single_indent)));
117 Text_t parenthesize(Text_t code, Text_t indent) {
118 if (Text$has(code, Text("\n"))) return Texts("(\n", indent, indent_code(code), "\n", indent, ")");
119 else return Texts("(", code, ")");
122 CONSTFUNC ast_t *unwrap_block(ast_t *ast) {
123 if (ast == NULL) return NULL;
124 while (ast->tag == Block && Match(ast, Block)->statements && Match(ast, Block)->statements->next == NULL) {
125 ast = Match(ast, Block)->statements->ast;
127 if (ast->tag == Block && Match(ast, Block)->statements == NULL) return NULL;
131 OptionalText_t termify_inline(ast_t *ast, Table_t comments) {
132 if (range_has_comment(ast->start, ast->end, comments)) return NONE_TEXT;
138 case StackReference: return parenthesize(format_inline_code(ast, comments), EMPTY_TEXT);
139 default: return format_inline_code(ast, comments);
143 Text_t termify(ast_t *ast, Table_t comments, Text_t indent) {
149 case StackReference: return parenthesize(format_code(ast, comments, indent), indent);
150 default: return format_inline_code(ast, comments);