compiler works

This commit is contained in:
2026-06-18 23:37:28 +02:00
parent 2d043ca39f
commit 9c0a40a336
7 changed files with 155 additions and 50 deletions

View File

@@ -72,7 +72,7 @@ void noomC_compiler_init(noomC_Compiler* compiler) {
compiler->localc = 0; compiler->localc = 0;
compiler->upvalc = 0; compiler->upvalc = 0;
compiler->curstack = 0; compiler->curstack = -1;
} }
static noom_Exit noomC_emit(noomV_Function* func, const noomV_Inst inst) { static noom_Exit noomC_emit(noomV_Function* func, const noomV_Inst inst) {
@@ -167,7 +167,9 @@ static noom_Exit noomC_compile_expr(
noomC_Compiler* compiler, noomC_Compiler* compiler,
const noomP_Parser* parser, const noomP_Parser* parser,
noomV_Function* func, noomV_Function* func,
const noomP_Node* node) { const noomP_Node* node,
// retc of -1 means all values!!!!!!!!!!!
int retc) {
noom_Exit result; noom_Exit result;
// Baba is You OST is a very cool soundtrack to code to Can recommend // Baba is You OST is a very cool soundtrack to code to Can recommend
if (node->type == NOOMP_NODE_NILLITERAL) { if (node->type == NOOMP_NODE_NILLITERAL) {
@@ -190,7 +192,8 @@ static noom_Exit noomC_compile_expr(
if (node->type == NOOMP_NODE_STRINGLITERAL) { if (node->type == NOOMP_NODE_STRINGLITERAL) {
unsigned char fucking_destination = compiler->curstack++; unsigned char fucking_destination = compiler->curstack++;
noom_Exit result = noomC_addconst_str(compiler, vm, "but DID YOU KNOW", 16); noom_Exit result = noomC_addconst_str(compiler, vm, "but DID YOU KNOW", 16);
return result; if(result) return result;
return noomC_emit_Aus(func, NOOMV_INSTR_PUSHCONST, 0, fucking_destination);
} }
if (node->type == NOOMP_NODE_BINARYOPERATOR) { if (node->type == NOOMP_NODE_BINARYOPERATOR) {
if (node->subnodec != 2) return NOOM_EINTERNAL; if (node->subnodec != 2) return NOOM_EINTERNAL;
@@ -199,7 +202,7 @@ static noom_Exit noomC_compile_expr(
// concat is special // concat is special
noom_uint_t amount = 1; noom_uint_t amount = 1;
const noomP_Node* n = node->subnodes[1]; const noomP_Node* n = node->subnodes[1];
if ((result = noomC_compile_expr(vm, compiler, parser, func, node->subnodes[0]))) return result; if ((result = noomC_compile_expr(vm, compiler, parser, func, node->subnodes[0], 1))) return result;
// we have no flattening so we unwind it ourselves // we have no flattening so we unwind it ourselves
// unlike all left-associative ones, like +, where 1 + 2 + 3 is (1 + 2) + 3, // unlike all left-associative ones, like +, where 1 + 2 + 3 is (1 + 2) + 3,
// concat is right-associate, like ^, meaning 1 .. 2 .. 3 is 1 .. (2 .. 3). // concat is right-associate, like ^, meaning 1 .. 2 .. 3 is 1 .. (2 .. 3).
@@ -208,10 +211,10 @@ static noom_Exit noomC_compile_expr(
if (amount > NOOM_USHORT_MAX) return NOOM_EINTERNAL; if (amount > NOOM_USHORT_MAX) return NOOM_EINTERNAL;
amount++; amount++;
if (noom_startswith(parser->code + n->source_offset, "..")) { if (noom_startswith(parser->code + n->source_offset, "..")) {
if ((result = noomC_compile_expr(vm, compiler, parser, func, n->subnodes[0]))) return result; if ((result = noomC_compile_expr(vm, compiler, parser, func, n->subnodes[0], 1))) return result;
n = n->subnodes[1]; n = n->subnodes[1];
} else { } else {
if ((result = noomC_compile_expr(vm, compiler, parser, func, n))) return result; if ((result = noomC_compile_expr(vm, compiler, parser, func, n, 1))) return result;
break; break;
} }
} }
@@ -220,30 +223,31 @@ static noom_Exit noomC_compile_expr(
return noomC_emit_Aus(func, NOOMV_INSTR_CONCAT, 0, amount - 1); return noomC_emit_Aus(func, NOOMV_INSTR_CONCAT, 0, amount - 1);
} }
if ((result = noomC_compile_expr(vm, compiler, parser, func, node->subnodes[0]))) return result; if ((result = noomC_compile_expr(vm, compiler, parser, func, node->subnodes[0], 1))) return result;
if ((result = noomC_compile_expr(vm, compiler, parser, func, node->subnodes[1]))) return result; if ((result = noomC_compile_expr(vm, compiler, parser, func, node->subnodes[1], 1))) return result;
// this consumes 2 operands and pushes 1 value, thus having a net stack effect of removing 1 item // this consumes 2 operands and pushes 1 value, thus having a net stack effect of removing 1 item
compiler->curstack--; compiler->curstack--;
return noomC_emit_ABC(func, NOOMV_INSTR_OP, 1, noomC_what_bop_is_this(parser, node->source_offset), 0); return noomC_emit_ABC(func, NOOMV_INSTR_OP, 1, noomC_what_bop_is_this(parser, node->source_offset), 0);
} }
if (node->type == NOOMP_NODE_CALL) { if (node->type == NOOMP_NODE_CALL || node->type == NOOMP_NODE_METHODCALL) {
unsigned char fucking_destination = compiler->curstack; // welcome to multivalue hell
// Here we don't fucking increment this fucking destination unsigned char returnToGlory = compiler->curstack;
// Because the fucking function call fucking increments it fucking anyway noom_bool_t isMethod = node->type == NOOMP_NODE_METHODCALL;
for (int i = 1; i < node->subnodec; i++) { if((result = noomC_compile_expr(vm, compiler, parser, func, node->subnodes[0], 1))) return result;
// push node->subnodes[i] to stack or something unsigned char funcIdx = compiler->curstack;
if(isMethod) {
noomP_Node *field = node->subnodes[1];
const char *fieldname = parser->code + field->source_offset;
noom_uint_t fieldlen = noomL_tokenlen(fieldname, 0, parser->version);
noom_uint_t constidx = func->constsize;
if((result = noomC_addconst_str(compiler, vm, fieldname, fieldlen))) return result;
if((result = noomC_emit_Aus(func, NOOMV_INSTR_GETMETHOD, 0, constidx))) return result;
} }
return noomC_emit_Aus(func, NOOMV_INSTR_JMP, 0, /* where do i start......... */ 0); for(int i = isMethod ? 2 : 1; i < node->subnodec; i++) {
noom_bool_t isLast = i == (node->subnodec-1);
if((result = noomC_compile_expr(vm, compiler, parser, func, node->subnodes[i], isLast ? -1 : 1))) return result;
} }
if (node->type == NOOMP_NODE_METHODCALL) { return noomC_emit_Aus(func, NOOMV_INSTR_CALL, funcIdx, retc+1);
unsigned char fucking_destination = compiler->curstack;
// Here we don't fucking increment this fucking destination
// Because the fucking function call fucking increments it fucking anyway
// push parent value... probably already processed below if you make it i = 0
for (int i = 1; i < node->subnodec; i++) {
// push node->subnodes[i] to stack or something
}
return noomC_emit_Aus(func, NOOMV_INSTR_JMP, 0, /* where do i start......... */ 0);
} }
if (node->type == NOOMP_NODE_VARIABLE) { if (node->type == NOOMP_NODE_VARIABLE) {
noomC_LocalInfo info; noomC_LocalInfo info;
@@ -257,9 +261,24 @@ static noom_Exit noomC_compile_expr(
return noomC_emit_Aus(func, NOOMV_INSTR_PUSHVAL, 0, info.idx); return noomC_emit_Aus(func, NOOMV_INSTR_PUSHVAL, 0, info.idx);
case NOOMC_UPVAL: case NOOMC_UPVAL:
return noomC_emit_Aus(func, NOOMV_INSTR_PUSHUPVAL, 0, info.idx); return noomC_emit_Aus(func, NOOMV_INSTR_PUSHUPVAL, 0, info.idx);
case NOOMC_GLOBAL: case NOOMC_GLOBAL: {
// FIXME: handle globals noom_uint_t constidx = compiler->target->constsize;
return NOOM_EINTERNAL; if((result = noomC_addconst_str(compiler, vm, varname, namelen))) return result;
if(parser->version == NOOM_VERSION_51) {
return noomC_emit_Aus(func, NOOMV_INSTR_PUSHGLOBAL, 0, constidx);
}
noomC_LocalInfo _ENV;
if((result = noomC_identifyLocal(compiler, &_ENV, "_ENV", 4))) return result;
// not meant to be possible
if(_ENV.type == NOOMC_GLOBAL) return NOOM_EINTERNAL;
// most likely branch in human history
if(_ENV.type == NOOMC_UPVAL) {
return noomC_emit_Aus(func, NOOMV_INSTR_PUSHUPVAL, _ENV.idx, constidx);
}
// bitchass
if((result = noomC_emit_Aus(func, NOOMV_INSTR_PUSHVAL, 0, _ENV.idx))) return result;
return noomC_emit_Aus(func, NOOMV_INSTR_GETFIELD, 0, constidx);
}
} }
// forgot a case // forgot a case
return NOOM_EINTERNAL; return NOOM_EINTERNAL;
@@ -332,7 +351,7 @@ static noom_Exit noomC_add_stuff_to_function(noom_LuaVM* vm, noomC_Compiler* com
compiler->curstack++; compiler->curstack++;
} else { } else {
const noomP_Node* value_node = node->subnodes[1]; const noomP_Node* value_node = node->subnodes[1];
const noom_Exit r = noomC_compile_expr(vm, compiler, parser, func, value_node); const noom_Exit r = noomC_compile_expr(vm, compiler, parser, func, value_node, 1);
if (r != NOOM_OK) return r; if (r != NOOM_OK) return r;
} }
@@ -393,15 +412,22 @@ static noom_Exit noomC_add_stuff_to_function(noom_LuaVM* vm, noomC_Compiler* com
return noomC_compile_block(vm, compiler, parser, func, node); return noomC_compile_block(vm, compiler, parser, func, node);
} }
if(node->type == NOOMP_NODE_CALL || node->type == NOOMP_NODE_METHODCALL) {
return noomC_compile_expr(vm, compiler, parser, func, node, 0);
}
return NOOM_EINTERNAL; return NOOM_EINTERNAL;
} }
noom_Exit noomC_compile(noom_LuaVM* vm, const noomP_Parser* parser, const noomP_Node* node, noomV_String* chunkname, noomV_Table* env) { noom_Exit noomC_compile(noom_LuaVM* vm, const noomP_Parser* parser, const noomP_Node* node, noomV_String* chunkname, noomV_Table* env, noomV_Value *outFunc) {
if (node->type != NOOMP_NODE_PROGRAM) return NOOM_EINTERNAL; if (node->type != NOOMP_NODE_PROGRAM) return NOOM_EINTERNAL;
noomV_Function* program = noomV_allocFunc(vm, chunkname); noomV_Function* program = noomV_allocFunc(vm, chunkname);
if (program == 0) return NOOM_ENOMEM; if (program == 0) return NOOM_ENOMEM;
outFunc->tag = NOOMV_VOBJ;
outFunc->obj = &program->obj;
noomC_Compiler compiler; noomC_Compiler compiler;
noomC_compiler_init(&compiler); noomC_compiler_init(&compiler);
compiler.target = program; compiler.target = program;
@@ -416,20 +442,8 @@ noom_Exit noomC_compile(noom_LuaVM* vm, const noomP_Parser* parser, const noomP_
upval.stolen = 1; upval.stolen = 1;
upval.constant = 0; upval.constant = 0;
noomC_addUpval(&compiler, upval); noomC_addUpval(&compiler, upval);
}
noom_Exit status = noomC_compile_block(vm, &compiler, parser, program, node);
if (status != NOOM_OK) return status;
if (parser->version > NOOM_VERSION_51) {
// TODO: we need to wrap the value as a *closure*, with one upvalue, the environment (_ENV). // TODO: we need to wrap the value as a *closure*, with one upvalue, the environment (_ENV).
} }
if (vm->mainThread->stacklen == vm->mainThread->stackcap) { return noomC_compile_block(vm, &compiler, parser, program, node);
vm->mainThread->stackcap = vm->mainThread->stackcap ? vm->mainThread->stackcap * 2 : 16;
vm->mainThread->stack = noom_realloc(vm->mainThread->stack, sizeof(noomV_Value) * vm->mainThread->stackcap);
}
vm->mainThread->stack[vm->mainThread->stacklen++] =
(noomV_Value){.tag = NOOMV_VOBJ, .autoclose = 0, .isptr = 0, .obj = (noomV_Object*)program};
return NOOM_OK;
} }

View File

@@ -39,4 +39,4 @@ typedef struct noomC_Compiler {
void noomC_compiler_init(noomC_Compiler* compiler); void noomC_compiler_init(noomC_Compiler* compiler);
// pushes the compiled function on the stack, or just crashes lol // pushes the compiled function on the stack, or just crashes lol
noom_Exit noomC_compile(noom_LuaVM* vm, const noomP_Parser* parser, const noomP_Node* node, noomV_String* chunkname, noomV_Table* env); noom_Exit noomC_compile(noom_LuaVM* vm, const noomP_Parser* parser, const noomP_Node* node, noomV_String* chunkname, noomV_Table* env, noomV_Value *outFunc);

View File

@@ -1,3 +1,6 @@
#ifndef NOOM_LEXER
#define NOOM_LEXER
#include "noom.h" #include "noom.h"
typedef enum noomL_TokenType { typedef enum noomL_TokenType {
@@ -50,3 +53,5 @@ const char* noomL_formatTokenType(noomL_TokenType token_type);
noomL_ErrorType noomL_lex(const char* s, noom_uint_t start, noomL_Token* token, noom_LuaVersion version); // TODO: add more error data noomL_ErrorType noomL_lex(const char* s, noom_uint_t start, noomL_Token* token, noom_LuaVersion version); // TODO: add more error data
// UB if syntax error // UB if syntax error
noom_uint_t noomL_tokenlen(const char* s, noom_uint_t start, noom_LuaVersion version); noom_uint_t noomL_tokenlen(const char* s, noom_uint_t start, noom_LuaVersion version);
#endif

View File

@@ -1,7 +1,10 @@
#include <stdio.h> // for now #include <stdio.h> // for now
#include <stdlib.h>
#include "helper.h" #include "helper.h"
#include "error.h" #include "error.h"
#include "noom.h" #include "noom.h"
#include "compiler.h"
#include "vm.h"
void tab(noom_uint_t amount) { void tab(noom_uint_t amount) {
amount *= 2; amount *= 2;
@@ -38,8 +41,10 @@ int the_theoretical_function_to_execute_your_code_that_should_be_replaced_later(
noomP_Parser parser; noomP_Parser parser;
noomP_Node* program; noomP_Node* program;
noom_LuaVM *vm = noom_createVM(NOOM_VERSION_51);
// goodbye "shitass" you will be missed // goodbye "shitass" you will be missed
int success = noomP_parse(code, filename, NOOM_VERSION_54, &program, &parser); int success = noomP_parse(code, filename, NOOM_VERSION_51, &program, &parser);
if (success == 0) { if (success == 0) {
puts("LEX OUTPUT:"); puts("LEX OUTPUT:");
fputs("\x1b[48;2;10;10;10m", stdout); fputs("\x1b[48;2;10;10;10m", stdout);
@@ -90,6 +95,36 @@ int the_theoretical_function_to_execute_your_code_that_should_be_replaced_later(
noom_free(buf); noom_free(buf);
} }
noomV_Value peak;
noom_Exit e = noomC_compile(vm, &parser, program, 0, 0, &peak);
if(e) {
printf("error: %d\n", e);
exit(e);
}
noomV_Function *f = (noomV_Function *)peak.obj;
for(int i = 0; i < f->codesize; i++) {
noomV_Inst inst = f->code[i];
noomV_DisInfo dis = noomV_disInfo[inst.op];
printf("%s %d ", dis.name, inst.a);
switch(dis.arg) {
case NOOMV_DIS_BC:
printf("%d, %d", inst.b, inst.c);
break;
case NOOMV_DIS_uD:
printf("%d", inst.us);
break;
case NOOMV_DIS_sD:
printf("%d", inst.ss);
break;
}
printf("\n");
}
// freeing time // freeing time
noomP_Node* last_node = parser.last_node; noomP_Node* last_node = parser.last_node;
while (last_node) { while (last_node) {
@@ -99,6 +134,9 @@ int the_theoretical_function_to_execute_your_code_that_should_be_replaced_later(
noom_free(last_node); noom_free(last_node);
last_node = next; last_node = next;
} }
noom_destroyVM(vm);
return success; return success;
} }

View File

@@ -1,3 +1,6 @@
#ifndef NOOM_PARSER
#define NOOM_PARSER
#include "noom.h" #include "noom.h"
#include "lexer.h" #include "lexer.h"
@@ -168,3 +171,5 @@ noomP_Node* noomP_parseStatement(noomP_Parser* parser);
int noomP_parse(const char* code, const char* filename, noom_LuaVersion version, noomP_Node** outpointer, noomP_Parser* parser); int noomP_parse(const char* code, const char* filename, noom_LuaVersion version, noomP_Node** outpointer, noomP_Parser* parser);
int noomP_initParser(noomP_Parser* parser, const char* code, const char* filename, noom_LuaVersion version); int noomP_initParser(noomP_Parser* parser, const char* code, const char* filename, noom_LuaVersion version);
#endif

View File

@@ -1,5 +1,25 @@
#include "vm.h" #include "vm.h"
#include "helper.h" #include "helper.h"
#include <stdio.h>
noomV_DisInfo noomV_disInfo[NOOMV_INSTR_NOP2] = {
[NOOMV_INSTR_PUSHNIL] = {
.name = "PUSHNIL",
.arg = NOOMV_DIS_uD,
},
[NOOMV_INSTR_PUSHCONST] = {
.name = "PUSHCONST",
.arg = NOOMV_DIS_uD,
},
[NOOMV_INSTR_PUSHGLOBAL] = {
.name = "PUSHGLOBAL",
.arg = NOOMV_DIS_uD,
},
[NOOMV_INSTR_CALL] = {
.name = "CALL",
.arg = NOOMV_DIS_uD,
},
};
noomV_Object* noomV_allocObj(noom_LuaVM* vm, noomV_ObjTag tag, noom_uint_t size) { noomV_Object* noomV_allocObj(noom_LuaVM* vm, noomV_ObjTag tag, noom_uint_t size) {
noomV_Object* o = noom_alloc(size); noomV_Object* o = noom_alloc(size);
@@ -55,6 +75,14 @@ noomV_Table* noomV_allocTable(noom_LuaVM* vm) {
} }
void noomV_freeObj(noomV_Object* obj) { void noomV_freeObj(noomV_Object* obj) {
printf("%d\n", obj->tag);
if(obj->tag == NOOMV_OFUNC) {
noomV_Function *f = (noomV_Function *)obj;
noom_free(f->consts);
noom_free(f->upvals);
noom_free(f->locals);
noom_free(f->code);
}
noom_free(obj); noom_free(obj);
} }

View File

@@ -114,19 +114,23 @@ typedef enum noomV_Opcode : unsigned char {
// all returns are pushed. // all returns are pushed.
NOOMV_INSTR_CALL, NOOMV_INSTR_CALL,
// pops (table, field), and pushes table[field] // pops (table, field), and pushes `table[field]`
NOOMV_INSTR_GETTABLE, NOOMV_INSTR_GETTABLE,
// pops (table, field, value), and sets table[field] = value // pops (table, field, value), and sets `table[field] = value`
NOOMV_INSTR_SETTABLE, NOOMV_INSTR_SETTABLE,
// pops op.uD values, then sets it as an array starting at op.a+1 in the table at the new top; // pops op.uD values, then sets it as an array starting at op.a+1 in the table at the new top;
// if that is confused, it basically does this: // if that is confused, it basically does this:
// int table = stacksize - op.uD - 1; // int table = stacksize - op.uD - 1;
// for(int i = 0; i < op.uD; i++) stack[table][op.a + 1 + i] = stack[table + i + 1]; // for(int i = 0; i < op.uD; i++) `stack[table][op.a + 1 + i] = stack[table + i + 1];`
NOOMV_INSTR_SETLIST, NOOMV_INSTR_SETLIST,
// pops table, pushes table[consts[op.uD]], an optimization for indexing fields // pops table, pushes `table[consts[op.uD]]`, an optimization for indexing fields
NOOMV_INSTR_GETFIELD, NOOMV_INSTR_GETFIELD,
// pops (table, value), sets table[consts[op.uD]] = value, an optimization for changing fields // pops (table, value), sets `table[consts[op.uD]] = value`, an optimization for changing fields
NOOMV_INSTR_SETFIELD, NOOMV_INSTR_SETFIELD,
// pushes `(*upvals[op.A])[consts[op.uD]]`
NOOMV_INSTR_GETUPFIELD,
// pops [value], sets `(*upvals[op.A])[consts[op.uD]] = value`
NOOMV_ISNTR_SETUPFIELD,
// does a unary or binary operation. // does a unary or binary operation.
// if op.a == 1, its a unary operation. // if op.a == 1, its a unary operation.
@@ -155,7 +159,7 @@ typedef enum noomV_Opcode : unsigned char {
// For bullshit // For bullshit
// Take the top value without popping it, push value[consts[op.uD]] like GETFIELD would, then swap the top 2 values. // Take the top value without popping it, push `value[consts[op.uD]]` like GETFIELD would, then swap the top 2 values.
// This is for a:foo() and such // This is for a:foo() and such
NOOMV_INSTR_GETMETHOD, NOOMV_INSTR_GETMETHOD,
// rotate the the top op.a items by op.sD // rotate the the top op.a items by op.sD
@@ -174,6 +178,17 @@ typedef enum noomV_Opcode : unsigned char {
NOOMV_INSTR_NOP2 = 0xff, NOOMV_INSTR_NOP2 = 0xff,
} noomV_Opcode; } noomV_Opcode;
typedef struct noomV_DisInfo {
const char *name;
enum {
NOOMV_DIS_BC,
NOOMV_DIS_uD,
NOOMV_DIS_sD,
} arg;
} noomV_DisInfo;
extern noomV_DisInfo noomV_disInfo[NOOMV_INSTR_NOP2];
typedef struct noomV_Inst { typedef struct noomV_Inst {
noomV_Opcode op; noomV_Opcode op;
unsigned char a; unsigned char a;