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: break and continue statements
DONE: truthiness rethink DONE: truthiness rethink
DONE: string concat with the + operator 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: are compounds shallow or deep copies?
TODO: functions, and all of their features TODO: functions, and all of their features
TODO: Assertion-based test scripts TODO: Assertion-based test scripts

View File

@@ -147,6 +147,30 @@ static int writeLiteralTypeToCache(LiteralArray* literalCache, Literal literal)
return pushLiteralArray(literalCache, lit); 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) { static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAddressesPtr, void* continueAddressesPtr) {
//grow if the bytecode space is too small //grow if the bytecode space is too small
if (compiler->capacity < compiler->count + 1) { if (compiler->capacity < compiler->count + 1) {
@@ -166,25 +190,7 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd
break; break;
case NODE_LITERAL: { case NODE_LITERAL: {
//ensure the literal is in the cache writeLiteralToCompiler(compiler, node->atomic.literal);
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
}
} }
break; break;
@@ -461,6 +467,48 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd
compiler->count += sizeof(unsigned short); //2 bytes compiler->count += sizeof(unsigned short); //2 bytes
} }
break; 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; 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) { static bool execNegate(Interpreter* interpreter) {
//negate the top literal on the stack (numbers only) //negate the top literal on the stack (numbers only)
Literal lit = popLiteralArray(&interpreter->stack); Literal lit = popLiteralArray(&interpreter->stack);
@@ -657,6 +669,12 @@ static void execInterpreter(Interpreter* interpreter) {
} }
break; break;
case OP_LITERAL_RAW:
if (!rawLiteral(interpreter)) {
return;
}
break;
case OP_NEGATE: case OP_NEGATE:
if (!execNegate(interpreter)) { if (!execNegate(interpreter)) {
return; return;

View File

@@ -73,6 +73,11 @@ void freeNode(Node* node) {
freeNode(node->path.thenPath); freeNode(node->path.thenPath);
freeNode(node->path.elsePath); freeNode(node->path.elsePath);
break; 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; *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) { void printNode(Node* node) {
if (node == NULL) { if (node == NULL) {
return; return;
@@ -271,6 +296,11 @@ void printNode(Node* node) {
printf(")"); printf(")");
break; break;
// case NODE_INCREMENT_PREFIX:
// case NODE_INCREMENT_POSTFIX:
// //TODO
// break;
default: default:
printf("[internal] unkown node type in printNode: %d\n", node->type); 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_FOR, //for control flow
NODE_PATH_BREAK, NODE_PATH_BREAK,
NODE_PATH_CONTINUE, NODE_PATH_CONTINUE,
NODE_INCREMENT_PREFIX,
NODE_INCREMENT_POSTFIX,
} NodeType; } NodeType;
typedef struct NodeLiteral { typedef struct NodeLiteral {
@@ -90,6 +92,12 @@ typedef struct NodePath {
Node* elsePath; Node* elsePath;
} NodePath; } NodePath;
typedef struct NodeIncrement {
NodeType type;
Literal identifier;
int increment;
} NodeIncrement;
union _node { union _node {
NodeType type; NodeType type;
NodeLiteral atomic; NodeLiteral atomic;
@@ -102,6 +110,7 @@ union _node {
NodeVarTypes varTypes; NodeVarTypes varTypes;
NodeVarDecl varDecl; NodeVarDecl varDecl;
NodePath path; NodePath path;
NodeIncrement increment;
}; };
void freeNode(Node* node); void freeNode(Node* node);
@@ -115,5 +124,7 @@ void emitNodePair(Node** nodeHandle, Node* left, Node* right);
void emitNodeVarTypes(Node** nodeHandle, Literal literal); void emitNodeVarTypes(Node** nodeHandle, Literal literal);
void emitNodeVarDecl(Node** nodeHandle, Literal identifier, Literal type, Node* expression); 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 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); void printNode(Node* node);

View File

@@ -10,6 +10,7 @@ typedef enum Opcode {
//data //data
OP_LITERAL, OP_LITERAL,
OP_LITERAL_LONG, //for more than 256 literals in a chunk OP_LITERAL_LONG, //for more than 256 literals in a chunk
OP_LITERAL_RAW, //forcibly get the raw value of the literal
//arithmetic operators //arithmetic operators
OP_NEGATE, OP_NEGATE,

View File

@@ -541,6 +541,50 @@ static Opcode castingInfix(Parser* parser, Node** nodeHandle) {
return OP_TYPE_CAST; 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 ParseRule parseRules[] = { //must match the token types
//types //types
{atomic, NULL, PREC_PRIMARY},// TOKEN_NULL, {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_MULTIPLY_ASSIGN,
{NULL, NULL, PREC_NONE},// TOKEN_DIVIDE_ASSIGN, {NULL, NULL, PREC_NONE},// TOKEN_DIVIDE_ASSIGN,
{NULL, NULL, PREC_NONE},// TOKEN_MODULO_ASSIGN, {NULL, NULL, PREC_NONE},// TOKEN_MODULO_ASSIGN,
{NULL, NULL, PREC_NONE},// TOKEN_PLUS_PLUS, {incrementPrefix, incrementInfix, PREC_CALL},// TOKEN_PLUS_PLUS,
{NULL, NULL, PREC_NONE},// TOKEN_MINUS_MINUS, {decrementPrefix, decrementInfix, PREC_CALL},// TOKEN_MINUS_MINUS,
{NULL, binary, PREC_ASSIGNMENT},// TOKEN_ASSIGN, {NULL, binary, PREC_ASSIGNMENT},// TOKEN_ASSIGN,
//logical operators //logical operators
@@ -841,6 +885,13 @@ static void parsePrecedence(Parser* parser, Node** nodeHandle, PrecedenceRule ru
Node* rhsNode = NULL; Node* rhsNode = NULL;
const Opcode opcode = infixRule(parser, &rhsNode); //NOTE: infix rule must advance the parser 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); emitNodeBinary(nodeHandle, rhsNode, opcode);
if (!calcStaticBinaryArithmetic(parser, nodeHandle)) { if (!calcStaticBinaryArithmetic(parser, nodeHandle)) {

View File

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