FlagVM/flagpole/src/main.c

1009 lines
29 KiB
C

#include <stdio.h>
#include <unistd.h>
#include <ctype.h>
#define LAZY_IMPL
#include "lazy.h"
#include "token.h"
#include "var.h"
#include "ir.h"
bool is_int_literal(Lz_SB *sb) {
for (int i = 0; i < sb->cnt; ++i) {
char c = sb->data[i];
if (!(isdigit(c) || (i == 0 && c == '-'))) {
return false;
}
}
return true;
}
bool is_float_literal(Lz_SB *sb) {
for (int i = 0; i < sb->cnt-1; ++i) {
char c = sb->data[i];
if (!(isdigit(c) || (i == 0 && c == '-') || c == '.')) {
return false;
}
}
return sb->data[sb->cnt-1] == 'f';
}
bool is_double_literal(Lz_SB *sb) {
for (int i = 0; i < sb->cnt; ++i) {
char c = sb->data[i];
if (!(isdigit(c) || (i == 0 && c == '-') || c == '.')) {
return false;
}
}
return true;
}
bool is_hex_literal(Lz_SB *sb) {
if (sb->data[0] != '0' || sb->data[1] != 'x') {
return false;
}
for (int i = 2; i < sb->cnt; ++i) {
char c = sb->data[i];
if (c >= '0' && c <= '9') continue;
if (c >= 'a' && c <= 'f') continue;
if (c >= 'A' && c <= 'F') continue;
return false;
}
return true;
}
bool is_bin_literal(Lz_SB *sb) {
if (sb->data[0] != '0' || sb->data[1] != 'b') {
return false;
}
for (int i = 2; i < sb->cnt; ++i) {
char c = sb->data[i];
if (c == '0' && c == '1') continue;
return false;
}
return true;
}
bool SBeq(Lz_SB *sb, const char *cstr) {
size_t l = strlen(cstr);
if (l != sb->cnt) return false;
return !memcmp(sb->data, cstr, l);
}
void commentStack(void *stack) {
typedef Lz_DA(int) intstack;
intstack *s = stack;
printf(" ; Stack:");
lz_da_foreach(int, x, *s) {
printf(" %d", *x);
}
printf("\n");
}
static inline uint64_t lz_sb_readhex(Lz_SB *sb) {
Lz_SB clone = *sb;
clone.data += 2;
clone.cnt -= 2;
uint64_t val = 0;
lz_da_foreach(char, c, clone) {
val *= 0x10;
if (*c >= '0' && *c <= '9') {
val += *c - '0';
} else if (*c >= 'A' && *c <= 'F') {
val += *c - 'A' + 10;
} else if (*c >= 'a' && *c <= 'f') {
val += *c - 'a' + 10;
}
}
return val;
}
static inline bool isKW(Lz_SB *sb) {
return
SBeq(sb, "proc")
|| SBeq(sb, "endproc")
|| SBeq(sb, "return")
|| SBeq(sb, "ld8")
|| SBeq(sb, "st8")
|| SBeq(sb, "dup")
|| SBeq(sb, "swap")
|| SBeq(sb, "drop")
|| SBeq(sb, "while")
|| SBeq(sb, "do")
|| SBeq(sb, "if")
|| SBeq(sb, "then")
|| SBeq(sb, "endif")
|| SBeq(sb, "endwhile")
|| SBeq(sb, "break")
|| SBeq(sb, "continue")
|| SBeq(sb, "==")
|| SBeq(sb, "not")
|| SBeq(sb, "bor")
|| SBeq(sb, "band")
|| SBeq(sb, "u+")
|| SBeq(sb, "u-")
|| SBeq(sb, "u*")
|| SBeq(sb, "u/")
|| SBeq(sb, "u%")
|| SBeq(sb, "u>")
|| SBeq(sb, "u<")
|| SBeq(sb, "i+")
|| SBeq(sb, "i-")
|| SBeq(sb, "i*")
|| SBeq(sb, "i/")
|| SBeq(sb, "i%")
|| SBeq(sb, "i>")
|| SBeq(sb, "i<")
|| SBeq(sb, "pop")
|| SBeq(sb, "$inc")
;
}
#define IR_GET_2_ARGS \
IRValue x1, x2; \
if (irVStack.cnt >= 2) { \
x1 = lz_da_pop(irVStack); \
x2 = lz_da_pop(irVStack); \
} else if (irVStack.cnt == 1) { \
x1 = lz_da_pop(irVStack); \
x2 = (IRValue) { \
.typ = IRVAL_STACK, \
.val = ++vstackUnderflows \
}; \
} else if (irVStack.cnt == 0) { \
x1 = (IRValue) { \
.typ = IRVAL_STACK, \
.val = ++vstackUnderflows \
}; \
x2 = (IRValue) { \
.typ = IRVAL_STACK, \
.val = ++vstackUnderflows \
}; \
}
typedef enum {
LABEL_WHILE,
LABEL_IF,
} LabelKind;
typedef struct {
LabelKind typ;
int num;
} AsmLabel;
int main(uint argc, char **argv) {
int opt;
Lz_DA(FILE *) inpfiles = {};
while ((opt = getopt(argc, argv, "f:")) != -1) {
switch(opt) {
case 'f': {
FILE *inpfile = fopen(optarg, "r");
if (!inpfile) {
printf("Failed to open file %s\n", optarg);
exit(1);
}
lz_da_append(inpfiles, inpfile);
break;
}
default: break;
}
}
if (inpfiles.cnt == 0) {
printf("No file requested\n");
exit(1);
}
FILE *currFile = lz_da_pop(inpfiles);
TokenKind currTokenKind;
Lz_SB tokenAccumulator = {0};
int counter = 0;
bool isQuote = false;
bool isProc = false;
bool isInclude = false;
bool isComment = false;
Lz_DA(AsmLabel) labelStack = {0};
uint64_t allocHead = 0x7000000000000000;
char funcName[128];
Lz_DA(Variable) vars = {0};
char newchar;
Lz_DA(IRStatement) irStatements = {0};
Lz_DA(IRValue) irVStack = {0};
int irVCount = 0;
int vstackUnderflows = 0;
printf("include 'fvm.inc'\n");
printf("define STACK_START 0x6000000000000000\n");
printf("define STACK_SP 125\n");
printf("define STACK_INC 126\n");
printf("org 0x4000000000000000\n");
printf(" MovI64 STACK_SP, STACK_START\n");
printf(" MovI64 STACK_INC, 8\n");
printf(" Call __fp_user_main\n");
printf(" Halt\n");
printf("macro pushstack reg\n");
printf(" SubR64 STACK_SP, STACK_INC\n");
printf(" St64 reg, STACK_SP\n");
printf("end macro\n\n");
printf("macro popstack reg\n");
printf(" Ld64 reg, STACK_SP\n");
printf(" AddR64 STACK_SP, STACK_INC\n");
printf("end macro\n\n");
// Genuinely idk why goto is possessing me today
compileStart:
while ((newchar = fgetc(currFile)) != EOF) {
++counter;
if (isComment && newchar == '\n') isComment = false;
if (!isComment && newchar == '#') isComment = true;
if (isComment) continue;
if (isspace(newchar) && !isQuote) {
if (tokenAccumulator.cnt == 0) continue;
if (is_int_literal(&tokenAccumulator)) {
currTokenKind = TOKEN_INTLIT;
goto codegenIR;
} else if (is_float_literal(&tokenAccumulator)) {
currTokenKind = TOKEN_FLOATLIT;
goto codegenIR;
} else if (is_double_literal(&tokenAccumulator)) {
currTokenKind = TOKEN_DOUBLELIT;
goto codegenIR;
} else if (is_hex_literal(&tokenAccumulator)) {
currTokenKind = TOKEN_HEXLIT;
goto codegenIR;
} else if (is_bin_literal(&tokenAccumulator)) {
currTokenKind = TOKEN_BINLIT;
goto codegenIR;
} else {
currTokenKind = TOKEN_IDENTIFIER;
if (isKW(&tokenAccumulator)) {
currTokenKind = TOKEN_KEYWORD;
}
goto codegenIR;
}
}
if (newchar == '"') {
if (isQuote) {
currTokenKind = TOKEN_STRINGLIT;
isQuote = false;
goto codegenIR;
} else {
if (tokenAccumulator.cnt != 0) {
fprintf(stderr, "error %d\n", __LINE__);
exit(1);
} else {
isQuote = true;
}
continue;
}
}
lz_da_append(tokenAccumulator, newchar);
continue;
// Names suck but this also generates some asm for blocks
codegenIR:
//printf("I must gen code i am now Amista Azozin\n");
//fprintf(stderr,"Token type: %d\n", currTokenKind);
//fprintf(stderr,"Tok: "LZ_STR_FMT"\n", LZ_STR_PRINTF(tokenAccumulator));
printf(" ; "LZ_STR_FMT"\n", LZ_STR_PRINTF(tokenAccumulator));
switch (currTokenKind) {
case TOKEN_KEYWORD: {
if (SBeq(&tokenAccumulator, "proc")) {
isProc = true;
break;
}
if (SBeq(&tokenAccumulator, "endproc")) {
IRComplete(&irStatements, &irVStack);
vstackUnderflows = 0;
printf(" Ret\n");
printf("\n\n");
if (labelStack.cnt != 0) {
fprintf(stderr,
"Unmatched statement in function %s\n", funcName);
exit(1);
}
funcName[0] = 0;
break;
}
if (SBeq(&tokenAccumulator, "return")) {
IRComplete(&irStatements, &irVStack);
vstackUnderflows = 0;
printf(" Ret\n");
break;
}
if (SBeq(&tokenAccumulator, "ld8")) {
IRValue x1;
if (irVStack.cnt >= 1) {
x1 = lz_da_pop(irVStack);
} else if (irVStack.cnt == 0) {
x1 = (IRValue) {
.typ = IRVAL_STACK,
.val = 1
};
}
IRValue dstReg = (IRValue) {
.typ = IRVAL_VIRTUAL,
.val = ++irVCount
};
IRStatement s = (IRStatement) {
.dst = dstReg,
.op = IR_LD8,
.arg1 = x1
};
lz_da_append(irVStack, dstReg);
lz_da_append(irStatements, s);
break;
}
if (SBeq(&tokenAccumulator, "st8")) {
IR_GET_2_ARGS
IRValue dstReg = (IRValue) {
.typ = IRVAL_CONSTANT,
};
IRStatement s = (IRStatement) {
.dst = dstReg,
.op = IR_ST8,
.arg1 = x1,
.arg2 = x2
};
lz_da_append(irStatements, s);
break;
}
if (SBeq(&tokenAccumulator, "dup")) {
if (irVStack.cnt != 0) {
IRValue v = lz_da_pop(irVStack);
lz_da_append(irVStack, v);
lz_da_append(irVStack, v);
} else {
printf(" popstack 106\n");
printf(" pushstack 106\n");
printf(" pushstack 106\n");
}
break;
}
if (SBeq(&tokenAccumulator, "swap")) {
IRValue x1, x2;
if (irVStack.cnt >= 2) {
x1 = lz_da_pop(irVStack);
x2 = lz_da_pop(irVStack);
} else if (irVStack.cnt == 1) {
x1 = lz_da_pop(irVStack);
x2 = (IRValue) {
.typ = IRVAL_STACK,
.val = ++vstackUnderflows
};
} else if (irVStack.cnt == 0) {
x1 = (IRValue) {
.typ = IRVAL_STACK,
.val = ++vstackUnderflows
};
x2 = (IRValue) {
.typ = IRVAL_STACK,
.val = ++vstackUnderflows
};
}
lz_da_append(irVStack, x1);
lz_da_append(irVStack, x2);
break;
}
if (SBeq(&tokenAccumulator, "drop")) {
if (irVStack.cnt != 0)
lz_da_pop(irVStack);
else
printf(" popstack 118\n");
break;
}
if (SBeq(&tokenAccumulator, "while")) {
IRComplete(&irStatements, &irVStack);
AsmLabel lbl = (AsmLabel) {
.num = counter,
.typ = LABEL_WHILE
};
lz_da_append(labelStack, lbl);
commentStack(&labelStack);
printf("__whilehead_%d:\n", lbl.num);
break;
}
if (SBeq(&tokenAccumulator, "do")) {
IRComplete(&irStatements, &irVStack);
vstackUnderflows = 0;
AsmLabel lbl = lz_da_pop(labelStack);
if (lbl.typ != LABEL_WHILE) {
fprintf(stderr, "Unmatched do without a while\n");
exit(1);
}
lz_da_append(labelStack, lbl);
// TODO: Change flag setting to IR's job
printf(" popstack 108\n");
printf(" RSetF 108\n");
printf(" JmpIE __whiletail_%d\n", lbl.num);
break;
}
if (SBeq(&tokenAccumulator, "endwhile")) {
IRComplete(&irStatements, &irVStack);
vstackUnderflows = 0;
AsmLabel lbl = lz_da_pop(labelStack);
if (lbl.typ != LABEL_WHILE) {
fprintf(stderr, "Unmatched endwhile without while\n");
exit(1);
}
commentStack(&labelStack);
printf(" Jmp __whilehead_%d\n", lbl.num);
printf("__whiletail_%d:\n", lbl.num);
break;
}
if (SBeq(&tokenAccumulator, "break")) {
IRComplete(&irStatements, &irVStack);
AsmLabel lbl;
for (int i = labelStack.cnt; i >= 0; --i) {
if (labelStack.data[i].typ == LABEL_WHILE) {
lbl = labelStack.data[i];
}
}
printf(" Jmp __whiletail_%d\n", lbl.num);
break;
}
if (SBeq(&tokenAccumulator, "continue")) {
IRComplete(&irStatements, &irVStack);
AsmLabel lbl;
for (int i = labelStack.cnt; i >= 0; --i) {
if (labelStack.data[i].typ == LABEL_WHILE) {
lbl = labelStack.data[i];
}
}
printf(" Jmp __whilehead_%d\n", lbl.num);
break;
}
if (SBeq(&tokenAccumulator, "if")) {
break;
}
if (SBeq(&tokenAccumulator, "then")) {
IRComplete(&irStatements, &irVStack);
AsmLabel lbl = (AsmLabel) {
.num = counter,
.typ = LABEL_IF
};
lz_da_append(labelStack, lbl);
commentStack(&labelStack);
vstackUnderflows = 0;
printf(" popstack 123\n");
printf(" RSetF 123\n");
printf(" JmpIE __iftail_%d\n", lbl.num);
break;
}
if (SBeq(&tokenAccumulator, "endif")) {
IRComplete(&irStatements, &irVStack);
vstackUnderflows = 0;
commentStack(&labelStack);
AsmLabel lbl = lz_da_pop(labelStack);
if (lbl.typ != LABEL_IF) {
fprintf(stderr, "Unmatched endif without an if\n");
exit(1);
}
printf("__iftail_%d:\n", lbl.num);
break;
}
if (SBeq(&tokenAccumulator, "==")) {
IR_GET_2_ARGS
IRValue dstReg = (IRValue) {
.typ = IRVAL_VIRTUAL,
.val = ++irVCount
};
IRStatement s = (IRStatement) {
.dst = dstReg,
.op = IR_EQ,
.arg1 = x1,
.arg2 = x2
};
lz_da_append(irVStack, dstReg);
lz_da_append(irStatements, s);
break;
}
if (SBeq(&tokenAccumulator, "not")) {
IRValue x1;
if (irVStack.cnt >= 1) {
x1 = lz_da_pop(irVStack);
} else if (irVStack.cnt == 0) {
x1 = (IRValue) {
.typ = IRVAL_STACK,
.val = ++vstackUnderflows
};
}
IRValue dstReg = (IRValue) {
.typ = IRVAL_VIRTUAL,
.val = ++irVCount
};
IRStatement s = (IRStatement) {
.dst = dstReg,
.op = IR_NOT,
.arg1 = x1
};
lz_da_append(irVStack, dstReg);
lz_da_append(irStatements, s);
break;
}
if (SBeq(&tokenAccumulator, "band")) {
IR_GET_2_ARGS
IRValue dstReg = (IRValue) {
.typ = IRVAL_VIRTUAL,
.val = ++irVCount
};
IRStatement s = (IRStatement) {
.dst = dstReg,
.op = IR_AND,
.arg1 = x1,
.arg2 = x2
};
lz_da_append(irVStack, dstReg);
lz_da_append(irStatements, s);
break;
}
if (SBeq(&tokenAccumulator, "bor")) {
IR_GET_2_ARGS
IRValue dstReg = (IRValue) {
.typ = IRVAL_VIRTUAL,
.val = ++irVCount
};
IRStatement s = (IRStatement) {
.dst = dstReg,
.op = IR_OR,
.arg1 = x1,
.arg2 = x2
};
lz_da_append(irVStack, dstReg);
lz_da_append(irStatements, s);
break;
}
if (SBeq(&tokenAccumulator, "xor")) {
IR_GET_2_ARGS
IRValue dstReg = (IRValue) {
.typ = IRVAL_VIRTUAL,
.val = ++irVCount
};
IRStatement s = (IRStatement) {
.dst = dstReg,
.op = IR_XOR,
.arg1 = x1,
.arg2 = x2
};
lz_da_append(irVStack, dstReg);
lz_da_append(irStatements, s);
break;
}
if (SBeq(&tokenAccumulator, "u+")) {
IR_GET_2_ARGS
IRValue dstReg = (IRValue) {
.typ = IRVAL_VIRTUAL,
.val = ++irVCount
};
IRStatement s = (IRStatement) {
.dst = dstReg,
.op = IR_UADD,
.arg1 = x1,
.arg2 = x2
};
lz_da_append(irVStack, dstReg);
lz_da_append(irStatements, s);
break;
}
if (SBeq(&tokenAccumulator, "u-")) {
IR_GET_2_ARGS
IRValue dstReg = (IRValue) {
.typ = IRVAL_VIRTUAL,
.val = ++irVCount
};
IRStatement s = (IRStatement) {
.dst = dstReg,
.op = IR_USUB,
.arg1 = x1,
.arg2 = x2
};
lz_da_append(irVStack, dstReg);
lz_da_append(irStatements, s);
break;
}
if (SBeq(&tokenAccumulator, "u*")) {
IR_GET_2_ARGS
IRValue dstReg = (IRValue) {
.typ = IRVAL_VIRTUAL,
.val = ++irVCount
};
IRStatement s = (IRStatement) {
.dst = dstReg,
.op = IR_UMUL,
.arg1 = x1,
.arg2 = x2
};
lz_da_append(irVStack, dstReg);
lz_da_append(irStatements, s);
break;
}
if (SBeq(&tokenAccumulator, "u/")) {
IR_GET_2_ARGS
IRValue dstReg = (IRValue) {
.typ = IRVAL_VIRTUAL,
.val = ++irVCount
};
IRStatement s = (IRStatement) {
.dst = dstReg,
.op = IR_UDIV,
.arg1 = x1,
.arg2 = x2
};
lz_da_append(irVStack, dstReg);
lz_da_append(irStatements, s);
break;
}
if (SBeq(&tokenAccumulator, "u%")) {
IR_GET_2_ARGS
IRValue dstReg = (IRValue) {
.typ = IRVAL_VIRTUAL,
.val = ++irVCount
};
IRStatement s = (IRStatement) {
.dst = dstReg,
.op = IR_UMOD,
.arg1 = x1,
.arg2 = x2
};
lz_da_append(irVStack, dstReg);
lz_da_append(irStatements, s);
break;
}
if (SBeq(&tokenAccumulator, "u>")) {
IR_GET_2_ARGS
IRValue dstReg = (IRValue) {
.typ = IRVAL_VIRTUAL,
.val = ++irVCount
};
IRStatement s = (IRStatement) {
.dst = dstReg,
.op = IR_UGT,
.arg1 = x1,
.arg2 = x2
};
lz_da_append(irVStack, dstReg);
lz_da_append(irStatements, s);
break;
}
if (SBeq(&tokenAccumulator, "u<")) {
IR_GET_2_ARGS
IRValue dstReg = (IRValue) {
.typ = IRVAL_VIRTUAL,
.val = ++irVCount
};
IRStatement s = (IRStatement) {
.dst = dstReg,
.op = IR_ULT,
.arg1 = x1,
.arg2 = x2
};
lz_da_append(irVStack, dstReg);
lz_da_append(irStatements, s);
break;
}
if (SBeq(&tokenAccumulator, "i+")) {
IR_GET_2_ARGS
IRValue dstReg = (IRValue) {
.typ = IRVAL_VIRTUAL,
.val = ++irVCount
};
IRStatement s = (IRStatement) {
.dst = dstReg,
.op = IR_UADD,
.arg1 = x1,
.arg2 = x2
};
lz_da_append(irVStack, dstReg);
lz_da_append(irStatements, s);
break;
}
if (SBeq(&tokenAccumulator, "i-")) {
IR_GET_2_ARGS
IRValue dstReg = (IRValue) {
.typ = IRVAL_VIRTUAL,
.val = ++irVCount
};
IRStatement s = (IRStatement) {
.dst = dstReg,
.op = IR_USUB,
.arg1 = x1,
.arg2 = x2
};
lz_da_append(irVStack, dstReg);
lz_da_append(irStatements, s);
break;
}
if (SBeq(&tokenAccumulator, "i*")) {
IR_GET_2_ARGS
IRValue dstReg = (IRValue) {
.typ = IRVAL_VIRTUAL,
.val = ++irVCount
};
IRStatement s = (IRStatement) {
.dst = dstReg,
.op = IR_IMUL,
.arg1 = x1,
.arg2 = x2
};
lz_da_append(irVStack, dstReg);
lz_da_append(irStatements, s);
break;
}
if (SBeq(&tokenAccumulator, "i/")) {
IR_GET_2_ARGS
IRValue dstReg = (IRValue) {
.typ = IRVAL_VIRTUAL,
.val = ++irVCount
};
IRStatement s = (IRStatement) {
.dst = dstReg,
.op = IR_IDIV,
.arg1 = x1,
.arg2 = x2
};
lz_da_append(irVStack, dstReg);
lz_da_append(irStatements, s);
break;
}
if (SBeq(&tokenAccumulator, "i%")) {
IR_GET_2_ARGS
IRValue dstReg = (IRValue) {
.typ = IRVAL_VIRTUAL,
.val = ++irVCount
};
IRStatement s = (IRStatement) {
.dst = dstReg,
.op = IR_IMOD,
.arg1 = x1,
.arg2 = x2
};
lz_da_append(irVStack, dstReg);
lz_da_append(irStatements, s);
break;
}
if (SBeq(&tokenAccumulator, "i>")) {
IR_GET_2_ARGS
IRValue dstReg = (IRValue) {
.typ = IRVAL_VIRTUAL,
.val = ++irVCount
};
IRStatement s = (IRStatement) {
.dst = dstReg,
.op = IR_IGT,
.arg1 = x1,
.arg2 = x2
};
lz_da_append(irVStack, dstReg);
lz_da_append(irStatements, s);
break;
}
if (SBeq(&tokenAccumulator, "i<")) {
IR_GET_2_ARGS
IRValue dstReg = (IRValue) {
.typ = IRVAL_VIRTUAL,
.val = ++irVCount
};
IRStatement s = (IRStatement) {
.dst = dstReg,
.op = IR_ILT,
.arg1 = x1,
.arg2 = x2
};
lz_da_append(irVStack, dstReg);
lz_da_append(irStatements, s);
break;
}
if (SBeq(&tokenAccumulator, "$inc")) {
isInclude = true;
break;
}
printf("Unimplemented keyword: "LZ_STR_FMT"\n",
LZ_STR_PRINTF(tokenAccumulator));
exit(1);
}
case TOKEN_IDENTIFIER: {
if (isInclude) {
char *fname = malloc(tokenAccumulator.cnt+1);
memcpy(fname, tokenAccumulator.data, tokenAccumulator.cnt);
fname[tokenAccumulator.cnt] = 0;
FILE *f = fopen(fname, "r");
if (!f) {
fprintf(stderr, "Could not open file %s or doesn't exist\n",
fname);
}
lz_da_append(inpfiles, f);
isInclude = false;
break;
}
if (isProc) {
printf("__fp_user_"LZ_STR_FMT":\n",
LZ_STR_PRINTF(tokenAccumulator));
isProc = false;
IRValue arg = (IRValue) {
.typ = IRVAL_ARG,
.val = 0
};
if (tokenAccumulator.cnt < 127) {
memcpy(funcName, tokenAccumulator.data, tokenAccumulator.cnt);
funcName[tokenAccumulator.cnt] = 0;
} else {
memcpy(funcName, tokenAccumulator.data, 127);
funcName[127] = 0;
}
break;
}
if (tokenAccumulator.data[0] == ':') {
IRComplete(&irStatements, &irVStack);
vstackUnderflows = 0;
printf(" Call __fp_user_"LZ_STR_FMT"\n",
tokenAccumulator.cnt-1,
tokenAccumulator.data+1);
break;
}
if (tokenAccumulator.data[0] == '@') {
char varName[128];
if (tokenAccumulator.cnt < 128) {
memcpy(varName, tokenAccumulator.data+1,
tokenAccumulator.cnt-1);
varName[tokenAccumulator.cnt-1] = 0;
} else {
memcpy(varName, tokenAccumulator.data+1, 127);
varName[127] = 0;
}
uint64_t addr = 0;
lz_da_foreach(Variable, v, vars) {
if (!strcmp(v->name, varName) && !strcmp(v->func, funcName)) {
addr = v->addr;
break;
}
}
if (addr == 0) {
addr = allocHead;
Variable v = (Variable) {
.addr = addr
};
memcpy(&v.func, funcName, 128);
memcpy(&v.name, varName, 128);
lz_da_append(vars, v);
allocHead += 8;
}
IRValue x1;
if (irVStack.cnt >= 1) {
x1 = lz_da_pop(irVStack);
} else if (irVStack.cnt == 0) {
x1 = (IRValue) {
.typ = IRVAL_STACK,
.val = ++vstackUnderflows
};
}
IRValue dstReg = (IRValue) {
.typ = IRVAL_MEMORY,
.val = addr
};
IRStatement s = (IRStatement) {
.dst = dstReg,
.op = IR_NOP,
.arg1 = x1
};
lz_da_append(irStatements, s);
break;
}
if (tokenAccumulator.data[0] == '&') {
char varName[128];
if (tokenAccumulator.cnt < 128) {
memcpy(varName, tokenAccumulator.data+1,
tokenAccumulator.cnt-1);
varName[tokenAccumulator.cnt-1] = 0;
} else {
memcpy(varName, tokenAccumulator.data+1, 127);
varName[127] = 0;
}
uint64_t addr = 0;
lz_da_foreach(Variable, v, vars) {
if (!strcmp(v->name, varName) && !strcmp(v->func, funcName)) {
addr = v->addr;
break;
}
}
if (addr == 0) {
fprintf(stderr, "Undeclared variable %s in function %s\n",
varName, funcName);
exit(1);
}
IRValue dstReg = (IRValue) {
.typ = IRVAL_VIRTUAL,
.val = ++irVCount
};
IRValue x1 = (IRValue) {
.typ = IRVAL_MEMORY,
.val = addr
};
IRStatement s = (IRStatement) {
.dst = dstReg,
.op = IR_NOP,
.arg1 = x1
};
lz_da_append(irStatements, s);
lz_da_append(irVStack, dstReg);
break;
}
// Iirc there's not a general thing for identifiers so just fail?
fprintf(stderr, "Useless Identifier: "LZ_STR_FMT"\n",
LZ_STR_PRINTF(tokenAccumulator));
exit(0);
}
case TOKEN_INTLIT: {
uint64_t x = lz_sb_atoll(&tokenAccumulator);
IRValue v = (IRValue) {
.typ = IRVAL_CONSTANT,
.val = x
};
lz_da_append(irVStack, v);
break;
}
case TOKEN_HEXLIT: {
uint64_t x = lz_sb_readhex(&tokenAccumulator);
IRValue v = (IRValue) {
.typ = IRVAL_CONSTANT,
.val = x
};
lz_da_append(irVStack, v);
break;
}
case TOKEN_STRINGLIT: {
IRValue dstReg = (IRValue) {
.typ = IRVAL_VIRTUAL,
.val = ++irVCount
};
// This is a bad way of doing strings tbh
printf(" Jmp endstring%d\n", counter);
printf("string%d db \""LZ_STR_FMT"\", 0\n",
counter,
LZ_STR_PRINTF(tokenAccumulator));
printf("endstring%d:\n", counter);
printf(" MovI64 100, string%d\n", counter);
IRStatement s = (IRStatement) {
.dst = dstReg,
.op = IR_NOP,
.arg1 = IR_STR
};
lz_da_append(irVStack, dstReg);
lz_da_append(irStatements, s);
break;
//IRComplete(&irStatements, &irVStack);
//vstackUnderflows = 0;
//printf(" Jmp endstring%d\n", counter);
//printf("string%d db \""LZ_STR_FMT"\", 0\n",
// counter,
// LZ_STR_PRINTF(tokenAccumulator));
//printf("endstring%d:\n", counter);
//printf(" MovI64 100, string%d\n", counter);
//printf(" pushstack 100\n", counter);
// IRValue v = (IRValue) {
// .typ = IRVAL_STACK,
// .val = 1
// };
// lz_da_append(irVStack, v);
break;
}
default: {
printf("Bad: %d\n", currTokenKind);
exit(1);
}
}
tokenAccumulator.cnt = 0;
}
if (inpfiles.cnt != 0) {
currFile = lz_da_pop(inpfiles);
tokenAccumulator.cnt = 0;
isProc = false;
isQuote = false;
isInclude = false;
labelStack.cnt = 0;
goto compileStart;
}
}