aboutsummaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/ast-tree.c69
-rw-r--r--src/compiler/ast-tree.h8
-rw-r--r--src/compiler/lexer.c5
-rw-r--r--src/compiler/lexer.h1
-rw-r--r--src/compiler/parser.c9
-rw-r--r--src/compiler/parser.h1
6 files changed, 86 insertions, 7 deletions
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,