diff --git a/src/compiler.h b/src/compiler.h index bb366c9..2324b5f 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -6,6 +6,7 @@ typedef struct noomC_Local { unsigned int startpc; unsigned int endpc; const char *name; + noom_uint_t namelen; noom_bool_t dropped; noom_bool_t constant; noom_bool_t close; @@ -17,7 +18,8 @@ typedef struct noomC_Compiler { unsigned localc, constc; unsigned localcap, constcap; // constants index in the stack. - // We put it there so GC doesn't free them. + // We put it there so GC doesn't free them, and + // so we can allocate the function's consts arrays *ONCE* unsigned constidx; unsigned curstack; noomC_Local *locals; diff --git a/src/main.c b/src/main.c index 934fd18..dbe115c 100644 --- a/src/main.c +++ b/src/main.c @@ -243,12 +243,16 @@ int main(int argc, char **argv) { if (code == 0) return 1; int offset = 0; if (code[0] == '#' && code[1] == '!') for (offset = 2; code[offset] && code[offset] != '\n'; offset++); - return the_theoretical_function_to_execute_your_code_that_should_be_replaced_later(code + offset, argv[0], params.script_path); + int e = the_theoretical_function_to_execute_your_code_that_should_be_replaced_later(code + offset, argv[0], params.script_path); + noom_free(code); + return e; } if (params.use_stdin) { char* code = read_stdin(); if (code == 0) return 1; - return the_theoretical_function_to_execute_your_code_that_should_be_replaced_later(code, argv[0], "stdin"); + int e = the_theoretical_function_to_execute_your_code_that_should_be_replaced_later(code, argv[0], "stdin"); + noom_free(code); + return e; } if (params.enter_repl) { puts(NOOM_VERSION_TEXT); diff --git a/src/noom.h b/src/noom.h index 45dcddb..f7969a1 100644 --- a/src/noom.h +++ b/src/noom.h @@ -57,6 +57,60 @@ typedef enum noom_Exit { NOOM_EERROR, } noom_Exit; +typedef enum noom_UnaryOp { + // -x + NOOM_UNARY_NEGATE, + // ~x + NOOM_UNARY_BNOT, + // #x + NOOM_UNARY_LEN, + // not x + NOOM_UNARY_NOT, +} noom_UnaryOp; + +typedef enum noom_BinOp { + // Algebruh (Noom knows maths) + + // a + b + NOOM_BIN_ADD, + // a - b + NOOM_BIN_SUB, + // a * b + NOOM_BIN_MLT, + // a / b + NOOM_BIN_DIV, + // a // b + NOOM_BIN_IDIV, + // a ^ b + NOOM_BIN_EXP, + + // Comparison (thief of joy) + + // a == b + NOOM_BIN_EQL, + // a ~= b + NOOM_BIN_NEQL, + // a < b + NOOM_BIN_LESS, + // a <= b + NOOM_BIN_LESSEQL, + // a > b + NOOM_BIN_GREATER, + // a >= b + NOOM_BIN_GREATEREQL, + + // a & b + NOOM_BIN_BAND, + // a | b + NOOM_BIN_BOR, + // a ~ b + NOOM_BIN_BXOR, + // a << b + NOOM_BIN_BSHIFTL, + // a >> b + NOOM_BIN_BSHIFTR, +} noom_BinOp; + typedef struct noom_LuaVM noom_LuaVM; typedef noom_Exit noom_CFunction(noom_LuaVM *vm); diff --git a/src/vm.h b/src/vm.h index 059328d..10db3cb 100644 --- a/src/vm.h +++ b/src/vm.h @@ -84,76 +84,83 @@ typedef struct noomV_Pointer { typedef enum noomV_Opcode : unsigned char { NOOMV_INSTR_NOP = 0, - // A = consts[uD] - NOOMV_INSTR_LOADC, - // load from A an array of uD nils - NOOMV_INSTR_LOAD_NILARR, - // load from A an array of uD/2 booleans, stored in uD&1 - NOOMV_INSTR_LOAD_BOOLARR, - // A = B - NOOMV_INSTR_COPY, - // pc = uD + // Push data on the stack + + // Pushes the value at stack[op.uD] + NOOMV_INSTR_PUSHVAL, + // Pushes consts[op.uD] + NOOMV_INSTR_PUSHCONST, + // Pushes op.sD itself as an integer + NOOMV_INSTR_PUSHINT, + // Pushes op.uD nils + NOOMV_INSTR_PUSHNIL, + // Pushes op.a+1 booleans, encoded in op.uD, where the ith (0-indexed) boolean is encoded in `uD & (1 << i)` + NOOMV_INSTR_PUSHBOOLS, + // Pushes *upvals[op.uD] + NOOMV_INSTR_PUSHUPVAL, + // Pushes op.a varargs. If op.a is 0, it will push all of them, regardless of how many + NOOMV_INSTR_PUSHARGS, + // Pushes a new table. op.uD is the initial capacity + NOOMV_INSTR_CREATETABLE, + // Pushes a closure, using the prototype in protos[op.uD] + NOOMV_INSTR_PUSHCLOSURE, + + // High-level ops + + // Call the function stored at stack[op.a]. All values after that are treated at arguments. op.uD is the expected return count plus one, and if op.uD is 0, + // all returns are pushed. + NOOMV_INSTR_CALL, + + // pops (table, field), and pushes table[field] + NOOMV_INSTR_GETTABLE, + // 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]; + NOOMV_INSTR_SETLIST, + // 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 + NOOMV_INSTR_SETFIELD, + + // does a unary or binary operation. + // if op.a == 1, its a unary operation. + // if op.a == 2, its a binary operation. + // op.b stores the operation type. + NOOMV_INSTR_OP, + + // Control flow + + // returns from a function. The amount returned is from op.uD + NOOMV_INSTR_RET, + + // computes T = op.a << 16 + op.uD, jumps to T. NOOMV_INSTR_JMP, - // if(A) pc = uD - NOOMV_INSTR_JC, - // if(not A) pc = uD - NOOMV_INSTR_JNC, + // pops value, if value is truthy, does the same as JMP. + NOOMV_INSTR_CJMP, + // pops value, if value is falsy, does the same as JMP. + NOOMV_INSTR_CNJMP, - // A = B + C - NOOMV_INSTR_ADD, - // A = B - C - NOOMV_INSTR_SUB, - // A = -B - NOOMV_INSTR_NEG, - // A = B * C - NOOMV_INSTR_MUL, - // A = B / C - NOOMV_INSTR_DIV, - // A = B % C - NOOMV_INSTR_MOD, - // A = B // C - NOOMV_INSTR_FLOOR_DIV, - // A = B ^ C - NOOMV_INSTR_POW, + // For bullshit - // A = B == C - NOOMV_INSTR_EQ, - // A = B ~= C - NOOMV_INSTR_NEQ, - // A = B < C - NOOMV_INSTR_LT, - // A = B <= C - NOOMV_INSTR_LTE, - // A = B > C - NOOMV_INSTR_GT, - // A = B >= C - NOOMV_INSTR_GTE, + // 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 + NOOMV_INSTR_ROTATE, + // pop op.uD values + NOOMV_INSTR_POP, + // set the stack size to op.uD, inserting nils if need be, good for labels + NOOMV_INSTR_SETSTACK, - // A = not B - NOOMV_INSTR_NOT, - - // A = B & C - NOOMV_INSTR_BAND, - // A = B | C - NOOMV_INSTR_BOR, - // A = B ~ C - NOOMV_INSTR_BXOR, - // A = ~B - NOOMV_INSTR_BNOT, - // A = B << C - NOOMV_INSTR_LSHIFT, - // A = B >> C - NOOMV_INSTR_RSHIFT, - - // A = B .. C + // pop and concatenate the top op.uD values to a string and push it NOOMV_INSTR_CONCAT, - // A = #B - NOOMV_INSTR_LEN, - // A = B[C] - NOOMV_INSTR_GET, - // A[B] = C - NOOMV_INSTR_SET, + + // mark stack slot op.uD as to-be-closed + NOOMV_INSTR_CLOSE, NOOMV_INSTR_NOP2 = 0xff, } noomV_Opcode; @@ -181,6 +188,8 @@ typedef struct noomV_UpvalDesc { typedef struct noomV_LocalDesc { char *name; unsigned char stackIdx; + // to forbid changing it with debug.setlocal + noom_bool_t isConst; // offset of first instruction where local exists unsigned int pcStart; // offset of first instruction where local is dropped