compiler: various bits of progress
Reviewed-on: #12 Co-authored-by: tema5002 <tema5002@tuta.io> Co-committed-by: tema5002 <tema5002@tuta.io>
This commit was merged in pull request #12.
This commit is contained in:
886
src/compiler.c
886
src/compiler.c
File diff suppressed because it is too large
Load Diff
@@ -36,7 +36,48 @@ 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);
|
||||
|
||||
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);
|
||||
|
||||
static noom_Exit noomC_compile_proto(
|
||||
noom_LuaVM* vm,
|
||||
noomC_Compiler* parent_compiler,
|
||||
const noomP_Parser* parser,
|
||||
noomV_Function* parent_func,
|
||||
const noomP_Node* params_node,
|
||||
const noomP_Node* block_node,
|
||||
noom_bool_t has_self,
|
||||
noomV_Function** out_proto);
|
||||
noom_Exit noomC_emit_assign_to(
|
||||
noom_LuaVM* vm,
|
||||
noomC_Compiler* compiler,
|
||||
const noomP_Parser* parser,
|
||||
noomV_Function* func,
|
||||
const noomP_Node* target,
|
||||
unsigned char value_slot);
|
||||
noom_Exit noomC_compile_expr(
|
||||
noom_LuaVM* vm,
|
||||
noomC_Compiler* compiler,
|
||||
const noomP_Parser* parser,
|
||||
noomV_Function* func,
|
||||
const noomP_Node* node,
|
||||
// retc of -1 means all values!!!!!!!!!!!
|
||||
int retc);
|
||||
noom_Exit noomC_compile_block(noom_LuaVM* vm, noomC_Compiler* compiler, const noomP_Parser* parser, noomV_Function* func, const noomP_Node* node);
|
||||
noom_Exit noomC_add_stuff_to_function(noom_LuaVM* vm, noomC_Compiler* compiler, const noomP_Parser* parser, noomV_Function* func, const noomP_Node* node);
|
||||
|
||||
// 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, noomV_Value* outFunc);
|
||||
|
||||
34
src/helper.c
34
src/helper.c
@@ -2,33 +2,32 @@
|
||||
#include "lexer.h"
|
||||
#include "noom.h"
|
||||
|
||||
double noom_strtod(const char* s, const char** endptr, int* error) {
|
||||
// TODO make it actually output integers if the lua version allows that uhhhhh
|
||||
noomV_Value noom_tonumber_except_different_name_so_public_fucking_api_works(const char* s, const char** endptr, noom_LuaVersion luauauauaua) {
|
||||
// Num???? Is that a fucking noom reference???????
|
||||
double num = 0.0;
|
||||
|
||||
int error_but_different = 1;
|
||||
noom_float_t num = 0.0;
|
||||
|
||||
const noom_bool_t negative = *s == '-';
|
||||
if (*s == '-' || *s == '+')
|
||||
s++;
|
||||
|
||||
if (!noomL_isnumber(s[*s == '.'])) goto fuck;
|
||||
if (!noomL_isnumber(s[*s == '.'])) return (noomV_Value){ .tag = NOOMV_VNIL };
|
||||
|
||||
if (*s == '0' && noomL_lower(s[1]) == 'x') {
|
||||
s += 2;
|
||||
// if the string starts with "0x" but does not contain digits it's invalid
|
||||
noom_bool_t are_we_cooked = 1;
|
||||
noom_bool_t error = 1;
|
||||
while (noomL_ishex(*s)) {
|
||||
int digit;
|
||||
if (noomL_isnumber(*s)) digit = *s - '0';
|
||||
else digit = noomL_lower(*s) - 'a' + 10;
|
||||
|
||||
num = num * 16.0 + digit;
|
||||
are_we_cooked = 0;
|
||||
error = 0;
|
||||
s++;
|
||||
}
|
||||
|
||||
if (are_we_cooked) goto fuck;
|
||||
if (error) return (noomV_Value){ .tag = NOOMV_VNIL };
|
||||
|
||||
if (noomL_lower(*s) == 'p') {
|
||||
// damn then
|
||||
@@ -38,8 +37,8 @@ double noom_strtod(const char* s, const char** endptr, int* error) {
|
||||
if (*s == '-' || *s == '+')
|
||||
s++;
|
||||
|
||||
if (!noomL_isnumber(*s)) goto fuck;
|
||||
|
||||
if (!noomL_isnumber(*s)) return (noomV_Value){ .tag = NOOMV_VNIL };
|
||||
|
||||
while (noomL_isnumber(*s)) {
|
||||
exponent = exponent * 10 + (*s - '0');
|
||||
s++;
|
||||
@@ -48,10 +47,10 @@ double noom_strtod(const char* s, const char** endptr, int* error) {
|
||||
num *= noom_pow(2.0, exponent_negative ? -exponent : exponent);
|
||||
}
|
||||
} else {
|
||||
noom_bool_t are_we_cooked = 1;
|
||||
noom_bool_t error = 1;
|
||||
while (noomL_isnumber(*s)) {
|
||||
num = num * 10.0 + (*s - '0');
|
||||
are_we_cooked = 0;
|
||||
error = 0;
|
||||
s++;
|
||||
}
|
||||
if (*s == '.') {
|
||||
@@ -59,13 +58,13 @@ double noom_strtod(const char* s, const char** endptr, int* error) {
|
||||
|
||||
double fraction_divisor = 10.0;
|
||||
while (noomL_isnumber(*s)) {
|
||||
are_we_cooked = 0;
|
||||
error = 0;
|
||||
num += (double)(*s - '0') / fraction_divisor;
|
||||
fraction_divisor *= 10.0;
|
||||
s++;
|
||||
}
|
||||
}
|
||||
if (are_we_cooked) goto fuck;
|
||||
if (error) return (noomV_Value){ .tag = NOOMV_VNIL };
|
||||
|
||||
if (noomL_lower(*s) == 'e') {
|
||||
s++;
|
||||
@@ -74,7 +73,7 @@ double noom_strtod(const char* s, const char** endptr, int* error) {
|
||||
if (*s == '-' || *s == '+')
|
||||
s++;
|
||||
|
||||
if (!noomL_isnumber(*s)) goto fuck;
|
||||
if (!noomL_isnumber(*s)) return (noomV_Value){ .tag = NOOMV_VNIL };
|
||||
|
||||
while (noomL_isnumber(*s)) {
|
||||
exponent = exponent * 10 + (*s - '0');
|
||||
@@ -85,11 +84,8 @@ double noom_strtod(const char* s, const char** endptr, int* error) {
|
||||
}
|
||||
}
|
||||
|
||||
error_but_different = 0;
|
||||
fuck:
|
||||
if (endptr) *endptr = s;
|
||||
if (error) *error = error_but_different;
|
||||
return negative ? -num : num;
|
||||
return (noomV_Value){ .tag = NOOMV_VNUM, .number = negative ? -num : num };
|
||||
}
|
||||
|
||||
// made by some stranger on stack overflow
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
#include "noom.h"
|
||||
#include "vm.h"
|
||||
|
||||
#define NOOM_USHORT_MAX 0xffff
|
||||
|
||||
// isn't quite strtod, is it
|
||||
// doesn't skip whitespace unlike actual C stdlib strtod!!!!
|
||||
double noom_strtod(const char* s, const char** endptr, int* error);
|
||||
noomV_Value noom_tonumber_except_different_name_so_public_fucking_api_works(const char* s, const char** endptr, noom_LuaVersion luauauauaua);
|
||||
double noom_pow(double x, int y);
|
||||
|
||||
int noom_startswith(const char* str, const char* compare);
|
||||
|
||||
231
src/main.c
231
src/main.c
@@ -27,127 +27,145 @@ void print_node(const noomP_Node* node, noom_uint_t depth) {
|
||||
tab(depth + 1);
|
||||
printf("location: %lld\n", node->source_offset);
|
||||
|
||||
tab(depth + 1);
|
||||
printf("subnodes:\n");
|
||||
if (node->subnodec > 0) {
|
||||
tab(depth + 1);
|
||||
printf("subnodes (%llu):\n", node->subnodec);
|
||||
|
||||
for (noom_uint_t i = 0; i < node->subnodec; i++) {
|
||||
print_node(node->subnodes[i], depth + 1);
|
||||
for (noom_uint_t i = 0; i < node->subnodec; i++) {
|
||||
print_node(node->subnodes[i], depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
tab(depth);
|
||||
printf("}\n");
|
||||
}
|
||||
|
||||
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;
|
||||
if (node->subnodec) {
|
||||
printf(" with %lld entr%s {\n", node->subnodec, node->subnodec == 1 ? "y" : "ies");
|
||||
for (int i = 0; i < node->subnodec; i++) {
|
||||
pretty(code, version, node->subnodes[i], indent + 1);
|
||||
}
|
||||
for (noom_uint_t i = 0; i < indent; i++) putchar('\t');
|
||||
putchar('}');
|
||||
putchar('\n');
|
||||
}
|
||||
else
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
// #define LEX_OUTPUT
|
||||
#define PARSE_OUTPUT
|
||||
#define COMPILER_OUTPUT
|
||||
|
||||
int execute(const char* code, noom_LuaVersion version, const char* program_name, const char* filename) {
|
||||
noomP_Parser parser;
|
||||
noomP_Node* program;
|
||||
|
||||
// goodbye "shitass" you will be missed
|
||||
int success = noomP_parse(code, filename, version, &program, &parser);
|
||||
if (success == 0) {
|
||||
puts("LEX OUTPUT:");
|
||||
fputs("\x1b[48;2;10;10;10m", stdout);
|
||||
noom_uint_t pos = 0;
|
||||
while (1) {
|
||||
noomL_Token token;
|
||||
|
||||
noomL_ErrorType err = noomL_lex(code, pos, &token, version);
|
||||
if (err) break;
|
||||
|
||||
if (token.type == NOOML_TOKEN_KEYWORD) {
|
||||
fputs("\x1b[38;2;207;142;109m", stdout);
|
||||
for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]);
|
||||
} else if (token.type == NOOML_TOKEN_WHITESPACE) {
|
||||
for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]);
|
||||
} else if (token.type == NOOML_TOKEN_IDENTIFIER) {
|
||||
fputs("\x1b[38;2;255;255;255m", stdout);
|
||||
for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]);
|
||||
} else if (token.type == NOOML_TOKEN_SYMBOL) {
|
||||
fputs("\x1b[38;2;0;255;255m", stdout);
|
||||
for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]);
|
||||
} else if (token.type == NOOML_TOKEN_STRING) {
|
||||
fputs("\x1b[38;2;255;0;0m", stdout);
|
||||
for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]);
|
||||
} else if (token.type == NOOML_TOKEN_NUMBER) {
|
||||
fputs("\x1b[38;2;0;255;0m", stdout);
|
||||
for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]);
|
||||
} else {
|
||||
fputs("\x1b[0m\n", stdout);
|
||||
printf("%s ", noomL_formatTokenType(token.type));
|
||||
for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]);
|
||||
fputs("\x1b[48;2;10;10;10m", stdout);
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
pos += token.length;
|
||||
|
||||
if (token.type == NOOML_TOKEN_EOF) break;
|
||||
}
|
||||
puts("\x1b[0m");
|
||||
puts("PARSE OUTPUT:");
|
||||
print_node(program, 0);
|
||||
} else {
|
||||
noom_uint_t bleh = noom_format_error(&parser, program_name, NULL, 0);
|
||||
if (noomP_parse(code, filename, version, &program, &parser) < 0) {
|
||||
const noom_uint_t bleh = noom_format_error(&parser, program_name, NULL, 0);
|
||||
char* buf = noom_alloc(bleh);
|
||||
noom_format_error(&parser, program_name, buf, bleh);
|
||||
fputs(buf, stdout);
|
||||
noomP_freeNode(parser.last_node);
|
||||
noom_free(buf);
|
||||
}
|
||||
|
||||
if (success == 0) {
|
||||
noom_LuaVM* vm = noom_createVM(version);
|
||||
noomV_Value peak;
|
||||
|
||||
noom_Exit e = noomC_compile(vm, &parser, program, 0, 0, &peak);
|
||||
if (e) {
|
||||
printf("error: %d\n", e);
|
||||
success = e;
|
||||
noom_destroyVM(vm);
|
||||
goto wellShit;
|
||||
}
|
||||
|
||||
noomV_Function* f = (noomV_Function*)peak.obj;
|
||||
|
||||
printf("Insts: %u\n", f->codesize);
|
||||
printf("Consts: %hu\n", f->constsize);
|
||||
printf("Ups: %u\n", (int)f->upvalsize);
|
||||
printf("Locals: %u\n", (int)f->localsize);
|
||||
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_NONE:
|
||||
break;
|
||||
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");
|
||||
}
|
||||
noom_destroyVM(vm);
|
||||
return 1;
|
||||
}
|
||||
|
||||
wellShit:;
|
||||
// freeing time
|
||||
noomP_Node* last_node = parser.last_node;
|
||||
while (last_node) {
|
||||
noomP_Node* next = last_node->previous_node;
|
||||
// subnodes could be null if we OOM'd during a realloc of it
|
||||
if (last_node->subnodes) noom_free(last_node->subnodes);
|
||||
noom_free(last_node);
|
||||
last_node = next;
|
||||
}
|
||||
#ifdef LEX_OUTPUT
|
||||
puts("LEX OUTPUT:");
|
||||
fputs("\x1b[48;2;10;10;10m", stdout);
|
||||
noom_uint_t pos = 0;
|
||||
while (1) {
|
||||
noomL_Token token;
|
||||
|
||||
return success;
|
||||
noomL_ErrorType err = noomL_lex(code, pos, &token, version);
|
||||
if (err) break;
|
||||
|
||||
if (token.type == NOOML_TOKEN_KEYWORD) {
|
||||
fputs("\x1b[38;2;207;142;109m", stdout);
|
||||
for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]);
|
||||
} else if (token.type == NOOML_TOKEN_WHITESPACE) {
|
||||
for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]);
|
||||
} else if (token.type == NOOML_TOKEN_IDENTIFIER) {
|
||||
fputs("\x1b[38;2;255;255;255m", stdout);
|
||||
for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]);
|
||||
} else if (token.type == NOOML_TOKEN_SYMBOL) {
|
||||
fputs("\x1b[38;2;0;255;255m", stdout);
|
||||
for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]);
|
||||
} else if (token.type == NOOML_TOKEN_STRING) {
|
||||
fputs("\x1b[38;2;255;0;0m", stdout);
|
||||
for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]);
|
||||
} else if (token.type == NOOML_TOKEN_NUMBER) {
|
||||
fputs("\x1b[38;2;0;255;0m", stdout);
|
||||
for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]);
|
||||
} else {
|
||||
fputs("\x1b[0m\n", stdout);
|
||||
printf("%s ", noomL_formatTokenType(token.type));
|
||||
for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]);
|
||||
fputs("\x1b[48;2;10;10;10m", stdout);
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
pos += token.length;
|
||||
|
||||
if (token.type == NOOML_TOKEN_EOF) break;
|
||||
}
|
||||
puts("\x1b[0m");
|
||||
#endif
|
||||
|
||||
#ifdef PARSE_OUTPUT
|
||||
puts("PARSE OUTPUT:");
|
||||
pretty(code, version, program, 0);
|
||||
//print_node(program, 0);
|
||||
#endif
|
||||
|
||||
noom_LuaVM* vm = noom_createVM(version);
|
||||
noomV_Value peak;
|
||||
|
||||
const noom_Exit e = noomC_compile(vm, &parser, program, 0, 0, &peak);
|
||||
if (e) {
|
||||
printf("error: %d\n", e);
|
||||
noomP_freeNode(parser.last_node);
|
||||
return 1;
|
||||
}
|
||||
noomP_freeNode(parser.last_node);
|
||||
|
||||
#ifdef COMPILER_OUTPUT
|
||||
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_NONE:
|
||||
break;
|
||||
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");
|
||||
}
|
||||
#endif
|
||||
noom_destroyVM(vm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char* read_file(const char* filename) {
|
||||
@@ -271,6 +289,8 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
params.script_exec = argv[i];
|
||||
params.do_i_already_know_what_to_do = 1;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argv[i][1] == 'l') {
|
||||
@@ -283,6 +303,7 @@ int main(int argc, char** argv) {
|
||||
goto die;
|
||||
}
|
||||
version_string = argv[i];
|
||||
i++;
|
||||
}
|
||||
if (noom_strcmp(version_string, "51") == 0) params.lua_version = NOOM_VERSION_51;
|
||||
else if (noom_strcmp(version_string, "52") == 0) params.lua_version = NOOM_VERSION_52;
|
||||
@@ -304,12 +325,14 @@ int main(int argc, char** argv) {
|
||||
goto die;
|
||||
}
|
||||
if (params.lua_version != 0) {
|
||||
params.lua_version = NOOM_VERSION_54;
|
||||
if (!params.do_i_already_know_what_to_do) {
|
||||
params.enter_repl = 1;
|
||||
params.do_i_already_know_what_to_do = 1;
|
||||
}
|
||||
}
|
||||
if (params.lua_version == 0) {
|
||||
params.lua_version = NOOM_VERSION_54;
|
||||
}
|
||||
if (!params.do_i_already_know_what_to_do) {
|
||||
err = "script not set";
|
||||
goto die;
|
||||
|
||||
@@ -75,6 +75,7 @@ typedef enum noom_Exit {
|
||||
NOOM_EERROR,
|
||||
} noom_Exit;
|
||||
|
||||
// shouldn't this go to vm.h....?
|
||||
typedef enum noom_UnaryOp {
|
||||
// -x
|
||||
NOOM_UNARY_NEGATE,
|
||||
|
||||
10
src/parser.c
10
src/parser.c
@@ -1806,3 +1806,13 @@ int noomP_initParser(noomP_Parser* parser, const char* code, const char* filenam
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void noomP_freeNode(noomP_Node* node) {
|
||||
while (node) {
|
||||
noomP_Node* next = node->previous_node;
|
||||
// subnodes could be null if we OOM'd during a realloc of it
|
||||
if (node->subnodes) noom_free(node->subnodes);
|
||||
noom_free(node);
|
||||
node = next;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,5 +171,6 @@ 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);
|
||||
void noomP_freeNode(noomP_Node* node);
|
||||
|
||||
#endif
|
||||
|
||||
1
src/vm.h
1
src/vm.h
@@ -310,6 +310,7 @@ typedef struct noomV_Function {
|
||||
|
||||
// exactly 64 bytes, aka one cache line.
|
||||
// TODO: ensure it is 64-byte aligned for a perfect 1:1 struct to cache line ratio for perf
|
||||
// it IS 64 bit aligned with 7 bytes wasted ^^^^^^^
|
||||
typedef struct noomV_CallFrame {
|
||||
// stack index of function
|
||||
noom_uint_t funcIdx;
|
||||
|
||||
Reference in New Issue
Block a user