aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.c
blob: df89aa125e019ae4f55f35765ca4051ccc256938 (plain) (blame)
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
#include "all.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;
}