diff options
Diffstat (limited to 'src/codegen.c')
| -rw-r--r-- | src/codegen.c | 81 |
1 files changed, 55 insertions, 26 deletions
diff --git a/src/codegen.c b/src/codegen.c index a019af6..00a4e16 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -1,66 +1,95 @@ #include "all.h" +#include "str.h" static void emit_prelude(str *out) { str_append(out, "void _start(void){" - "uint8_t tape[30000]={0};" - "uint8_t*ptr=tape+15000;"); + "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 size_t;" - "typedef unsigned char uint8_t;"); + str_append(out, "typedef unsigned long sz;" + "typedef unsigned char u8;"); - 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;" - "}"); + 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, "syscall3(60,0,0,0);}"); } +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, int indent) { +void emit_node(str *out, ast_node_t *node) { for (; node; node = node->next) { switch (node->type) { + case AST_INC: - str_appendf(out, "*ptr+=%d;", node->val); + str_appendf(out, "*p+=%d;", node->val); break; case AST_DEC: - str_appendf(out, "*ptr-=%d;", node->val); + str_appendf(out, "*p-=%d;", node->val); break; case AST_PTR_INC: - str_appendf(out, "ptr+=%d;", node->val); + str_appendf(out, "p+=%d;", node->val); break; case AST_PTR_DEC: - str_appendf(out, "ptr-=%d;", node->val); + str_appendf(out, "p-=%d;", node->val); break; case AST_OUT: - str_appendf(out, "syscall3(1,1,ptr,1);"); + str_appendf(out, "sys3(1,1,(long)p,1);"); break; case AST_IN: - str_appendf(out, "syscall3(0,0,ptr,1);"); + str_appendf(out, "sys3(0,0,(long)p,1);"); break; case AST_LOOP: - str_append(out, "while(*ptr){"); + str_append(out, "while(*p){"); for (size_t i = 0; i < node->children.len; i++) { - emit_node(out, node->children._data[i], indent + 1); + emit_node(out, node->children._data[i]); } str_append(out, "}"); break; + case AST_CLEAR: + str_append(out, "*p=0;"); + break; } } } @@ -70,7 +99,7 @@ str gen_code(ast_node_t *ast) { emit_runtime(&out); emit_prelude(&out); - emit_node(&out, ast, 1); + emit_node(&out, ast); emit_epilogue(&out); return out; |
