mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 14:54:07 +10:00
Increment and decrement operators work
This commit is contained in:
@@ -147,6 +147,30 @@ static int writeLiteralTypeToCache(LiteralArray* literalCache, Literal literal)
|
||||
return pushLiteralArray(literalCache, lit);
|
||||
}
|
||||
|
||||
static int writeLiteralToCompiler(Compiler* compiler, Literal literal) {
|
||||
//get the index
|
||||
int index = findLiteralIndex(&compiler->literalCache, literal);
|
||||
if (index < 0) {
|
||||
index = pushLiteralArray(&compiler->literalCache, literal);
|
||||
}
|
||||
|
||||
//push the literal to the bytecode
|
||||
if (index >= 256) {
|
||||
//push a "long" index
|
||||
compiler->bytecode[compiler->count++] = OP_LITERAL_LONG; //1 byte
|
||||
*((unsigned short*)(compiler->bytecode + compiler->count)) = (unsigned short)index; //2 bytes
|
||||
|
||||
compiler->count += sizeof(unsigned short);
|
||||
}
|
||||
else {
|
||||
//push the index
|
||||
compiler->bytecode[compiler->count++] = OP_LITERAL; //1 byte
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)index; //1 byte
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAddressesPtr, void* continueAddressesPtr) {
|
||||
//grow if the bytecode space is too small
|
||||
if (compiler->capacity < compiler->count + 1) {
|
||||
@@ -166,25 +190,7 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd
|
||||
break;
|
||||
|
||||
case NODE_LITERAL: {
|
||||
//ensure the literal is in the cache
|
||||
int index = findLiteralIndex(&compiler->literalCache, node->atomic.literal);
|
||||
if (index < 0) {
|
||||
index = pushLiteralArray(&compiler->literalCache, node->atomic.literal);
|
||||
}
|
||||
|
||||
//push the node opcode to the bytecode
|
||||
if (index >= 256) {
|
||||
//push a "long" index
|
||||
compiler->bytecode[compiler->count++] = OP_LITERAL_LONG; //1 byte
|
||||
*((unsigned short*)(compiler->bytecode + compiler->count)) = (unsigned short)index; //2 bytes
|
||||
|
||||
compiler->count += sizeof(unsigned short);
|
||||
}
|
||||
else {
|
||||
//push the index
|
||||
compiler->bytecode[compiler->count++] = OP_LITERAL; //1 byte
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)index; //1 byte
|
||||
}
|
||||
writeLiteralToCompiler(compiler, node->atomic.literal);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -461,6 +467,48 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd
|
||||
compiler->count += sizeof(unsigned short); //2 bytes
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_INCREMENT_PREFIX: {
|
||||
//push the literal to the stack (twice)
|
||||
writeLiteralToCompiler(compiler, node->increment.identifier);
|
||||
writeLiteralToCompiler(compiler, node->increment.identifier);
|
||||
|
||||
//push the increment / decrement
|
||||
Literal increment = TO_INTEGER_LITERAL(node->increment.increment);
|
||||
writeLiteralToCompiler(compiler, increment);
|
||||
|
||||
//push the add opcode
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)OP_ADDITION; //1 byte
|
||||
|
||||
//push the assign
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)OP_VAR_ASSIGN; //1 byte
|
||||
|
||||
//leave the result on the stack
|
||||
writeLiteralToCompiler(compiler, node->increment.identifier);
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)OP_LITERAL_RAW; //1 byte
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_INCREMENT_POSTFIX: {
|
||||
//push the identifier's VALUE to the stack
|
||||
writeLiteralToCompiler(compiler, node->increment.identifier);
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)OP_LITERAL_RAW; //1 byte
|
||||
|
||||
//push the identifier (twice)
|
||||
writeLiteralToCompiler(compiler, node->increment.identifier);
|
||||
writeLiteralToCompiler(compiler, node->increment.identifier);
|
||||
|
||||
//push the increment / decrement
|
||||
Literal increment = TO_INTEGER_LITERAL(node->increment.increment);
|
||||
writeLiteralToCompiler(compiler, increment);
|
||||
|
||||
//push the add opcode
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)OP_ADDITION; //1 byte
|
||||
|
||||
//push the assign
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)OP_VAR_ASSIGN; //1 byte
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -176,6 +176,18 @@ static bool execPushLiteral(Interpreter* interpreter, bool lng) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool rawLiteral(Interpreter* interpreter) {
|
||||
Literal lit = popLiteralArray(&interpreter->stack);
|
||||
|
||||
if (!parseIdentifierToValue(interpreter, &lit)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pushLiteralArray(&interpreter->stack, lit);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool execNegate(Interpreter* interpreter) {
|
||||
//negate the top literal on the stack (numbers only)
|
||||
Literal lit = popLiteralArray(&interpreter->stack);
|
||||
@@ -657,6 +669,12 @@ static void execInterpreter(Interpreter* interpreter) {
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_LITERAL_RAW:
|
||||
if (!rawLiteral(interpreter)) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_NEGATE:
|
||||
if (!execNegate(interpreter)) {
|
||||
return;
|
||||
|
||||
@@ -73,6 +73,11 @@ void freeNode(Node* node) {
|
||||
freeNode(node->path.thenPath);
|
||||
freeNode(node->path.elsePath);
|
||||
break;
|
||||
|
||||
case NODE_INCREMENT_PREFIX:
|
||||
case NODE_INCREMENT_POSTFIX:
|
||||
freeLiteral(node->increment.identifier);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,6 +184,26 @@ void emitNodePath(Node** nodeHandle, NodeType type, Node* preClause, Node* postC
|
||||
*nodeHandle = tmp;
|
||||
}
|
||||
|
||||
void emiteNodePrefixIncrement(Node** nodeHandle, Literal identifier, int increment) {
|
||||
Node* tmp = ALLOCATE(Node, 1);
|
||||
|
||||
tmp->type = NODE_INCREMENT_PREFIX;
|
||||
tmp->increment.identifier = identifier;
|
||||
tmp->increment.increment = increment;
|
||||
|
||||
*nodeHandle = tmp;
|
||||
}
|
||||
|
||||
void emiteNodePostfixIncrement(Node** nodeHandle, Literal identifier, int increment) {
|
||||
Node* tmp = ALLOCATE(Node, 1);
|
||||
|
||||
tmp->type = NODE_INCREMENT_POSTFIX;
|
||||
tmp->increment.identifier = identifier;
|
||||
tmp->increment.increment = increment;
|
||||
|
||||
*nodeHandle = tmp;
|
||||
}
|
||||
|
||||
void printNode(Node* node) {
|
||||
if (node == NULL) {
|
||||
return;
|
||||
@@ -271,6 +296,11 @@ void printNode(Node* node) {
|
||||
printf(")");
|
||||
break;
|
||||
|
||||
// case NODE_INCREMENT_PREFIX:
|
||||
// case NODE_INCREMENT_POSTFIX:
|
||||
// //TODO
|
||||
// break;
|
||||
|
||||
default:
|
||||
printf("[internal] unkown node type in printNode: %d\n", node->type);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ typedef enum NodeType {
|
||||
NODE_PATH_FOR, //for control flow
|
||||
NODE_PATH_BREAK,
|
||||
NODE_PATH_CONTINUE,
|
||||
NODE_INCREMENT_PREFIX,
|
||||
NODE_INCREMENT_POSTFIX,
|
||||
} NodeType;
|
||||
|
||||
typedef struct NodeLiteral {
|
||||
@@ -90,6 +92,12 @@ typedef struct NodePath {
|
||||
Node* elsePath;
|
||||
} NodePath;
|
||||
|
||||
typedef struct NodeIncrement {
|
||||
NodeType type;
|
||||
Literal identifier;
|
||||
int increment;
|
||||
} NodeIncrement;
|
||||
|
||||
union _node {
|
||||
NodeType type;
|
||||
NodeLiteral atomic;
|
||||
@@ -102,6 +110,7 @@ union _node {
|
||||
NodeVarTypes varTypes;
|
||||
NodeVarDecl varDecl;
|
||||
NodePath path;
|
||||
NodeIncrement increment;
|
||||
};
|
||||
|
||||
void freeNode(Node* node);
|
||||
@@ -115,5 +124,7 @@ void emitNodePair(Node** nodeHandle, Node* left, Node* right);
|
||||
void emitNodeVarTypes(Node** nodeHandle, Literal literal);
|
||||
void emitNodeVarDecl(Node** nodeHandle, Literal identifier, Literal type, Node* expression);
|
||||
void emitNodePath(Node** nodeHandle, NodeType type, Node* preClause, Node* postClause, Node* condition, Node* thenPath, Node* elsePath);
|
||||
void emiteNodePrefixIncrement(Node** nodeHandle, Literal identifier, int increment);
|
||||
void emiteNodePostfixIncrement(Node** nodeHandle, Literal identifier, int increment);
|
||||
|
||||
void printNode(Node* node);
|
||||
|
||||
@@ -10,6 +10,7 @@ typedef enum Opcode {
|
||||
//data
|
||||
OP_LITERAL,
|
||||
OP_LITERAL_LONG, //for more than 256 literals in a chunk
|
||||
OP_LITERAL_RAW, //forcibly get the raw value of the literal
|
||||
|
||||
//arithmetic operators
|
||||
OP_NEGATE,
|
||||
|
||||
@@ -541,6 +541,50 @@ static Opcode castingInfix(Parser* parser, Node** nodeHandle) {
|
||||
return OP_TYPE_CAST;
|
||||
}
|
||||
|
||||
static Opcode incrementPrefix(Parser* parser, Node** nodeHandle) {
|
||||
advance(parser);
|
||||
|
||||
Node* node = NULL;
|
||||
identifier(parser, &node);
|
||||
|
||||
emiteNodePrefixIncrement(nodeHandle, node->atomic.literal, 1);
|
||||
|
||||
return OP_EOF;
|
||||
}
|
||||
|
||||
static Opcode incrementInfix(Parser* parser, Node** nodeHandle) {
|
||||
Node* node = NULL;
|
||||
identifier(parser, &node);
|
||||
|
||||
advance(parser);
|
||||
|
||||
emiteNodePostfixIncrement(nodeHandle, node->atomic.literal, 1);
|
||||
|
||||
return OP_EOF;
|
||||
}
|
||||
|
||||
static Opcode decrementPrefix(Parser* parser, Node** nodeHandle) {
|
||||
advance(parser);
|
||||
|
||||
Node* node = NULL;
|
||||
identifier(parser, &node);
|
||||
|
||||
emiteNodePrefixIncrement(nodeHandle, node->atomic.literal, -1);
|
||||
|
||||
return OP_EOF;
|
||||
}
|
||||
|
||||
static Opcode decrementInfix(Parser* parser, Node** nodeHandle) {
|
||||
Node* node = NULL;
|
||||
identifier(parser, &node);
|
||||
|
||||
advance(parser);
|
||||
|
||||
emiteNodePostfixIncrement(nodeHandle, node->atomic.literal, -1);
|
||||
|
||||
return OP_EOF;
|
||||
}
|
||||
|
||||
ParseRule parseRules[] = { //must match the token types
|
||||
//types
|
||||
{atomic, NULL, PREC_PRIMARY},// TOKEN_NULL,
|
||||
@@ -594,8 +638,8 @@ ParseRule parseRules[] = { //must match the token types
|
||||
{NULL, NULL, PREC_NONE},// TOKEN_MULTIPLY_ASSIGN,
|
||||
{NULL, NULL, PREC_NONE},// TOKEN_DIVIDE_ASSIGN,
|
||||
{NULL, NULL, PREC_NONE},// TOKEN_MODULO_ASSIGN,
|
||||
{NULL, NULL, PREC_NONE},// TOKEN_PLUS_PLUS,
|
||||
{NULL, NULL, PREC_NONE},// TOKEN_MINUS_MINUS,
|
||||
{incrementPrefix, incrementInfix, PREC_CALL},// TOKEN_PLUS_PLUS,
|
||||
{decrementPrefix, decrementInfix, PREC_CALL},// TOKEN_MINUS_MINUS,
|
||||
{NULL, binary, PREC_ASSIGNMENT},// TOKEN_ASSIGN,
|
||||
|
||||
//logical operators
|
||||
@@ -841,6 +885,13 @@ static void parsePrecedence(Parser* parser, Node** nodeHandle, PrecedenceRule ru
|
||||
|
||||
Node* rhsNode = NULL;
|
||||
const Opcode opcode = infixRule(parser, &rhsNode); //NOTE: infix rule must advance the parser
|
||||
|
||||
if (opcode == OP_EOF) {
|
||||
freeNode(*nodeHandle);
|
||||
*nodeHandle = rhsNode;
|
||||
return; //we're done here
|
||||
}
|
||||
|
||||
emitNodeBinary(nodeHandle, rhsNode, opcode);
|
||||
|
||||
if (!calcStaticBinaryArithmetic(parser, nodeHandle)) {
|
||||
|
||||
Reference in New Issue
Block a user