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
100
101
102
103
104
105
106
|
#include "all.h"
#include "str.h"
static void emit_prelude(str *out) {
str_append(out, "void _start(void){"
"struct termios orig;"
"rawon(0, &orig);"
"u8 t[30000]={0};"
"u8*p=t+15000;");
}
static void emit_runtime(str *out) {
str_append(out, "typedef unsigned long sz;"
"typedef unsigned char u8;");
str_append(out, "typedef unsigned int tcflag_t;"
"typedef unsigned char cc_t;"
"typedef unsigned int speed_t;");
str_append(out, "struct termios{tcflag_t c_iflag;tcflag_t c_oflag;tcflag_t "
"c_cflag;tcflag_t c_lflag;cc_t c_line;cc_t c_cc[19];speed_t "
"c_ispeed; speed_t c_ospeed;};");
str_append(out, "static inline long sys3(long n, long a1, long a2, long a3){"
"long ret;"
"__asm__ volatile ("
"\"syscall\""
":\"=a\"(ret)"
":\"a\"(n),\"D\"(a1),\"S\"(a2),\"d\"(a3)"
":\"rcx\",\"r11\",\"memory\""
");"
"return ret;"
"}");
str_append(out, "static void rawon(int fd,struct termios *orig){"
"sys3(16,fd,0x5401,(long)orig);"
"struct termios t=*orig;"
"t.c_lflag&=~(2|010|0100000);"
"t.c_cc[6]=1;"
"t.c_cc[5]=0;"
"sys3(16,fd,0x5402,(long)&t);"
"}");
str_append(out, "static void rawoff(int fd,struct termios *orig){"
"sys3(16,fd,0x5402,(long)orig);"
"}");
}
static void emit_epilogue(str *out) {
str_append(out, "rawoff(0,&orig);sys3(60,0,0,0);}");
}
void emit_node(str *out, ast_node_t *node) {
for (; node; node = node->next) {
switch (node->type) {
case AST_INC:
str_appendf(out, "*p+=%d;", node->val);
break;
case AST_DEC:
str_appendf(out, "*p-=%d;", node->val);
break;
case AST_PTR_INC:
str_appendf(out, "p+=%d;", node->val);
break;
case AST_PTR_DEC:
str_appendf(out, "p-=%d;", node->val);
break;
case AST_OUT:
str_appendf(out, "sys3(1,1,(long)p,1);");
break;
case AST_IN:
str_appendf(out, "sys3(0,0,(long)p,1);");
break;
case AST_LOOP:
str_append(out, "while(*p){");
for (size_t i = 0; i < node->children.len; i++) {
emit_node(out, node->children._data[i]);
}
str_append(out, "}");
break;
case AST_CLEAR:
str_append(out, "*p=0;");
break;
}
}
}
str gen_code(ast_node_t *ast) {
str out = {0};
emit_runtime(&out);
emit_prelude(&out);
emit_node(&out, ast);
emit_epilogue(&out);
return out;
}
|