diff --git a/docs/TODO.txt b/docs/TODO.txt index 79e21b4..ac7c13d 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -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 diff --git a/source/compiler.c b/source/compiler.c index b7bc704..1ff8d3b 100644 --- a/source/compiler.c +++ b/source/compiler.c @@ -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; } } diff --git a/source/interpreter.c b/source/interpreter.c index af7344f..4e652d4 100644 --- a/source/interpreter.c +++ b/source/interpreter.c @@ -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; diff --git a/source/node.c b/source/node.c index 52e709d..5322c8c 100644 --- a/source/node.c +++ b/source/node.c @@ -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); } diff --git a/source/node.h b/source/node.h index 0383783..4a140ba 100644 --- a/source/node.h +++ b/source/node.h @@ -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); diff --git a/source/opcodes.h b/source/opcodes.h index 01edc6c..582b201 100644 --- a/source/opcodes.h +++ b/source/opcodes.h @@ -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, diff --git a/source/parser.c b/source/parser.c index 4744e99..ab2360d 100644 --- a/source/parser.c +++ b/source/parser.c @@ -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)) { diff --git a/test/jumps.toy b/test/jumps.toy index 9d959c8..68de224 100644 --- a/test/jumps.toy +++ b/test/jumps.toy @@ -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; }