From 6098f88cc5d8ff1b8251415e476d1ed902c4c32b Mon Sep 17 00:00:00 2001 From: cannoli-fruit Date: Sat, 25 Jul 2026 04:16:02 -0400 Subject: [PATCH] Implemented start of flagpole compiler and a few new things here and there for said compiler --- flagpole/bldit.lua | 63 +++++++++++ flagpole/src/main.c | 243 +++++++++++++++++++++++++++++++++++++++++ flagpole/src/token.h | 11 ++ flagpole/tests/fvm.inc | 1 + flagpole/tests/hw.fp | 14 +++ src/interp.c | 20 ++++ tests/cmp.asm | 19 ++++ tests/fvm.inc | 32 +++++- 8 files changed, 401 insertions(+), 2 deletions(-) create mode 100644 flagpole/bldit.lua create mode 100644 flagpole/src/main.c create mode 100644 flagpole/src/token.h create mode 120000 flagpole/tests/fvm.inc create mode 100644 flagpole/tests/hw.fp create mode 100644 tests/cmp.asm diff --git a/flagpole/bldit.lua b/flagpole/bldit.lua new file mode 100644 index 0000000..1377498 --- /dev/null +++ b/flagpole/bldit.lua @@ -0,0 +1,63 @@ +bldit_version = "1.1.3" +package_version = "1.1.3" + +dependencies = {} + +exec_name = "fvmfpc" +libs = "-Wall -Wextra" +includes = "-I../Lazyc" + +execute = function(str) + print(str) + return os.execute(str) +end + +targets = { + default = { + build = function() + e,h,c = execute("rm -fr build") + if c ~= 0 and c ~= nil then + print("Build Error") + print("GIVEN UP") + return c + end + e,h,c = execute("mkdir build") + if c ~= 0 and c ~= nil then + print("Build Error") + print("GIVEN UP") + return c + end + cmd = [[find src -type f -name "*.c" -print]] + p = io.popen(cmd) + assert(p, "File detection error, GIVEN UP") + + for f in p:lines() do + base = f:match("([^/]+)%.c$") + obj = "build/"..base..".o" + cc = "cc -c '"..f.."' -o '"..obj.."' "..includes + e,h,c = execute(cc) + if c ~= 0 and c ~= nil then + print("Compilation Error") + print("GIVEN UP") + return c + end + end + p:close() + e,h,c = execute("cc build/*.o "..libs.." -o "..exec_name) + if c ~= 0 and c ~= nil then + print("Compilation Error") + print("GIVEN UP") + return c + end + return 0 + end, + install = function() + e,h,c = execute("cp "..exec_name.." /bin") + return c or 0 + end, + uninstall = function() + e,h,c = execute("rm /bin"..exec_name) + return c or 0 + end, + } +} diff --git a/flagpole/src/main.c b/flagpole/src/main.c new file mode 100644 index 0000000..6a4326d --- /dev/null +++ b/flagpole/src/main.c @@ -0,0 +1,243 @@ +#include +#include +#include +#define LAZY_IMPL +#include "lazy.h" +#include "token.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); +} + +static inline bool isKW(Lz_SB *sb) { + return + SBeq(sb, "proc") + || SBeq(sb, "endproc") + || SBeq(sb, "ld8") + || SBeq(sb, "st8") + || SBeq(sb, "dup") + ; +} + +int main(uint argc, char **argv) { + int opt; + FILE *inpfile = stdin; + while ((opt = getopt(argc, argv, "f:")) != -1) { + switch(opt) { + case 'f': + inpfile = fopen(optarg, "r"); + if (!inpfile) { + printf("Failed to open file %s\n", optarg); + exit(1); + } + break; + default: + break; + } + } + + TokenKind currTokenKind; + Lz_SB tokenAccumulator = {0}; + int counter = 0; + bool isQuote = false; + bool isProc = false; + Lz_DA(int) labelStack = {0}; + char newchar; + printf("include 'fvm.inc'\n"); + printf("define STACK_START 0x6000000000000000\n"); + printf("define STACK_SP 125\n"); + printf("org 0x4000000000000000\n"); + printf(" MovI64 STACK_SP, STACK_START\n"); + printf(" Call __fp_user_main\n"); + printf(" Halt\n"); + printf("macro pushstack reg\n"); + printf(" MovI64 124, 8\n"); + printf(" SubR64 STACK_SP, 124\n"); + printf(" St64 reg, STACK_SP\n"); + printf("end macro\n\n"); + printf("macro popstack reg\n"); + printf(" MovI64 124, 8\n"); + printf(" Ld64 reg, STACK_SP\n"); + printf(" AddR64 STACK_SP, 124\n"); + printf("end macro\n\n"); + while ((newchar = fgetc(inpfile)) != EOF) { + ++counter; + if (isspace(newchar) && !isQuote) { + if (tokenAccumulator.cnt == 0) continue; + if (is_int_literal(&tokenAccumulator)) { + currTokenKind = TOKEN_INTLIT; + goto codegen; + } else if (is_float_literal(&tokenAccumulator)) { + currTokenKind = TOKEN_FLOATLIT; + goto codegen; + } else if (is_double_literal(&tokenAccumulator)) { + currTokenKind = TOKEN_DOUBLELIT; + goto codegen; + } else if (is_hex_literal(&tokenAccumulator)) { + currTokenKind = TOKEN_HEXLIT; + goto codegen; + } else if (is_bin_literal(&tokenAccumulator)) { + currTokenKind = TOKEN_BINLIT; + goto codegen; + } else { + currTokenKind = TOKEN_IDENTIFIER; + if (isKW(&tokenAccumulator)) { + currTokenKind = TOKEN_KEYWORD; + } + goto codegen; + } + } + if (newchar == '"') { + if (isQuote) { + currTokenKind = TOKEN_STRINGLIT; + isQuote = false; + goto codegen; + } else { + if (tokenAccumulator.cnt != 0) { + fprintf(stderr, "error %d\n", __LINE__); + exit(1); + } else { + isQuote = true; + } + continue; + } + } + lz_da_append(tokenAccumulator, newchar); + continue; +codegen: + //printf("I must gen code i am now Amista Azozin\n"); + //printf("Token type: %d\n", currTokenKind); + //printf("Tok: "LZ_STR_FMT"\n", LZ_STR_PRINTF(tokenAccumulator)); + switch (currTokenKind) { + case TOKEN_KEYWORD: { + if (SBeq(&tokenAccumulator, "proc")) { + isProc = true; + break; + } + if (SBeq(&tokenAccumulator, "endproc")) { + printf(" Ret\n"); + printf("\n\n"); + break; + } + if (SBeq(&tokenAccumulator, "ld8")) { + printf(" popstack 101\n"); + printf(" Ld8 102, 101\n"); + printf(" pushstack 102\n"); + break; + } + if (SBeq(&tokenAccumulator, "st8")) { + printf(" popstack 101\n"); + printf(" popstack 102\n"); + printf(" St8 102, 101\n"); + break; + } + if (SBeq(&tokenAccumulator, "dup")) { + printf(" popstack 106\n"); + printf(" pushstack 106\n"); + printf(" pushstack 106\n"); + break; + } + printf("Unknown keyword: "LZ_STR_FMT"\n", + LZ_STR_PRINTF(tokenAccumulator)); + exit(1); + } + case TOKEN_IDENTIFIER: { + if (isProc) { + printf("__fp_user_"LZ_STR_FMT":\n", + LZ_STR_PRINTF(tokenAccumulator)); + isProc = false; + 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: { + printf(" MovI64 103, "LZ_STR_FMT"\n", + LZ_STR_PRINTF(tokenAccumulator)); + printf(" pushstack 103\n"); + break; + } + case TOKEN_HEXLIT: { + printf(" MovI64 103, "LZ_STR_FMT"\n", + LZ_STR_PRINTF(tokenAccumulator)); + printf(" pushstack 103\n"); + break; + } + case TOKEN_STRINGLIT: { + 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); + break; + } + default: { + printf("Bad: %d\n", currTokenKind); + exit(1); + } + } + tokenAccumulator.cnt = 0; + } +} diff --git a/flagpole/src/token.h b/flagpole/src/token.h new file mode 100644 index 0000000..cdd418d --- /dev/null +++ b/flagpole/src/token.h @@ -0,0 +1,11 @@ +typedef enum { + TOKEN_NULL, + TOKEN_INTLIT, + TOKEN_FLOATLIT, + TOKEN_DOUBLELIT, + TOKEN_HEXLIT, + TOKEN_BINLIT, + TOKEN_STRINGLIT, + TOKEN_IDENTIFIER, + TOKEN_KEYWORD +} TokenKind; diff --git a/flagpole/tests/fvm.inc b/flagpole/tests/fvm.inc new file mode 120000 index 0000000..01b9137 --- /dev/null +++ b/flagpole/tests/fvm.inc @@ -0,0 +1 @@ +../../tests/fvm.inc \ No newline at end of file diff --git a/flagpole/tests/hw.fp b/flagpole/tests/hw.fp new file mode 100644 index 0000000..2001686 --- /dev/null +++ b/flagpole/tests/hw.fp @@ -0,0 +1,14 @@ +proc main + "H" ld8 0xCFFFFFFFFFFFFFFD st8 + "e" ld8 0xCFFFFFFFFFFFFFFD st8 + "l" ld8 0xCFFFFFFFFFFFFFFD st8 + "l" ld8 0xCFFFFFFFFFFFFFFD st8 + "o" ld8 0xCFFFFFFFFFFFFFFD st8 + " " ld8 0xCFFFFFFFFFFFFFFD st8 + "W" ld8 0xCFFFFFFFFFFFFFFD st8 + "o" ld8 0xCFFFFFFFFFFFFFFD st8 + "r" ld8 0xCFFFFFFFFFFFFFFD st8 + "l" ld8 0xCFFFFFFFFFFFFFFD st8 + "d" ld8 0xCFFFFFFFFFFFFFFD st8 + "!" ld8 0xCFFFFFFFFFFFFFFD st8 +endproc diff --git a/src/interp.c b/src/interp.c index 6fe6c23..6fd5430 100644 --- a/src/interp.c +++ b/src/interp.c @@ -133,6 +133,9 @@ int main(int argc, char **argv) { unsigned char inputs[9]; for (size_t i = 0; i < inpcnt; ++i) { inputs[i] = memory_get8(xPc+i+1); + if (DEBUG) { + printf("X%d: 0x%8X\n", i, inputs[i]); + } } xPc += 1; xPc += inpcnt; @@ -171,12 +174,29 @@ int main(int argc, char **argv) { memory_set8(registers[addr], registers[src]&0xFF); break; } + case 0x8C: { // St64 + unsigned char src = inputs[0]; + unsigned char addr = inputs[1]; + memory_set64(registers[addr], registers[src]); + break; + } case 0x93: { // Ld8 unsigned char dst = inputs[0]; unsigned char addr = inputs[1]; + if (DEBUG) { + printf("Ld8\n"); + printf("Dst val: %8X\n", registers[dst]); + printf("Addr val: %8X\n", registers[addr]); + } registers[dst] = memory_get8(registers[addr]); break; } + case 0x8D: { // Ld64 + unsigned char dst = inputs[0]; + unsigned char addr = inputs[1]; + registers[dst] = memory_get64(registers[addr]); + break; + } case 0x42: { // RSetF unsigned char reg = inputs[0]; int64_t val = *(int64_t*)(®isters[reg]); //Fuckery diff --git a/tests/cmp.asm b/tests/cmp.asm new file mode 100644 index 0000000..260d6a7 --- /dev/null +++ b/tests/cmp.asm @@ -0,0 +1,19 @@ +include "fvm.inc" + +org 0x4000000000000000 + MovI64 r95, UART_TX + MovI64 r2, 8 + MovI64 r3, 2 + MovI64 r4, 0x30 ; ascii for 0 + Cmp64 r2, r3 + JmpIP Greater +LessEq: + AddR64 r3, r4 + St8 r3, r95 + Jmp Ending +Greater: + AddR64 r2, r4 + ; MovI64 r2, 0x38 + St8 r2, r95 +Ending: + Halt diff --git a/tests/fvm.inc b/tests/fvm.inc index 342e980..5ff80cc 100644 --- a/tests/fvm.inc +++ b/tests/fvm.inc @@ -236,6 +236,18 @@ macro St8 dst, addr db addr end macro +macro Ld64 dst, addr + db 0x8D + db dst + db addr +end macro + +macro St64 dst, addr + db 0x8C + db dst + db addr +end macro + macro AddR64 dst, src db 0x6E db dst @@ -266,6 +278,12 @@ macro ModR64 dst, src db src end macro +macro Cmp64 A, B + db 0x7D + db A + db B +end macro + macro RSetF reg db 0x42 db reg @@ -291,12 +309,22 @@ macro JmpIZ addr JmpRIZ 127 end macro -macro callR addr +macro JmpRIP addr + db 0xC3 + db addr +end macro + +macro JmpIP addr + MovI64 127, addr + JmpRIP 127 +end macro + +macro CallR addr db 0x46 db addr end macro -macro call val +macro Call val MovI64 127, val db 0x46 db 127