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