From 431893bf60c3d300e8a284e64f514042c8d76412 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Thu, 28 Nov 2024 13:43:26 +1100 Subject: [PATCH] WIP: Started on break & continue, needs Toy_Array in Toy_Value first --- .notes/break-continue-theory.toy | 19 +++++++++++++++++++ source/toy_ast.c | 16 ++++++++++++++++ source/toy_ast.h | 14 ++++++++++++++ source/toy_parser.c | 24 ++++++++++++++++++++++-- source/toy_routine.c | 24 ++++++++++++++++++++++++ tests/cases/test_ast.c | 4 ++++ 6 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 .notes/break-continue-theory.toy diff --git a/.notes/break-continue-theory.toy b/.notes/break-continue-theory.toy new file mode 100644 index 0000000..bf71254 --- /dev/null +++ b/.notes/break-continue-theory.toy @@ -0,0 +1,19 @@ +while (a) { //stored in an array + while (b) { //stored in an array + while(c) { //stored in an array + + //just peek at the array's top + continue; + + //these are stored in a second array + break; + break; + break; + } //breaks are updated here + + //but what about these? + break; + break; + break; + } +} diff --git a/source/toy_ast.c b/source/toy_ast.c index 4850745..9c72c14 100644 --- a/source/toy_ast.c +++ b/source/toy_ast.c @@ -126,6 +126,22 @@ void Toy_private_emitAstWhileThen(Toy_Bucket** bucketHandle, Toy_Ast** astHandle (*astHandle) = tmp; } +void Toy_private_emitAstBreak(Toy_Bucket** bucketHandle, Toy_Ast** astHandle) { + Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Ast)); + + tmp->type = TOY_AST_BREAK; + + (*astHandle) = tmp; +} + +void Toy_private_emitAstContinue(Toy_Bucket** bucketHandle, Toy_Ast** astHandle) { + Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Ast)); + + tmp->type = TOY_AST_CONTINUE; + + (*astHandle) = tmp; +} + void Toy_private_emitAstPrint(Toy_Bucket** bucketHandle, Toy_Ast** astHandle) { Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Ast)); diff --git a/source/toy_ast.h b/source/toy_ast.h index c11a015..3f45944 100644 --- a/source/toy_ast.h +++ b/source/toy_ast.h @@ -20,6 +20,8 @@ typedef enum Toy_AstType { TOY_AST_ASSERT, TOY_AST_IF_THEN_ELSE, TOY_AST_WHILE_THEN, + TOY_AST_BREAK, + TOY_AST_CONTINUE, TOY_AST_PRINT, TOY_AST_VAR_DECLARE, @@ -138,6 +140,14 @@ typedef struct Toy_AstWhileThen { Toy_Ast* thenBranch; } Toy_AstWhileThen; +typedef struct Toy_AstBreak { + Toy_AstType type; +} Toy_AstBreak; + +typedef struct Toy_AstContinue { + Toy_AstType type; +} Toy_AstContinue; + typedef struct Toy_AstPrint { Toy_AstType type; Toy_Ast* child; @@ -185,6 +195,8 @@ union Toy_Ast { //32 | 64 BITNESS Toy_AstAssert assert; //16 | 24 Toy_AstIfThenElse ifThenElse; //16 | 32 Toy_AstWhileThen whileThen; //16 | 24 + Toy_AstBreak breakPoint; //4 | 4 + Toy_AstContinue continuePoint; //4 | 4 Toy_AstPrint print; //8 | 16 Toy_AstVarDeclare varDeclare; //16 | 24 Toy_AstVarAssign varAssign; //16 | 24 @@ -207,6 +219,8 @@ void Toy_private_emitAstCompound(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, void Toy_private_emitAstAssert(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* child, Toy_Ast* msg); void Toy_private_emitAstIfThenElse(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* condBranch, Toy_Ast* thenBranch, Toy_Ast* elseBranch); void Toy_private_emitAstWhileThen(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* condBranch, Toy_Ast* thenBranch); +void Toy_private_emitAstBreak(Toy_Bucket** bucketHandle, Toy_Ast** rootHandle); +void Toy_private_emitAstContinue(Toy_Bucket** bucketHandle, Toy_Ast** rootHandle); void Toy_private_emitAstPrint(Toy_Bucket** bucketHandle, Toy_Ast** astHandle); void Toy_private_emitAstVariableDeclaration(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_String* name, Toy_Ast* expr); diff --git a/source/toy_parser.c b/source/toy_parser.c index 9910bf5..8cee9e2 100644 --- a/source/toy_parser.c +++ b/source/toy_parser.c @@ -716,6 +716,16 @@ static void makeWhileStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast Toy_private_emitAstWhileThen(bucketHandle, rootHandle, condBranch, thenBranch); } +static void makeBreakStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) { + Toy_private_emitAstBreak(bucketHandle, rootHandle); + consume(parser, TOY_TOKEN_OPERATOR_SEMICOLON, "Expected ';' at the end of break statement"); +} + +static void makeContinueStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) { + Toy_private_emitAstContinue(bucketHandle, rootHandle); + consume(parser, TOY_TOKEN_OPERATOR_SEMICOLON, "Expected ';' at the end of continue statement"); +} + static void makePrintStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) { makeExpr(bucketHandle, parser, rootHandle); Toy_private_emitAstPrint(bucketHandle, rootHandle); @@ -788,8 +798,6 @@ static void makeStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** ro return; } - //TODO: break & continue - //while-then else if (match(parser, TOY_TOKEN_KEYWORD_WHILE)) { makeWhileStmt(bucketHandle, parser, rootHandle); @@ -800,6 +808,18 @@ static void makeStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** ro //return //import + //break + else if (match(parser, TOY_TOKEN_KEYWORD_BREAK)) { + makeBreakStmt(bucketHandle, parser, rootHandle); + return; + } + + //continue + else if (match(parser, TOY_TOKEN_KEYWORD_CONTINUE)) { + makeContinueStmt(bucketHandle, parser, rootHandle); + return; + } + //print else if (match(parser, TOY_TOKEN_KEYWORD_PRINT)) { makePrintStmt(bucketHandle, parser, rootHandle); diff --git a/source/toy_routine.c b/source/toy_routine.c index 55d2537..2b72f3d 100644 --- a/source/toy_routine.c +++ b/source/toy_routine.c @@ -380,6 +380,22 @@ static unsigned int writeInstructionWhileThen(Toy_Routine** rt, Toy_AstWhileThen return 0; } +static unsigned int writeInstructionBreak(Toy_Routine** rt, Toy_AstBreak ast) { + //TODO: implement break + fprintf(stderr, TOY_CC_ERROR "COMPILER ERROR: Keyword 'break' not yet implemented\n" TOY_CC_RESET); + (*rt)->panic = true; + + return 0; +} + +static unsigned int writeInstructionContinue(Toy_Routine** rt, Toy_AstContinue ast) { + //TODO: implement continue + fprintf(stderr, TOY_CC_ERROR "COMPILER ERROR: Keyword 'continue' not yet implemented\n" TOY_CC_RESET); + (*rt)->panic = true; + + return 0; +} + static unsigned int writeInstructionPrint(Toy_Routine** rt, Toy_AstPrint ast) { //the thing to print writeRoutineCode(rt, ast.child); @@ -638,6 +654,14 @@ static unsigned int writeRoutineCode(Toy_Routine** rt, Toy_Ast* ast) { result += writeInstructionWhileThen(rt, ast->whileThen); break; + case TOY_AST_BREAK: + result += writeInstructionBreak(rt, ast->breakPoint); + break; + + case TOY_AST_CONTINUE: + result += writeInstructionContinue(rt, ast->continuePoint); + break; + case TOY_AST_PRINT: result += writeInstructionPrint(rt, ast->print); break; diff --git a/tests/cases/test_ast.c b/tests/cases/test_ast.c index f90be48..cb75698 100644 --- a/tests/cases/test_ast.c +++ b/tests/cases/test_ast.c @@ -27,6 +27,8 @@ int test_sizeof_ast_64bit() { TEST_SIZEOF(Toy_AstAssert, 24); TEST_SIZEOF(Toy_AstIfThenElse, 32); TEST_SIZEOF(Toy_AstWhileThen, 24); + TEST_SIZEOF(Toy_AstBreak, 4); + TEST_SIZEOF(Toy_AstContinue, 4); TEST_SIZEOF(Toy_AstPrint, 16); TEST_SIZEOF(Toy_AstVarDeclare, 24); TEST_SIZEOF(Toy_AstVarAssign, 24); @@ -63,6 +65,8 @@ int test_sizeof_ast_32bit() { TEST_SIZEOF(Toy_AstAssert, 12); TEST_SIZEOF(Toy_AstIfThenElse, 16); TEST_SIZEOF(Toy_AstWhileThen, 12); + TEST_SIZEOF(Toy_AstBreak, 4); + TEST_SIZEOF(Toy_AstContinue, 4); TEST_SIZEOF(Toy_AstPrint, 8); TEST_SIZEOF(Toy_AstVarDeclare, 12); TEST_SIZEOF(Toy_AstVarAssign, 16);