mirror of
https://github.com/CPunch/Cosmo.git
synced 2024-11-14 03:50:04 +00:00
Minor refactoring, added OP_GETMETHOD
You can use ':' without invoking. So you can grab a method binding to an object and later call it. Also some GC bugs were fixed. A new preprocessor macro (VM_DEBUG) has been added. Defining this macro will print each instruction thats being executed in the VM, as well as print each call.
This commit is contained in:
parent
e995bb75fb
commit
2864c7be53
@ -4,6 +4,8 @@
|
|||||||
#include "cobj.h"
|
#include "cobj.h"
|
||||||
#include "cmem.h"
|
#include "cmem.h"
|
||||||
|
|
||||||
|
// ================================================================ [BASELIB] ================================================================
|
||||||
|
|
||||||
int cosmoB_print(CState *state, int nargs, CValue *args) {
|
int cosmoB_print(CState *state, int nargs, CValue *args) {
|
||||||
for (int i = 0; i < nargs; i++) {
|
for (int i = 0; i < nargs; i++) {
|
||||||
CObjString *str = cosmoV_toString(state, args[i]);
|
CObjString *str = cosmoV_toString(state, args[i]);
|
||||||
|
22
src/cdebug.c
22
src/cdebug.c
@ -22,6 +22,12 @@ int u16OperandInstruction(const char *name, CChunk *chunk, int offset) {
|
|||||||
return offset + 1 + (sizeof(uint16_t) / sizeof(INSTRUCTION));
|
return offset + 1 + (sizeof(uint16_t) / sizeof(INSTRUCTION));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int JumpInstruction(const char *name, CChunk *chunk, int offset, int dir) {
|
||||||
|
int jmp = ((int)readu16Chunk(chunk, offset + 1)) * dir;
|
||||||
|
printf("%-16s [%05d] - jumps to %04d", name, jmp, offset + 3 + jmp);
|
||||||
|
return offset + 1 + (sizeof(uint16_t) / sizeof(INSTRUCTION));
|
||||||
|
}
|
||||||
|
|
||||||
int u8u8OperandInstruction(const char *name, CChunk *chunk, int offset) {
|
int u8u8OperandInstruction(const char *name, CChunk *chunk, int offset) {
|
||||||
printf("%-16s [%03d] [%03d]", name, readu8Chunk(chunk, offset + 1), readu8Chunk(chunk, offset + 2));
|
printf("%-16s [%03d] [%03d]", name, readu8Chunk(chunk, offset + 1), readu8Chunk(chunk, offset + 2));
|
||||||
return offset + 3; // op + u8 + u8
|
return offset + 3; // op + u8 + u8
|
||||||
@ -51,7 +57,7 @@ int constInstruction(const char *name, CChunk *chunk, int offset) {
|
|||||||
|
|
||||||
void disasmChunk(CChunk *chunk, const char *name, int indent) {
|
void disasmChunk(CChunk *chunk, const char *name, int indent) {
|
||||||
printIndent(indent);
|
printIndent(indent);
|
||||||
printf("===[[ %s ]]===\n", name);
|
printf("===[[ disasm for %s ]]===\n", name);
|
||||||
|
|
||||||
for (size_t offset = 0; offset < chunk->count;) {
|
for (size_t offset = 0; offset < chunk->count;) {
|
||||||
offset = disasmInstr(chunk, offset, indent);
|
offset = disasmInstr(chunk, offset, indent);
|
||||||
@ -88,13 +94,13 @@ int disasmInstr(CChunk *chunk, int offset, int indent) {
|
|||||||
case OP_GETUPVAL:
|
case OP_GETUPVAL:
|
||||||
return u8OperandInstruction("OP_GETUPVAL", chunk, offset);
|
return u8OperandInstruction("OP_GETUPVAL", chunk, offset);
|
||||||
case OP_PEJMP:
|
case OP_PEJMP:
|
||||||
return u16OperandInstruction("OP_PEJMP", chunk, offset);
|
return JumpInstruction("OP_PEJMP", chunk, offset, 1);
|
||||||
case OP_EJMP:
|
case OP_EJMP:
|
||||||
return u16OperandInstruction("OP_EJMP", chunk, offset);
|
return JumpInstruction("OP_EJMP", chunk, offset, 1);
|
||||||
case OP_JMP:
|
case OP_JMP:
|
||||||
return u16OperandInstruction("OP_JMP", chunk, offset);
|
return JumpInstruction("OP_JMP", chunk, offset, 1);
|
||||||
case OP_JMPBACK:
|
case OP_JMPBACK:
|
||||||
return u16OperandInstruction("OP_JMPBACK", chunk, offset);
|
return JumpInstruction("OP_JMPBACK", chunk, offset, -1);
|
||||||
case OP_POP:
|
case OP_POP:
|
||||||
return u8OperandInstruction("OP_POP", chunk, offset);
|
return u8OperandInstruction("OP_POP", chunk, offset);
|
||||||
case OP_CALL:
|
case OP_CALL:
|
||||||
@ -133,10 +139,12 @@ int disasmInstr(CChunk *chunk, int offset, int indent) {
|
|||||||
return simpleInstruction("OP_NEWINDEX", offset);
|
return simpleInstruction("OP_NEWINDEX", offset);
|
||||||
case OP_NEWOBJECT:
|
case OP_NEWOBJECT:
|
||||||
return u16OperandInstruction("OP_NEWOBJECT", chunk, offset);
|
return u16OperandInstruction("OP_NEWOBJECT", chunk, offset);
|
||||||
case OP_GETOBJECT:
|
|
||||||
return constInstruction("OP_GETOBJECT", chunk, offset);
|
|
||||||
case OP_SETOBJECT:
|
case OP_SETOBJECT:
|
||||||
return constInstruction("OP_SETOBJECT", chunk, offset);
|
return constInstruction("OP_SETOBJECT", chunk, offset);
|
||||||
|
case OP_GETOBJECT:
|
||||||
|
return constInstruction("OP_GETOBJECT", chunk, offset);
|
||||||
|
case OP_GETMETHOD:
|
||||||
|
return constInstruction("OP_GETMETHOD", chunk, offset);
|
||||||
case OP_INVOKE:
|
case OP_INVOKE:
|
||||||
return u8u8u16OperandInstruction("OP_INVOKE", chunk, offset);
|
return u8u8u16OperandInstruction("OP_INVOKE", chunk, offset);
|
||||||
case OP_ITER:
|
case OP_ITER:
|
||||||
|
@ -6,4 +6,6 @@
|
|||||||
COSMO_API void disasmChunk(CChunk *chunk, const char *name, int indent);
|
COSMO_API void disasmChunk(CChunk *chunk, const char *name, int indent);
|
||||||
COSMO_API int disasmInstr(CChunk *chunk, int offset, int indent);
|
COSMO_API int disasmInstr(CChunk *chunk, int offset, int indent);
|
||||||
|
|
||||||
|
void printIndent(int indent);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#include "cstate.h"
|
#include "cstate.h"
|
||||||
|
|
||||||
//#define GC_STRESS
|
#define GC_STRESS
|
||||||
//#define GC_DEBUG
|
//#define GC_DEBUG
|
||||||
// arrays will grow by a factor of 2
|
// arrays will grow by a factor of 2
|
||||||
#define GROW_FACTOR 2
|
#define GROW_FACTOR 2
|
||||||
|
@ -111,7 +111,7 @@ typedef struct CObjUpval {
|
|||||||
|
|
||||||
#define IS_STRING(x) isObjType(x, COBJ_STRING)
|
#define IS_STRING(x) isObjType(x, COBJ_STRING)
|
||||||
#define IS_OBJECT(x) isObjType(x, COBJ_OBJECT)
|
#define IS_OBJECT(x) isObjType(x, COBJ_OBJECT)
|
||||||
#define IS_TABLE(x) isObjType(x, COBJ_TABLE)
|
#define IS_TABLE(x) isObjType(x, COBJ_TABLE)
|
||||||
#define IS_FUNCTION(x) isObjType(x, COBJ_FUNCTION)
|
#define IS_FUNCTION(x) isObjType(x, COBJ_FUNCTION)
|
||||||
#define IS_CFUNCTION(x) isObjType(x, COBJ_CFUNCTION)
|
#define IS_CFUNCTION(x) isObjType(x, COBJ_CFUNCTION)
|
||||||
#define IS_METHOD(x) isObjType(x, COBJ_METHOD)
|
#define IS_METHOD(x) isObjType(x, COBJ_METHOD)
|
||||||
@ -125,6 +125,8 @@ typedef struct CObjUpval {
|
|||||||
#define cosmoV_readMethod(x) ((CObjMethod*)cosmoV_readObj(x))
|
#define cosmoV_readMethod(x) ((CObjMethod*)cosmoV_readObj(x))
|
||||||
#define cosmoV_readClosure(x) ((CObjClosure*)cosmoV_readObj(x))
|
#define cosmoV_readClosure(x) ((CObjClosure*)cosmoV_readObj(x))
|
||||||
|
|
||||||
|
#define cosmoO_readCString(x) ((CObjString*)x)->str
|
||||||
|
|
||||||
static inline bool isObjType(CValue val, CObjType type) {
|
static inline bool isObjType(CValue val, CObjType type) {
|
||||||
return IS_OBJ(val) && cosmoV_readObj(val)->type == type;
|
return IS_OBJ(val) && cosmoV_readObj(val)->type == type;
|
||||||
}
|
}
|
||||||
@ -181,7 +183,7 @@ CObjString *cosmoO_allocateString(CState *state, const char *str, size_t sz, uin
|
|||||||
/*
|
/*
|
||||||
formats strings to push onto the VM stack, formatting supported:
|
formats strings to push onto the VM stack, formatting supported:
|
||||||
|
|
||||||
'%d' - decimal numbers [int]
|
'%d' - integers [int]
|
||||||
'%f' - floating point [double]
|
'%f' - floating point [double]
|
||||||
'%s' - strings [const char*]
|
'%s' - strings [const char*]
|
||||||
'%t' - cosmo tokens [CToken *]
|
'%t' - cosmo tokens [CToken *]
|
||||||
@ -191,8 +193,6 @@ CObjString *cosmoO_pushVFString(CState *state, const char *format, va_list args)
|
|||||||
COSMO_API void printObject(CObj *o);
|
COSMO_API void printObject(CObj *o);
|
||||||
const char *cosmoO_typeStr(CObj* obj);
|
const char *cosmoO_typeStr(CObj* obj);
|
||||||
|
|
||||||
#define cosmoO_readCString(x) ((CObjString*)x)->str
|
|
||||||
|
|
||||||
CObjString *cosmoO_toString(CState *state, CObj *obj);
|
CObjString *cosmoO_toString(CState *state, CObj *obj);
|
||||||
cosmo_Number cosmoO_toNumber(CState *state, CObj *obj);
|
cosmo_Number cosmoO_toNumber(CState *state, CObj *obj);
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ typedef enum {
|
|||||||
OP_NEWOBJECT,
|
OP_NEWOBJECT,
|
||||||
OP_SETOBJECT,
|
OP_SETOBJECT,
|
||||||
OP_GETOBJECT,
|
OP_GETOBJECT,
|
||||||
|
OP_GETMETHOD,
|
||||||
OP_INVOKE,
|
OP_INVOKE,
|
||||||
OP_ITER,
|
OP_ITER,
|
||||||
OP_NEXT,
|
OP_NEXT,
|
||||||
|
41
src/cparse.c
41
src/cparse.c
@ -31,7 +31,7 @@ typedef struct {
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FTYPE_FUNCTION,
|
FTYPE_FUNCTION,
|
||||||
FTYPE_METHOD, // a function bounded to an object (can use "this" identifer to access the current object :pog:)
|
FTYPE_METHOD,
|
||||||
FTYPE_SCRIPT
|
FTYPE_SCRIPT
|
||||||
} FunctionType;
|
} FunctionType;
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ typedef struct CCompilerState {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
CLexState *lex;
|
CLexState *lex;
|
||||||
CCompilerState *compiler;
|
CCompilerState *compiler;
|
||||||
CObjString *module; // name of the module (can be NULL)
|
CObjString *module; // name of the module
|
||||||
CState *state;
|
CState *state;
|
||||||
CToken current;
|
CToken current;
|
||||||
CToken previous; // token right after the current token
|
CToken previous; // token right after the current token
|
||||||
@ -747,28 +747,30 @@ static void _index(CParseState *pstate, bool canAssign, Precedence prec) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void invoke(CParseState *pstate, bool canAssign, Precedence prec) {
|
static void invoke(CParseState *pstate, bool canAssign, Precedence prec) {
|
||||||
int returnNum = pstate->compiler->expectedValues;
|
|
||||||
uint16_t name;
|
uint16_t name;
|
||||||
uint8_t args;
|
|
||||||
|
|
||||||
consume(pstate, TOKEN_IDENTIFIER, "Expected method name after ':'.");
|
consume(pstate, TOKEN_IDENTIFIER, "Expected method name after ':'.");
|
||||||
name = identifierConstant(pstate, &pstate->previous);
|
name = identifierConstant(pstate, &pstate->previous);
|
||||||
|
|
||||||
consume(pstate, TOKEN_LEFT_PAREN, "Expected '(' after method identifier!");
|
if (match(pstate, TOKEN_LEFT_PAREN)) { // invoke
|
||||||
args = parseArguments(pstate);
|
int returnNum = pstate->compiler->expectedValues;
|
||||||
|
uint8_t args = parseArguments(pstate);
|
||||||
|
|
||||||
// if we're not the last token in this expression or we're expecting multiple values, we should return only 1 value!!
|
// if we're not the last token in this expression or we're expecting multiple values, we should return only 1 value!!
|
||||||
if (!isLast(pstate, prec) || (returnNum > 1 && check(pstate, TOKEN_COMMA)))
|
if (!isLast(pstate, prec) || (returnNum > 1 && check(pstate, TOKEN_COMMA)))
|
||||||
returnNum = 1;
|
returnNum = 1;
|
||||||
|
|
||||||
writeu8(pstate, OP_INVOKE);
|
writeu8(pstate, OP_INVOKE);
|
||||||
writeu8(pstate, args);
|
writeu8(pstate, args);
|
||||||
writeu8(pstate, returnNum);
|
writeu8(pstate, returnNum);
|
||||||
writeu16(pstate, name);
|
writeu16(pstate, name);
|
||||||
|
|
||||||
valuePopped(pstate, args+1); // args + function
|
|
||||||
valuePushed(pstate, returnNum);
|
|
||||||
|
|
||||||
|
valuePopped(pstate, args+1); // args + function
|
||||||
|
valuePushed(pstate, returnNum);
|
||||||
|
} else { // just get the method
|
||||||
|
writeu8(pstate, OP_GETMETHOD);
|
||||||
|
writeu16(pstate, name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ++test.field[1]
|
// ++test.field[1]
|
||||||
@ -1570,10 +1572,9 @@ static void declaration(CParseState *pstate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static CObjFunction *endCompiler(CParseState *pstate) {
|
static CObjFunction *endCompiler(CParseState *pstate) {
|
||||||
popLocals(pstate, pstate->compiler->scopeDepth); // remove the locals from other scopes
|
popLocals(pstate, pstate->compiler->scopeDepth + 1); // remove the locals from other scopes
|
||||||
writeu8(pstate, OP_NIL);
|
|
||||||
writeu8(pstate, OP_RETURN);
|
writeu8(pstate, OP_RETURN);
|
||||||
writeu8(pstate, 1);
|
writeu8(pstate, 0);
|
||||||
|
|
||||||
// update pstate to next compiler state
|
// update pstate to next compiler state
|
||||||
CCompilerState *cachedCCState = pstate->compiler;
|
CCompilerState *cachedCCState = pstate->compiler;
|
||||||
|
169
src/cvm.c
169
src/cvm.c
@ -33,8 +33,9 @@ COSMO_API bool cosmoV_compileString(CState *state, const char *src, const char *
|
|||||||
|
|
||||||
if ((func = cosmoP_compileString(state, src, name)) != NULL) {
|
if ((func = cosmoP_compileString(state, src, name)) != NULL) {
|
||||||
// success
|
// success
|
||||||
|
#ifdef VM_DEBUG
|
||||||
disasmChunk(&func->chunk, func->module->str, 0);
|
disasmChunk(&func->chunk, func->module->str, 0);
|
||||||
|
#endif
|
||||||
// push function onto the stack so it doesn't it cleaned up by the GC, at the same stack location put our closure
|
// push function onto the stack so it doesn't it cleaned up by the GC, at the same stack location put our closure
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(func));
|
cosmoV_pushValue(state, cosmoV_newObj(func));
|
||||||
*(cosmoV_getTop(state, 0)) = cosmoV_newObj(cosmoO_newClosure(state, func));
|
*(cosmoV_getTop(state, 0)) = cosmoV_newObj(cosmoO_newClosure(state, func));
|
||||||
@ -296,6 +297,13 @@ static bool rawCall(CState *state, CObjClosure *closure, int args, int nresults,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool callCValue(CState *state, CValue func, int args, int nresults, int offset) {
|
bool callCValue(CState *state, CValue func, int args, int nresults, int offset) {
|
||||||
|
#ifdef VM_DEBUG
|
||||||
|
printf("\n");
|
||||||
|
printIndent(state->frameCount - 1);
|
||||||
|
printValue(func);
|
||||||
|
printf("()\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
if (GET_TYPE(func) != COSMO_TOBJ) {
|
if (GET_TYPE(func) != COSMO_TOBJ) {
|
||||||
cosmoV_error(state, "Cannot call non-function type %s!", cosmoV_typeStr(func));
|
cosmoV_error(state, "Cannot call non-function type %s!", cosmoV_typeStr(func));
|
||||||
return false;
|
return false;
|
||||||
@ -472,7 +480,10 @@ COSMO_API bool cosmoV_getMethod(CState *state, CObj *obj, CValue key, CValue *va
|
|||||||
|
|
||||||
// if the result is callable, wrap it in an method
|
// if the result is callable, wrap it in an method
|
||||||
if (IS_CALLABLE(*val)) {
|
if (IS_CALLABLE(*val)) {
|
||||||
|
// push object to stack so the GC can find it
|
||||||
|
cosmoV_pushValue(state, cosmoV_newObj(obj));
|
||||||
CObjMethod *method = cosmoO_newMethod(state, *val, obj);
|
CObjMethod *method = cosmoO_newMethod(state, *val, obj);
|
||||||
|
cosmoV_pop(state); // pop the object
|
||||||
*val = cosmoV_newObj(method);
|
*val = cosmoV_newObj(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -539,20 +550,22 @@ int cosmoV_execute(CState *state) {
|
|||||||
#define READUINT() (frame->pc += 2, *(uint16_t*)(&frame->pc[-2]))
|
#define READUINT() (frame->pc += 2, *(uint16_t*)(&frame->pc[-2]))
|
||||||
|
|
||||||
while (!state->panic) {
|
while (!state->panic) {
|
||||||
/*disasmInstr(&frame->closure->function->chunk, frame->pc - frame->closure->function->chunk.buf, 0);
|
#ifdef VM_DEBUG
|
||||||
printf("\n");*/
|
disasmInstr(&frame->closure->function->chunk, frame->pc - frame->closure->function->chunk.buf, state->frameCount - 1);
|
||||||
|
printf("\n");
|
||||||
|
#endif
|
||||||
switch (READBYTE()) {
|
switch (READBYTE()) {
|
||||||
case OP_LOADCONST: { // push const[uint] to stack
|
case OP_LOADCONST: { // push const[uint] to stack
|
||||||
uint16_t indx = READUINT();
|
uint16_t indx = READUINT();
|
||||||
cosmoV_pushValue(state, constants[indx]);
|
cosmoV_pushValue(state, constants[indx]);
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_SETGLOBAL: {
|
case OP_SETGLOBAL: {
|
||||||
uint16_t indx = READUINT();
|
uint16_t indx = READUINT();
|
||||||
CValue ident = constants[indx]; // grabs identifier
|
CValue ident = constants[indx]; // grabs identifier
|
||||||
CValue *val = cosmoT_insert(state, &state->globals, ident);
|
CValue *val = cosmoT_insert(state, &state->globals, ident);
|
||||||
*val = *cosmoV_pop(state); // sets the value in the hash table
|
*val = *cosmoV_pop(state); // sets the value in the hash table
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_GETGLOBAL: {
|
case OP_GETGLOBAL: {
|
||||||
uint16_t indx = READUINT();
|
uint16_t indx = READUINT();
|
||||||
@ -560,27 +573,27 @@ int cosmoV_execute(CState *state) {
|
|||||||
CValue val; // to hold our value
|
CValue val; // to hold our value
|
||||||
cosmoT_get(&state->globals, ident, &val);
|
cosmoT_get(&state->globals, ident, &val);
|
||||||
cosmoV_pushValue(state, val); // pushes the value to the stack
|
cosmoV_pushValue(state, val); // pushes the value to the stack
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_SETLOCAL: {
|
case OP_SETLOCAL: {
|
||||||
uint8_t indx = READBYTE();
|
uint8_t indx = READBYTE();
|
||||||
frame->base[indx] = *cosmoV_pop(state);
|
frame->base[indx] = *cosmoV_pop(state);
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_GETLOCAL: {
|
case OP_GETLOCAL: {
|
||||||
uint8_t indx = READBYTE();
|
uint8_t indx = READBYTE();
|
||||||
cosmoV_pushValue(state, frame->base[indx]);
|
cosmoV_pushValue(state, frame->base[indx]);
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_GETUPVAL: {
|
case OP_GETUPVAL: {
|
||||||
uint8_t indx = READBYTE();
|
uint8_t indx = READBYTE();
|
||||||
cosmoV_pushValue(state, *frame->closure->upvalues[indx]->val);
|
cosmoV_pushValue(state, *frame->closure->upvalues[indx]->val);
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_SETUPVAL: {
|
case OP_SETUPVAL: {
|
||||||
uint8_t indx = READBYTE();
|
uint8_t indx = READBYTE();
|
||||||
*frame->closure->upvalues[indx]->val = *cosmoV_pop(state);
|
*frame->closure->upvalues[indx]->val = *cosmoV_pop(state);
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_PEJMP: { // pop equality jump
|
case OP_PEJMP: { // pop equality jump
|
||||||
uint16_t offset = READUINT();
|
uint16_t offset = READUINT();
|
||||||
@ -588,7 +601,7 @@ int cosmoV_execute(CState *state) {
|
|||||||
if (isFalsey(cosmoV_pop(state))) { // pop, if the condition is false, jump!
|
if (isFalsey(cosmoV_pop(state))) { // pop, if the condition is false, jump!
|
||||||
frame->pc += offset;
|
frame->pc += offset;
|
||||||
}
|
}
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_EJMP: { // equality jump
|
case OP_EJMP: { // equality jump
|
||||||
uint16_t offset = READUINT();
|
uint16_t offset = READUINT();
|
||||||
@ -596,21 +609,21 @@ int cosmoV_execute(CState *state) {
|
|||||||
if (isFalsey(cosmoV_getTop(state, 0))) { // if the condition is false, jump!
|
if (isFalsey(cosmoV_getTop(state, 0))) { // if the condition is false, jump!
|
||||||
frame->pc += offset;
|
frame->pc += offset;
|
||||||
}
|
}
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_JMP: { // jump
|
case OP_JMP: { // jump
|
||||||
uint16_t offset = READUINT();
|
uint16_t offset = READUINT();
|
||||||
frame->pc += offset;
|
frame->pc += offset;
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_JMPBACK: {
|
case OP_JMPBACK: {
|
||||||
uint16_t offset = READUINT();
|
uint16_t offset = READUINT();
|
||||||
frame->pc -= offset;
|
frame->pc -= offset;
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_POP: { // pops value off the stack
|
case OP_POP: { // pops value off the stack
|
||||||
cosmoV_setTop(state, READBYTE());
|
cosmoV_setTop(state, READBYTE());
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_CALL: {
|
case OP_CALL: {
|
||||||
uint8_t args = READBYTE();
|
uint8_t args = READBYTE();
|
||||||
@ -618,7 +631,7 @@ int cosmoV_execute(CState *state) {
|
|||||||
if (cosmoV_call(state, args, nres) != COSMOVM_OK) {
|
if (cosmoV_call(state, args, nres) != COSMOVM_OK) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_CLOSURE: {
|
case OP_CLOSURE: {
|
||||||
uint16_t index = READUINT();
|
uint16_t index = READUINT();
|
||||||
@ -638,17 +651,17 @@ int cosmoV_execute(CState *state) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_CLOSE: {
|
case OP_CLOSE: {
|
||||||
closeUpvalues(state, state->top - 1);
|
closeUpvalues(state, state->top - 1);
|
||||||
cosmoV_pop(state);
|
cosmoV_pop(state);
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_NEWTABLE: {
|
case OP_NEWTABLE: {
|
||||||
uint16_t pairs = READUINT();
|
uint16_t pairs = READUINT();
|
||||||
cosmoV_makeTable(state, pairs);
|
cosmoV_makeTable(state, pairs);
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_NEWARRAY: {
|
case OP_NEWARRAY: {
|
||||||
uint16_t pairs = READUINT();
|
uint16_t pairs = READUINT();
|
||||||
@ -667,7 +680,7 @@ int cosmoV_execute(CState *state) {
|
|||||||
// once done, pop everything off the stack + push new table
|
// once done, pop everything off the stack + push new table
|
||||||
cosmoV_setTop(state, pairs + 1); // + 1 for our table
|
cosmoV_setTop(state, pairs + 1); // + 1 for our table
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(newObj));
|
cosmoV_pushValue(state, cosmoV_newObj(newObj));
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_INDEX: {
|
case OP_INDEX: {
|
||||||
StkPtr key = cosmoV_getTop(state, 0); // key should be the top of the stack
|
StkPtr key = cosmoV_getTop(state, 0); // key should be the top of the stack
|
||||||
@ -705,7 +718,7 @@ int cosmoV_execute(CState *state) {
|
|||||||
cosmoV_error(state, "Couldn't index type %s!", cosmoV_typeStr(*temp));
|
cosmoV_error(state, "Couldn't index type %s!", cosmoV_typeStr(*temp));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_NEWINDEX: {
|
case OP_NEWINDEX: {
|
||||||
StkPtr value = cosmoV_getTop(state, 0); // value is at the top of the stack
|
StkPtr value = cosmoV_getTop(state, 0); // value is at the top of the stack
|
||||||
@ -744,31 +757,12 @@ int cosmoV_execute(CState *state) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_NEWOBJECT: {
|
case OP_NEWOBJECT: {
|
||||||
uint16_t pairs = READUINT();
|
uint16_t pairs = READUINT();
|
||||||
cosmoV_makeObject(state, pairs);
|
cosmoV_makeObject(state, pairs);
|
||||||
break;
|
continue;
|
||||||
}
|
|
||||||
case OP_GETOBJECT: {
|
|
||||||
CValue val; // to hold our value
|
|
||||||
StkPtr temp = cosmoV_getTop(state, 0); // that should be the object
|
|
||||||
uint16_t ident = READUINT(); // use for the key
|
|
||||||
|
|
||||||
// sanity check
|
|
||||||
if (IS_OBJ(*temp)) {
|
|
||||||
if (!cosmoV_get(state, cosmoV_readObj(*temp), constants[ident], &val))
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
CObjString *field = cosmoV_toString(state, constants[ident]);
|
|
||||||
cosmoV_error(state, "Couldn't get field '%s' from type %s!", field->str, cosmoV_typeStr(*temp));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
cosmoV_setTop(state, 1); // pops the object
|
|
||||||
cosmoV_pushValue(state, val); // pushes the field result
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case OP_SETOBJECT: {
|
case OP_SETOBJECT: {
|
||||||
StkPtr value = cosmoV_getTop(state, 0); // value is at the top of the stack
|
StkPtr value = cosmoV_getTop(state, 0); // value is at the top of the stack
|
||||||
@ -787,7 +781,45 @@ int cosmoV_execute(CState *state) {
|
|||||||
|
|
||||||
// pop everything off the stack
|
// pop everything off the stack
|
||||||
cosmoV_setTop(state, 2);
|
cosmoV_setTop(state, 2);
|
||||||
break;
|
continue;
|
||||||
|
}
|
||||||
|
case OP_GETOBJECT: {
|
||||||
|
CValue val; // to hold our value
|
||||||
|
StkPtr temp = cosmoV_getTop(state, 0); // that should be the object
|
||||||
|
uint16_t ident = READUINT(); // use for the key
|
||||||
|
|
||||||
|
// sanity check
|
||||||
|
if (IS_OBJ(*temp)) {
|
||||||
|
if (!cosmoV_get(state, cosmoV_readObj(*temp), constants[ident], &val))
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
CObjString *field = cosmoV_toString(state, constants[ident]);
|
||||||
|
cosmoV_error(state, "Couldn't get field '%s' from type %s!", field->str, cosmoV_typeStr(*temp));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cosmoV_setTop(state, 1); // pops the object
|
||||||
|
cosmoV_pushValue(state, val); // pushes the field result
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case OP_GETMETHOD: {
|
||||||
|
CValue val; // to hold our value
|
||||||
|
StkPtr temp = cosmoV_getTop(state, 0); // that should be the object
|
||||||
|
uint16_t ident = READUINT(); // use for the key
|
||||||
|
|
||||||
|
// this is almost identical to GETOBJECT, however cosmoV_getMethod is used instead of just cosmoV_get
|
||||||
|
if (IS_OBJ(*temp)) {
|
||||||
|
if (!cosmoV_getMethod(state, cosmoV_readObj(*temp), constants[ident], &val))
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
CObjString *field = cosmoV_toString(state, constants[ident]);
|
||||||
|
cosmoV_error(state, "Couldn't get field '%s' from type %s!", field->str, cosmoV_typeStr(*temp));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cosmoV_setTop(state, 1); // pops the object
|
||||||
|
cosmoV_pushValue(state, val); // pushes the field result
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
case OP_INVOKE: {
|
case OP_INVOKE: {
|
||||||
uint8_t args = READBYTE();
|
uint8_t args = READBYTE();
|
||||||
@ -809,7 +841,7 @@ int cosmoV_execute(CState *state) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_ITER: {
|
case OP_ITER: {
|
||||||
StkPtr temp = cosmoV_getTop(state, 0); // should be the object/table
|
StkPtr temp = cosmoV_getTop(state, 0); // should be the object/table
|
||||||
@ -877,7 +909,7 @@ int cosmoV_execute(CState *state) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_NEXT: {
|
case OP_NEXT: {
|
||||||
uint8_t nresults = READBYTE();
|
uint8_t nresults = READBYTE();
|
||||||
@ -897,23 +929,23 @@ int cosmoV_execute(CState *state) {
|
|||||||
cosmoV_setTop(state, nresults); // pop the return values
|
cosmoV_setTop(state, nresults); // pop the return values
|
||||||
frame->pc += jump;
|
frame->pc += jump;
|
||||||
}
|
}
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_ADD: { // pop 2 values off the stack & try to add them together
|
case OP_ADD: { // pop 2 values off the stack & try to add them together
|
||||||
NUMBEROP(cosmoV_newNumber, +);
|
NUMBEROP(cosmoV_newNumber, +);
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_SUB: { // pop 2 values off the stack & try to subtracts them
|
case OP_SUB: { // pop 2 values off the stack & try to subtracts them
|
||||||
NUMBEROP(cosmoV_newNumber, -)
|
NUMBEROP(cosmoV_newNumber, -)
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_MULT: { // pop 2 values off the stack & try to multiplies them together
|
case OP_MULT: { // pop 2 values off the stack & try to multiplies them together
|
||||||
NUMBEROP(cosmoV_newNumber, *)
|
NUMBEROP(cosmoV_newNumber, *)
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_DIV: { // pop 2 values off the stack & try to divides them
|
case OP_DIV: { // pop 2 values off the stack & try to divides them
|
||||||
NUMBEROP(cosmoV_newNumber, /)
|
NUMBEROP(cosmoV_newNumber, /)
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_MOD: {
|
case OP_MOD: {
|
||||||
StkPtr valA = cosmoV_getTop(state, 1);
|
StkPtr valA = cosmoV_getTop(state, 1);
|
||||||
@ -925,11 +957,11 @@ int cosmoV_execute(CState *state) {
|
|||||||
cosmoV_error(state, "Expected numbers, got %s and %s!", cosmoV_typeStr(*valA), cosmoV_typeStr(*valB));
|
cosmoV_error(state, "Expected numbers, got %s and %s!", cosmoV_typeStr(*valA), cosmoV_typeStr(*valB));
|
||||||
return -1; \
|
return -1; \
|
||||||
} \
|
} \
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_NOT: {
|
case OP_NOT: {
|
||||||
cosmoV_pushBoolean(state, isFalsey(cosmoV_pop(state)));
|
cosmoV_pushBoolean(state, isFalsey(cosmoV_pop(state)));
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_NEGATE: { // pop 1 value off the stack & try to negate
|
case OP_NEGATE: { // pop 1 value off the stack & try to negate
|
||||||
StkPtr val = cosmoV_getTop(state, 0);
|
StkPtr val = cosmoV_getTop(state, 0);
|
||||||
@ -941,7 +973,7 @@ int cosmoV_execute(CState *state) {
|
|||||||
cosmoV_error(state, "Expected number, got %s!", cosmoV_typeStr(*val));
|
cosmoV_error(state, "Expected number, got %s!", cosmoV_typeStr(*val));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_COUNT: { // pop 1 value off the stack & if it's a table return the amount of active entries it has
|
case OP_COUNT: { // pop 1 value off the stack & if it's a table return the amount of active entries it has
|
||||||
StkPtr temp = cosmoV_getTop(state, 0);
|
StkPtr temp = cosmoV_getTop(state, 0);
|
||||||
@ -954,12 +986,12 @@ int cosmoV_execute(CState *state) {
|
|||||||
CObjTable *tbl = (CObjTable*)cosmoV_readObj(*temp);
|
CObjTable *tbl = (CObjTable*)cosmoV_readObj(*temp);
|
||||||
cosmoV_pop(state);
|
cosmoV_pop(state);
|
||||||
cosmoV_pushNumber(state, cosmoT_count(&tbl->tbl)); // pushes the count onto the stack
|
cosmoV_pushNumber(state, cosmoT_count(&tbl->tbl)); // pushes the count onto the stack
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_CONCAT: {
|
case OP_CONCAT: {
|
||||||
uint8_t vals = READBYTE();
|
uint8_t vals = READBYTE();
|
||||||
cosmoV_concat(state, vals);
|
cosmoV_concat(state, vals);
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_INCLOCAL: { // this leaves the value on the stack
|
case OP_INCLOCAL: { // this leaves the value on the stack
|
||||||
int8_t inc = READBYTE() - 128; // amount we're incrementing by
|
int8_t inc = READBYTE() - 128; // amount we're incrementing by
|
||||||
@ -975,7 +1007,7 @@ int cosmoV_execute(CState *state) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_INCGLOBAL: {
|
case OP_INCGLOBAL: {
|
||||||
int8_t inc = READBYTE() - 128; // amount we're incrementing by
|
int8_t inc = READBYTE() - 128; // amount we're incrementing by
|
||||||
@ -992,7 +1024,7 @@ int cosmoV_execute(CState *state) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_INCUPVAL: {
|
case OP_INCUPVAL: {
|
||||||
int8_t inc = READBYTE() - 128; // amount we're incrementing by
|
int8_t inc = READBYTE() - 128; // amount we're incrementing by
|
||||||
@ -1008,7 +1040,7 @@ int cosmoV_execute(CState *state) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_INCINDEX: {
|
case OP_INCINDEX: {
|
||||||
int8_t inc = READBYTE() - 128; // amount we're incrementing by
|
int8_t inc = READBYTE() - 128; // amount we're incrementing by
|
||||||
@ -1065,7 +1097,7 @@ int cosmoV_execute(CState *state) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_INCOBJECT: {
|
case OP_INCOBJECT: {
|
||||||
int8_t inc = READBYTE() - 128; // amount we're incrementing by
|
int8_t inc = READBYTE() - 128; // amount we're incrementing by
|
||||||
@ -1119,7 +1151,7 @@ int cosmoV_execute(CState *state) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_EQUAL: {
|
case OP_EQUAL: {
|
||||||
// pop vals
|
// pop vals
|
||||||
@ -1128,27 +1160,27 @@ int cosmoV_execute(CState *state) {
|
|||||||
|
|
||||||
// compare & push
|
// compare & push
|
||||||
cosmoV_pushBoolean(state, cosmoV_equal(*valA, *valB));
|
cosmoV_pushBoolean(state, cosmoV_equal(*valA, *valB));
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_GREATER: {
|
case OP_GREATER: {
|
||||||
NUMBEROP(cosmoV_newBoolean, >)
|
NUMBEROP(cosmoV_newBoolean, >)
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_LESS: {
|
case OP_LESS: {
|
||||||
NUMBEROP(cosmoV_newBoolean, <)
|
NUMBEROP(cosmoV_newBoolean, <)
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_GREATER_EQUAL: {
|
case OP_GREATER_EQUAL: {
|
||||||
NUMBEROP(cosmoV_newBoolean, >=)
|
NUMBEROP(cosmoV_newBoolean, >=)
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_LESS_EQUAL: {
|
case OP_LESS_EQUAL: {
|
||||||
NUMBEROP(cosmoV_newBoolean, <=)
|
NUMBEROP(cosmoV_newBoolean, <=)
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_TRUE: cosmoV_pushBoolean(state, true); break;
|
case OP_TRUE: cosmoV_pushBoolean(state, true); continue;
|
||||||
case OP_FALSE: cosmoV_pushBoolean(state, false); break;
|
case OP_FALSE: cosmoV_pushBoolean(state, false); continue;
|
||||||
case OP_NIL: cosmoV_pushValue(state, cosmoV_newNil()); break;
|
case OP_NIL: cosmoV_pushValue(state, cosmoV_newNil()); continue;
|
||||||
case OP_RETURN: {
|
case OP_RETURN: {
|
||||||
uint8_t res = READBYTE();
|
uint8_t res = READBYTE();
|
||||||
return res;
|
return res;
|
||||||
@ -1157,7 +1189,6 @@ int cosmoV_execute(CState *state) {
|
|||||||
CERROR("unknown opcode!");
|
CERROR("unknown opcode!");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
//cosmoV_printStack(state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef READBYTE
|
#undef READBYTE
|
||||||
|
Loading…
Reference in New Issue
Block a user