Increment and decrement operators work

This commit is contained in:
2022-08-21 00:23:01 +01:00
parent c64d451287
commit b385b461e0
8 changed files with 185 additions and 26 deletions

View File

@@ -11,9 +11,9 @@ DONE: for-then
DONE: break and continue statements
DONE: truthiness rethink
DONE: string concat with the + operator
DONE: increment & decrement operators
TODO: increment & decrement operators
TODO: a = b = c = 1;
TODO: a = b = c = 1; ?
TODO: are compounds shallow or deep copies?
TODO: functions, and all of their features
TODO: Assertion-based test scripts

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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,

View File

@@ -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)) {

View File

@@ -27,7 +27,7 @@ assert whileCounter == 10, "while-loop failed";
//test for loop
var forCache = 0;
for (var i = 0; i < 20; i = i + 1) {
for (var i = 0; i < 20; i++) {
forCache = i;
}
@@ -61,7 +61,7 @@ while (continueWhileCache < 10) {
//test break - for
for (var i = 0; i < 10; i = i + 1) {
for (var i = 0; i < 10; i++) {
if (i >= 7) {
break;
}
@@ -71,7 +71,7 @@ for (var i = 0; i < 10; i = i + 1) {
//test break - continue
for (var i = 0; i < 10; i = i + 1) {
for (var i = 0; i < 10; i++) {
if (i >= 7) {
continue;
}