diff options
-rw-r--r-- | code/main.felan | 7 | ||||
-rw-r--r-- | src/compiler/ast-tree.c | 69 | ||||
-rw-r--r-- | src/compiler/ast-tree.h | 8 | ||||
-rw-r--r-- | src/compiler/lexer.c | 5 | ||||
-rw-r--r-- | src/compiler/lexer.h | 1 | ||||
-rw-r--r-- | src/compiler/parser.c | 9 | ||||
-rw-r--r-- | src/compiler/parser.h | 1 | ||||
-rw-r--r-- | src/runner/runner.c | 161 | ||||
-rw-r--r-- | src/runner/runner.h | 2 |
9 files changed, 185 insertions, 78 deletions
diff --git a/code/main.felan b/code/main.felan index 890e402..1a87625 100644 --- a/code/main.felan +++ b/code/main.felan @@ -3,8 +3,13 @@ main :: () -> void { i := 0; while i < 10 { + if i == 7 + break; + else if i % 2 == 0 { + i += 1; + continue; + } putc @cast(i,u8)+'0'; i += 1; - break; } }; diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c index e0c9c71..3640236 100644 --- a/src/compiler/ast-tree.c +++ b/src/compiler/ast-tree.c @@ -151,6 +151,7 @@ const char *AST_TREE_TOKEN_STRINGS[] = { "AST_TREE_TOKEN_KEYWORD_PUTC", "AST_TREE_TOKEN_KEYWORD_RETURN", "AST_TREE_TOKEN_KEYWORD_BREAK", + "AST_TREE_TOKEN_KEYWORD_CONTINUE", "AST_TREE_TOKEN_KEYWORD_IF", "AST_TREE_TOKEN_KEYWORD_WHILE", "AST_TREE_TOKEN_KEYWORD_COMPTIME", @@ -312,8 +313,12 @@ void astTreePrint(const AstTree *tree, int indent) { case AST_TREE_TOKEN_VALUE_NULL: case AST_TREE_TOKEN_VALUE_UNDEFINED: case AST_TREE_TOKEN_VARIABLE_DEFINE: - case AST_TREE_TOKEN_KEYWORD_BREAK: goto RETURN_SUCCESS; + case AST_TREE_TOKEN_KEYWORD_BREAK: + case AST_TREE_TOKEN_KEYWORD_CONTINUE: { + AstTreeLoopControl *meatadata = tree->metadata; + printf("count=%d", meatadata->count); + } case AST_TREE_TOKEN_OPERATOR_LOGICAL_NOT: case AST_TREE_TOKEN_OPERATOR_PLUS: case AST_TREE_TOKEN_OPERATOR_MINUS: { @@ -734,8 +739,13 @@ void astTreeDestroy(AstTree tree) { case AST_TREE_TOKEN_VALUE_UNDEFINED: case AST_TREE_TOKEN_VALUE_VOID: case AST_TREE_TOKEN_VARIABLE_DEFINE: + return; case AST_TREE_TOKEN_KEYWORD_BREAK: + case AST_TREE_TOKEN_KEYWORD_CONTINUE: { + AstTreeLoopControl *meatadata = tree.metadata; + free(meatadata); return; + } case AST_TREE_TOKEN_VALUE_NAMESPACE: { AstTreeNamespace *metadata = tree.metadata; free(metadata); @@ -1019,7 +1029,6 @@ AstTree *copyAstTreeBack(AstTree *tree, AstTreeVariables oldVariables[], return tree; case AST_TREE_TOKEN_VALUE_NULL: case AST_TREE_TOKEN_VALUE_UNDEFINED: - case AST_TREE_TOKEN_KEYWORD_BREAK: case AST_TREE_TOKEN_BUILTIN_CAST: case AST_TREE_TOKEN_BUILTIN_TYPE_OF: case AST_TREE_TOKEN_BUILTIN_IMPORT: @@ -1042,7 +1051,18 @@ AstTree *copyAstTreeBack(AstTree *tree, AstTreeVariables oldVariables[], copyAstTreeBack(tree->type, oldVariables, newVariables, variables_size, safetyCheck), tree->str_begin, tree->str_end); + case AST_TREE_TOKEN_KEYWORD_BREAK: + case AST_TREE_TOKEN_KEYWORD_CONTINUE: { + AstTreeLoopControl *metadata = tree->metadata; + AstTreeLoopControl *new_metadata = a404m_malloc(sizeof(*new_metadata)); + new_metadata->count = metadata->count; + + return newAstTree(tree->token, new_metadata, + copyAstTreeBack(tree->type, oldVariables, newVariables, + variables_size, safetyCheck), + tree->str_begin, tree->str_end); + } case AST_TREE_TOKEN_VALUE_NAMESPACE: { AstTreeNamespace *metadata = tree->metadata; AstTreeNamespace *newMetadata = a404m_malloc(sizeof(*newMetadata)); @@ -1984,6 +2004,7 @@ AstTreeRoot *makeAstRoot(const ParserNode *parsedRoot, char *filePath) { case PARSER_TOKEN_KEYWORD_PUTC: case PARSER_TOKEN_KEYWORD_RETURN: case PARSER_TOKEN_KEYWORD_BREAK: + case PARSER_TOKEN_KEYWORD_CONTINUE: case PARSER_TOKEN_CONSTANT: case PARSER_TOKEN_VARIABLE: case PARSER_TOKEN_SYMBOL_EOL: @@ -2161,7 +2182,9 @@ AstTree *astTreeParse(const ParserNode *parserNode) { case PARSER_TOKEN_KEYWORD_UNDEFINED: return astTreeParseKeyword(parserNode, AST_TREE_TOKEN_VALUE_UNDEFINED); case PARSER_TOKEN_KEYWORD_BREAK: - return astTreeParseKeyword(parserNode, AST_TREE_TOKEN_KEYWORD_BREAK); + return astTreeParseLoopControl(parserNode, AST_TREE_TOKEN_KEYWORD_BREAK); + case PARSER_TOKEN_KEYWORD_CONTINUE: + return astTreeParseLoopControl(parserNode, AST_TREE_TOKEN_KEYWORD_CONTINUE); case PARSER_TOKEN_KEYWORD_PUTC: return astTreeParsePutc(parserNode); case PARSER_TOKEN_KEYWORD_RETURN: @@ -2367,6 +2390,7 @@ AstTree *astTreeParseFunction(const ParserNode *parserNode) { case PARSER_TOKEN_KEYWORD_PUTC: case PARSER_TOKEN_KEYWORD_RETURN: case PARSER_TOKEN_KEYWORD_BREAK: + case PARSER_TOKEN_KEYWORD_CONTINUE: case PARSER_TOKEN_KEYWORD_COMPTIME: case PARSER_TOKEN_KEYWORD_STRUCT: case PARSER_TOKEN_CONSTANT: @@ -2658,6 +2682,13 @@ AstTree *astTreeParseKeyword(const ParserNode *parserNode, AstTreeToken token) { parserNode->str_end); } +AstTree *astTreeParseLoopControl(const ParserNode *parserNode, + AstTreeToken token) { + AstTreeLoopControl *meatadata = a404m_malloc(sizeof(*meatadata)); + return newAstTree(token, meatadata, NULL, parserNode->str_begin, + parserNode->str_end); +} + AstTree *astTreeParsePutc(const ParserNode *parserNode) { ParserNodeSingleChildMetadata *node_metadata = parserNode->metadata; @@ -2986,6 +3017,7 @@ AstTree *astTreeParseCurlyBracket(const ParserNode *parserNode) { case PARSER_TOKEN_KEYWORD_PUTC: case PARSER_TOKEN_KEYWORD_RETURN: case PARSER_TOKEN_KEYWORD_BREAK: + case PARSER_TOKEN_KEYWORD_CONTINUE: case PARSER_TOKEN_KEYWORD_COMPTIME: case PARSER_TOKEN_KEYWORD_STRUCT: case PARSER_TOKEN_CONSTANT: @@ -3327,6 +3359,7 @@ bool isConst(AstTree *tree) { case AST_TREE_TOKEN_KEYWORD_PUTC: case AST_TREE_TOKEN_KEYWORD_RETURN: case AST_TREE_TOKEN_KEYWORD_BREAK: + case AST_TREE_TOKEN_KEYWORD_CONTINUE: case AST_TREE_TOKEN_VARIABLE_DEFINE: case AST_TREE_TOKEN_OPERATOR_ASSIGN: case AST_TREE_TOKEN_OPERATOR_PLUS: @@ -3552,6 +3585,7 @@ AstTree *makeTypeOf(AstTree *value) { case AST_TREE_TOKEN_KEYWORD_PUTC: case AST_TREE_TOKEN_KEYWORD_RETURN: case AST_TREE_TOKEN_KEYWORD_BREAK: + case AST_TREE_TOKEN_KEYWORD_CONTINUE: case AST_TREE_TOKEN_KEYWORD_IF: case AST_TREE_TOKEN_KEYWORD_WHILE: case AST_TREE_TOKEN_SCOPE: @@ -3629,6 +3663,7 @@ bool typeIsEqualBack(const AstTree *type0, const AstTree *type1) { case AST_TREE_TOKEN_KEYWORD_PUTC: case AST_TREE_TOKEN_KEYWORD_RETURN: case AST_TREE_TOKEN_KEYWORD_BREAK: + case AST_TREE_TOKEN_KEYWORD_CONTINUE: case AST_TREE_TOKEN_KEYWORD_IF: case AST_TREE_TOKEN_KEYWORD_WHILE: case AST_TREE_TOKEN_KEYWORD_COMPTIME: @@ -3853,6 +3888,7 @@ AstTree *getValue(AstTree *tree, bool copy) { case AST_TREE_TOKEN_SHAPE_SHIFTER_ELEMENT: { bool shouldRet = false; u32 breakCount = 0; + bool shouldContinue = false; AstTreeScope *scope = a404m_malloc(sizeof(*scope)); scope->expressions = a404m_malloc(0); scope->expressions_size = 0; @@ -3867,8 +3903,8 @@ AstTree *getValue(AstTree *tree, bool copy) { .str_end = NULL, }; - AstTree *value = - runExpression(tree, scope, &shouldRet, false, true, &breakCount); + AstTree *value = runExpression(tree, scope, &shouldRet, false, true, + &breakCount, &shouldContinue); if (!copy) { astTreeDelete(tree); @@ -3893,6 +3929,7 @@ AstTree *getValue(AstTree *tree, bool copy) { case AST_TREE_TOKEN_KEYWORD_PUTC: case AST_TREE_TOKEN_KEYWORD_RETURN: case AST_TREE_TOKEN_KEYWORD_BREAK: + case AST_TREE_TOKEN_KEYWORD_CONTINUE: case AST_TREE_TOKEN_VARIABLE_DEFINE: case AST_TREE_TOKEN_NONE: } @@ -3932,6 +3969,7 @@ bool isIntType(AstTree *type) { case AST_TREE_TOKEN_KEYWORD_PUTC: case AST_TREE_TOKEN_KEYWORD_RETURN: case AST_TREE_TOKEN_KEYWORD_BREAK: + case AST_TREE_TOKEN_KEYWORD_CONTINUE: case AST_TREE_TOKEN_KEYWORD_IF: case AST_TREE_TOKEN_KEYWORD_WHILE: case AST_TREE_TOKEN_KEYWORD_COMPTIME: @@ -4060,6 +4098,7 @@ bool isEqual(AstTree *left, AstTree *right) { case AST_TREE_TOKEN_KEYWORD_PUTC: case AST_TREE_TOKEN_KEYWORD_RETURN: case AST_TREE_TOKEN_KEYWORD_BREAK: + case AST_TREE_TOKEN_KEYWORD_CONTINUE: case AST_TREE_TOKEN_KEYWORD_IF: case AST_TREE_TOKEN_KEYWORD_WHILE: case AST_TREE_TOKEN_KEYWORD_COMPTIME: @@ -4304,6 +4343,8 @@ bool setAllTypes(AstTree *tree, AstTreeSetTypesHelper helper, return setTypesReturn(tree, helper, function); case AST_TREE_TOKEN_KEYWORD_BREAK: return setTypesBreak(tree, helper); + case AST_TREE_TOKEN_KEYWORD_CONTINUE: + return setTypesContinue(tree, helper); case AST_TREE_TOKEN_TYPE_FUNCTION: return setTypesTypeFunction(tree, helper); case AST_TREE_TOKEN_FUNCTION_CALL: @@ -4755,6 +4796,23 @@ bool setTypesBreak(AstTree *tree, AstTreeSetTypesHelper helper) { return false; } + AstTreeLoopControl *meatadata = tree->metadata; + meatadata->count = 1; + + tree->type = &AST_TREE_VOID_TYPE; + return true; +} + +bool setTypesContinue(AstTree *tree, AstTreeSetTypesHelper helper) { + if (helper.loops_size == 0) { + printError(tree->str_begin, tree->str_end, + "`continue` can't be here, it needs to be inside a loop"); + return false; + } + + AstTreeLoopControl *meatadata = tree->metadata; + meatadata->count = 1; + tree->type = &AST_TREE_VOID_TYPE; return true; } @@ -5058,7 +5116,6 @@ bool setTypesVariable(AstTree *tree, AstTreeSetTypesHelper helper, AstTreeVariable *variable = setTypesFindVariable( tree->str_begin, tree->str_end, helper, functionCall); if (variable == NULL) { - printError(tree->str_begin, tree->str_end, "No candidate found"); goto RETURN_ERROR; } diff --git a/src/compiler/ast-tree.h b/src/compiler/ast-tree.h index fd1f123..1330efa 100644 --- a/src/compiler/ast-tree.h +++ b/src/compiler/ast-tree.h @@ -28,6 +28,7 @@ typedef enum AstTreeToken { AST_TREE_TOKEN_KEYWORD_PUTC, AST_TREE_TOKEN_KEYWORD_RETURN, AST_TREE_TOKEN_KEYWORD_BREAK, + AST_TREE_TOKEN_KEYWORD_CONTINUE, AST_TREE_TOKEN_KEYWORD_IF, AST_TREE_TOKEN_KEYWORD_WHILE, AST_TREE_TOKEN_KEYWORD_COMPTIME, @@ -298,6 +299,10 @@ typedef struct AstTreeShapeShifterElement { size_t index; } AstTreeShapeShifterElement; +typedef struct AstTreeLoopControl { + u32 count; +} AstTreeLoopControl; + #ifdef PRINT_COMPILE_TREE void astTreePrint(const AstTree *tree, int indent); void astTreeVariablePrint(const AstTreeVariable *variable, int indent); @@ -358,6 +363,8 @@ AstTree *astTreeParseValue(const ParserNode *parserNode, AstTreeToken token, size_t metadata_size, AstTree *type); AstTree *astTreeParseString(const ParserNode *parserNode); AstTree *astTreeParseKeyword(const ParserNode *parserNode, AstTreeToken token); +AstTree *astTreeParseLoopControl(const ParserNode *parserNode, + AstTreeToken token); AstTree *astTreeParsePutc(const ParserNode *parserNode); AstTree *astTreeParseReturn(const ParserNode *parserNode); AstTree *astTreeParseBinaryOperator(const ParserNode *parserNode, @@ -411,6 +418,7 @@ bool setTypesPutc(AstTree *tree, AstTreeSetTypesHelper helper); bool setTypesReturn(AstTree *tree, AstTreeSetTypesHelper helper, AstTreeFunction *function); bool setTypesBreak(AstTree *tree, AstTreeSetTypesHelper helper); +bool setTypesContinue(AstTree *tree, AstTreeSetTypesHelper helper); bool setTypesTypeFunction(AstTree *tree, AstTreeSetTypesHelper helper); bool setTypesFunctionCall(AstTree *tree, AstTreeSetTypesHelper helper); bool setTypesVariable(AstTree *tree, AstTreeSetTypesHelper helper, diff --git a/src/compiler/lexer.c b/src/compiler/lexer.c index 517e650..6804080 100644 --- a/src/compiler/lexer.c +++ b/src/compiler/lexer.c @@ -100,6 +100,7 @@ const char *LEXER_TOKEN_STRINGS[] = { "LEXER_TOKEN_KEYWORD_RETURN", "LEXER_TOKEN_KEYWORD_PUTC", "LEXER_TOKEN_KEYWORD_BREAK", + "LEXER_TOKEN_KEYWORD_CONTINUE", "LEXER_TOKEN_KEYWORD_COMPTIME", "LEXER_TOKEN_SYMBOL_EOL", @@ -171,7 +172,7 @@ static const char *LEXER_KEYWORD_STRINGS[] = { "f32", "f64", "f128", "bool", "putc", "return", "true", "false", "if", "else", "while", "comptime", "null", "struct", "undefined", "code", "lazy", "namespace", - "shape_shifter", "break", + "shape_shifter", "break", "continue", }; static const LexerToken LEXER_KEYWORD_TOKENS[] = { LEXER_TOKEN_KEYWORD_TYPE, @@ -207,6 +208,7 @@ static const LexerToken LEXER_KEYWORD_TOKENS[] = { LEXER_TOKEN_KEYWORD_NAMESPACE, LEXER_TOKEN_KEYWORD_SHAPE_SHIFTER, LEXER_TOKEN_KEYWORD_BREAK, + LEXER_TOKEN_KEYWORD_CONTINUE, }; static const size_t LEXER_KEYWORD_SIZE = sizeof(LEXER_KEYWORD_TOKENS) / sizeof(*LEXER_KEYWORD_TOKENS); @@ -522,6 +524,7 @@ lexerPushClear(LexerNodeArray *array, size_t *array_size, char const *iter, case LEXER_TOKEN_SYMBOL_OPEN_BRACKET: case LEXER_TOKEN_KEYWORD_SHAPE_SHIFTER: case LEXER_TOKEN_KEYWORD_BREAK: + case LEXER_TOKEN_KEYWORD_CONTINUE: if (*array_size == array->size) { *array_size += 1 + *array_size / 2; array->data = diff --git a/src/compiler/lexer.h b/src/compiler/lexer.h index 641e7c8..0cc19cd 100644 --- a/src/compiler/lexer.h +++ b/src/compiler/lexer.h @@ -112,6 +112,7 @@ typedef enum LexerToken { LEXER_TOKEN_ORDER11 = LEXER_TOKEN_KEYWORD_RETURN, LEXER_TOKEN_KEYWORD_PUTC, LEXER_TOKEN_KEYWORD_BREAK, + LEXER_TOKEN_KEYWORD_CONTINUE, LEXER_TOKEN_KEYWORD_COMPTIME, LEXER_TOKEN_SYMBOL_EOL, diff --git a/src/compiler/parser.c b/src/compiler/parser.c index 4193fd3..b7a6e46 100644 --- a/src/compiler/parser.c +++ b/src/compiler/parser.c @@ -61,6 +61,7 @@ const char *PARSER_TOKEN_STRINGS[] = { "PARSER_TOKEN_KEYWORD_PUTC", "PARSER_TOKEN_KEYWORD_BREAK", + "PARSER_TOKEN_KEYWORD_CONTINUE", "PARSER_TOKEN_KEYWORD_RETURN", "PARSER_TOKEN_KEYWORD_IF", "PARSER_TOKEN_KEYWORD_WHILE", @@ -282,6 +283,7 @@ void parserNodePrint(const ParserNode *node, int indent) { case PARSER_TOKEN_KEYWORD_NULL: case PARSER_TOKEN_KEYWORD_UNDEFINED: case PARSER_TOKEN_KEYWORD_BREAK: + case PARSER_TOKEN_KEYWORD_CONTINUE: goto RETURN_SUCCESS; case PARSER_TOKEN_VALUE_INT: { ParserNodeIntMetadata *metadata = node->metadata; @@ -586,6 +588,7 @@ void parserNodeDelete(ParserNode *node) { case PARSER_TOKEN_KEYWORD_NULL: case PARSER_TOKEN_KEYWORD_UNDEFINED: case PARSER_TOKEN_KEYWORD_BREAK: + case PARSER_TOKEN_KEYWORD_CONTINUE: goto RETURN_SUCCESS; case PARSER_TOKEN_VALUE_BOOL: { ParserNodeBoolMetadata *metadata = node->metadata; @@ -929,6 +932,8 @@ ParserNode *parseNode(LexerNode *node, LexerNode *begin, LexerNode *end, return parserNoMetadata(node, parent, PARSER_TOKEN_KEYWORD_UNDEFINED); case LEXER_TOKEN_KEYWORD_BREAK: return parserNoMetadata(node, parent, PARSER_TOKEN_KEYWORD_BREAK); + case LEXER_TOKEN_KEYWORD_CONTINUE: + return parserNoMetadata(node, parent, PARSER_TOKEN_KEYWORD_CONTINUE); case LEXER_TOKEN_KEYWORD_PUTC: return parserPutc(node, end, parent); case LEXER_TOKEN_KEYWORD_RETURN: @@ -1720,6 +1725,7 @@ ParserNode *parserFunction(LexerNode *node, LexerNode *begin, LexerNode *end, case PARSER_TOKEN_KEYWORD_NULL: case PARSER_TOKEN_KEYWORD_UNDEFINED: case PARSER_TOKEN_KEYWORD_BREAK: + case PARSER_TOKEN_KEYWORD_CONTINUE: case PARSER_TOKEN_KEYWORD_PUTC: case PARSER_TOKEN_KEYWORD_RETURN: case PARSER_TOKEN_KEYWORD_STRUCT: @@ -2258,6 +2264,7 @@ bool isExpression(ParserNode *node) { case PARSER_TOKEN_KEYWORD_NULL: case PARSER_TOKEN_KEYWORD_UNDEFINED: case PARSER_TOKEN_KEYWORD_BREAK: + case PARSER_TOKEN_KEYWORD_CONTINUE: case PARSER_TOKEN_KEYWORD_STRUCT: return true; case PARSER_TOKEN_ROOT: @@ -2340,6 +2347,7 @@ bool isType(ParserNode *node) { case PARSER_TOKEN_KEYWORD_PUTC: case PARSER_TOKEN_KEYWORD_RETURN: case PARSER_TOKEN_KEYWORD_BREAK: + case PARSER_TOKEN_KEYWORD_CONTINUE: case PARSER_TOKEN_OPERATOR_ASSIGN: case PARSER_TOKEN_OPERATOR_SUM_ASSIGN: case PARSER_TOKEN_OPERATOR_SUB_ASSIGN: @@ -2463,6 +2471,7 @@ bool isValue(ParserNode *node) { case PARSER_TOKEN_KEYWORD_PUTC: case PARSER_TOKEN_KEYWORD_RETURN: case PARSER_TOKEN_KEYWORD_BREAK: + case PARSER_TOKEN_KEYWORD_CONTINUE: case PARSER_TOKEN_KEYWORD_WHILE: return false; case PARSER_TOKEN_NONE: diff --git a/src/compiler/parser.h b/src/compiler/parser.h index 4a1b5ac..a322747 100644 --- a/src/compiler/parser.h +++ b/src/compiler/parser.h @@ -58,6 +58,7 @@ typedef enum ParserToken { PARSER_TOKEN_KEYWORD_PUTC, PARSER_TOKEN_KEYWORD_BREAK, + PARSER_TOKEN_KEYWORD_CONTINUE, PARSER_TOKEN_KEYWORD_RETURN, PARSER_TOKEN_KEYWORD_IF, PARSER_TOKEN_KEYWORD_WHILE, diff --git a/src/runner/runner.c b/src/runner/runner.c index 847c6b2..63c8435 100644 --- a/src/runner/runner.c +++ b/src/runner/runner.c @@ -95,21 +95,23 @@ AstTree *runAstTreeFunction(AstTree *tree, AstTreeFunctionCallParam *arguments, bool shouldRet = false; u32 breakCount = 0; + bool shouldContinue = false; for (size_t i = 0; i < arguments_size; ++i) { AstTreeFunctionCallParam param = arguments[i]; AstTreeVariable *arg = function->arguments.data[i]; - AstTree *value = runExpression(param.value, &function->scope, &shouldRet, - false, isComptime, &breakCount); + AstTree *value = + runExpression(param.value, &function->scope, &shouldRet, false, + isComptime, &breakCount, &shouldContinue); runnerVariableSetValueWihtoutConstCheck(arg, value); } shouldRet = false; for (size_t i = 0; i < function->scope.expressions_size; ++i) { - AstTree *ret = - runExpression(function->scope.expressions[i], &function->scope, - &shouldRet, false, isComptime, &breakCount); + AstTree *ret = runExpression(function->scope.expressions[i], + &function->scope, &shouldRet, false, + isComptime, &breakCount, &shouldContinue); if (shouldRet) { return ret; } else { @@ -130,11 +132,12 @@ AstTree *runAstTreeBuiltin(AstTree *tree, AstTreeScope *scope, bool shouldRet = false; u32 breakCount = 0; + bool shouldContinue = false; for (size_t i = 0; i < arguments_size; ++i) { AstTreeFunctionCallParam param = arguments[i]; args.data[i] = runExpression(param.value, scope, &shouldRet, false, - isComptime, &breakCount); + isComptime, &breakCount, &shouldContinue); } if (shouldRet) { @@ -386,8 +389,8 @@ AstTree *runAstTreeBuiltin(AstTree *tree, AstTreeScope *scope, case AST_TREE_TOKEN_BUILTIN_NEG: { AstTree *value = args.data[0]; bool shouldRet = false; - ret = - runExpression(value, scope, &shouldRet, false, isComptime, &breakCount); + ret = runExpression(value, scope, &shouldRet, false, isComptime, + &breakCount, &shouldContinue); switch (value->type->token) { case AST_TREE_TOKEN_TYPE_I8: *(i8 *)ret->metadata = -*(i8 *)ret->metadata; @@ -435,9 +438,9 @@ AstTree *runAstTreeBuiltin(AstTree *tree, AstTreeScope *scope, case AST_TREE_TOKEN_BUILTIN_ADD: { bool shouldRet = false; ret = runExpression(args.data[0], scope, &shouldRet, false, isComptime, - &breakCount); + &breakCount, &shouldContinue); AstTree *right = runExpression(args.data[1], scope, &shouldRet, false, - isComptime, &breakCount); + isComptime, &breakCount, &shouldContinue); switch (ret->type->token) { case AST_TREE_TOKEN_TYPE_I8: @@ -488,9 +491,9 @@ AstTree *runAstTreeBuiltin(AstTree *tree, AstTreeScope *scope, case AST_TREE_TOKEN_BUILTIN_SUB: { bool shouldRet = false; ret = runExpression(args.data[0], scope, &shouldRet, false, isComptime, - &breakCount); + &breakCount, &shouldContinue); AstTree *right = runExpression(args.data[1], scope, &shouldRet, false, - isComptime, &breakCount); + isComptime, &breakCount, &shouldContinue); switch (ret->type->token) { case AST_TREE_TOKEN_TYPE_I8: @@ -541,9 +544,9 @@ AstTree *runAstTreeBuiltin(AstTree *tree, AstTreeScope *scope, case AST_TREE_TOKEN_BUILTIN_MUL: { bool shouldRet = false; ret = runExpression(args.data[0], scope, &shouldRet, false, isComptime, - &breakCount); + &breakCount, &shouldContinue); AstTree *right = runExpression(args.data[1], scope, &shouldRet, false, - isComptime, &breakCount); + isComptime, &breakCount, &shouldContinue); switch (ret->type->token) { case AST_TREE_TOKEN_TYPE_I8: @@ -594,9 +597,9 @@ AstTree *runAstTreeBuiltin(AstTree *tree, AstTreeScope *scope, case AST_TREE_TOKEN_BUILTIN_DIV: { bool shouldRet = false; ret = runExpression(args.data[0], scope, &shouldRet, false, isComptime, - &breakCount); + &breakCount, &shouldContinue); AstTree *right = runExpression(args.data[1], scope, &shouldRet, false, - isComptime, &breakCount); + isComptime, &breakCount, &shouldContinue); switch (ret->type->token) { case AST_TREE_TOKEN_TYPE_I8: @@ -647,9 +650,9 @@ AstTree *runAstTreeBuiltin(AstTree *tree, AstTreeScope *scope, case AST_TREE_TOKEN_BUILTIN_MOD: { bool shouldRet = false; ret = runExpression(args.data[0], scope, &shouldRet, false, isComptime, - &breakCount); + &breakCount, &shouldContinue); AstTree *right = runExpression(args.data[1], scope, &shouldRet, false, - isComptime, &breakCount); + isComptime, &breakCount, &shouldContinue); switch (ret->type->token) { case AST_TREE_TOKEN_TYPE_I8: @@ -685,9 +688,9 @@ AstTree *runAstTreeBuiltin(AstTree *tree, AstTreeScope *scope, case AST_TREE_TOKEN_BUILTIN_EQUAL: { bool shouldRet = false; AstTree *left = runExpression(args.data[0], scope, &shouldRet, false, - isComptime, &breakCount); + isComptime, &breakCount, &shouldContinue); AstTree *right = runExpression(args.data[1], scope, &shouldRet, false, - isComptime, &breakCount); + isComptime, &breakCount, &shouldContinue); ret = newAstTree(AST_TREE_TOKEN_VALUE_BOOL, a404m_malloc(sizeof(AstTreeBool)), @@ -761,9 +764,9 @@ AstTree *runAstTreeBuiltin(AstTree *tree, AstTreeScope *scope, case AST_TREE_TOKEN_BUILTIN_NOT_EQUAL: { bool shouldRet = false; AstTree *left = runExpression(args.data[0], scope, &shouldRet, false, - isComptime, &breakCount); + isComptime, &breakCount, &shouldContinue); AstTree *right = runExpression(args.data[1], scope, &shouldRet, false, - isComptime, &breakCount); + isComptime, &breakCount, &shouldContinue); ret = newAstTree(AST_TREE_TOKEN_VALUE_BOOL, a404m_malloc(sizeof(AstTreeBool)), @@ -837,9 +840,9 @@ AstTree *runAstTreeBuiltin(AstTree *tree, AstTreeScope *scope, case AST_TREE_TOKEN_BUILTIN_GREATER: { bool shouldRet = false; AstTree *left = runExpression(args.data[0], scope, &shouldRet, false, - isComptime, &breakCount); + isComptime, &breakCount, &shouldContinue); AstTree *right = runExpression(args.data[1], scope, &shouldRet, false, - isComptime, &breakCount); + isComptime, &breakCount, &shouldContinue); ret = newAstTree(AST_TREE_TOKEN_VALUE_BOOL, a404m_malloc(sizeof(AstTreeBool)), @@ -906,9 +909,9 @@ AstTree *runAstTreeBuiltin(AstTree *tree, AstTreeScope *scope, case AST_TREE_TOKEN_BUILTIN_SMALLER: { bool shouldRet = false; AstTree *left = runExpression(args.data[0], scope, &shouldRet, false, - isComptime, &breakCount); + isComptime, &breakCount, &shouldContinue); AstTree *right = runExpression(args.data[1], scope, &shouldRet, false, - isComptime, &breakCount); + isComptime, &breakCount, &shouldContinue); ret = newAstTree(AST_TREE_TOKEN_VALUE_BOOL, a404m_malloc(sizeof(AstTreeBool)), @@ -975,9 +978,9 @@ AstTree *runAstTreeBuiltin(AstTree *tree, AstTreeScope *scope, case AST_TREE_TOKEN_BUILTIN_GREATER_OR_EQUAL: { bool shouldRet = false; AstTree *left = runExpression(args.data[0], scope, &shouldRet, false, - isComptime, &breakCount); + isComptime, &breakCount, &shouldContinue); AstTree *right = runExpression(args.data[1], scope, &shouldRet, false, - isComptime, &breakCount); + isComptime, &breakCount, &shouldContinue); ret = newAstTree(AST_TREE_TOKEN_VALUE_BOOL, a404m_malloc(sizeof(AstTreeBool)), @@ -1048,9 +1051,9 @@ AstTree *runAstTreeBuiltin(AstTree *tree, AstTreeScope *scope, case AST_TREE_TOKEN_BUILTIN_SMALLER_OR_EQUAL: { bool shouldRet = false; AstTree *left = runExpression(args.data[0], scope, &shouldRet, false, - isComptime, &breakCount); + isComptime, &breakCount, &shouldContinue); AstTree *right = runExpression(args.data[1], scope, &shouldRet, false, - isComptime, &breakCount); + isComptime, &breakCount, &shouldContinue); ret = newAstTree(AST_TREE_TOKEN_VALUE_BOOL, a404m_malloc(sizeof(AstTreeBool)), @@ -1133,20 +1136,22 @@ RETURN: } AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, - bool isLeft, bool isComptime, u32 *breakCount) { + bool isLeft, bool isComptime, u32 *breakCount, + bool *shouldContinue) { switch (expr->token) { case AST_TREE_TOKEN_KEYWORD_PUTC: { AstTreeSingleChild *metadata = expr->metadata; AstTree *tree = runExpression(metadata, scope, shouldRet, false, isComptime, - breakCount); + breakCount, shouldContinue); putchar((u8) * (AstTreeInt *)tree->metadata); astTreeDelete(tree); return &AST_TREE_VOID_VALUE; } case AST_TREE_TOKEN_FUNCTION_CALL: { AstTreeFunctionCall *metadata = expr->metadata; - AstTree *function = runExpression(metadata->function, scope, shouldRet, - false, isComptime, breakCount); + AstTree *function = + runExpression(metadata->function, scope, shouldRet, false, isComptime, + breakCount, shouldContinue); AstTree *result; if (function->token == AST_TREE_TOKEN_FUNCTION) { result = runAstTreeFunction(function, metadata->parameters, @@ -1177,14 +1182,14 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, case AST_TREE_TOKEN_OPERATOR_ASSIGN: { AstTreeInfix *metadata = expr->metadata; AstTree *l = runExpression(metadata->left, scope, shouldRet, true, - isComptime, breakCount); + isComptime, breakCount, shouldContinue); if (l->token != AST_TREE_TOKEN_VARIABLE) { UNREACHABLE; } AstTreeVariable *left = l->metadata; - runnerVariableSetValue(left, - runExpression(metadata->right, scope, shouldRet, - false, isComptime, breakCount)); + runnerVariableSetValue(left, runExpression(metadata->right, scope, + shouldRet, false, isComptime, + breakCount, shouldContinue)); astTreeDelete(l); return copyAstTree(left->value); } @@ -1193,7 +1198,7 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, *shouldRet = true; if (metadata->value != NULL) { return runExpression(metadata->value, scope, shouldRet, false, isComptime, - breakCount); + breakCount, shouldContinue); } else { return &AST_TREE_VOID_VALUE; } @@ -1205,22 +1210,23 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, value = copyAstTree(variable->initValue); } else { value = runExpression(variable->initValue, scope, shouldRet, false, - isComptime, breakCount); + isComptime, breakCount, shouldContinue); } runnerVariableSetValue(variable, value); return &AST_TREE_VOID_VALUE; } case AST_TREE_TOKEN_KEYWORD_IF: { AstTreeIf *metadata = expr->metadata; - AstTree *condition = runExpression(metadata->condition, scope, shouldRet, - false, isComptime, breakCount); + AstTree *condition = + runExpression(metadata->condition, scope, shouldRet, false, isComptime, + breakCount, shouldContinue); AstTree *ret; if (*(AstTreeBool *)condition->metadata) { ret = runExpression(metadata->ifBody, scope, shouldRet, isLeft, - isComptime, breakCount); + isComptime, breakCount, shouldContinue); } else if (metadata->elseBody != NULL) { ret = runExpression(metadata->elseBody, scope, shouldRet, isLeft, - isComptime, breakCount); + isComptime, breakCount, shouldContinue); } else { ret = &AST_TREE_VOID_VALUE; } @@ -1231,8 +1237,9 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, AstTreeWhile *metadata = expr->metadata; AstTree *ret = &AST_TREE_VOID_VALUE; while (!*shouldRet) { - AstTree *tree = runExpression(metadata->condition, scope, shouldRet, - false, isComptime, breakCount); + AstTree *tree = + runExpression(metadata->condition, scope, shouldRet, false, + isComptime, breakCount, shouldContinue); bool conti = *(AstTreeBool *)tree->metadata; astTreeDelete(tree); if (!conti) { @@ -1240,8 +1247,11 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, } astTreeDelete(ret); ret = runExpression(metadata->body, scope, shouldRet, isLeft, isComptime, - breakCount); - if (*breakCount != 0) { + breakCount, shouldContinue); + if (*breakCount == 1 && *shouldContinue) { + *breakCount -= 1; + *shouldContinue = false; + } else if (*breakCount != 0) { *breakCount -= 1; break; } @@ -1251,7 +1261,7 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, case AST_TREE_TOKEN_KEYWORD_COMPTIME: { AstTreeSingleChild *operand = expr->metadata; return runExpression((AstTree *)operand, scope, shouldRet, isLeft, - isComptime, breakCount); + isComptime, breakCount, shouldContinue); } case AST_TREE_TOKEN_SCOPE: { AstTreeScope *metadata = expr->metadata; @@ -1261,7 +1271,10 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, astTreeDelete(ret); ret = runExpression(metadata->expressions[i], scope, shouldRet, i == metadata->expressions_size - 1 && isLeft, - isComptime, breakCount); + isComptime, breakCount, shouldContinue); + if (*breakCount > 0) { + break; + } } return ret; } @@ -1269,8 +1282,9 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, case AST_TREE_TOKEN_OPERATOR_MINUS: case AST_TREE_TOKEN_OPERATOR_PLUS: { AstTreeUnary *metadata = expr->metadata; - AstTree *function = runExpression(metadata->function->value, scope, - shouldRet, false, isComptime, breakCount); + AstTree *function = + runExpression(metadata->function->value, scope, shouldRet, false, + isComptime, breakCount, shouldContinue); AstTreeFunctionCallParam arguments[] = { (AstTreeFunctionCallParam){ .nameBegin = NULL, @@ -1296,8 +1310,9 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, case AST_TREE_TOKEN_OPERATOR_LOGICAL_AND: case AST_TREE_TOKEN_OPERATOR_LOGICAL_OR: { AstTreeInfix *metadata = expr->metadata; - AstTree *function = runExpression(metadata->function->value, scope, - shouldRet, false, isComptime, breakCount); + AstTree *function = + runExpression(metadata->function->value, scope, shouldRet, false, + isComptime, breakCount, shouldContinue); AstTreeFunctionCallParam arguments[] = { (AstTreeFunctionCallParam){ @@ -1382,7 +1397,7 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, case AST_TREE_TOKEN_OPERATOR_DEREFERENCE: { AstTreeSingleChild *metadata = expr->metadata; AstTree *operand = runExpression(metadata, scope, shouldRet, false, - isComptime, breakCount); + isComptime, breakCount, shouldContinue); if (operand->token != AST_TREE_TOKEN_VARIABLE) { printLog("%s", AST_TREE_TOKEN_STRINGS[operand->token]); UNREACHABLE; @@ -1407,7 +1422,7 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, } if (variable->isLazy) { return runExpression(variable->value, scope, shouldRet, false, - isComptime, breakCount); + isComptime, breakCount, shouldContinue); } else { return copyAstTree(variable->value); } @@ -1416,7 +1431,7 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, case AST_TREE_TOKEN_OPERATOR_ACCESS: { AstTreeAccess *metadata = expr->metadata; AstTree *tree = runExpression(metadata->object, scope, shouldRet, true, - isComptime, breakCount); + isComptime, breakCount, shouldContinue); if (tree->token != AST_TREE_TOKEN_VARIABLE) { UNREACHABLE; } @@ -1430,9 +1445,9 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, if (array_metadata->parameters.size == 0) { UNREACHABLE; } else { - AstTree *sizeTree = - runExpression(array_metadata->parameters.data[0], scope, - shouldRet, false, isComptime, breakCount); + AstTree *sizeTree = runExpression(array_metadata->parameters.data[0], + scope, shouldRet, false, isComptime, + breakCount, shouldContinue); if (sizeTree->token != AST_TREE_TOKEN_VALUE_INT) { UNREACHABLE; } else { @@ -1489,7 +1504,7 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, AstTreeVariable *member = metadata->variables.data[i]; AstTree *type = member->type; member->type = runExpression(member->type, scope, shouldRet, isLeft, - isComptime, breakCount); + isComptime, breakCount, shouldContinue); if (type != member->type) { astTreeDelete(type); } @@ -1498,8 +1513,9 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, } case AST_TREE_TOKEN_OPERATOR_POINTER: { AstTreeSingleChild *metadata = expr->metadata; - AstTreeSingleChild *newMetadata = runExpression( - metadata, scope, shouldRet, isLeft, isComptime, breakCount); + AstTreeSingleChild *newMetadata = + runExpression(metadata, scope, shouldRet, isLeft, isComptime, + breakCount, shouldContinue); return newAstTree(AST_TREE_TOKEN_OPERATOR_POINTER, newMetadata, copyAstTree(expr->type), expr->str_begin, expr->str_end); @@ -1507,7 +1523,7 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, case AST_TREE_TOKEN_OPERATOR_ARRAY_ACCESS: { AstTreeBracket *metadata = expr->metadata; AstTree *operand = runExpression(metadata->operand, scope, shouldRet, true, - isComptime, breakCount); + isComptime, breakCount, shouldContinue); if (operand->token != AST_TREE_TOKEN_VARIABLE) { UNREACHABLE; @@ -1517,7 +1533,7 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, AstTree *array_indexNode = runExpression(metadata->parameters.data[0], scope, shouldRet, false, - isComptime, breakCount); + isComptime, breakCount, shouldContinue); if (array_indexNode->token != AST_TREE_TOKEN_VALUE_INT) { UNREACHABLE; @@ -1533,9 +1549,9 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, if (array_type_metadata->parameters.size != 1) { UNREACHABLE; } - AstTree *arraySize_tree = - runExpression(array_type_metadata->parameters.data[0], scope, - shouldRet, false, isComptime, breakCount); + AstTree *arraySize_tree = runExpression( + array_type_metadata->parameters.data[0], scope, shouldRet, false, + isComptime, breakCount, shouldContinue); if (arraySize_tree->token != AST_TREE_TOKEN_VALUE_INT) { UNREACHABLE; } @@ -1601,7 +1617,14 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, copyAstTree(expr->type), expr->str_begin, expr->str_end); } case AST_TREE_TOKEN_KEYWORD_BREAK: { - *breakCount += 1; + AstTreeLoopControl *metadata = expr->metadata; + *breakCount = metadata->count; + return copyAstTree(&AST_TREE_VOID_VALUE); + } + case AST_TREE_TOKEN_KEYWORD_CONTINUE: { + AstTreeLoopControl *metadata = expr->metadata; + *breakCount = metadata->count; + *shouldContinue = true; return copyAstTree(&AST_TREE_VOID_VALUE); } case AST_TREE_TOKEN_NONE: diff --git a/src/runner/runner.h b/src/runner/runner.h index df8ff21..5a12db3 100644 --- a/src/runner/runner.h +++ b/src/runner/runner.h @@ -17,4 +17,4 @@ AstTree *runAstTreeBuiltin(AstTree *tree, AstTreeScope *scope, size_t arguments_size, bool isComptime); AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, - bool isLeft, bool isComptime, u32 *breakCount); + bool isLeft, bool isComptime, u32 *breakCount,bool *shouldContinue); |