compiler works
This commit is contained in:
@@ -72,7 +72,7 @@ void noomC_compiler_init(noomC_Compiler* compiler) {
|
||||
|
||||
compiler->localc = 0;
|
||||
compiler->upvalc = 0;
|
||||
compiler->curstack = 0;
|
||||
compiler->curstack = -1;
|
||||
}
|
||||
|
||||
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,
|
||||
const noomP_Parser* parser,
|
||||
noomV_Function* func,
|
||||
const noomP_Node* node) {
|
||||
const noomP_Node* node,
|
||||
// retc of -1 means all values!!!!!!!!!!!
|
||||
int retc) {
|
||||
noom_Exit result;
|
||||
// Baba is You OST is a very cool soundtrack to code to Can recommend
|
||||
if (node->type == NOOMP_NODE_NILLITERAL) {
|
||||
@@ -190,7 +192,8 @@ static noom_Exit noomC_compile_expr(
|
||||
if (node->type == NOOMP_NODE_STRINGLITERAL) {
|
||||
unsigned char fucking_destination = compiler->curstack++;
|
||||
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->subnodec != 2) return NOOM_EINTERNAL;
|
||||
@@ -199,7 +202,7 @@ static noom_Exit noomC_compile_expr(
|
||||
// concat is special
|
||||
noom_uint_t amount = 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
|
||||
// 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).
|
||||
@@ -208,10 +211,10 @@ static noom_Exit noomC_compile_expr(
|
||||
if (amount > NOOM_USHORT_MAX) return NOOM_EINTERNAL;
|
||||
amount++;
|
||||
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];
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
@@ -220,30 +223,31 @@ static noom_Exit noomC_compile_expr(
|
||||
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[1]))) 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], 1))) return result;
|
||||
// this consumes 2 operands and pushes 1 value, thus having a net stack effect of removing 1 item
|
||||
compiler->curstack--;
|
||||
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) {
|
||||
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
|
||||
for (int i = 1; i < node->subnodec; i++) {
|
||||
// push node->subnodes[i] to stack or something
|
||||
if (node->type == NOOMP_NODE_CALL || node->type == NOOMP_NODE_METHODCALL) {
|
||||
// welcome to multivalue hell
|
||||
unsigned char returnToGlory = compiler->curstack;
|
||||
noom_bool_t isMethod = node->type == NOOMP_NODE_METHODCALL;
|
||||
if((result = noomC_compile_expr(vm, compiler, parser, func, node->subnodes[0], 1))) return result;
|
||||
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);
|
||||
}
|
||||
if (node->type == NOOMP_NODE_METHODCALL) {
|
||||
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
|
||||
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;
|
||||
}
|
||||
return noomC_emit_Aus(func, NOOMV_INSTR_JMP, 0, /* where do i start......... */ 0);
|
||||
return noomC_emit_Aus(func, NOOMV_INSTR_CALL, funcIdx, retc+1);
|
||||
}
|
||||
if (node->type == NOOMP_NODE_VARIABLE) {
|
||||
noomC_LocalInfo info;
|
||||
@@ -257,9 +261,24 @@ static noom_Exit noomC_compile_expr(
|
||||
return noomC_emit_Aus(func, NOOMV_INSTR_PUSHVAL, 0, info.idx);
|
||||
case NOOMC_UPVAL:
|
||||
return noomC_emit_Aus(func, NOOMV_INSTR_PUSHUPVAL, 0, info.idx);
|
||||
case NOOMC_GLOBAL:
|
||||
// FIXME: handle globals
|
||||
return NOOM_EINTERNAL;
|
||||
case NOOMC_GLOBAL: {
|
||||
noom_uint_t constidx = compiler->target->constsize;
|
||||
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
|
||||
return NOOM_EINTERNAL;
|
||||
@@ -332,7 +351,7 @@ static noom_Exit noomC_add_stuff_to_function(noom_LuaVM* vm, noomC_Compiler* com
|
||||
compiler->curstack++;
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
if(node->type == NOOMP_NODE_CALL || node->type == NOOMP_NODE_METHODCALL) {
|
||||
return noomC_compile_expr(vm, compiler, parser, func, node, 0);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
noomV_Function* program = noomV_allocFunc(vm, chunkname);
|
||||
if (program == 0) return NOOM_ENOMEM;
|
||||
|
||||
outFunc->tag = NOOMV_VOBJ;
|
||||
outFunc->obj = &program->obj;
|
||||
|
||||
noomC_Compiler compiler;
|
||||
noomC_compiler_init(&compiler);
|
||||
compiler.target = program;
|
||||
@@ -416,20 +442,8 @@ noom_Exit noomC_compile(noom_LuaVM* vm, const noomP_Parser* parser, const noomP_
|
||||
upval.stolen = 1;
|
||||
upval.constant = 0;
|
||||
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).
|
||||
}
|
||||
|
||||
if (vm->mainThread->stacklen == vm->mainThread->stackcap) {
|
||||
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;
|
||||
return noomC_compile_block(vm, &compiler, parser, program, node);
|
||||
}
|
||||
|
||||
@@ -39,4 +39,4 @@ typedef struct noomC_Compiler {
|
||||
void noomC_compiler_init(noomC_Compiler* compiler);
|
||||
|
||||
// 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);
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#ifndef NOOM_LEXER
|
||||
#define NOOM_LEXER
|
||||
|
||||
#include "noom.h"
|
||||
|
||||
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
|
||||
// UB if syntax error
|
||||
noom_uint_t noomL_tokenlen(const char* s, noom_uint_t start, noom_LuaVersion version);
|
||||
|
||||
#endif
|
||||
|
||||
40
src/main.c
40
src/main.c
@@ -1,7 +1,10 @@
|
||||
#include <stdio.h> // for now
|
||||
#include <stdlib.h>
|
||||
#include "helper.h"
|
||||
#include "error.h"
|
||||
#include "noom.h"
|
||||
#include "compiler.h"
|
||||
#include "vm.h"
|
||||
|
||||
void tab(noom_uint_t amount) {
|
||||
amount *= 2;
|
||||
@@ -38,8 +41,10 @@ int the_theoretical_function_to_execute_your_code_that_should_be_replaced_later(
|
||||
noomP_Parser parser;
|
||||
noomP_Node* program;
|
||||
|
||||
noom_LuaVM *vm = noom_createVM(NOOM_VERSION_51);
|
||||
|
||||
// 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) {
|
||||
puts("LEX OUTPUT:");
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
noomP_Node* last_node = parser.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);
|
||||
last_node = next;
|
||||
}
|
||||
|
||||
noom_destroyVM(vm);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#ifndef NOOM_PARSER
|
||||
#define NOOM_PARSER
|
||||
|
||||
#include "noom.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_initParser(noomP_Parser* parser, const char* code, const char* filename, noom_LuaVersion version);
|
||||
|
||||
#endif
|
||||
|
||||
28
src/vm.c
28
src/vm.c
@@ -1,5 +1,25 @@
|
||||
#include "vm.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* o = noom_alloc(size);
|
||||
@@ -55,6 +75,14 @@ noomV_Table* noomV_allocTable(noom_LuaVM* vm) {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
27
src/vm.h
27
src/vm.h
@@ -114,19 +114,23 @@ typedef enum noomV_Opcode : unsigned char {
|
||||
// all returns are pushed.
|
||||
NOOMV_INSTR_CALL,
|
||||
|
||||
// pops (table, field), and pushes table[field]
|
||||
// pops (table, field), and pushes `table[field]`
|
||||
NOOMV_INSTR_GETTABLE,
|
||||
// pops (table, field, value), and sets table[field] = value
|
||||
// pops (table, field, value), and sets `table[field] = value`
|
||||
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;
|
||||
// if that is confused, it basically does this:
|
||||
// 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,
|
||||
// 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,
|
||||
// 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,
|
||||
// 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.
|
||||
// if op.a == 1, its a unary operation.
|
||||
@@ -155,7 +159,7 @@ typedef enum noomV_Opcode : unsigned char {
|
||||
|
||||
// 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
|
||||
NOOMV_INSTR_GETMETHOD,
|
||||
// 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_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 {
|
||||
noomV_Opcode op;
|
||||
unsigned char a;
|
||||
|
||||
Reference in New Issue
Block a user