added "for x in y" loops

This commit is contained in:
2026-07-11 15:16:43 +10:00
parent f777d55775
commit 8ef6a4e649
6 changed files with 163 additions and 25 deletions

View File

@@ -519,11 +519,18 @@ void appendNodeToBuff(CometASTNode* node, StringBuffer* buff) {
sbAppend(buff, " "); sbAppend(buff, " ");
appendNodeToBuff(node->data.AST_FOR_STATEMENT.ident, buff); appendNodeToBuff(node->data.AST_FOR_STATEMENT.ident, buff);
sbAppend(buff, " in "); sbAppend(buff, " in ");
appendNodeToBuff(node->data.AST_FOR_STATEMENT.start, buff);
sbAppend(buff, ".."); if (node->data.AST_FOR_STATEMENT.array) {
appendNodeToBuff(node->data.AST_FOR_STATEMENT.end, buff); appendNodeToBuff(node->data.AST_FOR_STATEMENT.array, buff);
sbAppend(buff, " step "); } else {
appendNodeToBuff(node->data.AST_FOR_STATEMENT.step, buff); appendNodeToBuff(node->data.AST_FOR_STATEMENT.start, buff);
sbAppend(buff, "..");
appendNodeToBuff(node->data.AST_FOR_STATEMENT.end, buff);
sbAppend(buff, " step ");
appendNodeToBuff(node->data.AST_FOR_STATEMENT.step, buff);
}
sbAppend(buff, " {\n"); sbAppend(buff, " {\n");
appendNodeToBuff(node->data.AST_FOR_STATEMENT.program, buff); appendNodeToBuff(node->data.AST_FOR_STATEMENT.program, buff);
sbAppend(buff, " }"); sbAppend(buff, " }");

View File

@@ -108,6 +108,7 @@ struct CometASTNode {
CometASTNode* end; CometASTNode* end;
CometASTNode* step; CometASTNode* step;
CometASTNode* program; CometASTNode* program;
CometASTNode* array;
} AST_FOR_STATEMENT; } AST_FOR_STATEMENT;
struct AST_IF_STATEMENT { struct AST_IF_STATEMENT {
CometASTNode* expression; CometASTNode* expression;

View File

@@ -3857,6 +3857,105 @@ ResultType(CompiledValue, ErrorMessage) visitForStatement(CometCompiler* c, Come
}; };
append(c->loopContexts, loopContext); append(c->loopContexts, loopContext);
char* ident = forStmt.ident->data.AST_IDENTIFIER.ident;
// create env for for loop
CometEnvironment* forLoopEnv = newEnvironment("forLoop", c->env, false);
c->env = forLoopEnv;
ResultType(CometType, ErrorMessage) iterType = getType(c, forStmt.type);
if (iterType.error)
return Error(CompiledValue, ErrorMessage, iterType.as.error);
if (forStmt.array) { // we're looping over an array
// get array type
ResultType(CometType, ErrorMessage) arrayType = resolveType(c, forStmt.array);
if (arrayType.as.success.typeKind != COMET_ARRAY) {
ErrorMessage errMsg = createError(
c->inputFilePath,
c->sourceCode,
"TypeMismatch",
"Attempted to loop over something that isn't an array",
NULL,
forStmt.array->lineNum,
forStmt.array->startCol,
forStmt.array->endCol
);
return Error(CompiledValue, ErrorMessage, errMsg);
}
CometType elemType = *arrayType.as.success.arrayType->elem;
// build zero
CometOperand zeroVal = createOperand(CO_IMMEDIATE);
zeroVal.imm.typeKind = COMET_INT;
zeroVal.imm.intVal = 0;
CometOperand zeroConst = storeConst(c, zeroVal);
buildPushConst(c, zeroConst);
uint32_t idx = defineVar(c->env, "i", RECORD_LOCAL, zeroVal, iterType.as.success, false);
uint32_t currentValue = defineVar(c->env, ident, RECORD_LOCAL, zeroVal, elemType, false);
buildStore(c, idx);
resolveLabel(c, mainLabel);
// get iterator
buildLoad(c, idx);
// get list size
ResultType(CompiledValue, ErrorMessage) arrayVal = visitValue(c, forStmt.array);
if (arrayVal.error)
return arrayVal;
buildListLength(c);
buildEq(c, iterType.as.success);
buildJumpIfTrue(c, endLabel);
// get value
arrayVal = visitValue(c, forStmt.array);
if (arrayVal.error)
return arrayVal;
buildLoad(c, idx);
buildListAt(c);
buildStore(c, currentValue);
// compile the body of the for loop
ResultType(CompiledValue, ErrorMessage) bodyResult = compile(c, forStmt.program);
if (bodyResult.error)
return bodyResult;
resolveLabel(c, continueLabel);
buildLoad(c, idx);
// build one
CometOperand oneVal = createOperand(CO_IMMEDIATE);
oneVal.imm.typeKind = COMET_SMALL;
oneVal.imm.smallVal = 1;
CometOperand oneConst = storeConst(c, oneVal);
buildPushConst(c, oneConst);
// add the one to the iterator var
buildAdd(c, iterType.as.success);
// save the iterator value
buildStore(c, idx);
// jump back to the start of the for loop
buildJump(c, mainLabel);
resolveLabel(c, endLabel);
// exit the for loop's env
c->env = destroyEnv(forLoopEnv);
pop(c->loopContexts);
return Success(CompiledValue, ErrorMessage, NO_VALUE);
}
// resolve start and end types // resolve start and end types
ResultType(CometType, ErrorMessage) startType = resolveType(c, forStmt.start); ResultType(CometType, ErrorMessage) startType = resolveType(c, forStmt.start);
if (startType.error) if (startType.error)
@@ -3866,11 +3965,7 @@ ResultType(CompiledValue, ErrorMessage) visitForStatement(CometCompiler* c, Come
return Error(CompiledValue, ErrorMessage, endType.as.error); return Error(CompiledValue, ErrorMessage, endType.as.error);
CometType resultType = unifyType(startType.as.success, endType.as.success); CometType resultType = unifyType(startType.as.success, endType.as.success);
char* ident = forStmt.ident->data.AST_IDENTIFIER.ident;
// create env for for loop
CometEnvironment* forLoopEnv = newEnvironment("forLoop", c->env, false);
c->env = forLoopEnv;
// define iterator variable // define iterator variable
ResultType(CompiledValue, ErrorMessage) start = visitValue(c, forStmt.start); ResultType(CompiledValue, ErrorMessage) start = visitValue(c, forStmt.start);
@@ -3909,7 +4004,7 @@ ResultType(CompiledValue, ErrorMessage) visitForStatement(CometCompiler* c, Come
if (step.error) if (step.error)
return Error(CompiledValue, ErrorMessage, step.as.error); return Error(CompiledValue, ErrorMessage, step.as.error);
CometType addType = unifyType(startType.as.success, stepType.as.success); CometType addType = unifyType(iterType.as.success, stepType.as.success);
// add the step to the iterator var // add the step to the iterator var
buildAdd(c, addType); buildAdd(c, addType);

View File

@@ -473,6 +473,9 @@ CometASTNode* controlFlowSimplify(CometCompiler* c, CometASTNode* ast) {
if (expr->nodeType == AST_BOOL && expr->data.AST_BOOL.value == false) { if (expr->nodeType == AST_BOOL && expr->data.AST_BOOL.value == false) {
return NULL; return NULL;
} }
ast->data.AST_IF_STATEMENT.program = controlFlowSimplify(c, ast->data.AST_IF_STATEMENT.program);
break; break;
} }
@@ -482,6 +485,14 @@ CometASTNode* controlFlowSimplify(CometCompiler* c, CometASTNode* ast) {
if (expr->nodeType == AST_BOOL && expr->data.AST_BOOL.value == false) { if (expr->nodeType == AST_BOOL && expr->data.AST_BOOL.value == false) {
return NULL; return NULL;
} }
ast->data.AST_WHILE_STATEMENT.program = controlFlowSimplify(c, ast->data.AST_WHILE_STATEMENT.program);
break;
}
case AST_FOR_STATEMENT: {
ast->data.AST_FOR_STATEMENT.program = controlFlowSimplify(c, ast->data.AST_FOR_STATEMENT.program);
break; break;
} }

View File

@@ -1143,6 +1143,7 @@ ResultType(astNodePtr, ErrorMessage) parseWhileStatement(CometParser* parser) {
ResultType(astNodePtr, ErrorMessage) parseForStatement(CometParser* parser) { ResultType(astNodePtr, ErrorMessage) parseForStatement(CometParser* parser) {
// basic format // basic format
// for int i in 0 .. 10 {} // for int i in 0 .. 10 {}
// for int x in y {}
uint32_t lineNum = parser->currentToken->lineNum; uint32_t lineNum = parser->currentToken->lineNum;
uint32_t startCol = parser->currentToken->startCol; uint32_t startCol = parser->currentToken->startCol;
@@ -1174,6 +1175,35 @@ ResultType(astNodePtr, ErrorMessage) parseForStatement(CometParser* parser) {
parserNextToken(parser); parserNextToken(parser);
bool isArrayLoop = !currentTokenIs(parser, CT_DOT_DOT);
if (isArrayLoop) { // we're looping over an array
ResultType(astNodePtr, ErrorMessage) array = parseExpression(parser, PRECEDENCE_LOWEST);
if (array.error) {
return array;
}
ResultType(astNodePtr, ErrorMessage) block = parseOptionalBlockStatement(parser);
if (block.error) {
return block;
}
CometASTNode* stmt = AST_NODE(
AST_FOR_STATEMENT,
lineNum,
type.as.success,
ident,
NULL,
NULL,
NULL,
block.as.success,
array.as.success
);
stmt->startCol = startCol;
stmt->endCol = block.as.success->endCol;
return Success(astNodePtr, ErrorMessage, stmt);
}
ResultType(astNodePtr, ErrorMessage) start = parseExpression(parser, PRECEDENCE_LOWEST); ResultType(astNodePtr, ErrorMessage) start = parseExpression(parser, PRECEDENCE_LOWEST);
if (start.error) { if (start.error) {
return start; return start;
@@ -1217,7 +1247,8 @@ ResultType(astNodePtr, ErrorMessage) parseForStatement(CometParser* parser) {
start.as.success, start.as.success,
end.as.success, end.as.success,
stepNode.as.success, stepNode.as.success,
block.as.success block.as.success,
NULL
); );
stmt->startCol = startCol; stmt->startCol = startCol;
stmt->endCol = block.as.success->endCol; stmt->endCol = block.as.success->endCol;

View File

@@ -1,18 +1,11 @@
struct Foo { import io
int x = 5 + 5
func foo() -> int {
int f = 2 * 10
return 2 + 2 + f + self.x
}
init() {
}
}
func main() -> int { func main() -> int {
Foo f = new Foo() int[3] array = [1, 2, 3]
return f.foo() for int x in array {
io.println("%n", x)
}
return 0
} }