これは acl4v1 がないとビルドできないので、これから acl4v1 も wiki に書きます。
#define UseGraph 1
#define a_Version 1
#include <acl4v1.c>
#if (UseGraph != 0)
#include <windows.h>
#include "a4_t0002.c"
a_Win *win;
void openWin(intptr_t x, intptr_t y) { win = a_malloc(_a_ sizeof (a_Win)); a_Win_ini(_a_ win, (int) x, (int) y, "graph", 0x000000); }
void setPix(intptr_t x, intptr_t y, intptr_t c) { win->buf[x + y * win->xsz] = (uint32_t) c; }
void flushWin() { a_Win_flushAll0(win); }
void waitInf() { if (win != NULL) { flushWin(); } for (;;) Sleep(1000); }
#endif
a_class(MiniCompiler_Sub) {
int mod;
int lb; VecChr vc[2];
// mod=0: for文.
// lb+0:continue0, lb+1:continue, lb+2:continue2, lb+3:break.
// vc0:繰り返し条件, vc1:cotinue時のインクリメント処理など.
};
a_class(MiniCompiler) {
a_Token0 *t0;
a_BufFree bf[1];
a_VecChr *vc;
a_VecChr stk[1], lbl[1];
int tmpNo, tmpLb, autoClose;
};
int eval_hook1(a_Preprocessor_Eval *w, a_Token0 *t0, int pri, const char *t, intptr_t *pi);
a_static void MiniCompiler_ini(MiniCompiler *w);
a_static void MiniCompiler_din(MiniCompiler *w);
a_static char *MiniCompiler_compile(MiniCompiler *w, int pri);
int main(int argc, const char **argv)
{
const char *src = getArg(argc, argv, "src:", ""); char *t, *tt;
VecChr vc0[1], vc1[1], vc2[1], vc3[1]; VecChr_ini4(_a_ vc0, vc1, vc2, vc3);
BufFree bf[1]; a_BufFree_ini(_a_ bf); Token0 t0[1]; Token0_ini1(t0);
Preprocessor_Eval ev[1]; Preprocessor_Eval_ini(_a_ ev); ev->err = 0;
ev->hook1 = eval_hook1; ev->v[0] = bf; ev->v[1] = vc3;
if (strtol(getArg(argc, argv, "prepro:", "0"), NULL, 0) != 0) {
int mod = strtol(getArg(argc, argv, "mod:", "1"), NULL, 0);
a_Preprocessor_ini1(src, -1, mod, vc0);
puts(vc0->p);
}
if (strtol(getArg(argc, argv, "calc:", "0"), NULL, 0) != 0) {
a_Preprocessor_ini1(src, -1, 2, vc0);
t0->s = vc0->p; t0->s1 = vc0->p + VecChr_N(vc0);
for (;;) {
t = Token1_get(t0);
if (t0->c == ',' || t0->c == ';') { printf("%c ", t0->c); continue; }
if (t0->c == 0) break;
t0->s = t; intptr_t i = Preprocessor_eval(ev, t0, 0x7fff);
if (ev->err != 0) break;
printf("%d", (int) i);
}
printf("\n");
}
if (strtol(getArg(argc, argv, "x86asm:", "0"), NULL, 0) != 0) {
a_VecChr_iniArg(_a_ vc0, src, 2+16);
for (t = vc0->p;;) {
tt = strstr(t, "LBL("); if (tt == NULL) break;
t = strchr(tt, ')'); if (t == NULL) break;
VecChr_printf(vc1, "#defineX %.*s defEnum(0)\n", t - tt - 4, tt + 4);
}
VecChr_printf(vc2, "imm<sys>:#include \"x86asm.h\"\ndefEnum(0, 2)\n%s%s", vc1->p, vc0->p);
VecChr_N(vc0) = 0; a_Preprocessor_ini1(vc2->p, -1, 2, vc0);
if (strtol(getArg(argc, argv, "dbg:", "0"), NULL, 0) != 0) puts(vc0->p);
intptr_t pass, lbl[999];
for (pass = 0; pass < 2; pass++) {
t0->s = vc0->p; t0->s1 = vc0->p + VecChr_N(vc0);
VecChr_N(vc1) = 0;
for (;;) {
t = Token1_get(t0); intptr_t n = t0->len, i, j, k, m;
if (t0->c == ',' || t0->c == ';') continue;
if (t0->c == 0) break;
if (n == 3 && memcmp(t, "LBL", 3) == 0) {
i = Preprocessor_eval(ev, t0, 0x7fff);
if (0 <= i && i < 999) lbl[i] = VecChr_N(vc1);
}
m = 0;
if (n == 4 && memcmp(t, "DB_L", 4) == 0) m = 1;
if (n == 4 && memcmp(t, "DW_L", 4) == 0) m = 2;
if (n == 4 && memcmp(t, "DD_L", 4) == 0) m = 4;
if (m > 0) {
Token1_get(t0); i = Preprocessor_eval(ev, t0, 0x7fff);
Token1_get(t0); j = Preprocessor_eval(ev, t0, 0x7fff);
Token1_get(t0); k = Preprocessor_eval(ev, t0, 0x7fff); Token1_get(t0);
if (i == 1) { i = VecChr_N(vc1); } else if (i > 1 && i < 999) { i = lbl[i]; }
if (j == 1) { j = VecChr_N(vc1); } else if (j > 1 && j < 999) { j = lbl[j]; }
i = i - j + k;
goto db_i;
}
m = 0;
if (n == 2 && memcmp(t, "DB", 2) == 0) m = 1;
if (n == 2 && memcmp(t, "DW", 2) == 0) m = 2;
if (n == 2 && memcmp(t, "DD", 2) == 0) m = 4;
if (m > 0) {
i = Preprocessor_eval(ev, t0, 0x7fff);
db_i:
*(char *)VecChr_stkAdd(vc1, 1) = i & 0xff;
if (m > 1) *(char *)VecChr_stkAdd(vc1, 1) = (i >> 8) & 0xff;
if (m > 2) *(char *)VecChr_stkAdd(vc1, 1) = (i >> 16) & 0xff;
if (m > 3) *(char *)VecChr_stkAdd(vc1, 1) = (i >> 24) & 0xff;
}
}
}
hexDump(vc1->p, VecChr_N(vc1), stdout);
}
if (strtol(getArg(argc, argv, "clang:", "0"), NULL, 0) != 0) {
a_Preprocessor_ini1(src, -1, 2, vc0);
t0->s = vc0->p; t0->s1 = vc0->p + a_VecChr_N(vc0);
MiniCompiler mc[1]; MiniCompiler_ini(mc); mc->t0 = t0; mc->vc = vc1;
MiniCompiler_compile(mc, 99); a_VecChr_replace(vc1, 0, 0, mc->lbl->p, a_VecChr_N(mc->lbl));
MiniCompiler_din(mc); a_VecChr_reserve0(vc1);
if (strtol(getArg(argc, argv, "dbg:", "0"), NULL, 0) != 0) puts(vc1->p);
a_VecChr_printf(vc2, "imm<sys>:#include \"a4vm-clang-v0.h\"\nEnt_III(256,256,0);\n%s\nLev_III(256,256,0);\n", vc1->p);
VecChr_N(vc0) = 0; a_Preprocessor_ini1(vc2->p, -1, 2, vc0);
if (strtol(getArg(argc, argv, "dbg:", "0"), NULL, 0) != 0) puts(vc0->p);
VecChr_N(vc1) = 0; t0->s = vc0->p; t0->s1 = vc0->p + VecChr_N(vc0);
for (;;) {
t = Token1_get(t0);
if (t0->c == ',' || t0->c == ';') continue;
if (t0->c == 0) break;
t0->s = t;
intptr_t i = Preprocessor_eval(ev, t0, 0x7fff);
if (ev->err != 0) break;
*(intptr_t *)VecChr_stkAdd(vc1, sizeof (intptr_t)) = i;
if (strtol(getArg(argc, argv, "dbg:", "0"), NULL, 0) != 0) printf("%d ", (int) i);
}
if (strtol(getArg(argc, argv, "dbg:", "0"), NULL, 0) != 0) printf("\n\n");
intptr_t *bp = (intptr_t *) vc1->p, bn = VecChr_N(vc1) / sizeof (intptr_t);
intptr_t a4arg[10]; a4arg[0] = 0; A4vm_exec0(bp, bn, 10, a4arg);
}
Preprocessor_Eval_din(_a_ ev);
VecChr_din4(_a_ vc0, vc1, vc2, vc3); BufFree_flush(_a_ bf); BufFree_din(_a_ bf);
a_malloc_debugList(_a);
a_DbgObjInfTbl_debugList(_a);
return 0;
}
int eval_hook1(a_Preprocessor_Eval *w, a_Token0 *t0, int pri, const char *t, intptr_t *pi)
{
BufFree *bf = w->v[0];
VecChr *vcTmp = w->v[1];
intptr_t n = t0->len; (void) pri;
if (n >= 2 && t[0] == 0x22) {
char *s;
VecChr_N(vcTmp) = 0; VecChr_puts(vcTmp, t + 1, n - 2);
VecChr_convEsc(vcTmp);
*pi = (intptr_t) (s = BufFree_malloc(_a_ bf, VecChr_N(vcTmp) + 1));
memcpy(s, vcTmp->p, VecChr_N(vcTmp) + 1);
return 1;
}
if (n == 6 && memcmp(t, "printf", 6) == 0) { *pi = (intptr_t) printf; return 1; }
#if (UseGraph != 0)
if (n == 7 && memcmp(t, "openWin", 7) == 0) { *pi = (intptr_t) openWin; return 1; }
if (n == 6 && memcmp(t, "setPix", 6) == 0) { *pi = (intptr_t) setPix; return 1; }
if (n == 8 && memcmp(t, "flushWin", 8) == 0) { *pi = (intptr_t) flushWin; return 1; }
if (n == 7 && memcmp(t, "waitInf", 7) == 0) { *pi = (intptr_t) waitInf; return 1; }
#endif
return 0;
}
a_static void MiniCompiler_ini(MiniCompiler *w)
{
a_BufFree_ini(_a_ w->bf); a_VecChr_ini4(_a_ w->stk, w->lbl, 0, 0); w->tmpNo = 0; w->tmpLb = 0; w->autoClose = 0;
}
a_static void MiniCompiler_din(MiniCompiler *w)
{
a_BufFree_flush(_a_ w->bf); a_BufFree_din(_a_ w->bf); a_VecChr_din4(_a_ w->stk, w->lbl, 0, 0);
}
a_static char *MiniCompiler_newTmp(MiniCompiler *w)
{
char s[256];
intptr_t n = sprintf(s, "tmp%d", w->tmpNo++);
char *v = a_BufFree_malloc(_a_ w->bf, n + 1);
memcpy(v, s, n + 1);
return v;
}
#define MiniCompiler_compile_Macro0(pri, fmt) vv = MiniCompiler_compile(w, pri); tv = MiniCompiler_newTmp(w); a_VecChr_printf(w->vc, fmt, tv, v, vv); v = tv; goto op2
a_static char *MiniCompiler_compile(MiniCompiler *w, int pri)
{
char *v, *tv, *vv;
op1:
const char *tt, *t = a_Token1_get(w->t0); intptr_t n = w->t0->len; uint32_t c = w->t0->c;
if (w->autoClose > 0) { w->t0->s = t; c = '}'; w->autoClose--; }
if (c == '}') {
MiniCompiler_Sub *sb = VecChr_stkTop(w->stk, sizeof (MiniCompiler_Sub));
if (sb->mod == 0) {
a_VecChr_printf(w->vc, "Lbl_T(LT%04d);\n%s%sLbl_T(LT%04d);\n", sb->lb + 1, sb->vc[1].p, sb->vc[0].p, sb->lb + 3);
a_VecChr_din4(_a_ &sb->vc[0], &sb->vc[1], 0, 0); VecChr_stkRmv(w->stk, sizeof (MiniCompiler_Sub)); goto op1;
}
w->t0->s = t; return NULL;
}
if (n == 0) return NULL;
if (c == '-') {
tv = MiniCompiler_compile(w, 1); v = MiniCompiler_newTmp(w);
a_VecChr_printf(w->vc, "Mul(%s, %s, CInt:-1);\n", v, tv); goto op2;
}
if (c == ';') { if (pri == 98) { w->t0->s = t; return NULL; } a_VecChr_printf(w->vc, "Semi();\n"); w->tmpNo = 0; w->autoClose *= -1; goto op1; }
if (c == '(') { v = MiniCompiler_compile(w, 99); a_Token1_get(w->t0); goto op2; } // (...)
tt = Token1_get(w->t0); if (w->t0->c == ':') { // コードラベル宣言.
a_VecChr_printf(w->vc, "Lbl_T(%.*s);\n", n, t);
a_VecChr_printf(w->lbl, "#defineX %.*s defEnum(1)\n", n, t);
goto op1;
}
if (n == 2 && memcmp(t, "if", 2) == 0 && w->t0->c == '(') {
v = MiniCompiler_compile(w, 99); a_Token1_get(w->t0); // ')'.
tt = a_Token1_get(w->t0);
if (w->t0->len == 4 && memcmp(tt, "goto", 4) == 0) {
tt = a_Token1_get(w->t0); a_VecChr_printf(w->vc, "Jne(%s, CInt:0, Txt:%.*s);\n", v, w->t0->len, tt); goto op1;
}
w->t0->s = t; return NULL;
}
if (n == 3 && memcmp(t, "for", 2) == 0 && w->t0->c == '(') {
MiniCompiler_compile(w, 98); Token1_get(w->t0);
MiniCompiler_Sub *sb = a_VecChr_stkAdd(w->stk, sizeof (MiniCompiler_Sub));
sb->mod = 0;
sb->lb = w->tmpLb; w->tmpLb += 4;
a_VecChr_ini4(_a_ &sb->vc[0], &sb->vc[1], 0, 0);
a_VecChr_printf(w->vc, "Jmp_T(LT%04d);\n", sb->lb + 2);
a_VecChr_printf(w->vc, "Lbl_T(LT%04d);\n", sb->lb + 0);
a_VecChr *vc0 = w->vc; w->vc = &sb->vc[0];
a_VecChr_printf(w->vc, "Lbl_T(LT%04d);\n", sb->lb + 2);
v = MiniCompiler_compile(w, 98); Token1_get(w->t0);
if (v == NULL) { a_VecChr_printf(w->vc, "Jmp_T(LT%04d);\n", sb->lb + 0); }
else { a_VecChr_printf(w->vc, "Jne(%s, CInt:0, Txt:LT%04d);\n", v, sb->lb + 0); }
w->vc = &sb->vc[1];
v = MiniCompiler_compile(w, 98); Token1_get(w->t0); // ')'
w->vc = vc0; w->tmpNo = 0;
tt = a_Token1_get(w->t0); if (w->t0->c != '{') { w->t0->s = tt; w->autoClose--; }
goto op1;
}
if (n == 13 && memcmp(t, "Mul64Shr_RRRI", 13) == 0) {
for (;;) {
Token1_get(w->t0); if (w->t0->c == ';') break;
}
a_VecChr_printf(w->vc, "%.*s\n", w->t0->s - t, t);
goto op1;
}
if (n == 7 && memcmp(t, "openWin", 7) == 0) goto cFunc;
if (n == 6 && memcmp(t, "setPix", 6) == 0) goto cFunc;
if (n == 8 && memcmp(t, "flushWin", 8) == 0) goto cFunc;
if (n == 7 && memcmp(t, "waitInf", 7) == 0) goto cFunc;
if (n == 6 && memcmp(t, "printf", 6) == 0) {
cFunc:
a_VecChr vc0[1]; a_VecChr_ini(_a_ vc0); a_VecChr_printf(vc0, "%.*s(", n, t);
for (;;) {
t = Token1_get(w->t0); if (w->t0->c == ')') break;
if (w->t0->c == ',') continue;
w->t0->s = t; v = MiniCompiler_compile(w, 98); tt = MiniCompiler_newTmp(w);
a_VecChr_printf(w->vc, "Let(%s, %s);\n", tt, v);
a_VecChr_printf(vc0, "%s,", tt);
}
n = a_VecChr_N(vc0); if (vc0->p[n - 1] == ',') n--;
a_VecChr_printf(w->vc, "%.*s);\n", n, vc0->p); a_VecChr_din(_a_ vc0); v = "tmp0"; goto op2;
}
w->t0->s = tt; // 一度読み込んだ未解釈の演算子をt0に押し戻す.
if (n == 3 && memcmp(t, "int", 3) == 0) {
for (;;) {
t = a_Token1_get(w->t0); if (*t == ';') break;
if (*t == ',') continue;
a_VecChr_printf(w->vc, "#defineX %.*s Int:defEnum(0)\n", w->t0->len, t);
}
w->t0->s = t; goto op1;
}
if (('0' <= *t && *t <= '9') || *t == 0x22) {
v = a_BufFree_malloc(_a_ w->bf, n + 1 + 5);
memcpy(v, "CInt:", 5); memcpy(v + 5, t, n); v[n + 5] = '\0';
} else {
v = a_BufFree_malloc(_a_ w->bf, n + 1);
memcpy(v, t, n); v[n] = '\0';
}
op2:
t = Token1_get(w->t0); c = w->t0->c; n = w->t0->len;
if (n == 0) return v;
if (c == ('+' | '+' << 8) && pri >= 1) {
tv = MiniCompiler_newTmp(w);
a_VecChr_printf(w->vc, "Let(%s, %s); Add(%s, %s, CInt:1);\n", tv, v, v, v);
v = tv; goto op2;
}
if (c == '*' && pri >= 4) { MiniCompiler_compile_Macro0( 3, "Mul(%s, %s, %s);\n"); }
if (c == '/' && pri >= 4) { MiniCompiler_compile_Macro0( 3, "Div(%s, %s, %s);\n"); }
if (c == '%' && pri >= 4) { MiniCompiler_compile_Macro0( 3, "Mod(%s, %s, %s);\n"); }
if (c == '+' && pri >= 5) { MiniCompiler_compile_Macro0( 4, "Add(%s, %s, %s);\n"); }
if (c == '-' && pri >= 5) { MiniCompiler_compile_Macro0( 4, "Sub(%s, %s, %s);\n"); }
if (c == ('<' | '<' << 8) && pri >= 6) { MiniCompiler_compile_Macro0( 5, "Shl(%s, %s, %s);\n"); }
if (c == ('>' | '>' << 8) && pri >= 6) { MiniCompiler_compile_Macro0( 5, "Shr(%s, %s, %s);\n"); }
if (c == ('<' | '=' << 8) && pri >= 7) { MiniCompiler_compile_Macro0( 6, "Cle(%s, %s, %s);\n"); }
if (c == '<' && pri >= 7) { MiniCompiler_compile_Macro0( 6, "Clt(%s, %s, %s);\n"); }
if (c == ('>' | '=' << 8) && pri >= 7) { MiniCompiler_compile_Macro0( 6, "Cge(%s, %s, %s);\n"); }
if (c == '>' && pri >= 7) { MiniCompiler_compile_Macro0( 6, "Cgt(%s, %s, %s);\n"); }
if (c == ('=' | '=' << 8) && pri >= 8) { MiniCompiler_compile_Macro0( 7, "Ceq(%s, %s, %s);\n"); }
if (c == ('!' | '=' << 8) && pri >= 8) { MiniCompiler_compile_Macro0( 7, "Cne(%s, %s, %s);\n"); }
if (c == '&' && pri >= 9) { MiniCompiler_compile_Macro0( 8, "And(%s, %s, %s);\n"); }
if (c == '^' && pri >= 10) { MiniCompiler_compile_Macro0( 9, "Xor(%s, %s, %s);\n"); }
if (c == '|' && pri >= 11) { MiniCompiler_compile_Macro0(10, "Or_(%s, %s, %s);\n"); }
if (c == '=' && pri >= 15) { a_VecChr_printf(w->vc, "Let(%s, %s);\n", v, MiniCompiler_compile(w, 15)); goto op2; }
if (c == ';' && pri >= 98) { if (pri == 98) { w->t0->s = t; return v; } a_VecChr_printf(w->vc, "Semi();\n"); w->tmpNo = 0; w->autoClose *= -1; goto op1; }
w->t0->s = t; return v; // 一度読み込んだ未解釈の演算子をt0に押し戻してからreturn.
}