Compare commits

...

1 Commits

Author SHA1 Message Date
Kayne Ruse 813da3e1aa WIP Adding for-loop to parser & compiler 2026-05-21 11:26:59 +10:00
8 changed files with 103 additions and 6 deletions
+22
View File
@@ -147,6 +147,16 @@ void Toy_private_emitAstWhileThen(Toy_Bucket** bucketHandle, Toy_Ast** astHandle
(*astHandle) = tmp; (*astHandle) = tmp;
} }
void Toy_private_emitAstForThen(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* condBranch, Toy_Ast* thenBranch) {
Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Ast));
tmp->type = TOY_AST_FOR_THEN;
tmp->forThen.condBranch = condBranch;
tmp->forThen.thenBranch = thenBranch;
(*astHandle) = tmp;
}
void Toy_private_emitAstBreak(Toy_Bucket** bucketHandle, Toy_Ast** astHandle) { void Toy_private_emitAstBreak(Toy_Bucket** bucketHandle, Toy_Ast** astHandle) {
Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Ast)); Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Ast));
@@ -244,6 +254,16 @@ void Toy_private_emitAstAttribute(Toy_Bucket** bucketHandle, Toy_Ast** astHandle
(*astHandle) = tmp; (*astHandle) = tmp;
} }
void Toy_private_emitAstIterable(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* expr) {
Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Ast));
tmp->type = TOY_AST_ITERABLE;
tmp->iterable.left = (*astHandle);
tmp->iterable.right = expr;
(*astHandle) = tmp;
}
void Toy_private_emitAstStackPop(Toy_Bucket** bucketHandle, Toy_Ast** astHandle) { void Toy_private_emitAstStackPop(Toy_Bucket** bucketHandle, Toy_Ast** astHandle) {
Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Ast)); Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Ast));
@@ -293,6 +313,7 @@ const char* Toy_private_getAstTypeAsCString(Toy_AstType type) {
case TOY_AST_ASSERT: return "ASSERT"; case TOY_AST_ASSERT: return "ASSERT";
case TOY_AST_IF_THEN_ELSE: return "IF_THEN_ELSE"; case TOY_AST_IF_THEN_ELSE: return "IF_THEN_ELSE";
case TOY_AST_WHILE_THEN: return "WHILE_THEN"; case TOY_AST_WHILE_THEN: return "WHILE_THEN";
case TOY_AST_FOR_THEN: return "FOR_THEN";
case TOY_AST_BREAK: return "BREAK"; case TOY_AST_BREAK: return "BREAK";
case TOY_AST_CONTINUE: return "CONTINUE"; case TOY_AST_CONTINUE: return "CONTINUE";
case TOY_AST_RETURN: return "RETURN"; case TOY_AST_RETURN: return "RETURN";
@@ -305,6 +326,7 @@ const char* Toy_private_getAstTypeAsCString(Toy_AstType type) {
case TOY_AST_FN_DECLARE: return "FN_DECLARE"; case TOY_AST_FN_DECLARE: return "FN_DECLARE";
case TOY_AST_FN_INVOKE: return "FN_INVOKE"; case TOY_AST_FN_INVOKE: return "FN_INVOKE";
case TOY_AST_ATTRIBUTE: return "ATTRIBUTE"; case TOY_AST_ATTRIBUTE: return "ATTRIBUTE";
case TOY_AST_ITERABLE: return "ITERABLE";
case TOY_AST_STACK_POP: return "STACK_POP"; case TOY_AST_STACK_POP: return "STACK_POP";
+18
View File
@@ -22,6 +22,7 @@ typedef enum Toy_AstType {
TOY_AST_ASSERT, TOY_AST_ASSERT,
TOY_AST_IF_THEN_ELSE, TOY_AST_IF_THEN_ELSE,
TOY_AST_WHILE_THEN, TOY_AST_WHILE_THEN,
TOY_AST_FOR_THEN,
TOY_AST_BREAK, TOY_AST_BREAK,
TOY_AST_CONTINUE, TOY_AST_CONTINUE,
TOY_AST_RETURN, TOY_AST_RETURN,
@@ -34,6 +35,7 @@ typedef enum Toy_AstType {
TOY_AST_FN_DECLARE, TOY_AST_FN_DECLARE,
TOY_AST_FN_INVOKE, TOY_AST_FN_INVOKE,
TOY_AST_ATTRIBUTE, TOY_AST_ATTRIBUTE,
TOY_AST_ITERABLE,
TOY_AST_STACK_POP, //BUGFIX: force a single stack pop for expression statements TOY_AST_STACK_POP, //BUGFIX: force a single stack pop for expression statements
@@ -171,6 +173,12 @@ typedef struct Toy_AstWhileThen {
Toy_Ast* thenBranch; Toy_Ast* thenBranch;
} Toy_AstWhileThen; } Toy_AstWhileThen;
typedef struct Toy_AstForThen {
Toy_AstType type;
Toy_Ast* condBranch;
Toy_Ast* thenBranch;
} Toy_AstForThen;
typedef struct Toy_AstBreak { typedef struct Toy_AstBreak {
Toy_AstType type; Toy_AstType type;
} Toy_AstBreak; } Toy_AstBreak;
@@ -228,6 +236,12 @@ typedef struct Toy_AstAttribute {
Toy_Ast* right; Toy_Ast* right;
} Toy_AstAttribute; } Toy_AstAttribute;
typedef struct Toy_AstIterable {
Toy_AstType type;
Toy_Ast* left;
Toy_Ast* right;
} Toy_AstIterable;
typedef struct Toy_AstStackPop { typedef struct Toy_AstStackPop {
Toy_AstType type; Toy_AstType type;
Toy_Ast* child; Toy_Ast* child;
@@ -259,6 +273,7 @@ union Toy_Ast { //see 'test_ast.c' for bitness tests
Toy_AstAssert assert; Toy_AstAssert assert;
Toy_AstIfThenElse ifThenElse; Toy_AstIfThenElse ifThenElse;
Toy_AstWhileThen whileThen; Toy_AstWhileThen whileThen;
Toy_AstForThen forThen;
Toy_AstBreak breakPoint; Toy_AstBreak breakPoint;
Toy_AstContinue continuePoint; Toy_AstContinue continuePoint;
Toy_AstReturn fnReturn; Toy_AstReturn fnReturn;
@@ -269,6 +284,7 @@ union Toy_Ast { //see 'test_ast.c' for bitness tests
Toy_AstFnDeclare fnDeclare; Toy_AstFnDeclare fnDeclare;
Toy_AstFnInvoke fnInvoke; Toy_AstFnInvoke fnInvoke;
Toy_AstAttribute attribute; Toy_AstAttribute attribute;
Toy_AstIterable iterable;
Toy_AstStackPop stackPop; Toy_AstStackPop stackPop;
Toy_AstPass pass; Toy_AstPass pass;
Toy_AstError error; Toy_AstError error;
@@ -290,6 +306,7 @@ void Toy_private_emitAstAggregate(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_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_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_emitAstWhileThen(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* condBranch, Toy_Ast* thenBranch);
void Toy_private_emitAstForThen(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_emitAstBreak(Toy_Bucket** bucketHandle, Toy_Ast** rootHandle);
void Toy_private_emitAstContinue(Toy_Bucket** bucketHandle, Toy_Ast** rootHandle); void Toy_private_emitAstContinue(Toy_Bucket** bucketHandle, Toy_Ast** rootHandle);
void Toy_private_emitAstReturn(Toy_Bucket** bucketHandle, Toy_Ast** astHandle); void Toy_private_emitAstReturn(Toy_Bucket** bucketHandle, Toy_Ast** astHandle);
@@ -302,6 +319,7 @@ void Toy_private_emitAstVariableAccess(Toy_Bucket** bucketHandle, Toy_Ast** astH
void Toy_private_emitAstFunctionDeclaration(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_String* name, Toy_Ast* params, Toy_Ast* body); void Toy_private_emitAstFunctionDeclaration(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_String* name, Toy_Ast* params, Toy_Ast* body);
void Toy_private_emitAstFunctionInvokation(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* params); void Toy_private_emitAstFunctionInvokation(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* params);
void Toy_private_emitAstAttribute(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* expr); void Toy_private_emitAstAttribute(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* expr);
void Toy_private_emitAstIterable(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* expr);
void Toy_private_emitAstStackPop(Toy_Bucket** bucketHandle, Toy_Ast** astHandle); void Toy_private_emitAstStackPop(Toy_Bucket** bucketHandle, Toy_Ast** astHandle);
+2 -1
View File
@@ -91,6 +91,7 @@ static void attr_arrayPopBack(Toy_VM* vm, Toy_FunctionNative* self) {
} }
static void attr_arrayForEach(Toy_VM* vm, Toy_FunctionNative* self) { static void attr_arrayForEach(Toy_VM* vm, Toy_FunctionNative* self) {
//URGENT: replace with for-loop
(void)self; (void)self;
Toy_Value compound = Toy_popStack(&vm->stack); Toy_Value compound = Toy_popStack(&vm->stack);
@@ -241,7 +242,7 @@ static void attr_tableForEach(Toy_VM* vm, Toy_FunctionNative* self) {
(void)vm; (void)vm;
(void)self; (void)self;
//URGENT: attr_tableForEach //URGENT: replace with for-loop
} }
Toy_Value Toy_private_handleTableAttributes(Toy_VM* vm, Toy_Value compound, Toy_Value attribute) { Toy_Value Toy_private_handleTableAttributes(Toy_VM* vm, Toy_Value compound, Toy_Value attribute) {
+19
View File
@@ -718,6 +718,15 @@ static unsigned int writeInstructionWhileThen(Toy_Bytecode** mb, Toy_AstWhileThe
return 0; return 0;
} }
static unsigned int writeInstructionForThen(Toy_Bytecode** mb, Toy_AstForThen ast) {
//URGENT: WIP
(void)mb;
(void)ast;
(*mb)->panic = true;
return 1;
}
static unsigned int writeInstructionBreak(Toy_Bytecode** mb, Toy_AstBreak ast) { static unsigned int writeInstructionBreak(Toy_Bytecode** mb, Toy_AstBreak ast) {
//unused //unused
(void)ast; (void)ast;
@@ -1244,6 +1253,10 @@ static unsigned int writeBytecodeFromAst(Toy_Bytecode** mb, Toy_Ast* ast) {
result += writeInstructionWhileThen(mb, ast->whileThen); result += writeInstructionWhileThen(mb, ast->whileThen);
break; break;
case TOY_AST_FOR_THEN:
result += writeInstructionForThen(mb, ast->forThen);
break;
case TOY_AST_BREAK: case TOY_AST_BREAK:
result += writeInstructionBreak(mb, ast->breakPoint); result += writeInstructionBreak(mb, ast->breakPoint);
break; break;
@@ -1284,6 +1297,12 @@ static unsigned int writeBytecodeFromAst(Toy_Bytecode** mb, Toy_Ast* ast) {
result += writeInstructionAttribute(mb, ast->attribute); result += writeInstructionAttribute(mb, ast->attribute);
break; break;
case TOY_AST_ITERABLE:
//the 'in' keyword is only valid within a for-loop's condition
fprintf(stderr, TOY_CC_ERROR "COMPILER ERROR: the 'in' keyword is only valid within a for-loop's condition\n" TOY_CC_RESET);
(*mb)->panic = true;
break;
case TOY_AST_STACK_POP: case TOY_AST_STACK_POP:
result += writeInstructionStackPop(mb, ast->stackPop); result += writeInstructionStackPop(mb, ast->stackPop);
break; break;
+1
View File
@@ -12,6 +12,7 @@ typedef enum Toy_OpcodeType {
TOY_OPCODE_ACCESS, TOY_OPCODE_ACCESS,
TOY_OPCODE_INVOKE, //for calling functions TOY_OPCODE_INVOKE, //for calling functions
TOY_OPCODE_ATTRIBUTE, //for accessing parts of compounds TOY_OPCODE_ATTRIBUTE, //for accessing parts of compounds
TOY_OPCODE_ITERABLE, //for operating on all members of a compound
TOY_OPCODE_DUPLICATE, //duplicate the top of the stack TOY_OPCODE_DUPLICATE, //duplicate the top of the stack
TOY_OPCODE_ELIMINATE, //remove the top of the stack TOY_OPCODE_ELIMINATE, //remove the top of the stack
+39 -4
View File
@@ -122,6 +122,7 @@ static Toy_AstFlag aggregate(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_
static Toy_AstFlag unaryPostfix(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle); static Toy_AstFlag unaryPostfix(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
static Toy_AstFlag invoke(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle); static Toy_AstFlag invoke(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
static Toy_AstFlag attribute(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle); static Toy_AstFlag attribute(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
static Toy_AstFlag iterable(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
//precedence definitions //precedence definitions
static ParsingTuple parsingRulesetTable[] = { static ParsingTuple parsingRulesetTable[] = {
@@ -156,7 +157,7 @@ static ParsingTuple parsingRulesetTable[] = {
{PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_FUNCTION, {PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_FUNCTION,
{PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_IF, {PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_IF,
{PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_IMPORT, {PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_IMPORT,
{PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_IN, {PREC_CALL,NULL,iterable},// TOY_TOKEN_KEYWORD_IN,
{PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_OF, {PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_OF,
{PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_PASS, {PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_PASS,
{PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_PRINT, {PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_PRINT,
@@ -760,6 +761,19 @@ static Toy_AstFlag attribute(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_
} }
} }
static Toy_AstFlag iterable(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) {
//infix must advance
advance(parser);
Toy_Ast* expr = NULL;
parsePrecedence(bucketHandle, parser, &expr, PREC_CALL);
Toy_private_emitAstIterable(bucketHandle, rootHandle, expr);
//TODO: check for var declare without assignment
return TOY_AST_FLAG_NONE;
}
//grammar rules //grammar rules
static void parsePrecedence(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle, ParsingPrecedence precRule) { static void parsePrecedence(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle, ParsingPrecedence precRule) {
//'step over' the token to parse //'step over' the token to parse
@@ -865,7 +879,7 @@ static void makeIfThenElseStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, To
makeExpr(bucketHandle, parser, &condBranch); makeExpr(bucketHandle, parser, &condBranch);
consume(parser, TOY_TOKEN_OPERATOR_PAREN_RIGHT, "Expected ')' after 'if' condition"); consume(parser, TOY_TOKEN_OPERATOR_PAREN_RIGHT, "Expected ')' after 'if' condition");
// { thenBranch } //{ thenBranch }
makeDeclarationStmt(bucketHandle, parser, &thenBranch, true); makeDeclarationStmt(bucketHandle, parser, &thenBranch, true);
//else { elseBranch } //else { elseBranch }
@@ -885,12 +899,29 @@ static void makeWhileStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast
makeExpr(bucketHandle, parser, &condBranch); makeExpr(bucketHandle, parser, &condBranch);
consume(parser, TOY_TOKEN_OPERATOR_PAREN_RIGHT, "Expected ')' after 'while' condition"); consume(parser, TOY_TOKEN_OPERATOR_PAREN_RIGHT, "Expected ')' after 'while' condition");
// { thenBranch } //{ thenBranch }
makeDeclarationStmt(bucketHandle, parser, &thenBranch, true); makeDeclarationStmt(bucketHandle, parser, &thenBranch, true);
Toy_private_emitAstWhileThen(bucketHandle, rootHandle, condBranch, thenBranch); Toy_private_emitAstWhileThen(bucketHandle, rootHandle, condBranch, thenBranch);
} }
static void makeForStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) {
Toy_Ast* condBranch = NULL;
Toy_Ast* thenBranch = NULL;
//for (condBranch)
consume(parser, TOY_TOKEN_OPERATOR_PAREN_LEFT, "Expected '(' after 'for' keyword");
makeExpr(bucketHandle, parser, &condBranch);
consume(parser, TOY_TOKEN_OPERATOR_PAREN_RIGHT, "Expected ')' after 'for' condition");
//TODO: check for an iterable node
//{ thenBranch }
makeDeclarationStmt(bucketHandle, parser, &thenBranch, true);
Toy_private_emitAstForThen(bucketHandle, rootHandle, condBranch, thenBranch);
}
static void makeBreakStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) { static void makeBreakStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) {
Toy_private_emitAstBreak(bucketHandle, rootHandle); Toy_private_emitAstBreak(bucketHandle, rootHandle);
consume(parser, TOY_TOKEN_OPERATOR_SEMICOLON, "Expected ';' at the end of break statement"); consume(parser, TOY_TOKEN_OPERATOR_SEMICOLON, "Expected ';' at the end of break statement");
@@ -1070,7 +1101,11 @@ static void makeStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** ro
return; return;
} }
//URGENT: for-pre-clause-post-then //for
else if (match(parser, TOY_TOKEN_KEYWORD_FOR)) {
makeForStmt(bucketHandle, parser, rootHandle);
return;
}
//break //break
else if (match(parser, TOY_TOKEN_KEYWORD_BREAK)) { else if (match(parser, TOY_TOKEN_KEYWORD_BREAK)) {
+1 -1
View File
@@ -29,7 +29,7 @@ typedef enum Toy_TokenType {
TOY_TOKEN_KEYWORD_DO, //unused TOY_TOKEN_KEYWORD_DO, //unused
TOY_TOKEN_KEYWORD_ELSE, TOY_TOKEN_KEYWORD_ELSE,
TOY_TOKEN_KEYWORD_EXPORT, //unused TOY_TOKEN_KEYWORD_EXPORT, //unused
TOY_TOKEN_KEYWORD_FOR, //unused TOY_TOKEN_KEYWORD_FOR,
TOY_TOKEN_KEYWORD_FOREACH, //unused TOY_TOKEN_KEYWORD_FOREACH, //unused
TOY_TOKEN_KEYWORD_FUNCTION, //remapped 'fn' TOY_TOKEN_KEYWORD_FUNCTION, //remapped 'fn'
TOY_TOKEN_KEYWORD_IF, TOY_TOKEN_KEYWORD_IF,
+1
View File
@@ -1060,6 +1060,7 @@ static unsigned int process(Toy_VM* vm) {
processIndex(vm); processIndex(vm);
break; break;
case TOY_OPCODE_ITERABLE: //tmp
case TOY_OPCODE_UNUSED: case TOY_OPCODE_UNUSED:
case TOY_OPCODE_PASS: case TOY_OPCODE_PASS:
case TOY_OPCODE_ERROR: case TOY_OPCODE_ERROR: