summaryrefslogtreecommitdiff
path: root/src/compiler/ast-tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/ast-tree.c')
-rw-r--r--src/compiler/ast-tree.c117
1 files changed, 105 insertions, 12 deletions
diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c
index 87f4755..8043561 100644
--- a/src/compiler/ast-tree.c
+++ b/src/compiler/ast-tree.c
@@ -23,6 +23,7 @@ const char *AST_TREE_TOKEN_STRINGS[] = {
"AST_TREE_TOKEN_FUNCTION_CALL",
"AST_TREE_TOKEN_VARIABLE",
+ "AST_TREE_TOKEN_VARIABLE_DEFINE",
"AST_TREE_TOKEN_VALUE_U64",
"AST_TREE_TOKEN_NONE",
@@ -73,6 +74,7 @@ void astTreePrint(const AstTree *tree, int indent) {
case AST_TREE_TOKEN_TYPE_TYPE:
case AST_TREE_TOKEN_TYPE_VOID:
case AST_TREE_TOKEN_TYPE_U64:
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
goto RETURN_SUCCESS;
case AST_TREE_TOKEN_KEYWORD_PRINT_U64: {
AstTreeSingleChild *metadata = tree->metadata;
@@ -175,6 +177,7 @@ void astTreeDestroy(AstTree tree) {
case AST_TREE_TOKEN_TYPE_VOID:
case AST_TREE_TOKEN_TYPE_U64:
case AST_TREE_TOKEN_VALUE_U64:
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
return;
case AST_TREE_TOKEN_KEYWORD_PRINT_U64: {
AstTreeSingleChild *metadata = tree.metadata;
@@ -262,6 +265,7 @@ AstTree *copyAstTree(AstTree *tree) {
case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
case AST_TREE_TOKEN_TYPE_FUNCTION:
case AST_TREE_TOKEN_FUNCTION_CALL:
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
case AST_TREE_TOKEN_NONE:
}
printLog("Bad token '%d'", tree->token);
@@ -288,7 +292,8 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
goto RETURN_ERROR;
}
ParserNode *node = (ParserNodeSingleChildMetadata *)eol->metadata;
- if (node->token != PARSER_TOKEN_CONSTANT) {
+ if (node->token != PARSER_TOKEN_CONSTANT &&
+ node->token != PARSER_TOKEN_VARIABLE) {
printLog("Unexpected %s", PARSER_TOKEN_STRINGS[node->token]);
goto RETURN_ERROR;
}
@@ -297,6 +302,7 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
AstTreeVariable *variable = a404m_malloc(sizeof(*variable));
variable->name_begin = node_metadata->name->str_begin;
variable->name_end = node_metadata->name->str_end;
+ variable->isConst = node->token == PARSER_TOKEN_CONSTANT;
if (!pushVariable(&root->variables, variable)) {
astTreeVariableDelete(variable);
@@ -312,7 +318,8 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
(ParserNodeSingleChildMetadata *)nodes->data[i]->metadata;
ParserNodeVariableMetadata *node_metadata = node->metadata;
- if (node->token != PARSER_TOKEN_CONSTANT) {
+ if (node->token != PARSER_TOKEN_CONSTANT &&
+ node->token != PARSER_TOKEN_VARIABLE) {
printLog("Only variables are allowed here");
goto RETURN_ERROR;
}
@@ -334,6 +341,7 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
case PARSER_TOKEN_TYPE_U64:
case PARSER_TOKEN_KEYWORD_PRINT_U64:
case PARSER_TOKEN_CONSTANT:
+ case PARSER_TOKEN_VARIABLE:
case PARSER_TOKEN_SYMBOL_EOL:
case PARSER_TOKEN_SYMBOL_CURLY_BRACKET:
case PARSER_TOKEN_SYMBOL_PARENTHESIS:
@@ -452,6 +460,7 @@ AstTree *astTreeParse(ParserNode *parserNode, AstTreeVariables **variables,
(void *)(AstTreeU64)(ParserNodeU64Metadata)parserNode->metadata);
case PARSER_TOKEN_KEYWORD_PRINT_U64:
return astTreeParsePrintU64(parserNode, variables, variables_size);
+ case PARSER_TOKEN_VARIABLE:
case PARSER_TOKEN_CONSTANT:
case PARSER_TOKEN_SYMBOL_EOL:
case PARSER_TOKEN_SYMBOL_PARENTHESIS:
@@ -516,6 +525,7 @@ AstTree *astTreeParseFunction(ParserNode *parserNode,
argument->type = type;
argument->name_begin = arg_metadata->name->str_begin;
argument->name_end = arg_metadata->name->str_end;
+ argument->isConst = false; // all arguments are not constants
if (!pushVariable(&function->arguments, argument)) {
astTreeVariableDelete(argument);
@@ -536,8 +546,7 @@ AstTree *astTreeParseFunction(ParserNode *parserNode,
goto RETURN_ERROR;
}
} else {
- AstTree *tree;
- tree = astTreeParse(node, variables, variables_size);
+ AstTree *tree = astTreeParse(node, variables, variables_size);
if (tree == NULL) {
goto RETURN_ERROR;
@@ -716,6 +725,7 @@ bool astTreeParseConstant(ParserNode *parserNode, AstTreeVariables **variables,
variable->value = value;
variable->name_begin = node_metadata->name->str_begin;
variable->name_end = node_metadata->name->str_end;
+ variable->isConst = true;
if (!pushVariable(variables[variables_size - 1], variable)) {
astTreeVariableDelete(variable);
@@ -727,6 +737,50 @@ RETURN_ERROR:
return false;
}
+AstTree *astTreeParseVariable(ParserNode *parserNode,
+ AstTreeVariables **variables,
+ size_t variables_size) {
+ ParserNodeVariableMetadata *node_metadata = parserNode->metadata;
+
+ if (node_metadata->value == NULL ||
+ node_metadata->name->token != PARSER_TOKEN_IDENTIFIER) {
+ printLog("Not supported");
+ return NULL;
+ }
+
+ AstTree *value =
+ astTreeParse(node_metadata->value, variables, variables_size);
+ if (value == NULL) {
+ goto RETURN_ERROR;
+ }
+
+ AstTree *type;
+ if (node_metadata->type == NULL) {
+ type = NULL;
+ } else {
+ type = astTreeParse(node_metadata->type, variables, variables_size);
+ if (type == NULL) {
+ goto RETURN_ERROR;
+ }
+ }
+
+ AstTreeVariable *variable = a404m_malloc(sizeof(*variable));
+ variable->type = type;
+ variable->value = value;
+ variable->name_begin = node_metadata->name->str_begin;
+ variable->name_end = node_metadata->name->str_end;
+ variable->isConst = false;
+
+ if (!pushVariable(variables[variables_size - 1], variable)) {
+ astTreeVariableDelete(variable);
+ goto RETURN_ERROR;
+ }
+
+ return newAstTree(AST_TREE_TOKEN_VARIABLE_DEFINE, variable);
+RETURN_ERROR:
+ return NULL;
+}
+
bool hasTypeOf(AstTree *value, const AstTree *type) {
if (value->token == AST_TREE_TOKEN_VARIABLE) {
AstTreeVariable *variable = value->metadata;
@@ -746,8 +800,9 @@ bool hasTypeOf(AstTree *value, const AstTree *type) {
case AST_TREE_TOKEN_FUNCTION_CALL:
case AST_TREE_TOKEN_VARIABLE:
case AST_TREE_TOKEN_VALUE_U64:
- case AST_TREE_TOKEN_NONE:
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
return false;
+ case AST_TREE_TOKEN_NONE:
}
goto ERROR;
case AST_TREE_TOKEN_TYPE_FUNCTION:
@@ -774,6 +829,7 @@ bool hasTypeOf(AstTree *value, const AstTree *type) {
case AST_TREE_TOKEN_TYPE_U64:
case AST_TREE_TOKEN_FUNCTION_CALL:
case AST_TREE_TOKEN_VARIABLE:
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
return false;
case AST_TREE_TOKEN_NONE:
}
@@ -786,6 +842,7 @@ bool hasTypeOf(AstTree *value, const AstTree *type) {
case AST_TREE_TOKEN_VARIABLE:
case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
case AST_TREE_TOKEN_VALUE_U64:
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
return false;
case AST_TREE_TOKEN_NONE:
}
@@ -813,6 +870,7 @@ bool isFunction(AstTree *value) {
case AST_TREE_TOKEN_TYPE_VOID:
case AST_TREE_TOKEN_TYPE_U64:
case AST_TREE_TOKEN_VALUE_U64:
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
return false;
case AST_TREE_TOKEN_NONE:
}
@@ -820,6 +878,29 @@ bool isFunction(AstTree *value) {
exit(1);
}
+bool isConst(AstTree *value) {
+ switch (value->token) {
+ 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_VALUE_U64:
+ return true;
+ case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
+ case AST_TREE_TOKEN_FUNCTION_CALL:
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
+ return false;
+ case AST_TREE_TOKEN_VARIABLE: {
+ AstTreeVariable *metadata = value->metadata;
+ return metadata->isConst;
+ }
+ case AST_TREE_TOKEN_NONE:
+ }
+ printLog("Bad token '%d'", value->token);
+ exit(1);
+}
+
AstTree *makeTypeOf(AstTree *value) {
switch (value->token) {
case AST_TREE_TOKEN_TYPE_TYPE:
@@ -854,6 +935,7 @@ AstTree *makeTypeOf(AstTree *value) {
AstTreeVariable *variable = value->metadata;
return copyAstTree(variable->type);
}
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
case AST_TREE_TOKEN_NONE:
}
@@ -866,6 +948,7 @@ bool typeIsEqual(const AstTree *type0, const AstTree *type1) {
case AST_TREE_TOKEN_FUNCTION:
case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
case AST_TREE_TOKEN_VALUE_U64:
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
return false;
case AST_TREE_TOKEN_TYPE_TYPE:
case AST_TREE_TOKEN_TYPE_VOID:
@@ -911,6 +994,7 @@ bool setAllTypes(AstTree *tree) {
case AST_TREE_TOKEN_TYPE_VOID:
case AST_TREE_TOKEN_TYPE_U64:
case AST_TREE_TOKEN_VALUE_U64:
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
return true;
case AST_TREE_TOKEN_FUNCTION:
return setTypesFunction(tree);
@@ -1052,6 +1136,7 @@ bool astTreeClean(AstTree *tree) {
case AST_TREE_TOKEN_TYPE_U64:
case AST_TREE_TOKEN_FUNCTION_CALL:
case AST_TREE_TOKEN_VALUE_U64:
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
return true;
case AST_TREE_TOKEN_NONE:
}
@@ -1096,16 +1181,24 @@ bool astTreeCleanAstVariable(AstTreeVariable *variable) {
return false;
}
AstTree *value = variable->value;
- if (value->token == AST_TREE_TOKEN_VARIABLE) {
- do {
- AstTreeVariable *value_metadata = value->metadata;
- AstTree *newValue = value_metadata->value;
- astTreeDelete(value);
- value = newValue;
- } while (value->token == AST_TREE_TOKEN_VARIABLE);
+ while (value->token == AST_TREE_TOKEN_VARIABLE) {
+ AstTreeVariable *value_metadata = value->metadata;
+ if (!value_metadata->isConst) {
+ break;
+ }
+ AstTree *newValue = value_metadata->value;
+ astTreeDelete(value);
+ value = newValue;
+ }
+
+ if (variable->value != value) {
variable->value = copyAstTree(value);
}
+ if (variable->isConst && !isConst(value)) {
+ return false;
+ }
+
return true;
}