summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler/ast-tree.c191
-rw-r--r--src/compiler/ast-tree.h17
-rw-r--r--src/compiler/lexer.c7
-rw-r--r--src/compiler/lexer.h1
-rw-r--r--src/compiler/parser.c107
-rw-r--r--src/compiler/parser.h5
-rw-r--r--src/main.c2
-rw-r--r--src/runner/runner.c181
-rw-r--r--src/runner/runner.h2
9 files changed, 404 insertions, 109 deletions
diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c
index f92b95c..aeb1391 100644
--- a/src/compiler/ast-tree.c
+++ b/src/compiler/ast-tree.c
@@ -222,12 +222,27 @@ void astTreePrint(const AstTree *tree, int indent) {
for (int i = 0; i < indent; ++i)
printf(" ");
printf("body=\n");
- astTreePrint(metadata->body, indent + 1);
+ astTreePrint(metadata->ifBody, indent + 1);
printf("\n");
for (int i = 0; i < indent; ++i)
printf(" ");
}
goto RETURN_SUCCESS;
+ case AST_TREE_TOKEN_SCOPE: {
+ AstTreeScope *metadata = tree->metadata;
+ printf(",\n");
+ for (int i = 0; i < indent; ++i)
+ printf(" ");
+ printf("expressions=[\n");
+ for (size_t i = 0; i < metadata->expressions_size; ++i) {
+ astTreePrint(metadata->expressions[i], indent + 1);
+ printf(",\n");
+ }
+ for (int i = 0; i < indent; ++i)
+ printf(" ");
+ printf("]");
+ }
+ goto RETURN_SUCCESS;
case AST_TREE_TOKEN_NONE:
}
@@ -332,10 +347,24 @@ void astTreeDestroy(AstTree tree) {
case AST_TREE_TOKEN_KEYWORD_IF: {
AstTreeIf *metadata = tree.metadata;
astTreeDelete(metadata->condition);
- astTreeDelete(metadata->body);
+ astTreeDelete(metadata->ifBody);
+ free(metadata);
+ }
+ return;
+ case AST_TREE_TOKEN_SCOPE: {
+ AstTreeScope *metadata = tree.metadata;
+ for (size_t i = 0; i < metadata->expressions_size; ++i) {
+ astTreeDelete(metadata->expressions[i]);
+ }
+ for (size_t i = 0; i < metadata->variables.size; ++i) {
+ astTreeVariableDelete(metadata->variables.data[i]);
+ }
+ free(metadata->expressions);
+ free(metadata->variables.data);
free(metadata);
}
return;
+
case AST_TREE_TOKEN_NONE:
}
UNREACHABLE;
@@ -793,9 +822,10 @@ AstTree *astTreeParse(ParserNode *parserNode, AstTreeHelper *helper) {
case PARSER_TOKEN_SYMBOL_EOL:
return astTreeParse((ParserNodeSingleChildMetadata *)parserNode->metadata,
helper);
+ case PARSER_TOKEN_SYMBOL_CURLY_BRACKET:
+ return astTreeParseCurlyBracket(parserNode, helper);
case PARSER_TOKEN_CONSTANT:
case PARSER_TOKEN_SYMBOL_PARENTHESIS:
- case PARSER_TOKEN_SYMBOL_CURLY_BRACKET:
case PARSER_TOKEN_SYMBOL_COMMA:
case PARSER_TOKEN_NONE:
case PARSER_TOKEN_ROOT:
@@ -1216,19 +1246,135 @@ AstTree *astTreeParseIf(ParserNode *parserNode, AstTreeHelper *helper) {
return NULL;
}
- AstTree *body = astTreeParse(node_metadata->body, helper);
- if (body == NULL) {
+ AstTree *ifBody = astTreeParse(node_metadata->ifBody, helper);
+ if (ifBody == NULL) {
return NULL;
}
+ AstTree *elseBody;
+ if(node_metadata->elseBody != NULL){
+ elseBody = astTreeParse(node_metadata->elseBody, helper);
+ if(elseBody == NULL){
+ return NULL;
+ }
+ }else{
+ elseBody = NULL;
+ }
+
AstTreeIf *metadata = a404m_malloc(sizeof(*metadata));
metadata->condition = condition;
- metadata->body = body;
+ metadata->ifBody = ifBody;
+ metadata->elseBody = elseBody;
return newAstTree(AST_TREE_TOKEN_KEYWORD_IF, metadata, NULL,
parserNode->str_begin, parserNode->str_end);
}
+AstTree *astTreeParseCurlyBracket(ParserNode *parserNode,
+ AstTreeHelper *p_helper) {
+ ParserNodeArray *body = parserNode->metadata;
+
+ size_t expressions_size = 0;
+
+ AstTreeScope *scope = a404m_malloc(sizeof(*scope));
+ scope->variables.data = a404m_malloc(0);
+ scope->variables.size = 0;
+ scope->expressions = a404m_malloc(0);
+ scope->expressions_size = 0;
+
+ size_t variables_size = p_helper->variables_size + 1;
+ AstTreeVariables *variables[variables_size];
+ for (size_t i = 0; i < p_helper->variables_size; ++i) {
+ variables[i] = p_helper->variables[i];
+ }
+ variables[variables_size - 1] = &scope->variables;
+
+ AstTreeHelper helper = {
+ .variables = variables,
+ .variables_size = variables_size,
+ .variable = p_helper->variable,
+ .globalDeps = p_helper->globalDeps,
+ };
+
+ for (size_t i = 0; i < body->size; ++i) {
+ ParserNode *node = body->data[i];
+ switch (node->token) {
+ case PARSER_TOKEN_SYMBOL_EOL:
+ node = (ParserNodeSingleChildMetadata *)node->metadata;
+ goto OK_NODE;
+ case PARSER_TOKEN_KEYWORD_IF:
+ goto OK_NODE;
+ case PARSER_TOKEN_ROOT:
+ case PARSER_TOKEN_IDENTIFIER:
+ case PARSER_TOKEN_VALUE_U64:
+ case PARSER_TOKEN_VALUE_BOOL:
+ case PARSER_TOKEN_TYPE_TYPE:
+ case PARSER_TOKEN_TYPE_FUNCTION:
+ case PARSER_TOKEN_TYPE_VOID:
+ case PARSER_TOKEN_TYPE_U64:
+ case PARSER_TOKEN_TYPE_BOOL:
+ case PARSER_TOKEN_KEYWORD_PRINT_U64:
+ case PARSER_TOKEN_KEYWORD_RETURN:
+ case PARSER_TOKEN_CONSTANT:
+ case PARSER_TOKEN_VARIABLE:
+ case PARSER_TOKEN_SYMBOL_CURLY_BRACKET:
+ case PARSER_TOKEN_SYMBOL_PARENTHESIS:
+ case PARSER_TOKEN_SYMBOL_COMMA:
+ case PARSER_TOKEN_OPERATOR_ASSIGN:
+ case PARSER_TOKEN_OPERATOR_PLUS:
+ case PARSER_TOKEN_OPERATOR_MINUS:
+ case PARSER_TOKEN_OPERATOR_SUM:
+ case PARSER_TOKEN_OPERATOR_SUB:
+ case PARSER_TOKEN_OPERATOR_MULTIPLY:
+ case PARSER_TOKEN_OPERATOR_DIVIDE:
+ case PARSER_TOKEN_OPERATOR_MODULO:
+ case PARSER_TOKEN_FUNCTION_DEFINITION:
+ case PARSER_TOKEN_FUNCTION_CALL:
+ printError(node->str_begin, node->str_end, "Unexpected %s",
+ PARSER_TOKEN_STRINGS[node->token]);
+ goto RETURN_ERROR;
+ case PARSER_TOKEN_NONE:
+ }
+ UNREACHABLE;
+ OK_NODE:
+
+ if (node->token == PARSER_TOKEN_CONSTANT) {
+ if (!astTreeParseConstant(node, &helper)) {
+ goto RETURN_ERROR;
+ }
+ } else {
+ AstTree *tree = astTreeParse(node, &helper);
+
+ if (tree == NULL) {
+ goto RETURN_ERROR;
+ }
+
+ if (expressions_size == scope->expressions_size) {
+ expressions_size += expressions_size / 2 + 1;
+ scope->expressions = a404m_realloc(
+ scope->expressions, expressions_size * sizeof(*scope->expressions));
+ }
+ scope->expressions[scope->expressions_size] = tree;
+ scope->expressions_size += 1;
+ }
+ }
+
+ scope->expressions =
+ a404m_realloc(scope->expressions,
+ scope->expressions_size * sizeof(*scope->expressions));
+
+ return newAstTree(AST_TREE_TOKEN_SCOPE, scope, NULL, parserNode->str_begin,
+ parserNode->str_end);
+
+RETURN_ERROR:
+ for (size_t i = 0; i < scope->expressions_size; ++i) {
+ // astTreeDelete(scope->expressions[i]);
+ }
+ free(scope->variables.data);
+ free(scope->expressions);
+ return NULL;
+}
+
AstTreeFunction *getFunction(AstTree *value) {
switch (value->token) {
case AST_TREE_TOKEN_FUNCTION:
@@ -1262,6 +1408,7 @@ AstTreeFunction *getFunction(AstTree *value) {
case AST_TREE_TOKEN_OPERATOR_MULTIPLY:
case AST_TREE_TOKEN_OPERATOR_DIVIDE:
case AST_TREE_TOKEN_OPERATOR_MODULO:
+ case AST_TREE_TOKEN_SCOPE:
return NULL;
case AST_TREE_TOKEN_NONE:
}
@@ -1293,6 +1440,7 @@ bool isConst(AstTree *value) {
case AST_TREE_TOKEN_OPERATOR_MULTIPLY:
case AST_TREE_TOKEN_OPERATOR_DIVIDE:
case AST_TREE_TOKEN_OPERATOR_MODULO:
+ case AST_TREE_TOKEN_SCOPE:
return false;
case AST_TREE_TOKEN_VARIABLE: {
AstTreeVariable *metadata = value->metadata;
@@ -1361,6 +1509,7 @@ AstTree *makeTypeOf(AstTree *value) {
case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
case AST_TREE_TOKEN_KEYWORD_RETURN:
case AST_TREE_TOKEN_KEYWORD_IF:
+ case AST_TREE_TOKEN_SCOPE:
case AST_TREE_TOKEN_NONE:
}
UNREACHABLE;
@@ -1384,6 +1533,7 @@ bool typeIsEqual(const AstTree *type0, const AstTree *type1) {
case AST_TREE_TOKEN_OPERATOR_MODULO:
case AST_TREE_TOKEN_OPERATOR_PLUS:
case AST_TREE_TOKEN_OPERATOR_MINUS:
+ case AST_TREE_TOKEN_SCOPE:
return false;
case AST_TREE_TOKEN_TYPE_TYPE:
case AST_TREE_TOKEN_TYPE_VOID:
@@ -1424,6 +1574,7 @@ bool typeIsEqual(const AstTree *type0, const AstTree *type1) {
bool isCircularDependencies(AstTreeHelper *helper, AstTreeVariable *variable,
AstTree *tree) {
switch (tree->token) {
+ case AST_TREE_TOKEN_SCOPE:
case AST_TREE_TOKEN_TYPE_TYPE:
case AST_TREE_TOKEN_TYPE_FUNCTION:
case AST_TREE_TOKEN_TYPE_VOID:
@@ -1543,7 +1694,10 @@ bool setAllTypes(AstTree *tree, AstTreeFunction *function) {
return setTypesVariableDefine(tree);
case AST_TREE_TOKEN_KEYWORD_IF:
return setTypesIf(tree, function);
+ case AST_TREE_TOKEN_SCOPE:
+ return setTypesScope(tree, function);
case AST_TREE_TOKEN_NONE:
+ break;
}
UNREACHABLE;
}
@@ -1733,7 +1887,7 @@ bool setTypesIf(AstTree *tree, AstTreeFunction *function) {
AstTreeIf *metadata = tree->metadata;
if (!setAllTypes(metadata->condition, function) ||
- !setAllTypes(metadata->body, function)) {
+ !setAllTypes(metadata->ifBody, function)) {
return false;
}
@@ -1748,6 +1902,26 @@ bool setTypesIf(AstTree *tree, AstTreeFunction *function) {
return true;
}
+bool setTypesScope(AstTree *tree, AstTreeFunction *function) {
+ AstTreeScope *metadata = tree->metadata;
+
+ tree->type = &AST_TREE_VOID_TYPE;
+
+ for (size_t i = 0; i < metadata->expressions_size; ++i) {
+ if (!setAllTypes(metadata->expressions[i], function)) {
+ return false;
+ }
+ }
+
+ for (size_t i = 0; i < metadata->variables.size; ++i) {
+ if (!setTypesAstVariable(metadata->variables.data[i])) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
bool setTypesAstInfix(AstTreeInfix *infix) {
return setAllTypes(&infix->left, NULL) && setAllTypes(&infix->right, NULL);
}
@@ -1787,8 +1961,10 @@ bool astTreeClean(AstTree *tree) {
case AST_TREE_TOKEN_OPERATOR_MULTIPLY:
case AST_TREE_TOKEN_OPERATOR_DIVIDE:
case AST_TREE_TOKEN_OPERATOR_MODULO:
+ case AST_TREE_TOKEN_SCOPE:
return true;
case AST_TREE_TOKEN_NONE:
+ break;
}
UNREACHABLE;
}
@@ -1879,6 +2055,7 @@ size_t astTreeTypeSize(AstTree tree) {
case AST_TREE_TOKEN_OPERATOR_MULTIPLY:
case AST_TREE_TOKEN_OPERATOR_DIVIDE:
case AST_TREE_TOKEN_OPERATOR_MODULO:
+ case AST_TREE_TOKEN_SCOPE:
case AST_TREE_TOKEN_NONE:
}
UNREACHABLE;
diff --git a/src/compiler/ast-tree.h b/src/compiler/ast-tree.h
index 38a6f66..594b213 100644
--- a/src/compiler/ast-tree.h
+++ b/src/compiler/ast-tree.h
@@ -33,6 +33,8 @@ typedef enum AstTreeToken {
AST_TREE_TOKEN_OPERATOR_DIVIDE,
AST_TREE_TOKEN_OPERATOR_MODULO,
+ AST_TREE_TOKEN_SCOPE,
+
AST_TREE_TOKEN_NONE,
} AstTreeToken;
@@ -109,7 +111,8 @@ typedef struct AstTreeReturn {
typedef struct AstTreeIf {
AstTree *condition;
- AstTree *body;
+ AstTree *ifBody;
+ AstTree *elseBody;
} AstTreeIf;
typedef struct AstTreeHelper {
@@ -141,31 +144,22 @@ AstTreeVariable *getVariable(AstTreeHelper *helper, char *name_begin,
char *name_end);
AstTree *astTreeParse(ParserNode *parserNode, AstTreeHelper *helper);
-
AstTree *astTreeParseFunction(ParserNode *parserNode, AstTreeHelper *helper);
-
AstTree *astTreeParseTypeFunction(ParserNode *parserNode,
AstTreeHelper *helper);
-
AstTree *astTreeParseFunctionCall(ParserNode *parserNode,
AstTreeHelper *helper);
-
AstTree *astTreeParseIdentifier(ParserNode *parserNode, AstTreeHelper *helper);
-
AstTree *astTreeParsePrintU64(ParserNode *parserNode, AstTreeHelper *helper);
AstTree *astTreeParseReturn(ParserNode *parserNode, AstTreeHelper *helper);
-
AstTree *astTreeParseBinaryOperator(ParserNode *parserNode,
AstTreeHelper *helper, AstTreeToken token);
-
AstTree *astTreeParseUnaryOperator(ParserNode *parserNode,
AstTreeHelper *helper, AstTreeToken token);
-
bool astTreeParseConstant(ParserNode *parserNode, AstTreeHelper *helper);
-
AstTree *astTreeParseVariable(ParserNode *parserNode, AstTreeHelper *helper);
-
AstTree *astTreeParseIf(ParserNode *parserNode, AstTreeHelper *helper);
+AstTree *astTreeParseCurlyBracket(ParserNode *parserNode, AstTreeHelper *helper);
AstTreeFunction *getFunction(AstTree *value);
bool isConst(AstTree *value);
@@ -188,6 +182,7 @@ bool setTypesOperatorInfix(AstTree *tree);
bool setTypesOperatorUnary(AstTree *tree);
bool setTypesVariableDefine(AstTree *tree);
bool setTypesIf(AstTree *tree,AstTreeFunction *function);
+bool setTypesScope(AstTree *tree,AstTreeFunction *function);
bool setTypesAstVariable(AstTreeVariable *variable);
bool setTypesAstInfix(AstTreeInfix *infix);
diff --git a/src/compiler/lexer.c b/src/compiler/lexer.c
index a61c3af..1f45be0 100644
--- a/src/compiler/lexer.c
+++ b/src/compiler/lexer.c
@@ -21,6 +21,7 @@ const char *LEXER_TOKEN_STRINGS[] = {
"LEXER_TOKEN_KEYWORD_TRUE",
"LEXER_TOKEN_KEYWORD_FALSE",
"LEXER_TOKEN_KEYWORD_IF",
+ "LEXER_TOKEN_KEYWORD_ELSE",
"LEXER_TOKEN_NUMBER",
@@ -68,14 +69,15 @@ const size_t LEXER_SYMBOL_SIZE =
sizeof(LEXER_SYMBOL_TOKENS) / sizeof(*LEXER_SYMBOL_TOKENS);
const char *LEXER_KEYWORD_STRINGS[] = {
- "type", "void", "u64", "bool", "print_u64", "return", "true", "false", "if",
+ "type", "void", "u64", "bool", "print_u64",
+ "return", "true", "false", "if", "else",
};
const LexerToken LEXER_KEYWORD_TOKENS[] = {
LEXER_TOKEN_KEYWORD_TYPE, LEXER_TOKEN_KEYWORD_VOID,
LEXER_TOKEN_KEYWORD_U64, LEXER_TOKEN_KEYWORD_BOOL,
LEXER_TOKEN_KEYWORD_PRINT_U64, LEXER_TOKEN_KEYWORD_RETURN,
LEXER_TOKEN_KEYWORD_TRUE, LEXER_TOKEN_KEYWORD_FALSE,
- LEXER_TOKEN_KEYWORD_IF,
+ LEXER_TOKEN_KEYWORD_IF, LEXER_TOKEN_KEYWORD_ELSE,
};
const size_t LEXER_KEYWORD_SIZE =
sizeof(LEXER_KEYWORD_TOKENS) / sizeof(*LEXER_KEYWORD_TOKENS);
@@ -208,6 +210,7 @@ void lexerPushClear(LexerNodeArray *array, size_t *array_size, char *iter,
case LEXER_TOKEN_KEYWORD_TRUE:
case LEXER_TOKEN_KEYWORD_FALSE:
case LEXER_TOKEN_KEYWORD_IF:
+ case LEXER_TOKEN_KEYWORD_ELSE:
case LEXER_TOKEN_NUMBER:
case LEXER_TOKEN_SYMBOL_EOL:
case LEXER_TOKEN_SYMBOL_OPEN_PARENTHESIS:
diff --git a/src/compiler/lexer.h b/src/compiler/lexer.h
index 4e74d1d..e7afd62 100644
--- a/src/compiler/lexer.h
+++ b/src/compiler/lexer.h
@@ -14,6 +14,7 @@ typedef enum LexerToken {
LEXER_TOKEN_KEYWORD_TRUE,
LEXER_TOKEN_KEYWORD_FALSE,
LEXER_TOKEN_KEYWORD_IF,
+ LEXER_TOKEN_KEYWORD_ELSE,
LEXER_TOKEN_NUMBER,
diff --git a/src/compiler/parser.c b/src/compiler/parser.c
index d4364af..b952dc1 100644
--- a/src/compiler/parser.c
+++ b/src/compiler/parser.c
@@ -297,8 +297,13 @@ void parserNodePrint(const ParserNode *node, int indent) {
printf(",\n");
for (int i = 0; i < indent; ++i)
printf(" ");
- printf("body=\n");
- parserNodePrint(metadata->body, indent + 1);
+ printf("ifBody=\n");
+ parserNodePrint(metadata->ifBody, indent + 1);
+ printf("\n,");
+ for (int i = 0; i < indent; ++i)
+ printf(" ");
+ printf("elseBody=\n");
+ parserNodePrint(metadata->elseBody, indent + 1);
printf("\n");
for (int i = 0; i < indent; ++i)
printf(" ");
@@ -404,7 +409,8 @@ void parserNodeDelete(ParserNode *node) {
case PARSER_TOKEN_KEYWORD_IF: {
ParserNodeIfMetadata *metadata = node->metadata;
parserNodeDelete(metadata->condition);
- parserNodeDelete(metadata->body);
+ parserNodeDelete(metadata->ifBody);
+ parserNodeDelete(metadata->elseBody);
free(metadata);
}
goto RETURN_SUCCESS;
@@ -577,6 +583,7 @@ ParserNode *parseNode(LexerNode *node, LexerNode *begin, LexerNode *end,
}
case LEXER_TOKEN_KEYWORD_IF:
return parserIf(node, end, parent);
+ case LEXER_TOKEN_KEYWORD_ELSE:
case LEXER_TOKEN_SYMBOL:
case LEXER_TOKEN_SYMBOL_OPEN_PARENTHESIS:
case LEXER_TOKEN_SYMBOL_OPEN_CURLY_BRACKET:
@@ -588,6 +595,23 @@ ParserNode *parseNode(LexerNode *node, LexerNode *begin, LexerNode *end,
ParserNode *getUntilCommonParent(ParserNode *node, ParserNode *parent) {
while (node != NULL && node != parent && node->parent != parent) {
+ if (node == node->parent) {
+ return NULL;
+ }
+
+ node = node->parent;
+ }
+ return node;
+}
+
+ParserNode *getUntilCommonParents(ParserNode *node, ParserNode *parent,
+ ParserNode *parent2) {
+ while (node != NULL && node != parent && node->parent != parent &&
+ node->parent != parent2) {
+ if (node == node->parent) {
+ return NULL;
+ }
+
node = node->parent;
}
return node;
@@ -616,6 +640,29 @@ ParserNode *getNextUsingCommonParent(LexerNode *node, LexerNode *end,
return NULL;
}
+LexerNode *getNextLexerNodeUsingCommonParent(LexerNode *node, LexerNode *end,
+ ParserNode *parent) {
+ ParserNode *parsed = getUntilCommonParent(node->parserNode, parent);
+ if (parsed == NULL) {
+ return NULL;
+ }
+
+ while (true) {
+ node += 1;
+ if (node >= end) {
+ return NULL;
+ }
+
+ ParserNode *newParsed = getUntilCommonParent(node->parserNode, parsed);
+
+ if (newParsed == NULL) {
+ return node;
+ }
+ }
+
+ return NULL;
+}
+
ParserNode *parserIdentifier(LexerNode *node, ParserNode *parent) {
return node->parserNode =
newParserNode(PARSER_TOKEN_IDENTIFIER, node->str_begin,
@@ -781,9 +828,11 @@ ParserNode *parserParenthesis(LexerNode *closing, LexerNode *begin,
for (LexerNode *iter = closing - 1; iter >= begin; --iter) {
if (iter->parserNode != NULL) {
- ParserNode *pNode = getUntilCommonParent(iter->parserNode, parent);
+ ParserNode *pNode =
+ getUntilCommonParents(iter->parserNode, parent, parserNode);
if (pNode == NULL) {
printLog("Bad node", pNode->str_begin, pNode->str_end);
+ return NULL;
} else {
pNode->parent = parserNode;
}
@@ -850,9 +899,11 @@ ParserNode *parserCurlyBrackets(LexerNode *closing, LexerNode *begin,
for (LexerNode *iter = closing - 1; iter >= begin; --iter) {
if (iter->parserNode != NULL) {
- ParserNode *pNode = getUntilCommonParent(iter->parserNode, parent);
+ ParserNode *pNode =
+ getUntilCommonParents(iter->parserNode, parent, parserNode);
if (pNode == NULL) {
- printLog("Bad node", pNode->str_begin, pNode->str_end);
+ printLog(iter->str_begin, iter->str_end, "Bad node");
+ return NULL;
} else {
pNode->parent = parserNode;
}
@@ -868,11 +919,11 @@ ParserNode *parserCurlyBrackets(LexerNode *closing, LexerNode *begin,
return NULL;
}
- parserNode->str_begin = opening->str_begin,
+ parserNode->str_begin = opening->str_begin;
parserNode->str_end = closing->str_end;
- opening->parserNode = parserNode;
- closing->parserNode = parserNode;
+ opening->parserNode = closing->parserNode = parserNode;
+
if (parserNodeArray(opening + 1, closing, parserNode)) {
return parserNode;
} else {
@@ -1156,7 +1207,9 @@ ParserNode *parserIf(LexerNode *node, LexerNode *end, ParserNode *parent) {
return NULL;
}
- ParserNode *body = getNextUsingCommonParent(conditionNode, end, parent);
+ LexerNode *bodyNode =
+ getNextLexerNodeUsingCommonParent(conditionNode, end, parent);
+ ParserNode *body = getUntilCommonParent(bodyNode->parserNode, parent);
if (body == NULL) {
printError(node->str_begin, node->str_end, "If has bad body");
@@ -1165,11 +1218,37 @@ ParserNode *parserIf(LexerNode *node, LexerNode *end, ParserNode *parent) {
ParserNodeIfMetadata *metadata = a404m_malloc(sizeof(*metadata));
metadata->condition = condition;
- metadata->body = body;
+ metadata->ifBody = body;
+
+ LexerNode *elseNode =
+ getNextLexerNodeUsingCommonParent(bodyNode, end, parent);
+ if (elseNode == NULL || elseNode->token != LEXER_TOKEN_KEYWORD_ELSE) {
+ metadata->elseBody = NULL;
+ return condition->parent = body->parent = node->parserNode =
+ newParserNode(PARSER_TOKEN_KEYWORD_IF, node->str_begin,
+ body->str_end, metadata, parent);
+ }
+
+ LexerNode *elseBodyNode = elseNode + 1;
+
+ if (elseBodyNode >= end || elseBodyNode->parserNode == NULL) {
+ printError(elseNode->str_begin, elseNode->str_end, "Else has bad body");
+ return NULL;
+ }
+
+ ParserNode *elseBody = getUntilCommonParent(elseBodyNode->parserNode, parent);
+
+ if (elseBody == NULL) {
+ printError(elseNode->str_begin, elseNode->str_end, "Else has bad body");
+ return NULL;
+ }
+
+ metadata->elseBody = elseBody;
- return condition->parent = body->parent = node->parserNode =
- newParserNode(PARSER_TOKEN_KEYWORD_IF, node->str_begin,
- node->str_end, metadata, parent);
+ return elseBody->parent = elseNode->parserNode = condition->parent =
+ body->parent = node->parserNode =
+ newParserNode(PARSER_TOKEN_KEYWORD_IF, node->str_begin,
+ elseBody->str_end, metadata, parent);
}
bool isAllArguments(const ParserNodeArray *nodes) {
diff --git a/src/compiler/parser.h b/src/compiler/parser.h
index cb90b71..60825a9 100644
--- a/src/compiler/parser.h
+++ b/src/compiler/parser.h
@@ -106,7 +106,8 @@ typedef bool ParserNodeBoolMetadata;
typedef struct ParserNodeIfMetadata {
ParserNode *condition;
- ParserNode *body;
+ ParserNode *ifBody;
+ ParserNode *elseBody;
}ParserNodeIfMetadata;
void parserNodePrint(const ParserNode *node, int indent);
@@ -122,7 +123,9 @@ ParserNode *parseNode(LexerNode *node, LexerNode *begin, LexerNode *end,
ParserNode *parent, bool *conti);
ParserNode *getUntilCommonParent(ParserNode *node, ParserNode *parent);
+ParserNode *getUntilCommonParents(ParserNode *node, ParserNode *parent,ParserNode *parent2);
ParserNode *getNextUsingCommonParent(LexerNode *node,LexerNode *end, ParserNode *parent);
+LexerNode *getNextLexerNodeUsingCommonParent(LexerNode *node,LexerNode *end, ParserNode *parent);
ParserNode *parserIdentifier(LexerNode *node, ParserNode *parent);
ParserNode *parserType(LexerNode *node, ParserNode *parent);
diff --git a/src/main.c b/src/main.c
index 8a61324..4b7747b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -111,7 +111,7 @@ int main(int argc, char *argv[]) {
return 1;
}
- const int ret = run(argv[1], false);
+ const int ret = run(argv[1], true);
fileDelete();
return ret;
}
diff --git a/src/runner/runner.c b/src/runner/runner.c
index 958658a..431305c 100644
--- a/src/runner/runner.c
+++ b/src/runner/runner.c
@@ -162,87 +162,122 @@ AstTree *runAstTreeFunction(AstTree *tree, AstTree **arguments,
AstTree *ret = &AST_TREE_VOID_VALUE;
for (size_t i = 0; i < function->scope.expressions_size; ++i) {
- AstTree *expr = function->scope.expressions[i];
- RUN:
- switch (expr->token) {
- case AST_TREE_TOKEN_KEYWORD_PRINT_U64: {
- AstTreeSingleChild *metadata = expr->metadata;
- AstTree *tree = calcAstTreeValue(metadata, &pages);
- printf("%lu", (AstTreeU64)tree->metadata);
- astTreeDelete(tree);
+ AstTree *r = runExpression(function->scope.expressions[i], &pages);
+ if (r) {
+ ret = r;
+ break;
}
- continue;
- case AST_TREE_TOKEN_FUNCTION_CALL: {
- AstTree *ret = calcAstTreeValue(expr, &pages);
- if (ret != &AST_TREE_VOID_VALUE) {
- astTreeDelete(ret);
- }
- }
- continue;
- case AST_TREE_TOKEN_OPERATOR_ASSIGN: {
- AstTreeInfix *metadata = expr->metadata;
- if (metadata->left.token == AST_TREE_TOKEN_VARIABLE) {
- AstTreeVariable *left = metadata->left.metadata;
- runnerVariableSetValue(&pages, left,
- calcAstTreeValue(&metadata->right, &pages));
- } else {
- UNREACHABLE;
- }
- }
- continue;
- case AST_TREE_TOKEN_KEYWORD_RETURN: {
- AstTreeReturn *metadata = expr->metadata;
- if (metadata->value != NULL) {
- ret = calcAstTreeValue(metadata->value, &pages);
- } else {
- ret = &AST_TREE_VOID_VALUE;
- }
- goto RETURN;
+ }
+
+ runnerVariablesDelete(pages.data[pages.size - 1]);
+ free(pages.data);
+
+ return ret;
+}
+
+AstTree *runExpression(AstTree *expr, RunnerVariablePages *pages) {
+ switch (expr->token) {
+ case AST_TREE_TOKEN_KEYWORD_PRINT_U64: {
+ AstTreeSingleChild *metadata = expr->metadata;
+ AstTree *tree = calcAstTreeValue(metadata, pages);
+ printf("%lu", (AstTreeU64)tree->metadata);
+ astTreeDelete(tree);
+ }
+ return NULL;
+ case AST_TREE_TOKEN_FUNCTION_CALL: {
+ AstTree *ret = calcAstTreeValue(expr, pages);
+ if (ret != &AST_TREE_VOID_VALUE) {
+ astTreeDelete(ret);
}
- continue;
- case AST_TREE_TOKEN_VARIABLE_DEFINE: {
- AstTreeVariable *variable = expr->metadata;
- runnerVariableSetValue(&pages, variable, copyAstTree(variable->value));
+ }
+ return NULL;
+ case AST_TREE_TOKEN_OPERATOR_ASSIGN: {
+ AstTreeInfix *metadata = expr->metadata;
+ if (metadata->left.token == AST_TREE_TOKEN_VARIABLE) {
+ AstTreeVariable *left = metadata->left.metadata;
+ runnerVariableSetValue(pages, left,
+ calcAstTreeValue(&metadata->right, pages));
+ } else {
+ UNREACHABLE;
}
- continue;
- case AST_TREE_TOKEN_KEYWORD_IF: {
- AstTreeIf *metadata = expr->metadata;
- AstTree *tree = calcAstTreeValue(metadata->condition, &pages);
- if ((AstTreeBool)tree->metadata) {
- expr = metadata->body;
- goto RUN;
- }
- astTreeDelete(tree);
+ }
+ return NULL;
+ case AST_TREE_TOKEN_KEYWORD_RETURN: {
+ AstTreeReturn *metadata = expr->metadata;
+ if (metadata->value != NULL) {
+ return calcAstTreeValue(metadata->value, pages);
+ } else {
+ return &AST_TREE_VOID_VALUE;
}
- continue;
- case AST_TREE_TOKEN_OPERATOR_PLUS:
- case AST_TREE_TOKEN_OPERATOR_MINUS:
- case AST_TREE_TOKEN_OPERATOR_SUM:
- case AST_TREE_TOKEN_OPERATOR_SUB:
- case AST_TREE_TOKEN_OPERATOR_MULTIPLY:
- case AST_TREE_TOKEN_OPERATOR_DIVIDE:
- case AST_TREE_TOKEN_OPERATOR_MODULO:
- case AST_TREE_TOKEN_FUNCTION:
- case AST_TREE_TOKEN_TYPE_TYPE:
- case AST_TREE_TOKEN_TYPE_FUNCTION:
- case AST_TREE_TOKEN_TYPE_VOID:
- case AST_TREE_TOKEN_TYPE_U64:
- case AST_TREE_TOKEN_TYPE_BOOL:
- case AST_TREE_TOKEN_VARIABLE:
- case AST_TREE_TOKEN_VALUE_VOID:
- case AST_TREE_TOKEN_VALUE_U64:
- case AST_TREE_TOKEN_VALUE_BOOL:
- case AST_TREE_TOKEN_NONE:
+ }
+ case AST_TREE_TOKEN_VARIABLE_DEFINE: {
+ AstTreeVariable *variable = expr->metadata;
+ runnerVariableSetValue(pages, variable, copyAstTree(variable->value));
+ }
+ return NULL;
+ case AST_TREE_TOKEN_KEYWORD_IF: {
+ AstTreeIf *metadata = expr->metadata;
+ AstTree *tree = calcAstTreeValue(metadata->condition, pages);
+ if ((AstTreeBool)tree->metadata) {
+ return runExpression(metadata->ifBody, pages);
+ } else {
+ return runExpression(metadata->elseBody, pages);
}
- printLog("Bad token %d", expr->token);
- UNREACHABLE;
+ astTreeDelete(tree);
}
+ return NULL;
+ case AST_TREE_TOKEN_SCOPE: {
+ AstTreeScope *metadata = expr->metadata;
-RETURN:
- runnerVariablesDelete(pages.data[pages.size - 1]);
- free(pages.data);
+ RunnerVariablePages newPages = {
+ .data = a404m_malloc((pages->size + 1) * sizeof(*newPages.data)),
+ .size = pages->size + 1,
+ };
- return ret;
+ for (size_t i = 0; i < pages->size; ++i) {
+ newPages.data[i] = pages->data[i];
+ }
+
+ newPages.data[pages->size] =
+ a404m_malloc(sizeof(*newPages.data[pages->size]));
+ newPages.data[pages->size]->size = 0;
+ newPages.data[pages->size]->data =
+ a404m_malloc(newPages.data[pages->size]->size *
+ sizeof(*newPages.data[pages->size]->data));
+
+ for (size_t i = 0; i < metadata->variables.size; ++i) {
+ AstTreeVariable *variable = metadata->variables.data[i];
+ runnerVariablePush(newPages.data[newPages.size - 1], variable);
+ }
+
+ for (size_t i = 0; i < metadata->expressions_size; ++i) {
+ AstTree *r = runExpression(metadata->expressions[i], &newPages);
+ if (r) {
+ return r;
+ }
+ }
+ }
+ return NULL;
+ case AST_TREE_TOKEN_OPERATOR_PLUS:
+ case AST_TREE_TOKEN_OPERATOR_MINUS:
+ case AST_TREE_TOKEN_OPERATOR_SUM:
+ case AST_TREE_TOKEN_OPERATOR_SUB:
+ case AST_TREE_TOKEN_OPERATOR_MULTIPLY:
+ case AST_TREE_TOKEN_OPERATOR_DIVIDE:
+ case AST_TREE_TOKEN_OPERATOR_MODULO:
+ case AST_TREE_TOKEN_FUNCTION:
+ case AST_TREE_TOKEN_TYPE_TYPE:
+ case AST_TREE_TOKEN_TYPE_FUNCTION:
+ case AST_TREE_TOKEN_TYPE_VOID:
+ case AST_TREE_TOKEN_TYPE_U64:
+ case AST_TREE_TOKEN_TYPE_BOOL:
+ case AST_TREE_TOKEN_VARIABLE:
+ case AST_TREE_TOKEN_VALUE_VOID:
+ case AST_TREE_TOKEN_VALUE_U64:
+ case AST_TREE_TOKEN_VALUE_BOOL:
+ case AST_TREE_TOKEN_NONE:
+ }
+ UNREACHABLE;
}
AstTree *calcAstTreeValue(AstTree *tree, RunnerVariablePages *pages) {
diff --git a/src/runner/runner.h b/src/runner/runner.h
index 758ed28..c1a2382 100644
--- a/src/runner/runner.h
+++ b/src/runner/runner.h
@@ -29,5 +29,7 @@ bool runAstTree(AstTreeRoot *root);
AstTree *runAstTreeFunction(AstTree *tree, AstTree **arguments,
size_t arguments_size,RunnerVariablePages *pages);
+AstTree* runExpression(AstTree *expr,RunnerVariablePages *pages);
+
AstTree *calcAstTreeValue(AstTree *tree,RunnerVariablePages *pages);
AstTree *deepCopyAstTree(AstTree *tree);