mirror of
https://github.com/CPunch/Cosmo.git
synced 2024-11-05 08:10:05 +00:00
minor refactoring, added inc and dec operators
This commit is contained in:
parent
3727d6bb7c
commit
46b99ab390
@ -8,8 +8,8 @@ class Test
|
||||
end
|
||||
end
|
||||
|
||||
-- stressing the GC
|
||||
for (var i = 0; ; i=i+1) do
|
||||
// stressing the GC
|
||||
for (var i = 0; ; i++) do
|
||||
var x = Test("Hello world " .. i)
|
||||
x.print()
|
||||
end
|
@ -1,7 +1,7 @@
|
||||
-- crafts a dummy class
|
||||
// crafts a dummy class
|
||||
class test end
|
||||
|
||||
-- instance of test
|
||||
// instance of test
|
||||
var obj = test()
|
||||
|
||||
test.__index = function(self, key)
|
||||
@ -11,4 +11,4 @@ test.__index = function(self, key)
|
||||
end
|
||||
end
|
||||
|
||||
print(obj["lol"]) -- should print 9001?
|
||||
print(obj["lol"]) // should print 9001?
|
48
src/cdebug.c
48
src/cdebug.c
@ -12,16 +12,26 @@ int simpleInstruction(const char *name, int offset) {
|
||||
return offset + 1; // consume opcode
|
||||
}
|
||||
|
||||
int shortOperandInstruction(const char *name, CChunk *chunk, int offset) {
|
||||
int u8OperandInstruction(const char *name, CChunk *chunk, int offset) {
|
||||
printf("%-16s [%03d]", name, readu8Chunk(chunk, offset + 1));
|
||||
return offset + 2;
|
||||
}
|
||||
|
||||
int longOperandInstruction(const char *name, CChunk *chunk, int offset) {
|
||||
int u16OperandInstruction(const char *name, CChunk *chunk, int offset) {
|
||||
printf("%-16s [%05d]", name, readu16Chunk(chunk, offset + 1));
|
||||
return offset + 1 + (sizeof(uint16_t) / sizeof(INSTRUCTION));
|
||||
}
|
||||
|
||||
int u8u8OperandInstruction(const char *name, CChunk *chunk, int offset) {
|
||||
printf("%-16s [%03d] [%03d]", name, readu8Chunk(chunk, offset + 1), readu8Chunk(chunk, offset + 2));
|
||||
return offset + 3; // op + u8 + u8
|
||||
}
|
||||
|
||||
int u8u16OperandInstruction(const char *name, CChunk *chunk, int offset) {
|
||||
printf("%-16s [%03d] [%05d]", name, readu8Chunk(chunk, offset + 1), readu16Chunk(chunk, offset + 2));
|
||||
return offset + 4; // op + u8 + u16
|
||||
}
|
||||
|
||||
int constInstruction(const char *name, CChunk *chunk, int offset, int indent) {
|
||||
int index = readu16Chunk(chunk, offset + 1);
|
||||
printf("%-16s [%05d] - ", name, index);
|
||||
@ -65,25 +75,25 @@ int disasmInstr(CChunk *chunk, int offset, int indent) {
|
||||
case OP_GETGLOBAL:
|
||||
return constInstruction("OP_GETGLOBAL", chunk, offset, indent);
|
||||
case OP_SETLOCAL:
|
||||
return shortOperandInstruction("OP_SETLOCAL", chunk, offset);
|
||||
return u8OperandInstruction("OP_SETLOCAL", chunk, offset);
|
||||
case OP_GETLOCAL:
|
||||
return shortOperandInstruction("OP_GETLOCAL", chunk, offset);
|
||||
return u8OperandInstruction("OP_GETLOCAL", chunk, offset);
|
||||
case OP_SETUPVAL:
|
||||
return shortOperandInstruction("OP_SETUPVAL", chunk, offset);
|
||||
return u8OperandInstruction("OP_SETUPVAL", chunk, offset);
|
||||
case OP_GETUPVAL:
|
||||
return shortOperandInstruction("OP_GETUPVAL", chunk, offset);
|
||||
return u8OperandInstruction("OP_GETUPVAL", chunk, offset);
|
||||
case OP_PEJMP:
|
||||
return longOperandInstruction("OP_PEJMP", chunk, offset);
|
||||
return u16OperandInstruction("OP_PEJMP", chunk, offset);
|
||||
case OP_EJMP:
|
||||
return longOperandInstruction("OP_EJMP", chunk, offset);
|
||||
return u16OperandInstruction("OP_EJMP", chunk, offset);
|
||||
case OP_JMP:
|
||||
return longOperandInstruction("OP_JMP", chunk, offset);
|
||||
return u16OperandInstruction("OP_JMP", chunk, offset);
|
||||
case OP_JMPBACK:
|
||||
return longOperandInstruction("OP_JMPBACK", chunk, offset);
|
||||
return u16OperandInstruction("OP_JMPBACK", chunk, offset);
|
||||
case OP_POP:
|
||||
return shortOperandInstruction("OP_POP", chunk, offset);
|
||||
return u8OperandInstruction("OP_POP", chunk, offset);
|
||||
case OP_CALL:
|
||||
return shortOperandInstruction("OP_CALL", chunk, offset);
|
||||
return u8OperandInstruction("OP_CALL", chunk, offset);
|
||||
case OP_CLOSURE: {
|
||||
int index = readu16Chunk(chunk, offset + 1);
|
||||
printf("%-16s [%05d] - ", "OP_CLOSURE", index);
|
||||
@ -109,13 +119,13 @@ int disasmInstr(CChunk *chunk, int offset, int indent) {
|
||||
case OP_CLOSE:
|
||||
return simpleInstruction("OP_CLOSE", offset);
|
||||
case OP_NEWOBJECT:
|
||||
return longOperandInstruction("OP_NEWOBJECT", chunk, offset);
|
||||
return u16OperandInstruction("OP_NEWOBJECT", chunk, offset);
|
||||
case OP_GETOBJECT:
|
||||
return simpleInstruction("OP_GETOBJECT", offset);
|
||||
case OP_SETOBJECT:
|
||||
return simpleInstruction("OP_SETOBJECT", offset);
|
||||
case OP_INVOKE:
|
||||
return shortOperandInstruction("OP_INVOKE", chunk, offset);
|
||||
return u8OperandInstruction("OP_INVOKE", chunk, offset);
|
||||
case OP_ADD:
|
||||
return simpleInstruction("OP_ADD", offset);
|
||||
case OP_SUB:
|
||||
@ -145,7 +155,15 @@ int disasmInstr(CChunk *chunk, int offset, int indent) {
|
||||
case OP_NEGATE:
|
||||
return simpleInstruction("OP_NEGATE", offset);
|
||||
case OP_CONCAT:
|
||||
return shortOperandInstruction("OP_CONCAT", chunk, offset);
|
||||
return u8OperandInstruction("OP_CONCAT", chunk, offset);
|
||||
case OP_INCLOCAL:
|
||||
return u8u8OperandInstruction("OP_INCLOCAL", chunk, offset);
|
||||
case OP_INCGLOBAL:
|
||||
return u8u16OperandInstruction("OP_INCGLOBAL", chunk, offset);
|
||||
case OP_INCUPVAL:
|
||||
return u8u8OperandInstruction("OP_INCLOCAL", chunk, offset);
|
||||
case OP_INCOBJECT:
|
||||
return u8u16OperandInstruction("OP_INCOBJECT", chunk, offset);
|
||||
case OP_RETURN:
|
||||
return simpleInstruction("OP_RETURN", offset);
|
||||
default:
|
||||
|
11
src/clex.c
11
src/clex.c
@ -109,8 +109,8 @@ void skipWhitespace(CLexState *state) {
|
||||
case '\t':
|
||||
next(state); // consume the whitespace
|
||||
break;
|
||||
case '-': // consume comments
|
||||
if (peekNext(state) == '-') {
|
||||
case '/': // consume comments
|
||||
if (peekNext(state) == '/') {
|
||||
|
||||
// skip to next line (also let \n be consumed on the next iteration to properly handle that)
|
||||
while (!isEnd(state) && peek(state) != '\n' && peek(state) != '\0') // if it's not a newline or null terminator
|
||||
@ -196,14 +196,15 @@ CToken cosmoL_scanToken(CLexState *state) {
|
||||
case '}': return makeToken(state, TOKEN_RIGHT_BRACE);
|
||||
case '[': return makeToken(state, TOKEN_LEFT_BRACKET);
|
||||
case ']': return makeToken(state, TOKEN_RIGHT_BRACKET);
|
||||
// fall through
|
||||
case ';': return makeToken(state, TOKEN_EOS);
|
||||
case ',': return makeToken(state, TOKEN_COMMA);
|
||||
case '+': return makeToken(state, TOKEN_PLUS);
|
||||
case '-': return makeToken(state, TOKEN_MINUS);
|
||||
case '*': return makeToken(state, TOKEN_STAR);
|
||||
case '/': return makeToken(state, TOKEN_SLASH);
|
||||
// two character tokens
|
||||
case '+':
|
||||
return match(state, '+') ? makeToken(state, TOKEN_PLUS_PLUS) : makeToken(state, TOKEN_PLUS);
|
||||
case '-':
|
||||
return match(state, '-') ? makeToken(state, TOKEN_MINUS_MINUS) : makeToken(state, TOKEN_MINUS);
|
||||
case '.':
|
||||
return match(state, '.') ? makeToken(state, TOKEN_DOT_DOT) : makeToken(state, TOKEN_DOT);
|
||||
case '!':
|
||||
|
@ -15,7 +15,9 @@ typedef enum {
|
||||
TOKEN_DOT,
|
||||
TOKEN_DOT_DOT,
|
||||
TOKEN_MINUS,
|
||||
TOKEN_MINUS_MINUS,
|
||||
TOKEN_PLUS,
|
||||
TOKEN_PLUS_PLUS,
|
||||
TOKEN_SLASH,
|
||||
TOKEN_STAR,
|
||||
TOKEN_EOS, // end of statement
|
||||
|
@ -76,6 +76,8 @@ void tableRemoveWhite(CState *state, CTable *tbl) {
|
||||
cosmoT_remove(state, tbl, entry->key);
|
||||
}
|
||||
}
|
||||
|
||||
cosmoT_checkShrink(state, tbl); // recovers the memory we're no longer using
|
||||
}
|
||||
|
||||
void markArray(CState *state, CValueArray *array) {
|
||||
|
@ -36,13 +36,16 @@
|
||||
|
||||
#define cosmoM_unfreezeGC(state) \
|
||||
state->freezeGC--; \
|
||||
printf("unfreezing state at %s:%d [%d]\n", __FILE__, __LINE__, state->freezeGC)
|
||||
printf("unfreezing state at %s:%d [%d]\n", __FILE__, __LINE__, state->freezeGC); \
|
||||
cosmoM_checkGarbage(state, 0)
|
||||
#else
|
||||
#define cosmoM_freezeGC(state) \
|
||||
state->freezeGC++
|
||||
|
||||
#define cosmoM_unfreezeGC(state) \
|
||||
state->freezeGC--
|
||||
state->freezeGC--; \
|
||||
cosmoM_checkGarbage(state, 0)
|
||||
|
||||
#endif
|
||||
|
||||
COSMO_API void *cosmoM_reallocate(CState *state, void *buf, size_t oldSize, size_t newSize);
|
||||
|
@ -29,7 +29,7 @@ typedef enum {
|
||||
OP_CALL, // calls top[-uint8_t]
|
||||
OP_CLOSURE,
|
||||
OP_CLOSE,
|
||||
OP_NEWOBJECT, //
|
||||
OP_NEWOBJECT,
|
||||
OP_GETOBJECT,
|
||||
OP_SETOBJECT,
|
||||
OP_INVOKE,
|
||||
@ -42,6 +42,10 @@ typedef enum {
|
||||
OP_NOT,
|
||||
OP_NEGATE,
|
||||
OP_CONCAT, // concats uint8_t vars on the stack
|
||||
OP_INCLOCAL, // pushes old value to stack, adds (uint8_t-128) to local[uint8_t]
|
||||
OP_INCGLOBAL, // pushes old value to stack, adds (uint8_t-128) to globals[const[uint16_t]]
|
||||
OP_INCUPVAL, // pushes old value to stack, adds (uint8_t-128) to closure->upval[uint8_t]
|
||||
OP_INCOBJECT, // pushes old value to stack, adds (uint8_t-128) to obj[const[uint16_t]]
|
||||
|
||||
// EQUALITY
|
||||
OP_EQUAL,
|
||||
@ -56,7 +60,6 @@ typedef enum {
|
||||
OP_NIL,
|
||||
|
||||
OP_RETURN
|
||||
|
||||
} COPCODE;
|
||||
} COPCODE; // there can be a max of 256 instructions
|
||||
|
||||
#endif
|
108
src/cparse.c
108
src/cparse.c
@ -130,9 +130,7 @@ static void errorAt(CParseState *pstate, CToken *token, const char * msg) {
|
||||
|
||||
if (token->type == TOKEN_EOF) {
|
||||
fprintf(stderr, " at end");
|
||||
} else if (token->type == TOKEN_ERROR) {
|
||||
|
||||
} else {
|
||||
} else if (!(token->type == TOKEN_ERROR)) {
|
||||
fprintf(stderr, " at '%.*s'", token->length, token->start);
|
||||
}
|
||||
|
||||
@ -446,22 +444,25 @@ static void _etterOP(CParseState *pstate, uint8_t op, int arg) {
|
||||
writeu8(pstate, arg);
|
||||
}
|
||||
|
||||
static void namedVariable(CParseState *pstate, CToken name, bool canAssign) {
|
||||
uint8_t opGet, opSet;
|
||||
static void namedVariable(CParseState *pstate, CToken name, bool canAssign, bool canIncrement) {
|
||||
uint8_t opGet, opSet, inc;
|
||||
int arg = getLocal(pstate->compiler, &name);
|
||||
|
||||
if (arg != -1) {
|
||||
// we found it in out local table!
|
||||
opGet = OP_GETLOCAL;
|
||||
opSet = OP_SETLOCAL;
|
||||
inc = OP_INCLOCAL;
|
||||
} else if ((arg = getUpvalue(pstate->compiler, &name)) != -1) {
|
||||
opGet = OP_GETUPVAL;
|
||||
opSet = OP_SETUPVAL;
|
||||
inc = OP_INCUPVAL;
|
||||
} else {
|
||||
// local & upvalue wasnt' found, assume it's a global!
|
||||
arg = identifierConstant(pstate, &name);
|
||||
opGet = OP_GETGLOBAL;
|
||||
opSet = OP_SETGLOBAL;
|
||||
inc = OP_INCGLOBAL;
|
||||
}
|
||||
|
||||
if (canAssign && match(pstate, TOKEN_EQUAL)) {
|
||||
@ -469,6 +470,24 @@ static void namedVariable(CParseState *pstate, CToken name, bool canAssign) {
|
||||
expression(pstate);
|
||||
_etterOP(pstate, opSet, arg);
|
||||
valuePopped(pstate, 1);
|
||||
} else if (canIncrement && match(pstate, TOKEN_PLUS_PLUS)) { // i++
|
||||
// now we increment the value
|
||||
writeu8(pstate, inc);
|
||||
writeu8(pstate, 128 + 1); // setting signed values in an unsigned int
|
||||
if (inc == OP_INCGLOBAL) // globals are stored with a u16
|
||||
writeu16(pstate, arg);
|
||||
else
|
||||
writeu8(pstate, arg);
|
||||
valuePushed(pstate, 1);
|
||||
} else if (canIncrement && match(pstate, TOKEN_MINUS_MINUS)) { // i--
|
||||
// now we increment the value
|
||||
writeu8(pstate, inc);
|
||||
writeu8(pstate, 128 - 1); // setting signed values in an unsigned int
|
||||
if (inc == OP_INCGLOBAL) // globals are stored with a u16
|
||||
writeu16(pstate, arg);
|
||||
else
|
||||
writeu8(pstate, arg);
|
||||
valuePushed(pstate, 1);
|
||||
} else {
|
||||
// getter
|
||||
_etterOP(pstate, opGet, arg);
|
||||
@ -502,7 +521,7 @@ static void anonFunction(CParseState *pstate, bool canAssign) {
|
||||
}
|
||||
|
||||
static void variable(CParseState *pstate, bool canAssign) {
|
||||
namedVariable(pstate, pstate->previous, canAssign);
|
||||
namedVariable(pstate, pstate->previous, canAssign, true);
|
||||
}
|
||||
|
||||
static void concat(CParseState *pstate, bool canAssign) {
|
||||
@ -577,19 +596,31 @@ static void object(CParseState *pstate, bool canAssign) {
|
||||
static void dot(CParseState *pstate, bool canAssign) {
|
||||
consume(pstate, TOKEN_IDENTIFIER, "Expected property name after '.'.");
|
||||
uint16_t name = identifierConstant(pstate, &pstate->previous);
|
||||
writeu8(pstate, OP_LOADCONST);
|
||||
writeu16(pstate, name);
|
||||
|
||||
if (canAssign && match(pstate, TOKEN_EQUAL)) {
|
||||
writeu8(pstate, OP_LOADCONST);
|
||||
writeu16(pstate, name);
|
||||
expression(pstate);
|
||||
writeu8(pstate, OP_SETOBJECT);
|
||||
valuePopped(pstate, 2); // pops key, value & object
|
||||
} else if (match(pstate, TOKEN_PLUS_PLUS)) { // increment the field
|
||||
writeu8(pstate, OP_INCOBJECT);
|
||||
writeu8(pstate, 128 + 1);
|
||||
writeu16(pstate, name);
|
||||
} else if (match(pstate, TOKEN_MINUS_MINUS)) { // decrement the field
|
||||
writeu8(pstate, OP_INCOBJECT);
|
||||
writeu8(pstate, 128 - 1);
|
||||
writeu16(pstate, name);
|
||||
} else if (match(pstate, TOKEN_LEFT_PAREN)) { // it's an invoked call
|
||||
writeu8(pstate, OP_LOADCONST);
|
||||
writeu16(pstate, name);
|
||||
uint8_t args = parseArguments(pstate);
|
||||
writeu8(pstate, OP_INVOKE);
|
||||
writeu8(pstate, args);
|
||||
valuePopped(pstate, args); // pops the function & the object but pushes a result
|
||||
} else {
|
||||
writeu8(pstate, OP_LOADCONST);
|
||||
writeu16(pstate, name);
|
||||
writeu8(pstate, OP_GETOBJECT);
|
||||
// pops key & object but also pushes the field so total popped is 1
|
||||
}
|
||||
@ -609,6 +640,63 @@ static void _index(CParseState *pstate, bool canAssign) {
|
||||
}
|
||||
}
|
||||
|
||||
static void increment(CParseState *pstate, int val) {
|
||||
CToken name = pstate->previous;
|
||||
if (match(pstate, TOKEN_DOT)) { // object?
|
||||
namedVariable(pstate, name, false, false); // just get the object
|
||||
|
||||
consume(pstate, TOKEN_IDENTIFIER, "Expected property name after '.'.");
|
||||
uint16_t name = identifierConstant(pstate, &pstate->previous);
|
||||
|
||||
writeu8(pstate, OP_INCOBJECT);
|
||||
writeu8(pstate, 128 + val); // setting signed values in an unsigned int
|
||||
writeu16(pstate, name);
|
||||
valuePopped(pstate, 1); // popped the object off the stack
|
||||
} else {
|
||||
uint8_t op;
|
||||
int arg = getLocal(pstate->compiler, &name);
|
||||
|
||||
if (arg != -1) {
|
||||
// we found it in out local table!
|
||||
op = OP_INCLOCAL;
|
||||
} else if ((arg = getUpvalue(pstate->compiler, &name)) != -1) {
|
||||
op = OP_INCUPVAL;
|
||||
} else {
|
||||
// local & upvalue wasnt' found, assume it's a global!
|
||||
arg = identifierConstant(pstate, &name);
|
||||
op = OP_INCGLOBAL;
|
||||
}
|
||||
|
||||
writeu8(pstate, op);
|
||||
writeu8(pstate, 128 + val); // setting signed values in an unsigned int
|
||||
if (op == OP_INCGLOBAL) // globals are stored with a u16
|
||||
writeu16(pstate, arg);
|
||||
else
|
||||
writeu8(pstate, arg);
|
||||
}
|
||||
|
||||
// increment the old value on the stack
|
||||
writeConstant(pstate, cosmoV_newNumber(val));
|
||||
writeu8(pstate, OP_ADD);
|
||||
}
|
||||
|
||||
// ++i
|
||||
static void preincrement(CParseState *pstate, bool canAssign) {
|
||||
// expect identifier
|
||||
consume(pstate, TOKEN_IDENTIFIER, "Expected identifier after '++'");
|
||||
|
||||
increment(pstate, 1);
|
||||
}
|
||||
|
||||
// --i
|
||||
static void predecrement(CParseState *pstate, bool canAssign) {
|
||||
// expect identifier
|
||||
consume(pstate, TOKEN_IDENTIFIER, "Expected identifier after '--'");
|
||||
|
||||
increment(pstate, -1);
|
||||
}
|
||||
|
||||
|
||||
ParseRule ruleTable[] = {
|
||||
[TOKEN_LEFT_PAREN] = {group, call_, PREC_CALL},
|
||||
[TOKEN_RIGHT_PAREN] = {NULL, NULL, PREC_NONE},
|
||||
@ -620,7 +708,9 @@ ParseRule ruleTable[] = {
|
||||
[TOKEN_DOT] = {NULL, dot, PREC_CALL},
|
||||
[TOKEN_DOT_DOT] = {NULL, concat, PREC_CONCAT},
|
||||
[TOKEN_MINUS] = {unary, binary, PREC_TERM},
|
||||
[TOKEN_MINUS_MINUS] = {predecrement, NULL, PREC_TERM},
|
||||
[TOKEN_PLUS] = {NULL, binary, PREC_TERM},
|
||||
[TOKEN_PLUS_PLUS] = {preincrement, NULL, PREC_TERM},
|
||||
[TOKEN_SLASH] = {NULL, binary, PREC_FACTOR},
|
||||
[TOKEN_STAR] = {NULL, binary, PREC_FACTOR},
|
||||
[TOKEN_EOS] = {NULL, NULL, PREC_NONE},
|
||||
@ -996,7 +1086,9 @@ static void forLoop(CParseState *pstate) {
|
||||
int bodyJmp = writeJmp(pstate, OP_JMP);
|
||||
|
||||
int iteratorStart = getChunk(pstate)->count;
|
||||
int savedPushed = pstate->compiler->pushedValues;
|
||||
expression(pstate);
|
||||
alignStack(pstate, savedPushed);
|
||||
consume(pstate, TOKEN_RIGHT_PAREN, "Expected ')' after iterator");
|
||||
|
||||
writeJmpBack(pstate, loopStart);
|
||||
|
19
src/ctable.c
19
src/ctable.c
@ -109,16 +109,11 @@ static CTableEntry *findEntry(CTableEntry *entries, int mask, CValue key) {
|
||||
|
||||
static void resizeTbl(CState *state, CTable *tbl, size_t newCapacity) {
|
||||
size_t size = sizeof(CTableEntry) * newCapacity;
|
||||
int cachedCount = tbl->count;
|
||||
cosmoM_checkGarbage(state, size); // if this allocation would cause a GC, run the GC
|
||||
|
||||
// if count > 8 and active entries < tombstones
|
||||
if (tbl->count > MIN_TABLE_CAPACITY && tbl->count - tbl->tombstones < tbl->tombstones) {
|
||||
int tombs = tbl->tombstones;
|
||||
tbl->tombstones = 0; // set this to 0 so in our recursive call to resizeTbl() this branch isn't run again
|
||||
resizeTbl(state, tbl, nextPow2((tbl->count - tombs) * GROW_FACTOR)); // shrink based on active entries to the next pow of 2
|
||||
cosmoM_updateThreshhold(state); // force a threshhold update since this *could* be such a huge memory difference
|
||||
if (tbl->count < cachedCount) // the GC removed some objects from this table and resized it, ignore our resize event!
|
||||
return;
|
||||
}
|
||||
|
||||
CTableEntry *entries = cosmoM_xmalloc(state, size);
|
||||
int newCount = 0;
|
||||
@ -151,6 +146,16 @@ static void resizeTbl(CState *state, CTable *tbl, size_t newCapacity) {
|
||||
tbl->tombstones = 0;
|
||||
}
|
||||
|
||||
bool cosmoT_checkShrink(CState *state, CTable *tbl) {
|
||||
// if count > 8 and active entries < tombstones
|
||||
if (tbl->count > MIN_TABLE_CAPACITY && tbl->count - tbl->tombstones < tbl->tombstones) {
|
||||
resizeTbl(state, tbl, nextPow2((tbl->count - tbl->tombstones) * GROW_FACTOR)); // shrink based on active entries to the next pow of 2
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// returns a pointer to the allocated value
|
||||
COSMO_API CValue* cosmoT_insert(CState *state, CTable *tbl, CValue key) {
|
||||
// make sure we have enough space allocated
|
||||
|
@ -22,6 +22,7 @@ COSMO_API void cosmoT_addTable(CState *state, CTable *from, CTable *to);
|
||||
COSMO_API CValue *cosmoT_insert(CState *state, CTable *tbl, CValue key);
|
||||
|
||||
CObjString *cosmoT_lookupString(CTable *tbl, const char *str, size_t length, uint32_t hash);
|
||||
bool cosmoT_checkShrink(CState *state, CTable *tbl);
|
||||
bool cosmoT_get(CTable *tbl, CValue key, CValue *val);
|
||||
bool cosmoT_remove(CState *state, CTable *tbl, CValue key);
|
||||
|
||||
|
74
src/cvm.c
74
src/cvm.c
@ -498,6 +498,80 @@ bool cosmoV_execute(CState *state) {
|
||||
cosmoV_pushValue(state, cosmoV_newObj(result));
|
||||
break;
|
||||
}
|
||||
case OP_INCLOCAL: { // this leaves the value on the stack
|
||||
int8_t inc = READBYTE() - 128; // ammount we're incrementing by
|
||||
uint8_t indx = READBYTE();
|
||||
StkPtr val = &frame->base[indx];
|
||||
|
||||
// check that it's a number value
|
||||
if (val->type == COSMO_TNUMBER) {
|
||||
cosmoV_pushValue(state, *val); // pushes old value onto the stack :)
|
||||
*val = cosmoV_newNumber(val->val.num + inc);
|
||||
} else {
|
||||
cosmoV_error(state, "Expected number!");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case OP_INCGLOBAL: {
|
||||
int8_t inc = READBYTE() - 128; // ammount we're incrementing by
|
||||
uint16_t indx = READUINT();
|
||||
CValue ident = constants[indx]; // grabs identifier
|
||||
CValue *val = cosmoT_insert(state, &state->globals, ident);
|
||||
|
||||
// check that it's a number value
|
||||
if (val->type == COSMO_TNUMBER) {
|
||||
cosmoV_pushValue(state, *val); // pushes old value onto the stack :)
|
||||
*val = cosmoV_newNumber(val->val.num + inc);
|
||||
} else {
|
||||
cosmoV_error(state, "Expected number!");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case OP_INCUPVAL: {
|
||||
int8_t inc = READBYTE() - 128; // ammount we're incrementing by
|
||||
uint8_t indx = READBYTE();
|
||||
CValue *val = frame->closure->upvalues[indx]->val;
|
||||
|
||||
// check that it's a number value
|
||||
if (val->type == COSMO_TNUMBER) {
|
||||
cosmoV_pushValue(state, *val); // pushes old value onto the stack :)
|
||||
*val = cosmoV_newNumber(val->val.num + inc);
|
||||
} else {
|
||||
cosmoV_error(state, "Expected number!");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case OP_INCOBJECT: {
|
||||
int8_t inc = READBYTE() - 128; // ammount we're incrementing by
|
||||
uint16_t indx = READUINT();
|
||||
StkPtr temp = cosmoV_getTop(state, 0); // object should be at the top of the stack
|
||||
CValue ident = constants[indx]; // grabs identifier
|
||||
|
||||
// sanity check
|
||||
if (!(temp->type == COSMO_TOBJ) || !(temp->val.obj->type == COBJ_OBJECT)) {
|
||||
cosmoV_error(state, "Couldn't set a field on a non-object!");
|
||||
break;
|
||||
}
|
||||
|
||||
CObjObject *object = (CObjObject*)temp->val.obj;
|
||||
CValue *val = cosmoT_insert(state, &object->tbl, ident);
|
||||
|
||||
// pop the object off the stack
|
||||
cosmoV_pop(state);
|
||||
|
||||
// check that it's a number value
|
||||
if (val->type == COSMO_TNUMBER) {
|
||||
cosmoV_pushValue(state, *val); // pushes old value onto the stack :)
|
||||
*val = cosmoV_newNumber(val->val.num + inc);
|
||||
} else {
|
||||
cosmoV_error(state, "Expected number!");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case OP_EQUAL: {
|
||||
// pop vals
|
||||
StkPtr valB = cosmoV_pop(state);
|
||||
|
Loading…
Reference in New Issue
Block a user