1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
// This file defines utility functions for autoformatting code
#include <stdbool.h>
#include <stdint.h>
#include "../ast.h"
#include "../parse/context.h"
#include "../stdlib/datatypes.h"
#include "../stdlib/optionals.h"
#include "../stdlib/tables.h"
#include "../stdlib/text.h"
#include "formatter.h"
const Text_t single_indent = Text(" ");
void add_line(Text_t *code, Text_t line, Text_t indent) {
if (code->length == 0) {
*code = line;
} else {
if (line.length > 0) *code = Texts(*code, "\n", indent, line);
else *code = Texts(*code, "\n");
}
}
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;
}
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);
}
CONSTFUNC bool should_have_blank_line(ast_t *ast) {
switch (ast->tag) {
case If:
case When:
case Repeat:
case While:
case For:
case Block:
case FunctionDef:
case StructDef:
case EnumDef:
case LangDef:
case ConvertDef:
case Extend:
case Defer: return true;
default: return false;
}
}
Text_t indent_code(Text_t code) {
if (code.length <= 0) return code;
return Texts(single_indent, Text$replace(code, Text("\n"), Texts("\n", single_indent)));
}
Text_t parenthesize(Text_t code, Text_t indent) {
if (Text$has(code, Text("\n"))) return Texts("(\n", indent, indent_code(code), "\n", indent, ")");
else return Texts("(", code, ")");
}
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;
}
OptionalText_t termify_inline(ast_t *ast, Table_t comments) {
if (range_has_comment(ast->start, ast->end, comments)) return NONE_TEXT;
switch (ast->tag) {
case BINOP_CASES:
case Not:
case Negative:
case HeapAllocate:
case StackReference: return parenthesize(format_inline_code(ast, comments), EMPTY_TEXT);
default: return format_inline_code(ast, comments);
}
}
Text_t termify(ast_t *ast, Table_t comments, Text_t indent) {
switch (ast->tag) {
case BINOP_CASES:
case Not:
case Negative:
case HeapAllocate:
case StackReference: return parenthesize(format_code(ast, comments, indent), indent);
default: return format_inline_code(ast, comments);
}
}
|