diff --git a/source/toy_ast_node.c b/source/toy_ast_node.c index 8740205..ebe4ca4 100644 --- a/source/toy_ast_node.c +++ b/source/toy_ast_node.c @@ -135,6 +135,10 @@ static void freeASTNodeCustom(Toy_ASTNode* node, bool freeSelf) { Toy_freeLiteral(node->import.identifier); Toy_freeLiteral(node->import.alias); break; + + case TOY_AST_NODE_PASS: + //EMPTY + break; } if (freeSelf) { @@ -383,3 +387,11 @@ void Toy_emitASTNodeImport(Toy_ASTNode** nodeHandle, Toy_Literal identifier, Toy *nodeHandle = tmp; } + +void Toy_emitASTNodePass(Toy_ASTNode** nodeHandle) { + Toy_ASTNode* tmp = TOY_ALLOCATE(Toy_ASTNode, 1); + + tmp->type = TOY_AST_NODE_PASS; + + *nodeHandle = tmp; +} \ No newline at end of file diff --git a/source/toy_ast_node.h b/source/toy_ast_node.h index ede7c59..05f14b7 100644 --- a/source/toy_ast_node.h +++ b/source/toy_ast_node.h @@ -34,6 +34,7 @@ typedef enum Toy_ASTNodeType { TOY_AST_NODE_PREFIX_DECREMENT, //decrement a variable TOY_AST_NODE_POSTFIX_DECREMENT, //decrement a variable TOY_AST_NODE_IMPORT, //import a library + TOY_AST_NODE_PASS, //for doing nothing } Toy_ASTNodeType; //literals @@ -238,6 +239,9 @@ typedef struct Toy_NodeImport { Toy_Literal alias; } Toy_NodeImport; +//for doing nothing +void Toy_emitASTNodePass(Toy_ASTNode** nodeHandle); + union Toy_private_node { Toy_ASTNodeType type; Toy_NodeLiteral atomic; diff --git a/source/toy_common.h b/source/toy_common.h index c0c671a..e6538c8 100644 --- a/source/toy_common.h +++ b/source/toy_common.h @@ -5,8 +5,8 @@ #include #define TOY_VERSION_MAJOR 0 -#define TOY_VERSION_MINOR 8 -#define TOY_VERSION_PATCH 3 +#define TOY_VERSION_MINOR 9 +#define TOY_VERSION_PATCH 0 #define TOY_VERSION_BUILD __DATE__ " " __TIME__ //platform/compiler-specific instructions diff --git a/source/toy_compiler.c b/source/toy_compiler.c index 57088ba..804ba36 100644 --- a/source/toy_compiler.c +++ b/source/toy_compiler.c @@ -965,6 +965,11 @@ static Toy_Opcode Toy_writeCompilerWithJumps(Toy_Compiler* compiler, Toy_ASTNode return TOY_OP_INDEX_ASSIGN; //override binary's instruction IF it is assign } break; + + case TOY_AST_NODE_PASS: { + return TOY_OP_PASS; + } + break; } return TOY_OP_EOF; diff --git a/source/toy_interpreter.c b/source/toy_interpreter.c index 63adba1..721a9fb 100644 --- a/source/toy_interpreter.c +++ b/source/toy_interpreter.c @@ -1827,6 +1827,10 @@ static void execInterpreter(Toy_Interpreter* interpreter) { while(opcode != TOY_OP_EOF && opcode != TOY_OP_SECTION_END && !interpreter->panic) { switch(opcode) { + case TOY_OP_PASS: + //DO NOTHING + break; + case TOY_OP_ASSERT: if (!execAssert(interpreter)) { return; diff --git a/source/toy_opcodes.h b/source/toy_opcodes.h index b7ceedf..45f0fbb 100644 --- a/source/toy_opcodes.h +++ b/source/toy_opcodes.h @@ -3,6 +3,9 @@ typedef enum Toy_Opcode { TOY_OP_EOF, + //do nothing + TOY_OP_PASS, + //basic statements TOY_OP_ASSERT, TOY_OP_PRINT, diff --git a/source/toy_parser.c b/source/toy_parser.c index 23bf72f..3e6fb7e 100644 --- a/source/toy_parser.c +++ b/source/toy_parser.c @@ -1350,13 +1350,36 @@ static void forStmt(Toy_Parser* parser, Toy_ASTNode** nodeHandle) { //read the clauses consume(parser, TOY_TOKEN_PAREN_LEFT, "Expected '(' at beginning of for clause"); - declaration(parser, &preClause); //allow defining variables in the pre-clause + //check the pre-clause + if (parser->current.type != TOY_TOKEN_SEMICOLON) { + declaration(parser, &preClause); //allow defining variables in the pre-clause + } + else { + consume(parser, TOY_TOKEN_SEMICOLON, "Expected ';' after empty declaration of for clause"); + Toy_emitASTNodePass(&preClause); + } - parsePrecedence(parser, &condition, PREC_TERNARY); - consume(parser, TOY_TOKEN_SEMICOLON, "Expected ';' after condition of for clause"); + //check the condition clause + if (parser->current.type != TOY_TOKEN_SEMICOLON) { + parsePrecedence(parser, &condition, PREC_TERNARY); + consume(parser, TOY_TOKEN_SEMICOLON, "Expected ';' after condition of for clause"); + } + else { + consume(parser, TOY_TOKEN_SEMICOLON, "Expected ';' after empty condition of for clause"); + //empty clause defaults to forever + Toy_Literal f = TOY_TO_BOOLEAN_LITERAL(true); + Toy_emitASTNodeLiteral(&condition, f); + } - parsePrecedence(parser, &postClause, PREC_ASSIGNMENT); - consume(parser, TOY_TOKEN_PAREN_RIGHT, "Expected ')' at end of for clause"); + //check the postfix clause + if (parser->current.type != TOY_TOKEN_PAREN_RIGHT) { + parsePrecedence(parser, &postClause, PREC_ASSIGNMENT); + consume(parser, TOY_TOKEN_PAREN_RIGHT, "Expected ')' at end of for clause"); + } + else { + consume(parser, TOY_TOKEN_PAREN_RIGHT, "Expected ')' after empty increment of for clause"); + Toy_emitASTNodePass(&postClause); + } //read the path declaration(parser, &thenPath); diff --git a/test/scripts/lib/runner/sample_bytecode.tb b/test/scripts/lib/runner/sample_bytecode.tb index 2fa78a9..2452480 100644 Binary files a/test/scripts/lib/runner/sample_bytecode.tb and b/test/scripts/lib/runner/sample_bytecode.tb differ