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
|
#include "all.h"
static void emit_prelude(str *out) {
str_append(out, "void _start(void){"
"uint8_t tape[30000]={0};"
"uint8_t*ptr=tape+15000;");
}
static void emit_runtime(str *out) {
str_append(out, "typedef unsigned long size_t;"
"typedef unsigned char uint8_t;");
str_append(out,
"static inline long syscall3(long n, long a1, void *a2, long a3){"
"long ret;"
"__asm__ volatile ("
"\"syscall\""
":\"=a\"(ret)"
":\"a\"(n),\"D\"(a1),\"S\"(a2),\"d\"(a3)"
":\"rcx\",\"r11\",\"memory\""
");"
"return ret;"
"}");
}
static void emit_epilogue(str *out) { str_append(out, "syscall3(60,0,0,0);}"); }
void emit_node(str *out, ast_node_t *node, int indent) {
for (; node; node = node->next) {
switch (node->type) {
case AST_INC:
str_appendf(out, "*ptr+=%d;", node->val);
break;
case AST_DEC:
str_appendf(out, "*ptr-=%d;", node->val);
break;
case AST_PTR_INC:
str_appendf(out, "ptr+=%d;", node->val);
break;
case AST_PTR_DEC:
str_appendf(out, "ptr-=%d;", node->val);
break;
case AST_OUT:
str_appendf(out, "syscall3(1,1,ptr,1);");
break;
case AST_IN:
str_appendf(out, "syscall3(0,0,ptr,1);");
break;
case AST_LOOP:
str_append(out, "while(*ptr){");
for (size_t i = 0; i < node->children.len; i++) {
emit_node(out, node->children._data[i], indent + 1);
}
str_append(out, "}");
break;
}
}
}
str gen_code(ast_node_t *ast) {
str out = {0};
emit_runtime(&out);
emit_prelude(&out);
emit_node(&out, ast, 1);
emit_epilogue(&out);
return out;
}
|