peak software
This commit is contained in:
@@ -6,6 +6,7 @@ typedef struct noomC_Local {
|
|||||||
unsigned int startpc;
|
unsigned int startpc;
|
||||||
unsigned int endpc;
|
unsigned int endpc;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
noom_uint_t namelen;
|
||||||
noom_bool_t dropped;
|
noom_bool_t dropped;
|
||||||
noom_bool_t constant;
|
noom_bool_t constant;
|
||||||
noom_bool_t close;
|
noom_bool_t close;
|
||||||
@@ -17,7 +18,8 @@ typedef struct noomC_Compiler {
|
|||||||
unsigned localc, constc;
|
unsigned localc, constc;
|
||||||
unsigned localcap, constcap;
|
unsigned localcap, constcap;
|
||||||
// constants index in the stack.
|
// 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 constidx;
|
||||||
unsigned curstack;
|
unsigned curstack;
|
||||||
noomC_Local *locals;
|
noomC_Local *locals;
|
||||||
|
|||||||
@@ -243,12 +243,16 @@ int main(int argc, char **argv) {
|
|||||||
if (code == 0) return 1;
|
if (code == 0) return 1;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
if (code[0] == '#' && code[1] == '!') for (offset = 2; code[offset] && code[offset] != '\n'; offset++);
|
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) {
|
if (params.use_stdin) {
|
||||||
char* code = read_stdin();
|
char* code = read_stdin();
|
||||||
if (code == 0) return 1;
|
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) {
|
if (params.enter_repl) {
|
||||||
puts(NOOM_VERSION_TEXT);
|
puts(NOOM_VERSION_TEXT);
|
||||||
|
|||||||
54
src/noom.h
54
src/noom.h
@@ -57,6 +57,60 @@ typedef enum noom_Exit {
|
|||||||
NOOM_EERROR,
|
NOOM_EERROR,
|
||||||
} noom_Exit;
|
} 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 struct noom_LuaVM noom_LuaVM;
|
||||||
|
|
||||||
typedef noom_Exit noom_CFunction(noom_LuaVM *vm);
|
typedef noom_Exit noom_CFunction(noom_LuaVM *vm);
|
||||||
|
|||||||
137
src/vm.h
137
src/vm.h
@@ -84,76 +84,83 @@ typedef struct noomV_Pointer {
|
|||||||
|
|
||||||
typedef enum noomV_Opcode : unsigned char {
|
typedef enum noomV_Opcode : unsigned char {
|
||||||
NOOMV_INSTR_NOP = 0,
|
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,
|
NOOMV_INSTR_JMP,
|
||||||
// if(A) pc = uD
|
// pops value, if value is truthy, does the same as JMP.
|
||||||
NOOMV_INSTR_JC,
|
NOOMV_INSTR_CJMP,
|
||||||
// if(not A) pc = uD
|
// pops value, if value is falsy, does the same as JMP.
|
||||||
NOOMV_INSTR_JNC,
|
NOOMV_INSTR_CNJMP,
|
||||||
|
|
||||||
// A = B + C
|
// For bullshit
|
||||||
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,
|
|
||||||
|
|
||||||
// A = B == C
|
// Take the top value without popping it, push value[consts[op.uD]] like GETFIELD would, then swap the top 2 values.
|
||||||
NOOMV_INSTR_EQ,
|
// This is for a:foo() and such
|
||||||
// A = B ~= C
|
NOOMV_INSTR_GETMETHOD,
|
||||||
NOOMV_INSTR_NEQ,
|
// rotate the the top op.a items by op.sD
|
||||||
// A = B < C
|
NOOMV_INSTR_ROTATE,
|
||||||
NOOMV_INSTR_LT,
|
// pop op.uD values
|
||||||
// A = B <= C
|
NOOMV_INSTR_POP,
|
||||||
NOOMV_INSTR_LTE,
|
// set the stack size to op.uD, inserting nils if need be, good for labels
|
||||||
// A = B > C
|
NOOMV_INSTR_SETSTACK,
|
||||||
NOOMV_INSTR_GT,
|
|
||||||
// A = B >= C
|
|
||||||
NOOMV_INSTR_GTE,
|
|
||||||
|
|
||||||
// A = not B
|
// pop and concatenate the top op.uD values to a string and push it
|
||||||
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
|
|
||||||
NOOMV_INSTR_CONCAT,
|
NOOMV_INSTR_CONCAT,
|
||||||
// A = #B
|
|
||||||
NOOMV_INSTR_LEN,
|
// mark stack slot op.uD as to-be-closed
|
||||||
// A = B[C]
|
NOOMV_INSTR_CLOSE,
|
||||||
NOOMV_INSTR_GET,
|
|
||||||
// A[B] = C
|
|
||||||
NOOMV_INSTR_SET,
|
|
||||||
|
|
||||||
NOOMV_INSTR_NOP2 = 0xff,
|
NOOMV_INSTR_NOP2 = 0xff,
|
||||||
} noomV_Opcode;
|
} noomV_Opcode;
|
||||||
@@ -181,6 +188,8 @@ typedef struct noomV_UpvalDesc {
|
|||||||
typedef struct noomV_LocalDesc {
|
typedef struct noomV_LocalDesc {
|
||||||
char *name;
|
char *name;
|
||||||
unsigned char stackIdx;
|
unsigned char stackIdx;
|
||||||
|
// to forbid changing it with debug.setlocal
|
||||||
|
noom_bool_t isConst;
|
||||||
// offset of first instruction where local exists
|
// offset of first instruction where local exists
|
||||||
unsigned int pcStart;
|
unsigned int pcStart;
|
||||||
// offset of first instruction where local is dropped
|
// offset of first instruction where local is dropped
|
||||||
|
|||||||
Reference in New Issue
Block a user