From f5e060051ec271cb00bbb7df9f03e95cb6dbc136 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Sat, 20 Aug 2022 13:27:47 +0100 Subject: [PATCH] While and for loops are working --- source/compiler.c | 64 +++++++++++++++++++++++++++++++++++++++++------ source/memory.h | 1 + source/parser.c | 42 ++++++++++++++++++++++++++++--- test/jumps.toy | 21 +++++++++++++++- 4 files changed, 116 insertions(+), 12 deletions(-) diff --git a/source/compiler.c b/source/compiler.c index 301e10a..2caa2cd 100644 --- a/source/compiler.c +++ b/source/compiler.c @@ -149,7 +149,7 @@ void writeCompiler(Compiler* compiler, Node* node) { if (compiler->capacity < compiler->count + 1) { int oldCapacity = compiler->capacity; - compiler->capacity = GROW_CAPACITY(oldCapacity); + compiler->capacity = GROW_CAPACITY_FAST(oldCapacity); compiler->bytecode = GROW_ARRAY(unsigned char, compiler->bytecode, oldCapacity, compiler->capacity); } @@ -322,13 +322,63 @@ void writeCompiler(Compiler* compiler, Node* node) { } break; - // case NODE_PATH_WHILE: { - // //cache the jump point - // int jumpToBeginning = compiler->count; - // compiler->count += sizeof(unsigned short); //2 bytes + case NODE_PATH_WHILE: { + //cache the jump point + unsigned short jumpFromEnd = compiler->count; - // // - // } + //process the condition + writeCompiler(compiler, node->path.condition); + + //if false, jump to end + compiler->bytecode[compiler->count++] = OP_IF_FALSE_JUMP; //1 byte + unsigned short jumpToEnd = compiler->count; + compiler->count += sizeof(unsigned short); //2 bytes + + //write the body + writeCompiler(compiler, node->path.thenPath); + + //jump to condition + compiler->bytecode[compiler->count++] = OP_JUMP; //1 byte + compiler->bytecode[compiler->count] = jumpFromEnd; + compiler->count += sizeof(unsigned short); //2 bytes + + //jump from condition + compiler->bytecode[jumpToEnd] = compiler->count; + } + break; + + case NODE_PATH_FOR: { + compiler->bytecode[compiler->count++] = OP_SCOPE_BEGIN; //1 byte + + //initial setup + writeCompiler(compiler, node->path.preClause); + + //conditional + unsigned short jumpFromEnd = compiler->count; + writeCompiler(compiler, node->path.condition); + + //if false jump to end + compiler->bytecode[compiler->count++] = OP_IF_FALSE_JUMP; //1 byte + unsigned short jumpToEnd = compiler->count; + compiler->count += sizeof(unsigned short); //2 bytes + + //write the body + compiler->bytecode[compiler->count++] = OP_SCOPE_BEGIN; //1 byte + writeCompiler(compiler, node->path.thenPath); + compiler->bytecode[compiler->count++] = OP_SCOPE_END; //1 byte + + //evaluate third clause, restart + writeCompiler(compiler, node->path.postClause); + + compiler->bytecode[compiler->count++] = OP_JUMP; //1 byte + compiler->bytecode[compiler->count] = jumpFromEnd; + compiler->count += sizeof(unsigned short); //2 bytes + + compiler->bytecode[jumpToEnd] = compiler->count; + + compiler->bytecode[compiler->count++] = OP_SCOPE_END; //1 byte + } + break; } } diff --git a/source/memory.h b/source/memory.h index 05575b3..c988867 100644 --- a/source/memory.h +++ b/source/memory.h @@ -5,6 +5,7 @@ #define ALLOCATE(type, count) ((type*)reallocate(NULL, 0, sizeof(type) * (count))) #define FREE(type, pointer) reallocate(pointer, sizeof(type), 0) #define GROW_CAPACITY(capacity) ((capacity) < 8 ? 8 : (capacity) * 2) +#define GROW_CAPACITY_FAST(capacity) ((capacity) < 32 ? 32 : (capacity) * 2) #define GROW_ARRAY(type, pointer, oldCount, count) (type*)reallocate((type*)pointer, sizeof(type) * (oldCount), sizeof(type) * (count)) #define SHRINK_ARRAY(type, pointer, oldCount, count) (type*)reallocate((type*)pointer, sizeof(type) * (oldCount), sizeof(type) * (count)) #define FREE_ARRAY(type, pointer, oldCount) reallocate((type*)pointer, sizeof(type) * (oldCount), 0) diff --git a/source/parser.c b/source/parser.c index 08c025f..124f361 100644 --- a/source/parser.c +++ b/source/parser.c @@ -925,11 +925,11 @@ static void ifStmt(Parser* parser, Node** nodeHandle) { Node* elsePath = NULL; //read the condition - consume(parser, TOKEN_PAREN_LEFT, "Expected '(' at end of if statement"); + consume(parser, TOKEN_PAREN_LEFT, "Expected '(' at beginning of if clause"); parsePrecedence(parser, &condition, PREC_TERNARY); //read the then path - consume(parser, TOKEN_PAREN_RIGHT, "Expected ')' at end of if statement"); + consume(parser, TOKEN_PAREN_RIGHT, "Expected ')' at end of if clause"); thenPath = ALLOCATE(Node, 1); declaration(parser, &thenPath); @@ -944,11 +944,45 @@ static void ifStmt(Parser* parser, Node** nodeHandle) { } static void whileStmt(Parser* parser, Node** nodeHandle) { - // + Node* condition = NULL; + Node* thenPath = NULL; + + //read the condition + consume(parser, TOKEN_PAREN_LEFT, "Expected '(' at beginning of while clause"); + parsePrecedence(parser, &condition, PREC_TERNARY); + + //read the then path + consume(parser, TOKEN_PAREN_RIGHT, "Expected ')' at end of while clause"); + thenPath = ALLOCATE(Node, 1); + declaration(parser, &thenPath); + + freeNode(*nodeHandle); //free the initial node + emitNodePath(nodeHandle, NODE_PATH_WHILE, NULL, NULL, condition, thenPath, NULL); } static void forStmt(Parser* parser, Node** nodeHandle) { - // + Node* preClause = ALLOCATE(Node, 1); + Node* postClause = NULL; + Node* condition = NULL; + Node* thenPath = ALLOCATE(Node, 1); + + //read the clauses + consume(parser, TOKEN_PAREN_LEFT, "Expected '(' at beginning of for clause"); + declaration(parser, &preClause); + + parsePrecedence(parser, &condition, PREC_TERNARY); + + consume(parser, TOKEN_SEMICOLON, "Expected ';' after condition of for clause"); + parsePrecedence(parser, &postClause, PREC_ASSIGNMENT); + + consume(parser, TOKEN_PAREN_RIGHT, "Expected ')' at end of for clause"); + + //read the path + thenPath = ALLOCATE(Node, 1); + declaration(parser, &thenPath); + + freeNode(*nodeHandle); //free the initial node + emitNodePath(nodeHandle, NODE_PATH_FOR, preClause, postClause, condition, thenPath, NULL); } //precedence functions diff --git a/test/jumps.toy b/test/jumps.toy index 151a622..c926910 100644 --- a/test/jumps.toy +++ b/test/jumps.toy @@ -18,4 +18,23 @@ else { } -print "All good"; \ No newline at end of file +//test while loop +var whileCounter = 0; +while (whileCounter < 10) { + whileCounter = whileCounter + 1; +} + +assert whileCounter == 10, "while-loop failed"; + + +//test for loop +var forCache = 0; +for (var i = 0; i < 20; i = i + 1) { + forCache = i; +} + +assert forCache == 19, "for-loop failed"; + + +print "All good"; +