diff options
-rw-r--r-- | src/compiler/ast-tree.c | 124 | ||||
-rw-r--r-- | src/compiler/ast-tree.h | 6 | ||||
-rw-r--r-- | src/compiler/lexer.c | 31 | ||||
-rw-r--r-- | src/compiler/lexer.h | 1 | ||||
-rw-r--r-- | src/compiler/parser.c | 34 | ||||
-rw-r--r-- | src/compiler/parser.h | 2 | ||||
-rw-r--r-- | src/runner/runner.c | 5 | ||||
-rw-r--r-- | test/main.felan | 2 |
8 files changed, 121 insertions, 84 deletions
diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c index 8cb1fce..22b1103 100644 --- a/src/compiler/ast-tree.c +++ b/src/compiler/ast-tree.c @@ -112,6 +112,7 @@ const char *AST_TREE_TOKEN_STRINGS[] = { "AST_TREE_TOKEN_KEYWORD_RETURN", "AST_TREE_TOKEN_KEYWORD_IF", "AST_TREE_TOKEN_KEYWORD_WHILE", + "AST_TREE_TOKEN_KEYWORD_COMPTIME", "AST_TREE_TOKEN_TYPE_FUNCTION", "AST_TREE_TOKEN_TYPE_TYPE", @@ -220,7 +221,8 @@ void astTreePrint(const AstTree *tree, int indent) { goto RETURN_SUCCESS; case AST_TREE_TOKEN_OPERATOR_PLUS: case AST_TREE_TOKEN_OPERATOR_MINUS: - case AST_TREE_TOKEN_KEYWORD_PRINT_U64: { + case AST_TREE_TOKEN_KEYWORD_PRINT_U64: + case AST_TREE_TOKEN_KEYWORD_COMPTIME: { AstTreeSingleChild *metadata = tree->metadata; printf(",\n"); for (int i = 0; i < indent; ++i) @@ -450,7 +452,8 @@ void astTreeDestroy(AstTree tree) { } case AST_TREE_TOKEN_OPERATOR_PLUS: case AST_TREE_TOKEN_OPERATOR_MINUS: - case AST_TREE_TOKEN_KEYWORD_PRINT_U64: { + case AST_TREE_TOKEN_KEYWORD_PRINT_U64: + case AST_TREE_TOKEN_KEYWORD_COMPTIME: { AstTreeSingleChild *metadata = tree.metadata; astTreeDelete(metadata); } @@ -557,13 +560,18 @@ void astTreeVariableDelete(AstTreeVariable *variable) { } void astTreeDelete(AstTree *tree) { - if (AST_TREE_TOKEN_STATIC_VARS_BEGIN > tree->token || - tree->token > AST_TREE_TOKEN_STATIC_VARS_END) { + if (astTreeShouldDelete(tree)) { astTreeDestroy(*tree); free(tree); } } +bool astTreeShouldDelete(AstTree *tree) { + return (AST_TREE_TOKEN_STATIC_VARS_BEGIN > tree->token || + tree->token > AST_TREE_TOKEN_STATIC_VARS_END) && + tree != &AST_TREE_VOID_VALUE; +} + void astTreeRootDelete(AstTreeRoot *root) { for (size_t i = 0; i < root->variables.size; ++i) { astTreeVariableDelete(root->variables.data[i]); @@ -677,7 +685,8 @@ AstTree *copyAstTree(AstTree *tree) { } case AST_TREE_TOKEN_OPERATOR_PLUS: case AST_TREE_TOKEN_OPERATOR_MINUS: - case AST_TREE_TOKEN_KEYWORD_PRINT_U64: { + case AST_TREE_TOKEN_KEYWORD_PRINT_U64: + case AST_TREE_TOKEN_KEYWORD_COMPTIME: { AstTreeSingleChild *metadata = tree->metadata; AstTreeSingleChild *new_metadata = copyAstTree(metadata); @@ -846,6 +855,7 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) { case PARSER_TOKEN_SYMBOL_PARENTHESIS: case PARSER_TOKEN_KEYWORD_IF: case PARSER_TOKEN_KEYWORD_WHILE: + case PARSER_TOKEN_KEYWORD_COMPTIME: case PARSER_TOKEN_TYPE_TYPE: case PARSER_TOKEN_TYPE_FUNCTION: case PARSER_TOKEN_TYPE_VOID: @@ -1104,6 +1114,8 @@ AstTree *astTreeParse(ParserNode *parserNode, AstTreeHelper *helper) { return astTreeParseIf(parserNode, helper); case PARSER_TOKEN_KEYWORD_WHILE: return astTreeParseWhile(parserNode, helper); + case PARSER_TOKEN_KEYWORD_COMPTIME: + return astTreeParseComptime(parserNode, helper); case PARSER_TOKEN_SYMBOL_EOL: return astTreeParse((ParserNodeSingleChildMetadata *)parserNode->metadata, helper); @@ -1223,6 +1235,7 @@ AstTree *astTreeParseFunction(ParserNode *parserNode, AstTreeHelper *p_helper) { case PARSER_TOKEN_TYPE_BOOL: case PARSER_TOKEN_KEYWORD_PRINT_U64: case PARSER_TOKEN_KEYWORD_RETURN: + case PARSER_TOKEN_KEYWORD_COMPTIME: case PARSER_TOKEN_CONSTANT: case PARSER_TOKEN_VARIABLE: case PARSER_TOKEN_SYMBOL_CURLY_BRACKET: @@ -1650,6 +1663,16 @@ AstTree *astTreeParseWhile(ParserNode *parserNode, AstTreeHelper *helper) { parserNode->str_begin, parserNode->str_end); } +AstTree *astTreeParseComptime(ParserNode *parserNode, AstTreeHelper *helper) { + ParserNodeSingleChildMetadata *node_metadata = parserNode->metadata; + + AstTreeSingleChild *metadata = + (AstTreeSingleChild *)astTreeParse((ParserNode *)node_metadata, helper); + + return newAstTree(AST_TREE_TOKEN_KEYWORD_COMPTIME, metadata, NULL, + parserNode->str_begin, parserNode->str_end); +} + AstTree *astTreeParseCurlyBracket(ParserNode *parserNode, AstTreeHelper *p_helper) { ParserNodeArray *body = parserNode->metadata; @@ -1708,6 +1731,7 @@ AstTree *astTreeParseCurlyBracket(ParserNode *parserNode, case PARSER_TOKEN_TYPE_BOOL: case PARSER_TOKEN_KEYWORD_PRINT_U64: case PARSER_TOKEN_KEYWORD_RETURN: + case PARSER_TOKEN_KEYWORD_COMPTIME: case PARSER_TOKEN_CONSTANT: case PARSER_TOKEN_VARIABLE: case PARSER_TOKEN_SYMBOL_CURLY_BRACKET: @@ -1807,6 +1831,7 @@ AstTreeFunction *getFunction(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_KEYWORD_COMPTIME: case AST_TREE_TOKEN_TYPE_TYPE: case AST_TREE_TOKEN_TYPE_FUNCTION: case AST_TREE_TOKEN_TYPE_VOID: @@ -1872,6 +1897,7 @@ bool isConst(AstTree *tree, AstTreeHelper *helper) { case AST_TREE_TOKEN_VALUE_INT: case AST_TREE_TOKEN_VALUE_FLOAT: case AST_TREE_TOKEN_VALUE_BOOL: + case AST_TREE_TOKEN_KEYWORD_COMPTIME: return true; case AST_TREE_TOKEN_KEYWORD_IF: { AstTreeIf *metadata = tree->metadata; @@ -1973,6 +1999,7 @@ AstTree *makeTypeOf(AstTree *value) { AstTreeVariable *variable = value->metadata; return copyAstTree(variable->type); } + case AST_TREE_TOKEN_KEYWORD_COMPTIME: case AST_TREE_TOKEN_OPERATOR_PLUS: case AST_TREE_TOKEN_OPERATOR_MINUS: { AstTreeSingleChild *metadata = value->metadata; @@ -2013,6 +2040,7 @@ bool typeIsEqual(const AstTree *type0, const AstTree *type1) { case AST_TREE_TOKEN_KEYWORD_RETURN: case AST_TREE_TOKEN_KEYWORD_IF: case AST_TREE_TOKEN_KEYWORD_WHILE: + case AST_TREE_TOKEN_KEYWORD_COMPTIME: case AST_TREE_TOKEN_VALUE_VOID: case AST_TREE_TOKEN_VALUE_INT: case AST_TREE_TOKEN_VALUE_FLOAT: @@ -2124,7 +2152,11 @@ AstTree *getValue(AstTree *tree, AstTreeSetTypesHelper helper) { 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: + case AST_TREE_TOKEN_KEYWORD_IF: + case AST_TREE_TOKEN_KEYWORD_WHILE: + case AST_TREE_TOKEN_KEYWORD_COMPTIME: + case AST_TREE_TOKEN_SCOPE: { AstTree *value = runExpression(tree, helper.pages); if (value == NULL) { printError(tree->str_begin, tree->str_end, "Unknown error"); @@ -2136,10 +2168,7 @@ AstTree *getValue(AstTree *tree, AstTreeSetTypesHelper helper) { } 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: } UNREACHABLE; @@ -2170,6 +2199,7 @@ bool isCircularDependencies(AstTreeHelper *helper, AstTreeVariable *variable, case AST_TREE_TOKEN_VALUE_FLOAT: case AST_TREE_TOKEN_VALUE_BOOL: return false; + case AST_TREE_TOKEN_KEYWORD_COMPTIME: case AST_TREE_TOKEN_OPERATOR_PLUS: case AST_TREE_TOKEN_OPERATOR_MINUS: { AstTreeSingleChild *metadata = tree->metadata; @@ -2323,6 +2353,8 @@ bool setAllTypes(AstTree *tree, AstTreeSetTypesHelper helper, return setTypesWhile(tree, helper, function); case AST_TREE_TOKEN_SCOPE: return setTypesScope(tree, helper, function); + case AST_TREE_TOKEN_KEYWORD_COMPTIME: + return setTypesComptime(tree, helper); case AST_TREE_TOKEN_NONE: break; } @@ -2791,6 +2823,25 @@ bool setTypesScope(AstTree *tree, AstTreeSetTypesHelper helper, return true; } +bool setTypesComptime(AstTree *tree, AstTreeSetTypesHelper helper) { + AstTreeSingleChild *operand = tree->metadata; + + if (!setAllTypes(operand, helper, NULL)) { + return false; + } + + AstTree *newTree = getValue(operand, helper); + + if (operand != newTree) { + astTreeDelete(operand); + operand = newTree; + } + tree->metadata = operand; + tree->type = copyAstTree(operand->type); + + return true; +} + bool setTypesAstInfix(AstTreeInfix *infix, AstTreeSetTypesHelper helper) { if (!setAllTypes(&infix->left, helper, NULL)) { return false; @@ -2803,58 +2854,3 @@ bool setTypesAstInfix(AstTreeInfix *infix, AstTreeSetTypesHelper helper) { return setAllTypes(&infix->right, newHelper, NULL); } - -size_t astTreeTypeSize(AstTree tree) { - switch (tree.token) { - case AST_TREE_TOKEN_TYPE_BOOL: - case AST_TREE_TOKEN_TYPE_I8: - case AST_TREE_TOKEN_TYPE_U8: - return 1; - case AST_TREE_TOKEN_TYPE_I16: - case AST_TREE_TOKEN_TYPE_U16: - case AST_TREE_TOKEN_TYPE_F16: - return 2; - case AST_TREE_TOKEN_TYPE_I32: - case AST_TREE_TOKEN_TYPE_U32: - case AST_TREE_TOKEN_TYPE_F32: - return 4; - case AST_TREE_TOKEN_TYPE_I64: - case AST_TREE_TOKEN_TYPE_U64: - case AST_TREE_TOKEN_TYPE_F64: - return 8; - case AST_TREE_TOKEN_TYPE_F128: - return 16; - 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_FUNCTION_CALL: - case AST_TREE_TOKEN_VARIABLE: - 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: - case AST_TREE_TOKEN_OPERATOR_ASSIGN: - 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_OPERATOR_EQUAL: - case AST_TREE_TOKEN_OPERATOR_NOT_EQUAL: - 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_KEYWORD_IF: - case AST_TREE_TOKEN_KEYWORD_WHILE: - 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 0294956..cc66ede 100644 --- a/src/compiler/ast-tree.h +++ b/src/compiler/ast-tree.h @@ -11,6 +11,7 @@ typedef enum AstTreeToken { AST_TREE_TOKEN_KEYWORD_RETURN, AST_TREE_TOKEN_KEYWORD_IF, AST_TREE_TOKEN_KEYWORD_WHILE, + AST_TREE_TOKEN_KEYWORD_COMPTIME, AST_TREE_TOKEN_TYPE_FUNCTION, AST_TREE_TOKEN_TYPE_TYPE, @@ -177,6 +178,7 @@ void astTreeDestroy(AstTree tree); void astTreeVariableDestroy(AstTreeVariable variable); void astTreeVariableDelete(AstTreeVariable *variable); void astTreeDelete(AstTree *tree); +bool astTreeShouldDelete(AstTree *tree); void astTreeRootDelete(AstTreeRoot *root); AstTree *newAstTree(AstTreeToken token, void *metadata, AstTree *type, @@ -211,6 +213,7 @@ bool astTreeParseConstant(ParserNode *parserNode, AstTreeHelper *helper); AstTree *astTreeParseVariable(ParserNode *parserNode, AstTreeHelper *helper); AstTree *astTreeParseIf(ParserNode *parserNode, AstTreeHelper *helper); AstTree *astTreeParseWhile(ParserNode *parserNode, AstTreeHelper *helper); +AstTree *astTreeParseComptime(ParserNode *parserNode, AstTreeHelper *helper); AstTree *astTreeParseCurlyBracket(ParserNode *parserNode, AstTreeHelper *helper); AstTree *astTreeParseParenthesis(ParserNode *parserNode, AstTreeHelper *helper); @@ -248,9 +251,8 @@ bool setTypesWhile(AstTree *tree, AstTreeSetTypesHelper helper, AstTreeFunction *function); bool setTypesScope(AstTree *tree, AstTreeSetTypesHelper helper, AstTreeFunction *function); +bool setTypesComptime(AstTree *tree, AstTreeSetTypesHelper helper); bool setTypesAstVariable(AstTreeVariable *variable, AstTreeSetTypesHelper helper); bool setTypesAstInfix(AstTreeInfix *infix, AstTreeSetTypesHelper helper); - -size_t astTreeTypeSize(AstTree tree); diff --git a/src/compiler/lexer.c b/src/compiler/lexer.c index 2b7a789..54b78ec 100644 --- a/src/compiler/lexer.c +++ b/src/compiler/lexer.c @@ -34,6 +34,7 @@ const char *LEXER_TOKEN_STRINGS[] = { "LEXER_TOKEN_KEYWORD_IF", "LEXER_TOKEN_KEYWORD_ELSE", "LEXER_TOKEN_KEYWORD_WHILE", + "LEXER_TOKEN_KEYWORD_COMPTIME", "LEXER_TOKEN_NUMBER", @@ -104,22 +105,23 @@ const size_t LEXER_SYMBOL_SIZE = sizeof(LEXER_SYMBOL_TOKENS) / sizeof(*LEXER_SYMBOL_TOKENS); const char *LEXER_KEYWORD_STRINGS[] = { - "type", "void", "i8", "u8", "i16", "u16", "i32", "u32", - "i64", "u64", "f16", "f32", "f64", "f128", "bool", "print_u64", - "return", "true", "false", "if", "else", "while", + "type", "void", "i8", "u8", "i16", "u16", "i32", "u32", + "i64", "u64", "f16", "f32", "f64", "f128", "bool", "print_u64", + "return", "true", "false", "if", "else", "while", "comptime", }; const LexerToken LEXER_KEYWORD_TOKENS[] = { - LEXER_TOKEN_KEYWORD_TYPE, LEXER_TOKEN_KEYWORD_VOID, - LEXER_TOKEN_KEYWORD_I8, LEXER_TOKEN_KEYWORD_U8, - LEXER_TOKEN_KEYWORD_I16, LEXER_TOKEN_KEYWORD_U16, - LEXER_TOKEN_KEYWORD_I32, LEXER_TOKEN_KEYWORD_U32, - LEXER_TOKEN_KEYWORD_I64, LEXER_TOKEN_KEYWORD_U64, - LEXER_TOKEN_KEYWORD_F16, LEXER_TOKEN_KEYWORD_F32, - LEXER_TOKEN_KEYWORD_F64, LEXER_TOKEN_KEYWORD_F128, - 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_ELSE, LEXER_TOKEN_KEYWORD_WHILE, + LEXER_TOKEN_KEYWORD_TYPE, LEXER_TOKEN_KEYWORD_VOID, + LEXER_TOKEN_KEYWORD_I8, LEXER_TOKEN_KEYWORD_U8, + LEXER_TOKEN_KEYWORD_I16, LEXER_TOKEN_KEYWORD_U16, + LEXER_TOKEN_KEYWORD_I32, LEXER_TOKEN_KEYWORD_U32, + LEXER_TOKEN_KEYWORD_I64, LEXER_TOKEN_KEYWORD_U64, + LEXER_TOKEN_KEYWORD_F16, LEXER_TOKEN_KEYWORD_F32, + LEXER_TOKEN_KEYWORD_F64, LEXER_TOKEN_KEYWORD_F128, + 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_ELSE, LEXER_TOKEN_KEYWORD_WHILE, + LEXER_TOKEN_KEYWORD_COMPTIME, }; const size_t LEXER_KEYWORD_SIZE = sizeof(LEXER_KEYWORD_TOKENS) / sizeof(*LEXER_KEYWORD_TOKENS); @@ -268,6 +270,7 @@ void lexerPushClear(LexerNodeArray *array, size_t *array_size, char *iter, case LEXER_TOKEN_KEYWORD_IF: case LEXER_TOKEN_KEYWORD_ELSE: case LEXER_TOKEN_KEYWORD_WHILE: + case LEXER_TOKEN_KEYWORD_COMPTIME: 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 570b472..7a6aa74 100644 --- a/src/compiler/lexer.h +++ b/src/compiler/lexer.h @@ -27,6 +27,7 @@ typedef enum LexerToken { LEXER_TOKEN_KEYWORD_IF, LEXER_TOKEN_KEYWORD_ELSE, LEXER_TOKEN_KEYWORD_WHILE, + LEXER_TOKEN_KEYWORD_COMPTIME, LEXER_TOKEN_NUMBER, diff --git a/src/compiler/parser.c b/src/compiler/parser.c index 405c921..9d95c1d 100644 --- a/src/compiler/parser.c +++ b/src/compiler/parser.c @@ -39,6 +39,7 @@ const char *PARSER_TOKEN_STRINGS[] = { "PARSER_TOKEN_KEYWORD_RETURN", "PARSER_TOKEN_KEYWORD_IF", "PARSER_TOKEN_KEYWORD_WHILE", + "PARSER_TOKEN_KEYWORD_COMPTIME", "PARSER_TOKEN_CONSTANT", "PARSER_TOKEN_VARIABLE", @@ -136,8 +137,8 @@ static constexpr ParserOrder PARSER_ORDER[] = { }, { .ltr = true, - ORDER_ARRAY(LEXER_TOKEN_KEYWORD_RETURN, - LEXER_TOKEN_KEYWORD_PRINT_U64, ), + ORDER_ARRAY(LEXER_TOKEN_KEYWORD_RETURN, LEXER_TOKEN_KEYWORD_PRINT_U64, + LEXER_TOKEN_KEYWORD_COMPTIME, ), }, { .ltr = true, @@ -147,6 +148,7 @@ static constexpr ParserOrder PARSER_ORDER[] = { .ltr = true, ORDER_ARRAY(LEXER_TOKEN_KEYWORD_IF, LEXER_TOKEN_KEYWORD_WHILE, ), }, + }; static constexpr size_t PARSER_ORDER_SIZE = @@ -236,6 +238,7 @@ void parserNodePrint(const ParserNode *node, int indent) { case PARSER_TOKEN_OPERATOR_PLUS: case PARSER_TOKEN_OPERATOR_MINUS: case PARSER_TOKEN_KEYWORD_PRINT_U64: + case PARSER_TOKEN_KEYWORD_COMPTIME: case PARSER_TOKEN_SYMBOL_COMMA: case PARSER_TOKEN_SYMBOL_EOL: { const ParserNodeSingleChildMetadata *metadata = node->metadata; @@ -459,6 +462,7 @@ void parserNodeDelete(ParserNode *node) { case PARSER_TOKEN_OPERATOR_PLUS: case PARSER_TOKEN_OPERATOR_MINUS: case PARSER_TOKEN_KEYWORD_PRINT_U64: + case PARSER_TOKEN_KEYWORD_COMPTIME: case PARSER_TOKEN_SYMBOL_COMMA: case PARSER_TOKEN_SYMBOL_EOL: { ParserNodeSingleChildMetadata *metadata = node->metadata; @@ -763,6 +767,8 @@ ParserNode *parseNode(LexerNode *node, LexerNode *begin, LexerNode *end, return parserIf(node, end, parent); case LEXER_TOKEN_KEYWORD_WHILE: return parserWhile(node, end, parent); + case LEXER_TOKEN_KEYWORD_COMPTIME: + return parserComptime(node, end, parent); case LEXER_TOKEN_KEYWORD_ELSE: case LEXER_TOKEN_SYMBOL: case LEXER_TOKEN_SYMBOL_OPEN_PARENTHESIS: @@ -1180,6 +1186,7 @@ ParserNode *parserFunction(LexerNode *node, LexerNode *begin, LexerNode *end, case PARSER_TOKEN_OPERATOR_SMALLER_OR_EQUAL: case PARSER_TOKEN_FUNCTION_DEFINITION: case PARSER_TOKEN_FUNCTION_CALL: + case PARSER_TOKEN_KEYWORD_COMPTIME: printError(bodyArray->data[i]->str_begin, bodyArray->data[i]->str_end, "Maybe forgot a ; with %s", PARSER_TOKEN_STRINGS[bodyArray->data[i]->token]); @@ -1475,6 +1482,26 @@ ParserNode *parserWhile(LexerNode *node, LexerNode *end, ParserNode *parent) { body->str_end, metadata, parent); } +ParserNode *parserComptime(LexerNode *node, LexerNode *end, + ParserNode *parent) { + LexerNode *next = node + 1; + if (next >= end) { + printError(node->str_begin, node->str_end, "Comptime has no operand"); + return NULL; + } + + ParserNode *operand = getUntilCommonParent(next->parserNode, parent); + + if (operand == NULL) { + printError(node->str_begin, node->str_end, "Comptime has bad operand"); + return NULL; + } + + return operand->parent = node->parserNode = newParserNode( + PARSER_TOKEN_KEYWORD_COMPTIME, node->str_begin, operand->str_end, + (ParserNodeSingleChildMetadata *)operand, parent); +} + bool isAllArguments(const ParserNodeArray *nodes) { for (size_t i = 0; i < nodes->size; ++i) { const ParserNode *node = nodes->data[i]; @@ -1519,6 +1546,7 @@ bool isExpression(ParserNode *node) { case PARSER_TOKEN_VALUE_BOOL: case PARSER_TOKEN_KEYWORD_IF: case PARSER_TOKEN_KEYWORD_WHILE: + case PARSER_TOKEN_KEYWORD_COMPTIME: case PARSER_TOKEN_TYPE_TYPE: case PARSER_TOKEN_TYPE_FUNCTION: case PARSER_TOKEN_TYPE_VOID: @@ -1568,6 +1596,7 @@ bool isType(ParserNode *node) { case PARSER_TOKEN_SYMBOL_PARENTHESIS: case PARSER_TOKEN_FUNCTION_CALL: case PARSER_TOKEN_KEYWORD_IF: + case PARSER_TOKEN_KEYWORD_COMPTIME: return true; case PARSER_TOKEN_CONSTANT: case PARSER_TOKEN_VARIABLE: @@ -1651,6 +1680,7 @@ bool isValue(ParserNode *node) { case PARSER_TOKEN_TYPE_F64: case PARSER_TOKEN_TYPE_F128: case PARSER_TOKEN_KEYWORD_IF: + case PARSER_TOKEN_KEYWORD_COMPTIME: case PARSER_TOKEN_SYMBOL_PARENTHESIS: return true; case PARSER_TOKEN_CONSTANT: diff --git a/src/compiler/parser.h b/src/compiler/parser.h index 2d0c828..bb54099 100644 --- a/src/compiler/parser.h +++ b/src/compiler/parser.h @@ -35,6 +35,7 @@ typedef enum ParserToken { PARSER_TOKEN_KEYWORD_RETURN, PARSER_TOKEN_KEYWORD_IF, PARSER_TOKEN_KEYWORD_WHILE, + PARSER_TOKEN_KEYWORD_COMPTIME, PARSER_TOKEN_CONSTANT, PARSER_TOKEN_VARIABLE, @@ -187,6 +188,7 @@ ParserNode *parserBinaryOrLeftOperator(LexerNode *node, LexerNode *begin, LexerToken laterToken); ParserNode *parserIf(LexerNode *node, LexerNode *end, ParserNode *parent); ParserNode *parserWhile(LexerNode *node, LexerNode *end, ParserNode *parent); +ParserNode *parserComptime(LexerNode *node, LexerNode *end, ParserNode *parent); bool isAllArguments(const ParserNodeArray *nodes); diff --git a/src/runner/runner.c b/src/runner/runner.c index cb2dc8f..47c825d 100644 --- a/src/runner/runner.c +++ b/src/runner/runner.c @@ -296,6 +296,10 @@ AstTree *runExpression(AstTree *expr, RunnerVariablePages *pages) { } return ret; } + case AST_TREE_TOKEN_KEYWORD_COMPTIME: { + AstTreeSingleChild *operand = expr->metadata; + return runExpression((AstTree *)operand, pages); + } case AST_TREE_TOKEN_SCOPE: { AstTreeScope *metadata = expr->metadata; @@ -335,7 +339,6 @@ AstTree *runExpression(AstTree *expr, RunnerVariablePages *pages) { free(newPages.data); return ret; } - return NULL; case AST_TREE_TOKEN_OPERATOR_PLUS: { AstTreeSingleChild *operand = runExpression(expr->metadata, pages); if (operand->type == &AST_TREE_U64_TYPE) { diff --git a/test/main.felan b/test/main.felan index b453f6b..f852c7e 100644 --- a/test/main.felan +++ b/test/main.felan @@ -1,5 +1,5 @@ main :: () -> void { - test(u64,i64); + comptime test(u64,u64); }; test :: (from:type, to:type) -> void { |