diff options
-rw-r--r-- | src/compiler/ast-tree.c | 135 | ||||
-rw-r--r-- | src/compiler/ast-tree.h | 19 | ||||
-rw-r--r-- | src/compiler/parser.c | 10 | ||||
-rw-r--r-- | src/main.c | 2 | ||||
-rw-r--r-- | src/runner/runner.c | 61 | ||||
-rw-r--r-- | src/runner/runner.h | 3 | ||||
-rw-r--r-- | test/main.felan | 16 |
7 files changed, 162 insertions, 84 deletions
diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c index 4d6c3ee..7211dd4 100644 --- a/src/compiler/ast-tree.c +++ b/src/compiler/ast-tree.c @@ -1,6 +1,7 @@ #include "ast-tree.h" #include "compiler/parser.h" +#include "runner/runner.h" #include "utils/log.h" #include "utils/memory.h" #include <stdint.h> @@ -882,7 +883,7 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) { } helper.variable = NULL; - if (!setAllTypesRoot(root, &helper) || !astTreeCleanRoot(root)) { + if (!setAllTypesRoot(root, &helper) || !astTreeCleanRoot(root, &helper)) { goto RETURN_ERROR; } @@ -1750,9 +1751,8 @@ AstTreeFunction *getFunction(AstTree *value) { UNREACHABLE; } -bool isConst(AstTree *value) { - switch (value->token) { - case AST_TREE_TOKEN_FUNCTION: +bool isConst(AstTree *tree, AstTreeHelper *helper) { + switch (tree->token) { case AST_TREE_TOKEN_TYPE_TYPE: case AST_TREE_TOKEN_TYPE_FUNCTION: case AST_TREE_TOKEN_TYPE_VOID: @@ -1769,10 +1769,26 @@ bool isConst(AstTree *value) { case AST_TREE_TOKEN_VALUE_INT: case AST_TREE_TOKEN_VALUE_BOOL: return true; + case AST_TREE_TOKEN_KEYWORD_IF: { + AstTreeIf *metadata = tree->metadata; + return isConst(metadata->condition, helper) && + isConst(metadata->ifBody, helper) && + (metadata->elseBody == NULL || isConst(metadata->elseBody, helper)); + } + case AST_TREE_TOKEN_FUNCTION_CALL: { + AstTreeFunctionCall *metadata = tree->metadata; + for (size_t i = 0; i < metadata->parameters_size; ++i) { + if (!isConst(metadata->parameters[i], helper)) { + return false; + } + } + return isConst(metadata->function, helper); + } + case AST_TREE_TOKEN_FUNCTION: { + AstTreeFunction *function; + } case AST_TREE_TOKEN_KEYWORD_PRINT_U64: case AST_TREE_TOKEN_KEYWORD_RETURN: - case AST_TREE_TOKEN_KEYWORD_IF: - case AST_TREE_TOKEN_FUNCTION_CALL: case AST_TREE_TOKEN_VARIABLE_DEFINE: case AST_TREE_TOKEN_OPERATOR_ASSIGN: case AST_TREE_TOKEN_OPERATOR_PLUS: @@ -1791,7 +1807,7 @@ bool isConst(AstTree *value) { case AST_TREE_TOKEN_SCOPE: return false; case AST_TREE_TOKEN_VARIABLE: { - AstTreeVariable *metadata = value->metadata; + AstTreeVariable *metadata = tree->metadata; return metadata->isConst; } case AST_TREE_TOKEN_NONE: @@ -1947,10 +1963,13 @@ bool typeIsEqual(const AstTree *type0, const AstTree *type1) { UNREACHABLE; } -AstTree *getValue(AstTree *tree) { +AstTree *getValue(AstTree *tree, AstTreeSetTypesHelper helper) { + if (!isConst(tree, helper.treeHelper)) { + printLog("Can't get value at compile time because it is not const"); + return NULL; + } switch (tree->token) { case AST_TREE_TOKEN_TYPE_FUNCTION: - return copyAstTree(tree); case AST_TREE_TOKEN_TYPE_TYPE: case AST_TREE_TOKEN_TYPE_VOID: case AST_TREE_TOKEN_TYPE_I8: @@ -1966,24 +1985,22 @@ AstTree *getValue(AstTree *tree) { case AST_TREE_TOKEN_TYPE_F64: case AST_TREE_TOKEN_TYPE_F128: case AST_TREE_TOKEN_TYPE_BOOL: - return tree; - case AST_TREE_TOKEN_VARIABLE: { - AstTreeVariable *metadata = tree->metadata; - if (metadata->isConst) { - return getValue(metadata->value); - } - } - case AST_TREE_TOKEN_FUNCTION: - case AST_TREE_TOKEN_KEYWORD_PRINT_U64: - case AST_TREE_TOKEN_KEYWORD_RETURN: - case AST_TREE_TOKEN_KEYWORD_IF: - case AST_TREE_TOKEN_KEYWORD_WHILE: - case AST_TREE_TOKEN_FUNCTION_CALL: - case AST_TREE_TOKEN_VARIABLE_DEFINE: case AST_TREE_TOKEN_VALUE_VOID: case AST_TREE_TOKEN_VALUE_INT: case AST_TREE_TOKEN_VALUE_FLOAT: case AST_TREE_TOKEN_VALUE_BOOL: + return copyAstTree(tree); + case AST_TREE_TOKEN_VARIABLE: { + AstTreeVariable *metadata = tree->metadata; + return getValue(metadata->value, helper); + } + case AST_TREE_TOKEN_FUNCTION_CALL: { + AstTree *value = runExpression(tree, helper.pages); + if (value == NULL) { + printError(tree->str_begin, tree->str_end, "Unknown error"); + } + return value; + } case AST_TREE_TOKEN_OPERATOR_ASSIGN: case AST_TREE_TOKEN_OPERATOR_PLUS: case AST_TREE_TOKEN_OPERATOR_MINUS: @@ -1997,7 +2014,19 @@ AstTree *getValue(AstTree *tree) { case AST_TREE_TOKEN_OPERATOR_GREATER: case AST_TREE_TOKEN_OPERATOR_SMALLER: case AST_TREE_TOKEN_OPERATOR_GREATER_OR_EQUAL: - case AST_TREE_TOKEN_OPERATOR_SMALLER_OR_EQUAL: + case AST_TREE_TOKEN_OPERATOR_SMALLER_OR_EQUAL: { + AstTree *value = calcAstTreeValue(tree, helper.pages); + if (value == NULL) { + printError(tree->str_begin, tree->str_end, "Unknown error"); + } + return value; + } + case AST_TREE_TOKEN_FUNCTION: + case AST_TREE_TOKEN_KEYWORD_PRINT_U64: + case AST_TREE_TOKEN_KEYWORD_RETURN: + case AST_TREE_TOKEN_KEYWORD_IF: + case AST_TREE_TOKEN_KEYWORD_WHILE: + case AST_TREE_TOKEN_VARIABLE_DEFINE: case AST_TREE_TOKEN_SCOPE: case AST_TREE_TOKEN_NONE: } @@ -2090,8 +2119,12 @@ bool setAllTypesRoot(AstTreeRoot *root, AstTreeHelper *helper) { } } + RunnerVariablePages pages = initRootPages(); + AstTreeSetTypesHelper setTypesHelper = { .lookingType = NULL, + .treeHelper = helper, + .pages = &pages, }; for (size_t i = 0; i < root->variables.size; ++i) { @@ -2351,10 +2384,11 @@ bool setTypesFunction(AstTree *tree, AstTreeSetTypesHelper helper) { } bool setTypesPrintU64(AstTree *tree, AstTreeSetTypesHelper _helper) { - (void)(_helper); AstTreeSingleChild *metadata = tree->metadata; AstTreeSetTypesHelper helper = { .lookingType = &AST_TREE_U64_TYPE, + .treeHelper = _helper.treeHelper, + .pages = _helper.pages, }; if (!setAllTypes(metadata, helper, NULL)) { return false; @@ -2450,7 +2484,7 @@ bool setTypesOperatorAssign(AstTree *tree, AstTreeSetTypesHelper helper) { } else if (!typeIsEqual(infix->left.type, infix->right.type)) { printError(tree->str_begin, tree->str_end, "Type mismatch"); return false; - } else if (isConst(&infix->left)) { + } else if (isConst(&infix->left, helper.treeHelper)) { printError(tree->str_begin, tree->str_end, "Constants can't be assigned"); return false; } else { @@ -2504,9 +2538,10 @@ bool setTypesVariableDefine(AstTree *tree, AstTreeSetTypesHelper helper) { bool setTypesAstVariable(AstTreeVariable *variable, AstTreeSetTypesHelper _helper) { - (void)_helper; AstTreeSetTypesHelper helper = { .lookingType = &AST_TREE_TYPE_TYPE, + .treeHelper = _helper.treeHelper, + .pages = _helper.pages, }; if (variable->type != NULL && !setAllTypes(variable->type, helper, NULL)) { @@ -2515,7 +2550,10 @@ bool setTypesAstVariable(AstTreeVariable *variable, if (variable->type != NULL) { AstTree *type = variable->type; - variable->type = getValue(type); + variable->type = getValue(type, helper); + if (variable->type == NULL) { + return false; + } astTreeDelete(type); } @@ -2614,25 +2652,32 @@ bool setTypesAstInfix(AstTreeInfix *infix, AstTreeSetTypesHelper helper) { } AstTreeSetTypesHelper newHelper = { .lookingType = infix->left.type, + .treeHelper = helper.treeHelper, + .pages = helper.pages, }; return setAllTypes(&infix->right, newHelper, NULL); } -bool astTreeCleanRoot(AstTreeRoot *root) { +bool astTreeCleanRoot(AstTreeRoot *root, AstTreeHelper *_helper) { + AstTreeSetTypesHelper helper = { + .lookingType = NULL, + .treeHelper = _helper, + .pages = helper.pages, + }; for (size_t i = 0; i < root->variables.size; ++i) { - astTreeClean(root->variables.data[i]->value); - astTreeClean(root->variables.data[i]->type); + astTreeClean(root->variables.data[i]->value, helper); + astTreeClean(root->variables.data[i]->type, helper); } return true; } -bool astTreeClean(AstTree *tree) { +bool astTreeClean(AstTree *tree, AstTreeSetTypesHelper helper) { switch (tree->token) { case AST_TREE_TOKEN_VARIABLE: - return astTreeCleanVariable(tree); + return astTreeCleanVariable(tree, helper); case AST_TREE_TOKEN_FUNCTION: - return astTreeCleanFunction(tree); + return astTreeCleanFunction(tree, helper); case AST_TREE_TOKEN_KEYWORD_PRINT_U64: case AST_TREE_TOKEN_KEYWORD_RETURN: case AST_TREE_TOKEN_KEYWORD_IF: @@ -2681,28 +2726,28 @@ bool astTreeClean(AstTree *tree) { UNREACHABLE; } -bool astTreeCleanFunction(AstTree *tree) { +bool astTreeCleanFunction(AstTree *tree, AstTreeSetTypesHelper helper) { AstTreeFunction *metadata = tree->metadata; for (size_t i = 0; i < metadata->arguments.size; ++i) { if (metadata->arguments.data[i]->value != NULL && - !astTreeClean(metadata->arguments.data[i]->value)) { + !astTreeClean(metadata->arguments.data[i]->value, helper)) { return false; } } - if (!astTreeClean(metadata->returnType)) { + if (!astTreeClean(metadata->returnType, helper)) { return false; } for (size_t i = 0; i < metadata->scope.expressions_size; ++i) { - if (!astTreeClean(metadata->scope.expressions[i])) { + if (!astTreeClean(metadata->scope.expressions[i], helper)) { return false; } } for (size_t i = 0; i < metadata->scope.variables.size; ++i) { - if (!astTreeCleanAstVariable(metadata->scope.variables.data[i])) { + if (!astTreeCleanAstVariable(metadata->scope.variables.data[i], helper)) { return false; } } @@ -2710,12 +2755,14 @@ bool astTreeCleanFunction(AstTree *tree) { return true; } -bool astTreeCleanVariable(AstTree *tree) { - return astTreeCleanAstVariable(tree->metadata); +bool astTreeCleanVariable(AstTree *tree, AstTreeSetTypesHelper helper) { + return astTreeCleanAstVariable(tree->metadata, helper); } -bool astTreeCleanAstVariable(AstTreeVariable *variable) { - if (!astTreeClean(variable->value) || !astTreeClean(variable->type)) { +bool astTreeCleanAstVariable(AstTreeVariable *variable, + AstTreeSetTypesHelper helper) { + if (!astTreeClean(variable->value, helper) || + !astTreeClean(variable->type, helper)) { return false; } AstTree *value = variable->value; @@ -2734,7 +2781,7 @@ bool astTreeCleanAstVariable(AstTreeVariable *variable) { variable->value = copyAstTree(value); } - if (variable->isConst && !isConst(value)) { + if (variable->isConst && !isConst(value, helper.treeHelper)) { return false; } diff --git a/src/compiler/ast-tree.h b/src/compiler/ast-tree.h index c8f5f75..18703c8 100644 --- a/src/compiler/ast-tree.h +++ b/src/compiler/ast-tree.h @@ -162,8 +162,12 @@ typedef struct AstTreeHelper { AstTreeVariables *globalDeps; } AstTreeHelper; +struct RunnerVariablePages; + typedef struct AstTreeSetTypesHelper { AstTree *lookingType; + AstTreeHelper *treeHelper; + struct RunnerVariablePages *pages; } AstTreeSetTypesHelper; void astTreePrint(const AstTree *tree, int indent); @@ -210,10 +214,10 @@ AstTree *astTreeParseCurlyBracket(ParserNode *parserNode, AstTree *astTreeParseParenthesis(ParserNode *parserNode, AstTreeHelper *helper); AstTreeFunction *getFunction(AstTree *value); -bool isConst(AstTree *value); +bool isConst(AstTree *tree, AstTreeHelper *helper); AstTree *makeTypeOf(AstTree *value); bool typeIsEqual(const AstTree *type0, const AstTree *type1); -AstTree *getValue(AstTree *tree); +AstTree *getValue(AstTree *tree, AstTreeSetTypesHelper helper); bool isCircularDependencies(AstTreeHelper *helper, AstTreeVariable *variable, AstTree *tree); @@ -247,10 +251,11 @@ bool setTypesAstVariable(AstTreeVariable *variable, AstTreeSetTypesHelper helper); bool setTypesAstInfix(AstTreeInfix *infix, AstTreeSetTypesHelper helper); -bool astTreeCleanRoot(AstTreeRoot *root); -bool astTreeClean(AstTree *tree); -bool astTreeCleanFunction(AstTree *tree); -bool astTreeCleanVariable(AstTree *tree); -bool astTreeCleanAstVariable(AstTreeVariable *variable); +bool astTreeCleanRoot(AstTreeRoot *root, AstTreeHelper *helper); +bool astTreeClean(AstTree *tree, AstTreeSetTypesHelper helper); +bool astTreeCleanFunction(AstTree *tree, AstTreeSetTypesHelper helper); +bool astTreeCleanVariable(AstTree *tree, AstTreeSetTypesHelper helper); +bool astTreeCleanAstVariable(AstTreeVariable *variable, + AstTreeSetTypesHelper helper); size_t astTreeTypeSize(AstTree tree); diff --git a/src/compiler/parser.c b/src/compiler/parser.c index c5721f1..b2cfd2b 100644 --- a/src/compiler/parser.c +++ b/src/compiler/parser.c @@ -56,6 +56,12 @@ const char *PARSER_TOKEN_STRINGS[] = { "PARSER_TOKEN_OPERATOR_MULTIPLY", "PARSER_TOKEN_OPERATOR_DIVIDE", "PARSER_TOKEN_OPERATOR_MODULO", + "PARSER_TOKEN_OPERATOR_EQUAL", + "PARSER_TOKEN_OPERATOR_NOT_EQUAL", + "PARSER_TOKEN_OPERATOR_GREATER", + "PARSER_TOKEN_OPERATOR_SMALLER", + "PARSER_TOKEN_OPERATOR_GREATER_OR_EQUAL", + "PARSER_TOKEN_OPERATOR_SMALLER_OR_EQUAL", "PARSER_TOKEN_FUNCTION_DEFINITION", @@ -1468,8 +1474,6 @@ bool isExpression(ParserNode *node) { case PARSER_TOKEN_VALUE_BOOL: case PARSER_TOKEN_KEYWORD_IF: case PARSER_TOKEN_KEYWORD_WHILE: - return true; - case PARSER_TOKEN_ROOT: case PARSER_TOKEN_TYPE_TYPE: case PARSER_TOKEN_TYPE_FUNCTION: case PARSER_TOKEN_TYPE_VOID: @@ -1486,6 +1490,8 @@ bool isExpression(ParserNode *node) { case PARSER_TOKEN_TYPE_F32: case PARSER_TOKEN_TYPE_F64: case PARSER_TOKEN_TYPE_F128: + return true; + case PARSER_TOKEN_ROOT: case PARSER_TOKEN_SYMBOL_EOL: case PARSER_TOKEN_SYMBOL_CURLY_BRACKET: case PARSER_TOKEN_SYMBOL_COMMA: @@ -114,7 +114,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 54d6cfc..05883f1 100644 --- a/src/runner/runner.c +++ b/src/runner/runner.c @@ -191,11 +191,7 @@ AstTree *runnerVariableGetValue(RunnerVariablePages *pages, UNREACHABLE; } -bool runAstTree(AstTreeRoot *root) { - constexpr char MAIN_STR[] = "main"; - constexpr size_t MAIN_STR_SIZE = - (sizeof(MAIN_STR) / sizeof(*MAIN_STR)) - sizeof(*MAIN_STR); - +RunnerVariablePages initRootPages() { RunnerVariablePages pages = { .data = a404m_malloc(sizeof(*pages.data)), .size = 1, @@ -206,6 +202,21 @@ bool runAstTree(AstTreeRoot *root) { pages.data[pages.size - 1]->data = a404m_malloc(0); pages.data[pages.size - 1]->size = 0; + return pages; +} + +void destroyRootPages(RunnerVariablePages pages) { + runnerVariablesDelete(pages.data[pages.size - 1]); + free(pages.data); +} + +bool runAstTree(AstTreeRoot *root) { + constexpr char MAIN_STR[] = "main"; + constexpr size_t MAIN_STR_SIZE = + (sizeof(MAIN_STR) / sizeof(*MAIN_STR)) - sizeof(*MAIN_STR); + + RunnerVariablePages pages = initRootPages(); + for (size_t i = 0; i < root->variables.size; ++i) { AstTreeVariable *variable = root->variables.data[i]; if (variable->isConst) { @@ -225,13 +236,11 @@ bool runAstTree(AstTreeRoot *root) { const bool ret = runAstTreeFunction(main, NULL, 0, &pages) == &AST_TREE_VOID_VALUE; - runnerVariablesDelete(pages.data[pages.size - 1]); - free(pages.data); + destroyRootPages(pages); return ret; } } - runnerVariablesDelete(pages.data[pages.size - 1]); - free(pages.data); + destroyRootPages(pages); printLog("main function is not found"); return false; } @@ -302,8 +311,8 @@ AstTree *runExpression(AstTree *expr, RunnerVariablePages *pages) { if (ret != &AST_TREE_VOID_VALUE) { astTreeDelete(ret); } + return ret; } - return NULL; case AST_TREE_TOKEN_OPERATOR_ASSIGN: { AstTreeInfix *metadata = expr->metadata; if (metadata->left.token == AST_TREE_TOKEN_VARIABLE) { @@ -436,6 +445,22 @@ AstTree *runExpression(AstTree *expr, RunnerVariablePages *pages) { AstTree *calcAstTreeValue(AstTree *tree, RunnerVariablePages *pages) { switch (tree->token) { + case AST_TREE_TOKEN_TYPE_TYPE: + case AST_TREE_TOKEN_TYPE_FUNCTION: + case AST_TREE_TOKEN_TYPE_VOID: + case AST_TREE_TOKEN_TYPE_BOOL: + case AST_TREE_TOKEN_TYPE_I8: + case AST_TREE_TOKEN_TYPE_U8: + case AST_TREE_TOKEN_TYPE_I16: + case AST_TREE_TOKEN_TYPE_U16: + case AST_TREE_TOKEN_TYPE_I32: + case AST_TREE_TOKEN_TYPE_U32: + case AST_TREE_TOKEN_TYPE_I64: + case AST_TREE_TOKEN_TYPE_U64: + case AST_TREE_TOKEN_TYPE_F16: + case AST_TREE_TOKEN_TYPE_F32: + case AST_TREE_TOKEN_TYPE_F64: + case AST_TREE_TOKEN_TYPE_F128: case AST_TREE_TOKEN_VALUE_VOID: case AST_TREE_TOKEN_VALUE_INT: case AST_TREE_TOKEN_VALUE_BOOL: @@ -578,22 +603,6 @@ AstTree *calcAstTreeValue(AstTree *tree, RunnerVariablePages *pages) { case AST_TREE_TOKEN_FUNCTION: case AST_TREE_TOKEN_KEYWORD_PRINT_U64: case AST_TREE_TOKEN_KEYWORD_RETURN: - case AST_TREE_TOKEN_TYPE_TYPE: - case AST_TREE_TOKEN_TYPE_FUNCTION: - case AST_TREE_TOKEN_TYPE_VOID: - case AST_TREE_TOKEN_TYPE_BOOL: - case AST_TREE_TOKEN_TYPE_I8: - case AST_TREE_TOKEN_TYPE_U8: - case AST_TREE_TOKEN_TYPE_I16: - case AST_TREE_TOKEN_TYPE_U16: - case AST_TREE_TOKEN_TYPE_I32: - case AST_TREE_TOKEN_TYPE_U32: - case AST_TREE_TOKEN_TYPE_I64: - case AST_TREE_TOKEN_TYPE_U64: - case AST_TREE_TOKEN_TYPE_F16: - case AST_TREE_TOKEN_TYPE_F32: - case AST_TREE_TOKEN_TYPE_F64: - case AST_TREE_TOKEN_TYPE_F128: case AST_TREE_TOKEN_VARIABLE_DEFINE: case AST_TREE_TOKEN_OPERATOR_ASSIGN: case AST_TREE_TOKEN_SCOPE: diff --git a/src/runner/runner.h b/src/runner/runner.h index c1a2382..02fd01e 100644 --- a/src/runner/runner.h +++ b/src/runner/runner.h @@ -24,6 +24,9 @@ void runnerVariablePush(RunnerVariables *variables,AstTreeVariable *variable); void runnerVariableSetValue(RunnerVariablePages *pages,AstTreeVariable *variable,AstTree *value); AstTree* runnerVariableGetValue(RunnerVariablePages *pages,AstTreeVariable *variable); +RunnerVariablePages initRootPages(); +void destroyRootPages(RunnerVariablePages pages); + bool runAstTree(AstTreeRoot *root); AstTree *runAstTreeFunction(AstTree *tree, AstTree **arguments, diff --git a/test/main.felan b/test/main.felan index 387bd90..b14a3ee 100644 --- a/test/main.felan +++ b/test/main.felan @@ -1,9 +1,17 @@ -test :: ()->void; - -main : test : () -> void { - a := 10; +main :: () -> void { + a :theType= 10; while a > 0 { print_u64 1; a = a -1; } }; + +theType :: getType(u64,i64); +signed :: true; + +getType :: (a:type,b:type)->type { + if signed + return a; + else + return b; +}; |