Implemented start of flagpole compiler and a few new things here and there for said compiler

This commit is contained in:
cannoli-fruit 2026-07-25 04:16:02 -04:00
commit 6098f88cc5
8 changed files with 401 additions and 2 deletions

63
flagpole/bldit.lua Normal file
View file

@ -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,
}
}

243
flagpole/src/main.c Normal file
View file

@ -0,0 +1,243 @@
#include <stdio.h>
#include <unistd.h>
#include <ctype.h>
#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;
}
}

11
flagpole/src/token.h Normal file
View file

@ -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;

1
flagpole/tests/fvm.inc Symbolic link
View file

@ -0,0 +1 @@
../../tests/fvm.inc

14
flagpole/tests/hw.fp Normal file
View file

@ -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

View file

@ -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*)(&registers[reg]); //Fuckery

19
tests/cmp.asm Normal file
View file

@ -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

View file

@ -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