Compare commits

3 Commits
main ... main

Author SHA1 Message Date
907f3aaf4d basic progress 2026-07-17 20:26:41 +02:00
9016b9fc53 fixed a lot of regressions and made strings somewhat functional 2026-07-05 13:35:03 +02:00
81d020bb74 main.c: small tweak
Reviewed-on: NeoFlock/noom#13
Co-authored-by: tema5002 <tema5002@tuta.io>
Co-committed-by: tema5002 <tema5002@tuta.io>
2026-07-02 16:59:18 +02:00
6 changed files with 293 additions and 159 deletions

View File

@@ -1,6 +1,7 @@
#include "noom.h"
#include "compiler.h"
#include "helper.h"
#include <stdio.h>
// COMPILATION!!!!!!!!!!!!!!!!!!!
// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⢲⣞⣭⣟⣿⣻⣷⢶⢦⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
@@ -33,7 +34,8 @@ typedef struct noomC_LocalInfo {
enum { NOOMC_GLOBAL,
NOOMC_LOCAL,
NOOMC_UPVAL } type;
unsigned int idx;
unsigned short idx;
bool isConst;
} noomC_LocalInfo;
noom_Exit noomC_addLocal(noomC_Compiler* c, noomC_Local local) {
@@ -48,15 +50,72 @@ noom_Exit noomC_addUpval(noomC_Compiler* c, noomC_Upval upval) {
return NOOM_OK;
}
int noomC_stealUpval(noomC_Compiler* c, const char* name, noom_uint_t namelen) {
noom_Exit noomC_addconst(noomV_Function* func, noomV_Value val) {
if (func->constsize == NOOM_USHORT_MAX) return NOOM_PLEASEHELPMEIAMSCARED;
noomV_Value* newConsts = noom_realloc(func->consts, sizeof(noomV_Value) * (func->constsize + 1));
if (newConsts == 0) return NOOM_ENOMEM;
func->consts = newConsts;
func->consts[func->constsize++] = val;
return NOOM_OK;
}
noom_Exit noomC_addconst_str(noomC_Compiler* c, noom_LuaVM* vm, const char* str, noom_uint_t len, noom_uint_t *outIdx) {
noomV_Function *f = c->target;
for(int i = 0; i < f->constsize; i++) {
noomV_Value v = f->consts[i];
if (v.tag != NOOMV_VOBJ) continue;
noomV_Object* o = v.obj;
if (o->tag != NOOMV_OSTR) continue;
noomV_String* s = (noomV_String*)o;
if (noom_memeq(s->data, s->len, str, len)) {
*outIdx = i;
return NOOM_OK;
}
}
noomV_String* s = 0;
{
noomC_Compiler *cp = c;
while(cp) {
for(int i = 0; i < f->constsize; i++) {
noomV_Value v = f->consts[i];
if (v.tag != NOOMV_VOBJ) continue;
noomV_Object* o = v.obj;
if (o->tag != NOOMV_OSTR) continue;
noomV_String* os = (noomV_String*)o;
if (noom_memeq(os->data, os->len, str, len)) {
s = os;
goto found;
}
}
cp = cp->parent;
}
}
s = noomV_allocStr(vm, str, len);
if (s == 0) return NOOM_ENOMEM;
found:
*outIdx = c->target->constsize;
return noomC_addconst(c->target, (noomV_Value){.tag = NOOMV_VOBJ, .autoclose = 0, .isptr = 0, .obj = (noomV_Object*)s});
}
noom_Exit noomC_stealUpval(noomC_Compiler* c, const char* name, noom_uint_t namelen, noomC_LocalInfo *local) {
// hold on hold on hold on but what if...
for (unsigned i = 0; i < c->upvalc; i++) {
const noomC_Upval u = c->upvals[i];
if (noom_memeq(u.name, u.namelen, name, namelen)) return (int)i;
if (noom_memeq(u.name, u.namelen, name, namelen)) {
local->type = NOOMC_UPVAL;
local->idx = i;
local->isConst = u.constant;
return NOOM_OK;
}
}
// damn it
if (c->parent == 0) return -1;
if (c->parent == 0) {
// signal that this is not found
local->type = NOOMC_GLOBAL;
local->isConst = false;
return NOOM_OK;
}
// maybe you have smth useful
for (int i = (int)c->parent->localc - 1; i >= 0; i--) {
@@ -64,67 +123,95 @@ int noomC_stealUpval(noomC_Compiler* c, const char* name, noom_uint_t namelen) {
if (l.dropped) continue;
if (noom_memeq(l.name, l.namelen, name, namelen)) {
// yay!!!! wahoo!!!! yippee!!!!!!!!!!!
if (c->upvalc == NOOMC_MAXUPVAL) return -1;
noomC_Upval upval;
upval.name = name;
upval.namelen = namelen;
upval.slot = (unsigned short)l.stackslot;
upval.stolen = 0;
upval.isParentUpvalue = false;
upval.constant = l.constant;
const unsigned idx = c->upvalc;
c->upvals[c->upvalc++] = upval;
return (int)idx;
local->type = NOOMC_UPVAL;
local->idx = c->upvalc;
local->isConst = upval.constant;
return noomC_addUpval(c, upval);
}
}
const int parent_upval = noomC_stealUpval(c->parent, name, namelen);
if (parent_upval >= 0) {
if (c->upvalc == NOOMC_MAXUPVAL) return -1;
noomC_Upval upval;
upval.name = name;
upval.namelen = namelen;
upval.slot = (unsigned short)parent_upval;
upval.stolen = 1;
upval.constant = c->parent->upvals[parent_upval].constant;
const unsigned idx = c->upvalc;
c->upvals[c->upvalc++] = upval;
return (int)idx;
noomC_LocalInfo parentUpval;
noom_Exit e = noomC_stealUpval(c->parent, name, namelen, &parentUpval);
if(e) return e;
if(parentUpval.type == NOOMC_GLOBAL) {
// not found
*local = parentUpval;
return NOOM_OK;
}
return -1;
noomC_Upval upval;
upval.name = name;
upval.namelen = namelen;
upval.slot = parentUpval.idx;
upval.isParentUpvalue = true;
upval.constant = parentUpval.isConst;
local->type = NOOMC_UPVAL;
local->idx = c->upvalc;
local->isConst = upval.constant;
return noomC_addUpval(c, upval);
}
static noomC_LocalInfo noomC_identifyLocal(noomC_Compiler* compiler, const char* name, noom_uint_t namelen) {
static noom_Exit noomC_identifyLocal(noomC_Compiler* compiler, const char* name, noom_uint_t namelen, noomC_LocalInfo *info) {
for (int i = compiler->localc - 1; i >= 0; i--) {
const noomC_Local l = compiler->locals[i];
if (l.dropped) continue;
if (noom_memeq(l.name, l.namelen, name, namelen)) {
return (noomC_LocalInfo){ .type = NOOMC_LOCAL, .idx = l.stackslot };
info->type = NOOMC_LOCAL;
info->idx = l.stackslot;
info->isConst = l.constant;
return NOOM_OK;
}
}
const int upval_idx = noomC_stealUpval(compiler, name, namelen);
if (upval_idx >= 0) {
return (noomC_LocalInfo){ .type = NOOMC_UPVAL, .idx = (unsigned)upval_idx };
}
return (noomC_LocalInfo){ .type = NOOMC_GLOBAL };
return noomC_stealUpval(compiler, name, namelen, info);
}
static noom_Exit noomC_identifyLocalAndSet(noomC_Compiler* compiler, const char* name, noom_uint_t namelen) {
const noomC_LocalInfo info = noomC_identifyLocal(compiler, name, namelen);
static noom_Exit noomC_identifyLocalAndSet(noomC_Compiler* compiler, noom_LuaVM *vm, const char* name, noom_uint_t namelen) {
// TODO: burn this with fire
noomC_LocalInfo info;
noom_Exit e = noomC_identifyLocal(compiler, name, namelen, &info);
if(e) return e;
if (info.type == NOOMC_LOCAL) return noomC_emit_AuD(compiler->target, NOOMV_INSTR_SETVAL, compiler->curstack++, (unsigned short)info.idx);
if (info.type == NOOMC_UPVAL) return noomC_emit_AuD(compiler->target, NOOMV_INSTR_SETUPVAL, compiler->curstack++, (unsigned short)info.idx);
if (info.type == NOOMC_GLOBAL) return noomC_emit_AuD(compiler->target, NOOMV_INSTR_SETGLOBAL, compiler->curstack++, (unsigned short)info.idx);
noom_uint_t fieldIdx;
e = noomC_addconst_str(compiler, vm, name, namelen, &fieldIdx);
if(e) return e;
if (info.type == NOOMC_GLOBAL) {
if(vm->version > NOOM_VERSION_51) {
noomC_LocalInfo _ENV;
e = noomC_identifyLocal(compiler, "_ENV", 4, &_ENV);
if(e) return e;
if(_ENV.type == NOOMC_GLOBAL) return NOOM_EINTERNAL;
if(_ENV.type == NOOMC_UPVAL) {
return noomC_emit_AuD(compiler->target, NOOMV_INSTR_SETGLOBAL, compiler->curstack++, fieldIdx);
}
// TODO: impl this bullshit
return NOOM_EINTERNAL;
}
return noomC_emit_AuD(compiler->target, NOOMV_INSTR_SETGLOBAL, compiler->curstack++, fieldIdx);
}
return NOOM_EINTERNAL;
}
void noomC_compiler_init(noomC_Compiler* compiler) {
compiler->parent = 0;
compiler->target = 0;
compiler->parent = NULL;
compiler->target = NULL;
compiler->localc = 0;
compiler->upvalc = 0;
compiler->curstack = 0;
compiler->stringTmpBuf = NULL;
compiler->maxStringLen = 0;
}
void noomC_compiler_deinit(noomC_Compiler* compiler) {
noom_free(compiler->stringTmpBuf);
}
noom_Exit noomC_emit(noomV_Function* func, noomV_Inst inst) {
@@ -135,36 +222,6 @@ noom_Exit noomC_emit(noomV_Function* func, noomV_Inst inst) {
return NOOM_OK;
}
noom_Exit noomC_addconst(noomV_Function* func, noomV_Value val) {
if (func->constsize == NOOM_USHORT_MAX) return NOOM_PLEASEHELPMEIAMSCARED;
noomV_Value* newConsts = noom_realloc(func->consts, sizeof(noomV_Value) * (func->constsize + 1));
if (newConsts == 0) return NOOM_ENOMEM;
func->consts = newConsts;
func->consts[func->constsize++] = val;
return NOOM_OK;
}
noomV_String* noomC_internString(const noomC_Compiler* c, noom_LuaVM* vm, const char* str, noom_uint_t len) {
while (c) {
const noomV_Function* f = c->target;
for (int i = 0; i < f->constsize; i++) {
const noomV_Value v = f->consts[i];
if (v.tag != NOOMV_VOBJ) continue;
noomV_Object* o = v.obj;
if (o->tag != NOOMV_OSTR) continue;
noomV_String* s = (noomV_String*)o;
if (noom_memeq(s->data, s->len, str, len)) return s;
}
c = c->parent;
}
return noomV_allocStr(vm, str, len);
}
noom_Exit noomC_addconst_str(noomC_Compiler* c, noom_LuaVM* vm, const char* str, noom_uint_t len) {
noomV_String* s = noomC_internString(c, vm, str, len);
if (s == 0) return NOOM_ENOMEM;
return noomC_addconst(c->target, (noomV_Value){.tag = NOOMV_VOBJ, .autoclose = 0, .isptr = 0, .obj = (noomV_Object*)s});
}
noom_BinOp noomC_lex_bin_op(const noomP_Parser* parser, noom_uint_t offset) {
const char* op = parser->code + offset;
@@ -205,10 +262,20 @@ noom_UnaryOp noomC_lex_un_op(const noomP_Parser* parser, noom_uint_t offset) {
return 0;
}
static const char* noomC_decode_string_token(const char* s, noom_LuaVersion how_the_fuck, noom_uint_t* outlen) {
static const char* noomC_decode_string_token(noomC_Compiler *c, const char* s, noom_uint_t tokenlen, noom_LuaVersion how_the_fuck, noom_uint_t* outlen) {
// token is bigger than contents, so if we can't even fit token, we def can't fit contents
if(c->maxStringLen < tokenlen) {
char *s = noom_realloc(c->stringTmpBuf, tokenlen);
if(s == NULL) return NULL;
c->stringTmpBuf = s;
c->maxStringLen = tokenlen;
}
// really not good for now
noom_memcpy(c->stringTmpBuf, s + 1, tokenlen - 1);
*outlen = tokenlen - 2;
// nah fuck it TODO atom pls save me
// actually don't i will repair this one day
return s;
return c->stringTmpBuf;
}
noom_Exit noomC_compile_proto(
@@ -218,7 +285,7 @@ noom_Exit noomC_compile_proto(
noomV_Function* parent_func,
const noomP_Node* params_node,
const noomP_Node* block_node,
noom_bool_t has_self,
bool has_self,
noomV_Function** out_proto) {
noom_Exit result;
@@ -232,10 +299,10 @@ noom_Exit noomC_compile_proto(
// [varname..., vararg?]
noom_uint_t param_count = 0;
noom_bool_t has_vararg = 0; // do we even need that
bool has_vararg = false; // do we even need that
for (noom_uint_t i = 0; i < params_node->subnodec; i++) {
if (params_node->subnodes[i]->type == NOOMP_NODE_VARARG) {
has_vararg = 1;
has_vararg = true;
} else {
param_count++;
}
@@ -248,9 +315,9 @@ noom_Exit noomC_compile_proto(
self_local.name = "self";
self_local.namelen = 4;
self_local.stackslot = 0;
self_local.dropped = 0;
self_local.constant = 0;
self_local.close = 0;
self_local.dropped = false;
self_local.constant = false;
self_local.close = false;
if ((result = noomC_addLocal(&child, self_local)) != NOOM_OK) return result;
child.curstack = 1;
param_count++;
@@ -268,9 +335,9 @@ noom_Exit noomC_compile_proto(
noomC_Local a;
a.startpc = 0;
a.endpc = 0;
a.dropped = 0;
a.close = 0;
a.constant = 0;
a.dropped = false;
a.close = false;
a.constant = false;
a.name = parser->code + p->source_offset;
a.namelen = length;
a.stackslot = child.curstack++;
@@ -300,7 +367,7 @@ noom_Exit noomC_emit_assign_to(
if (target->type == NOOMP_NODE_VARIABLE) {
const char* varname = parser->code + target->source_offset;
noom_uint_t namelen = noomL_tokenlen(varname, 0, parser->version);
return noomC_identifyLocalAndSet(compiler, varname, namelen);
return noomC_identifyLocalAndSet(compiler, vm, varname, namelen);
}
if (target->type == NOOMP_NODE_GETFIELD) {
@@ -340,7 +407,7 @@ noom_Exit noomC_compile_expr(
if (node->type == NOOMP_NODE_BOOLEANLITERAL) {
compiler->curstack++;
noom_uint_t length = noomL_tokenlen(parser->code, node->source_offset, parser->version);
noom_bool_t val = noom_memeq(parser->code + node->source_offset, length, "true", 4);
bool val = noom_memeq(parser->code + node->source_offset, length, "true", 4);
// TODO: analyze last instruction to optimize automatically
return noomC_emit_AuD(func, NOOMV_INSTR_PUSHBOOLS, 0, val ? 1 : 0);
}
@@ -354,10 +421,11 @@ noom_Exit noomC_compile_expr(
}
if (node->type == NOOMP_NODE_STRINGLITERAL) {
const unsigned short const_idx = func->constsize;
noom_uint_t const_idx;
noom_uint_t len;
const char* sptr = noomC_decode_string_token(parser->code + node->source_offset, parser->version, &len);
if ((result = noomC_addconst_str(compiler, vm, sptr, len)) != NOOM_OK) return result;
const char* sptr = noomC_decode_string_token(compiler, parser->code + node->source_offset, noomL_tokenlen(parser->code, node->source_offset, parser->version), parser->version, &len);
if(sptr == 0) return NOOM_ENOMEM;
if ((result = noomC_addconst_str(compiler, vm, sptr, len, &const_idx)) != NOOM_OK) return result;
compiler->curstack++;
return noomC_emit_AuD(func, NOOMV_INSTR_PUSHCONST, 0, const_idx);
}
@@ -387,9 +455,9 @@ noom_Exit noomC_compile_expr(
if (key_node->type == NOOMP_NODE_FIELDNAME) {
// string key
const unsigned short constidx = func->constsize;
noom_uint_t constidx;
const noom_uint_t length = noomL_tokenlen(parser->code, key_node->source_offset, parser->version);
if ((result = noomC_addconst_str(compiler, vm, parser->code + key_node->source_offset, length))) return result;
if ((result = noomC_addconst_str(compiler, vm, parser->code + key_node->source_offset, length, &constidx))) return result;
if ((result = noomC_compile_expr(vm, compiler, parser, func, val_node, 1))) return result;
compiler->curstack--;
if ((result = noomC_emit_AuD(func, NOOMV_INSTR_SETFIELD, table_slot, constidx))) return result;
@@ -400,7 +468,7 @@ noom_Exit noomC_compile_expr(
if ((result = noomC_emit_ABC(func, NOOMV_INSTR_SETTABLE, table_slot, 0, 0))) return result;
}
} else {
const noom_bool_t is_last = i == node->subnodec - 1;
const bool is_last = i == node->subnodec - 1;
if ((result = noomC_compile_expr(vm, compiler, parser, func, entry, is_last ? -1 : 1))) return result;
if (is_last) {
if ((result = noomC_emit_AuD(func, NOOMV_INSTR_SETLIST, table_slot, (unsigned short)array_idx))) return result;
@@ -466,9 +534,9 @@ noom_Exit noomC_compile_expr(
if (node->type == NOOMP_NODE_GETFIELD) {
if ((result = noomC_compile_expr(vm, compiler, parser, func, node->subnodes[0], 1))) return result;
noom_uint_t constidx = func->constsize;
noom_uint_t constidx;
// dumbass oneliner
if ((result = noomC_addconst_str(compiler, vm, parser->code + node->subnodes[1]->source_offset, noomL_tokenlen(parser->code, node->subnodes[1]->source_offset, parser->version)))) return result;
if ((result = noomC_addconst_str(compiler, vm, parser->code + node->subnodes[1]->source_offset, noomL_tokenlen(parser->code, node->subnodes[1]->source_offset, parser->version), &constidx))) return result;
return noomC_emit_AuD(func, NOOMV_INSTR_GETFIELD, 0, (unsigned short)constidx);
}
@@ -487,7 +555,7 @@ noom_Exit noomC_compile_expr(
node->type == NOOMP_NODE_TABLEMETHODCALL) {
// welcome to multivalue hell
const unsigned char returnToGlory = (unsigned char)compiler->curstack;
const noom_bool_t isMethod = node->type == NOOMP_NODE_METHODCALL || node->type == NOOMP_NODE_STRINGMETHODCALL || node->type == NOOMP_NODE_TABLEMETHODCALL;
const bool isMethod = node->type == NOOMP_NODE_METHODCALL || node->type == NOOMP_NODE_STRINGMETHODCALL || node->type == NOOMP_NODE_TABLEMETHODCALL;
if ((result = noomC_compile_expr(vm, compiler, parser, func, node->subnodes[0], 1))) return result;
const unsigned char funcIdx = (unsigned char)(compiler->curstack - 1);
@@ -495,8 +563,8 @@ noom_Exit noomC_compile_expr(
if (isMethod) {
const char* fieldname = parser->code + node->subnodes[1]->source_offset;
const noom_uint_t fieldlen = noomL_tokenlen(parser->code, node->subnodes[1]->source_offset, parser->version);
noom_uint_t constidx = func->constsize;
if ((result = noomC_addconst_str(compiler, vm, fieldname, fieldlen))) return result;
noom_uint_t constidx;
if ((result = noomC_addconst_str(compiler, vm, fieldname, fieldlen, &constidx))) return result;
compiler->curstack++; // self is pushed alongside the method
if ((result = noomC_emit_AuD(func, NOOMV_INSTR_GETMETHOD, funcIdx, (unsigned short)constidx))) return result;
}
@@ -510,7 +578,7 @@ noom_Exit noomC_compile_expr(
}
} else {
for (noom_uint_t i = isMethod ? 2 : 1; i < node->subnodec; i++) {
const noom_bool_t isLast = i == node->subnodec - 1;
const bool isLast = i == node->subnodec - 1;
if ((result = noomC_compile_expr(vm, compiler, parser, func, node->subnodes[i], isLast ? -1 : 1))) return result;
}
}
@@ -526,7 +594,38 @@ noom_Exit noomC_compile_expr(
if (node->type == NOOMP_NODE_VARIABLE) {
const char* varname = parser->code + node->source_offset;
noom_uint_t namelen = noomL_tokenlen(varname, 0, parser->version);
return noomC_identifyLocalAndSet(compiler, varname, namelen);
noomC_LocalInfo info;
result = noomC_identifyLocal(compiler, varname, namelen, &info);
if(result) return result;
compiler->curstack++;
switch (info.type) {
case NOOMC_LOCAL:
return noomC_emit_AuD(func, NOOMV_INSTR_PUSHVAL, 0, info.idx);
case NOOMC_UPVAL:
return noomC_emit_AuD(func, NOOMV_INSTR_PUSHUPVAL, 0, info.idx);
case NOOMC_GLOBAL: {
noom_uint_t constidx;
if((result = noomC_addconst_str(compiler, vm, varname, namelen, &constidx))) return result;
if(parser->version == NOOM_VERSION_51) {
return noomC_emit_AuD(func, NOOMV_INSTR_PUSHGLOBAL, 0, constidx);
}
noomC_LocalInfo _ENV;
if((result = noomC_identifyLocal(compiler, "_ENV", 4, &_ENV))) 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) {
if((result = noomC_emit_AuD(func, NOOMV_INSTR_PUSHUPVAL, _ENV.idx, constidx))) return result;
} else {
// bitchass
if((result = noomC_emit_AuD(func, NOOMV_INSTR_PUSHVAL, 0, _ENV.idx))) return result;
}
return noomC_emit_AuD(func, NOOMV_INSTR_GETFIELD, 0, constidx);
}
}
// forgot a case
return NOOM_EINTERNAL;
}
if (node->type == NOOMP_NODE_LAMBDAFUNCTIONLITERAL) {
@@ -569,7 +668,7 @@ noom_Exit noomC_add_stuff_to_function(noom_LuaVM* vm, noomC_Compiler* compiler,
unsigned int base_slot = compiler->curstack;
for (noom_uint_t i = 0; i < value_count; i++) {
noom_bool_t is_last = i == value_count - 1;
bool is_last = i == value_count - 1;
int wanted = is_last ? (int)(name_count - i) : 1;
if ((result = noomC_compile_expr(vm, compiler, parser, func, node->subnodes[name_count + i], wanted))) return result;
}
@@ -584,9 +683,9 @@ noom_Exit noomC_add_stuff_to_function(noom_LuaVM* vm, noomC_Compiler* compiler,
local.name = parser->code + varname_node->source_offset;
local.namelen = length;
local.stackslot = base_slot + i;
local.dropped = 0;
local.constant = 0;
local.close = 0;
local.dropped = false;
local.constant = false;
local.close = false;
for (noom_uint_t ai = 1; ai < varname_node->subnodec; ai++) {
noom_uint_t offset = varname_node->subnodes[ai]->source_offset;
@@ -595,10 +694,10 @@ noom_Exit noomC_add_stuff_to_function(noom_LuaVM* vm, noomC_Compiler* compiler,
noom_uint_t al = alength;
if (noom_memeq(ap, al, "close", 5)) {
if (local.close) return NOOM_EINTERNAL;
local.close = 1;
local.close = true;
} else if (noom_memeq(ap, al, "const", 5)) {
if (local.constant) return NOOM_EINTERNAL;
local.constant = 1;
local.constant = true;
} else {
return NOOM_EINTERNAL;
}
@@ -638,9 +737,9 @@ noom_Exit noomC_add_stuff_to_function(noom_LuaVM* vm, noomC_Compiler* compiler,
local.name = parser->code + varname_node->source_offset;
local.namelen = length;
local.stackslot = self_slot;
local.dropped = 0;
local.constant = 0;
local.close = 0;
local.dropped = false;
local.constant = false;
local.close = false;
return noomC_addLocal(compiler, local);
}
@@ -653,10 +752,10 @@ noom_Exit noomC_add_stuff_to_function(noom_LuaVM* vm, noomC_Compiler* compiler,
const noomP_Node* params_node = node->subnodes[1];
const noomP_Node* block_node = node->subnodes[2];
noom_bool_t has_self = 0;
bool has_self = false;
if (fname_node->subnodec > 0) {
const noomP_Node* last = fname_node->subnodes[fname_node->subnodec - 1];
if (last->type == NOOMP_NODE_METHODNAME) has_self = 1;
if (last->type == NOOMP_NODE_METHODNAME) has_self = true;
}
noomV_Function* proto;
@@ -693,7 +792,7 @@ noom_Exit noomC_add_stuff_to_function(noom_LuaVM* vm, noomC_Compiler* compiler,
unsigned char base_slot = (unsigned char)compiler->curstack;
for (noom_uint_t i = 0; i < node->subnodec; i++) {
noom_bool_t is_last = i == node->subnodec - 1;
bool is_last = i == node->subnodec - 1;
if ((result = noomC_compile_expr(vm, compiler, parser, func, node->subnodes[i], is_last ? -1 : 1))) return result;
}
@@ -705,10 +804,18 @@ noom_Exit noomC_add_stuff_to_function(noom_LuaVM* vm, noomC_Compiler* compiler,
noom_uint_t place_count = 0;
while (place_count < node->subnodec && node->subnodes[place_count]->type == NOOMP_NODE_ASSIGNPLACE) place_count++;
noom_uint_t value_count = node->subnodec - place_count;
// subtly wrong execution but also just wrong... order of instructions!
// TODO: burn it with fire
// WHY: assigning instructions fundamentally assume the value is on the top of the stack,
// so this is just bad. Lua also evalutes stuff differently, with f().x = g() calling f before g.
// IF WE WANT TO KEEP THE BROKEN ORDER: we should push all of the values first, then do the assignments in reverse order.
// IF WE WANT TO FIX THE ORDER: we'd need the emit_assign_to output extra information for the 2nd half of the assingment,
// so it can for example call f() and get th return but store how to assign to its result.
unsigned char value_base = (unsigned char)compiler->curstack;
for (noom_uint_t i = 0; i < value_count; i++) {
noom_bool_t is_last = i == value_count - 1;
bool is_last = i == value_count - 1;
int wanted = is_last ? (int)(place_count - i) : 1;
if ((result = noomC_compile_expr(vm, compiler, parser, func, node->subnodes[place_count + i], wanted))) return result;
}
@@ -884,11 +991,13 @@ noom_Exit noomC_compile(noom_LuaVM* vm, const noomP_Parser* parser, const noomP_
upval.name = "_ENV";
upval.namelen = 4;
upval.slot = 0;
upval.stolen = 1;
upval.constant = 0;
upval.isParentUpvalue = true;
upval.constant = false;
noomC_addUpval(&compiler, upval);
// TODO: we need to wrap the value as a *closure*, with one upvalue, the environment (_ENV).
}
return noomC_compile_block(vm, &compiler, parser, program, node);
noom_Exit err = noomC_compile_block(vm, &compiler, parser, program, node);
noomC_compiler_deinit(&compiler);
return err;
}

View File

@@ -8,9 +8,9 @@ typedef struct noomC_Local {
const char* name;
unsigned int namelen;
unsigned int stackslot;
noom_bool_t dropped;
noom_bool_t constant;
noom_bool_t close;
bool dropped;
bool constant;
bool close;
} noomC_Local;
typedef struct noomC_Upval {
@@ -18,8 +18,8 @@ typedef struct noomC_Upval {
unsigned int namelen;
unsigned short slot;
// if stolen, this means that slot is actually an upvalue index
noom_bool_t stolen;
noom_bool_t constant;
bool isParentUpvalue;
bool constant;
} noomC_Upval;
#define NOOMC_MAXLOCAL 200
@@ -29,6 +29,8 @@ typedef struct noomC_Compiler {
// steal constants from this
struct noomC_Compiler* parent;
noomV_Function* target;
char *stringTmpBuf;
noom_uint_t maxStringLen;
unsigned localc;
unsigned upvalc;
unsigned curstack;
@@ -36,19 +38,12 @@ typedef struct noomC_Compiler {
noomC_Upval upvals[NOOMC_MAXUPVAL];
} noomC_Compiler;
// TODO: probably many of these don't really need to be exposed to other code but whatever
noom_Exit noomC_addLocal(noomC_Compiler* c, noomC_Local local);
noom_Exit noomC_addUpval(noomC_Compiler* c, noomC_Upval upval);
int noomC_stealUpval(noomC_Compiler* c, const char* name, noom_uint_t namelen);
void noomC_compiler_init(noomC_Compiler* compiler);
void noomC_compiler_deinit(noomC_Compiler* compiler);
noom_Exit noomC_emit(noomV_Function* func, noomV_Inst inst);
#define noomC_emit_ABC(func, _op, _a, _b, _c) noomC_emit((func), (noomV_Inst){.op = (_op), .a = (_a), .b = (_b), .c = (_c)})
#define noomC_emit_AuD(func, _op, _a, _uD) noomC_emit((func), (noomV_Inst){.op = (_op), .a = (_a), .us = (_uD)})
noom_Exit noomC_addconst(noomV_Function* func, noomV_Value val);
noomV_String* noomC_internString(const noomC_Compiler* c, noom_LuaVM* vm, const char* str, noom_uint_t len);
noom_Exit noomC_addconst_str(noomC_Compiler* c, noom_LuaVM* vm, const char* str, noom_uint_t len);
noom_BinOp noomC_lex_bin_op(const noomP_Parser* parser, noom_uint_t offset);
noom_UnaryOp noomC_lex_un_op(const noomP_Parser* parser, noom_uint_t offset);
@@ -59,7 +54,7 @@ static noom_Exit noomC_compile_proto(
noomV_Function* parent_func,
const noomP_Node* params_node,
const noomP_Node* block_node,
noom_bool_t has_self,
bool has_self,
noomV_Function** out_proto);
noom_Exit noomC_emit_assign_to(
noom_LuaVM* vm,

View File

@@ -43,11 +43,10 @@ void print_node(const noomP_Node* node, noom_uint_t depth) {
void pretty(const char* code, noom_LuaVersion version, const noomP_Node* node, noom_uint_t indent) {
for (noom_uint_t i = 0; i < indent; i++) putchar('\t');
const noom_uint_t len = noomL_tokenlen(code, node->source_offset, version);
char* fuckoff = code;
const char c = fuckoff[node->source_offset + len];
fuckoff[node->source_offset + len] = '\0';
printf("%*s%s %s", (int)len, code + node->source_offset, code[node->source_offset] != '\0' ? " -" : "", noomP_formatNodeType(node->type));
fuckoff[node->source_offset + len] = c;
for (int i = 0; i < len; i++) {
putchar(*(code + node->source_offset + i));
}
printf("%s %s", code[node->source_offset] != '\0' ? " -" : "", noomP_formatNodeType(node->type));
if (node->subnodec) {
printf(" with %lld entr%s {\n", node->subnodec, node->subnodec == 1 ? "y" : "ies");
for (int i = 0; i < node->subnodec; i++) {
@@ -134,6 +133,7 @@ int execute(const char* code, noom_LuaVersion version, const char* program_name,
if (e) {
printf("error: %d\n", e);
noomP_freeNode(parser.last_node);
noom_destroyVM(vm);
return 1;
}
noomP_freeNode(parser.last_node);

View File

@@ -1,6 +1,10 @@
#ifndef NOOM_H
#define NOOM_H
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#define NN_STR(x) #x
#define NN_XSTR(x) NN_STR(x)
@@ -30,10 +34,9 @@ extern "C" {
// To prevent recursion from using up infinitely much memory
#define NOOM_MAXSTACK 16384
typedef unsigned long long int noom_uint_t;
typedef signed long long int noom_int_t;
typedef uintptr_t noom_uint_t;
typedef intptr_t noom_int_t;
typedef double noom_float_t;
typedef unsigned char noom_bool_t;
typedef enum noom_LuaVersion {
// no 5.0, at least for now, cause it doesn't seem to be used much and is a bit *weird*
@@ -161,7 +164,7 @@ typedef noom_int_t noom_slot_t;
noom_Exit noom_pushint(noom_LuaVM* vm, noom_int_t integer);
noom_Exit noom_pushnumber(noom_LuaVM* vm, noom_float_t number);
noom_Exit noom_pushbool(noom_LuaVM* vm, noom_bool_t boolean);
noom_Exit noom_pushbool(noom_LuaVM* vm, bool boolean);
noom_Exit noom_pushstring(noom_LuaVM* vm, const char* s);
noom_Exit noom_pushlstring(noom_LuaVM* vm, const char* s, noom_uint_t len);
noom_Exit noom_createtable(noom_LuaVM* vm, noom_uint_t prealloc);
@@ -277,7 +280,7 @@ noom_Exit noom_next(noom_LuaVM* vm);
// Taking data out
noom_Exit noom_tobool(noom_LuaVM* vm, noom_slot_t x, noom_bool_t* b);
noom_Exit noom_tobool(noom_LuaVM* vm, noom_slot_t x, bool* b);
noom_Exit noom_toint(noom_LuaVM* vm, noom_slot_t x, noom_int_t* n);
noom_Exit noom_tonumber(noom_LuaVM* vm, noom_slot_t x, noom_float_t* n);
// NOTE: the string is not automatically retained until function exit.

View File

@@ -76,14 +76,6 @@ noomV_DisInfo noomV_disInfo[NOOMV_INSTR_NOP2] = {
.name = "SETFIELD",
.arg = NOOMV_DIS_uD,
},
[NOOMV_INSTR_GETUPFIELD] = {
.name = "GETUPFIELD",
.arg = NOOMV_DIS_uD,
},
[NOOMV_ISNTR_SETUPFIELD] = {
.name = "SETUPFIELD",
.arg = NOOMV_DIS_uD,
},
[NOOMV_INSTR_OP] = {
.name = "OP",
@@ -259,9 +251,9 @@ noom_uint_t noomV_rawhashValue(noomV_Value v) {
}
}
noom_bool_t noomV_isNil(noomV_Value key) { return key.tag == NOOMV_VNIL; }
bool noomV_isNil(noomV_Value key) { return key.tag == NOOMV_VNIL; }
noom_bool_t noomV_isLegalKey(noomV_Value key) {
bool noomV_isLegalKey(noomV_Value key) {
if (key.tag == NOOMV_VNIL) return 0;
if (key.tag == NOOMV_VNUM) {
noom_float_t n = key.number;
@@ -271,7 +263,7 @@ noom_bool_t noomV_isLegalKey(noomV_Value key) {
return 1;
}
noom_bool_t noomV_rawequalValue(noomV_Value a, noomV_Value b) {
bool noomV_rawequalValue(noomV_Value a, noomV_Value b) {
// special case: integers and numbers
if (a.tag == NOOMV_VINT && b.tag == NOOMV_VNUM) {
return a.integer == b.number;
@@ -358,7 +350,7 @@ noom_Exit noomV_rawsetTable(noom_LuaVM* vm, noomV_Table* t, noomV_Value key, noo
noomV_Value key2 = t->entrydata[idx];
// tombstone, for creation!
if(key2.isptr) {
freshTomb = t->entrydata + idx;
if(freshTomb == 0) freshTomb = t->entrydata + idx;
idx++;
idx %= t->entries;
count++;
@@ -483,7 +475,7 @@ void noomV_freeObj(noom_LuaVM* vm, noomV_Object* obj) {
noom_Exit noomV_pushCallFrame(noom_LuaVM* vm, noomV_Thread* coro, noomV_CallFrame cf);
noomV_CallFrame* noomV_topCallFrame(noomV_Thread* coro) {
if (coro->calldepth == 0) return 0;
if (coro->calldepth == 0) return NULL;
return &coro->calls[coro->calldepth - 1];
}
@@ -575,3 +567,38 @@ void noom_destroyVM(noom_LuaVM* vm) {
}
noom_free(vm);
}
noom_Exit noomV_pushRawValue(noom_LuaVM *vm, noomV_Value val);
noom_Exit noomV_getStackValue(noom_LuaVM *vm, noom_slot_t slot, noomV_Value *outVal) {
noomV_Thread *curThread = vm->currentThread;
size_t stacksize = noom_getstacksize(vm);
if(slot < 0) slot += stacksize;
if(slot < 0) {
noomV_setErrorStr(vm, curThread, "stack underflow");
return NOOM_ERUNTIME;
}
if(slot >= stacksize) {
noomV_setErrorStr(vm, curThread, "stack overflow");
return NOOM_ENOSTACK;
}
if(curThread->calldepth == 0) {
*outVal = curThread->stack[slot];
} else {
noomV_CallFrame *cf = noomV_topCallFrame(curThread);
*outVal = curThread->stack[cf->funcIdx+1];
}
if(outVal->isptr) {
*outVal = outVal->ptr->value;
}
return NOOM_OK;
}
noom_Exit noomV_setStackValue(noom_LuaVM *vm, noom_slot_t slot, noomV_Value val);
noom_int_t noom_getstacksize(noom_LuaVM* vm) {
noomV_Thread *cur = vm->currentThread;
if(cur->calldepth == 0) return cur->stacklen;
noomV_CallFrame *cf = noomV_topCallFrame(cur);
return cur->stacklen - cf->funcIdx - 1;
}

View File

@@ -25,7 +25,7 @@ typedef enum noomV_ObjTag {
typedef struct noomV_Object {
noomV_ObjTag tag;
noom_bool_t marked;
bool marked;
struct noomV_Object* next;
struct noomV_Object* nextGray;
} noomV_Object;
@@ -43,11 +43,11 @@ typedef enum noomV_ValueTag : unsigned char {
typedef struct noomV_Value {
noomV_ValueTag tag;
// for stack slots
noom_bool_t autoclose;
bool autoclose;
// pointer to value
noom_bool_t isptr;
bool isptr;
union {
noom_bool_t boolean;
bool boolean;
noom_int_t integer;
noom_float_t number;
noom_CFunction* cfunc;
@@ -130,10 +130,6 @@ typedef enum noomV_Opcode : unsigned char {
NOOMV_INSTR_GETFIELD,
// 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.
@@ -211,14 +207,14 @@ typedef struct noomV_UpvalDesc {
char* name;
unsigned char idx;
// whether the index is a stack index
noom_bool_t isStack;
bool isStack;
} noomV_UpvalDesc;
typedef struct noomV_LocalDesc {
char* name;
unsigned char stackIdx;
// to forbid changing it with debug.setlocal
noom_bool_t isConst;
bool isConst;
// offset of first instruction where local exists
unsigned int pcStart;
// offset of first instruction where local is dropped
@@ -315,7 +311,7 @@ typedef struct noomV_CallFrame {
// stack index of function
noom_uint_t funcIdx;
noom_uint_t returnCount;
noom_bool_t isC;
bool isC;
noomV_Value errhandler;
noomV_Pointer** upvals;
union {
@@ -367,9 +363,9 @@ noomV_String* noomV_allocStr(noom_LuaVM* vm, const char* str, noom_uint_t len);
noomV_Function* noomV_allocFunc(noom_LuaVM* vm, noomV_String* chunkname);
noomV_Table* noomV_allocTable(noom_LuaVM* vm, noom_uint_t arraylen, noom_uint_t fields);
noom_uint_t noomV_rawhashValue(noomV_Value v);
noom_bool_t noomV_isNil(noomV_Value key);
noom_bool_t noomV_isLegalKey(noomV_Value key);
noom_bool_t noomV_rawequalValue(noomV_Value a, noomV_Value b);
bool noomV_isNil(noomV_Value key);
bool noomV_isLegalKey(noomV_Value key);
bool noomV_rawequalValue(noomV_Value a, noomV_Value b);
noomV_Value noomV_rawgetTable(noomV_Table* t, noomV_Value key);
noomV_Value noomV_rawgetiTable(noomV_Table* t, noom_int_t idx);
noom_Exit noomV_rawsetTable(noom_LuaVM* vm, noomV_Table* t, noomV_Value key, noomV_Value val);
@@ -392,4 +388,8 @@ noomV_CallFrame* noomV_topCallFrame(noomV_Thread* coro);
noom_Exit noomV_setThreadStackSize(noom_LuaVM* vm, noomV_Thread* coro, noom_int_t stack);
noom_Exit noomV_pushRawValue(noom_LuaVM *vm, noomV_Value val);
noom_Exit noomV_getStackValue(noom_LuaVM *vm, noom_slot_t slot, noomV_Value *outVal);
noom_Exit noomV_setStackValue(noom_LuaVM *vm, noom_slot_t slot, noomV_Value val);
#endif