diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | code/file.felan | 136 | ||||
-rw-r--r-- | code/main.felan | 133 | ||||
-rw-r--r-- | src/compiler/ast-tree.c | 68 | ||||
-rw-r--r-- | src/compiler/ast-tree.h | 12 | ||||
-rw-r--r-- | src/compiler/parser.c | 20 | ||||
-rw-r--r-- | src/compiler/parser.h | 1 | ||||
-rw-r--r-- | src/utils/file.c | 2 |
8 files changed, 214 insertions, 162 deletions
@@ -20,9 +20,9 @@ INC_DIRS := $(SRC_DIR) INC_FLAGS := $(addprefix -I,$(INC_DIRS)) # OP_FLAG := -Ofast -OP_FLAG := -O3 +# OP_FLAG := -O3 # OP_FLAG := -Oz -# OP_FLAG := -g +OP_FLAG := -g # CFLAGS := $(INC_FLAGS) -Wall -Wextra -std=gnu23 -DPRINT_STATISTICS -DPRINT_COMPILE_TREE $(OP_FLAG) CFLAGS := $(INC_FLAGS) -Wall -Wextra -std=gnu23 -DPRINT_STATISTICS $(OP_FLAG) diff --git a/code/file.felan b/code/file.felan index bccc1bd..715c8db 100644 --- a/code/file.felan +++ b/code/file.felan @@ -1,5 +1,133 @@ -test :: () -> void { - putc 'h'; - putc 'e'; - putc 'y'; +/* +@import("basic.felan"); + +print :: (value:[]u8)->void{ + i :u64 = 0; + while i < value.length { + putc value[i]; + i += @cast(1,u64); + } }; + +print :: (value:i64)->void{ + value := value; + str : [20]u8 = undefined; + i :u64= 19; + while { + str[i] = @cast(value % 10,u8) + '0'; + i -= @cast(1,u64); + value /= 10; + value != 0; + } {} + + j :u64= i+@cast(1,u64); + while j < @cast(20,u64) { + putc str[j]; + j += @cast(1,u64); + } +}; + +println :: (value:i64)->void{ + print(value); + putc '\n'; +}; + +println :: ()->void{ + putc '\n'; +}; + +main :: () -> void { + stones := 6; + player := 1; + while stones != 0 { + c := choose_ai(stones); + print("player: "); + print(player); + print(" ---------\n"); + println(stones); + println(c); + + if (stones == 2 || stones == 1) && stones == c { + print("player: "); + print(player); + print(" won\n"); + } + + stones -= c; + + player = (if (player == 1) 2 else 1); + } +}; + +choose_ai :: (stones_left:i64) -> i64 { + return (if (stones_left % 3 == 0) 1 else stones_left % 3); +}; +*/ +@import("basic.felan"); + +main :: () -> void { + stones := 6; + player := 1; + while stones > 0 { + r :res =minimax(stones,true); + stones -= r.move; + putc @cast(stones,u8) + '0'; + putc '\n'; + putc 'p'; + putc @cast(player,u8) + '0'; + putc '\n'; + player = (if player == 2 1 else 2); + } +}; + +res :: struct { + move : i64; + score : i64; +}; + +minimax :: (currentStones:i64, isMaximizing:bool) -> res { + if currentStones <= 0 { + r : res = undefined; + r.move = 0; + r.score = (if isMaximizing {-1;} else {1;}); + return r; + } + + found := false; + bestMove : res = undefined; + score := (if isMaximizing {-1000000;} else {1000000;}); + move := 1; + + while move <= 2 { + if currentStones - move >= 0 { + found = true; + result := minimax(currentStones - move, !isMaximizing); + if isMaximizing { + if result.score > score { + bestMove.move = move; + bestMove.score = result.score; + score = result.score; + } + }else{ + if result.score < score { + bestMove.move = move; + bestMove.score = result.score; + score = result.score; + } + } + } + move += 1; + } + + if !found { + r : res = undefined; + r.move = 0; + r.score = (if isMaximizing {-1;} else {1;}); + return r; + } + + return bestMove; +}; + + + diff --git a/code/main.felan b/code/main.felan index 715c8db..c2c3116 100644 --- a/code/main.felan +++ b/code/main.felan @@ -1,133 +1,14 @@ -/* -@import("basic.felan"); +// @import("basic.felan"); -print :: (value:[]u8)->void{ - i :u64 = 0; - while i < value.length { - putc value[i]; - i += @cast(1,u64); - } +f :: (comptime t:type) -> type { + return struct { + a:t; + }; }; -print :: (value:i64)->void{ - value := value; - str : [20]u8 = undefined; - i :u64= 19; - while { - str[i] = @cast(value % 10,u8) + '0'; - i -= @cast(1,u64); - value /= 10; - value != 0; - } {} - - j :u64= i+@cast(1,u64); - while j < @cast(20,u64) { - putc str[j]; - j += @cast(1,u64); - } -}; - -println :: (value:i64)->void{ - print(value); - putc '\n'; -}; - -println :: ()->void{ - putc '\n'; -}; - -main :: () -> void { - stones := 6; - player := 1; - while stones != 0 { - c := choose_ai(stones); - print("player: "); - print(player); - print(" ---------\n"); - println(stones); - println(c); - - if (stones == 2 || stones == 1) && stones == c { - print("player: "); - print(player); - print(" won\n"); - } - - stones -= c; - - player = (if (player == 1) 2 else 1); - } -}; - -choose_ai :: (stones_left:i64) -> i64 { - return (if (stones_left % 3 == 0) 1 else stones_left % 3); -}; -*/ -@import("basic.felan"); - main :: () -> void { - stones := 6; - player := 1; - while stones > 0 { - r :res =minimax(stones,true); - stones -= r.move; - putc @cast(stones,u8) + '0'; - putc '\n'; - putc 'p'; - putc @cast(player,u8) + '0'; - putc '\n'; - player = (if player == 2 1 else 2); - } -}; - -res :: struct { - move : i64; - score : i64; -}; - -minimax :: (currentStones:i64, isMaximizing:bool) -> res { - if currentStones <= 0 { - r : res = undefined; - r.move = 0; - r.score = (if isMaximizing {-1;} else {1;}); - return r; - } - - found := false; - bestMove : res = undefined; - score := (if isMaximizing {-1000000;} else {1000000;}); - move := 1; - - while move <= 2 { - if currentStones - move >= 0 { - found = true; - result := minimax(currentStones - move, !isMaximizing); - if isMaximizing { - if result.score > score { - bestMove.move = move; - bestMove.score = result.score; - score = result.score; - } - }else{ - if result.score < score { - bestMove.move = move; - bestMove.score = result.score; - score = result.score; - } - } - } - move += 1; - } - - if !found { - r : res = undefined; - r.move = 0; - r.score = (if isMaximizing {-1;} else {1;}); - return r; - } - - return bestMove; + a :: u8; + f(a); }; - diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c index 688fc8b..14c8276 100644 --- a/src/compiler/ast-tree.c +++ b/src/compiler/ast-tree.c @@ -1066,6 +1066,7 @@ AstTree *copyAstTreeBack(AstTree *tree, AstTreeVariables oldVariables[], new_metadata->arguments[i].name_end = arg.name_end; new_metadata->arguments[i].type = copyAstTreeBack(arg.type, oldVariables, newVariables, variables_size); + new_metadata->arguments[i].isComptime = arg.isComptime; } new_metadata->returnType = copyAstTreeBack( metadata->returnType, oldVariables, newVariables, variables_size); @@ -1666,6 +1667,12 @@ AstTreeRoot *makeAstRoot(const ParserNode *parsedRoot, char *filePath) { variable->isConst = node->token == PARSER_TOKEN_CONSTANT; variable->isLazy = node_metadata->isLazy; + if (node_metadata->isComptime && !variable->isConst) { + printError(node->str_begin, node->str_end, "Bad comptime %s", + PARSER_TOKEN_STRINGS[node->token]); + goto RETURN_ERROR; + } + if (!pushVariable(&helper, &root->variables, variable)) { astTreeVariableDelete(variable); goto RETURN_ERROR; @@ -2183,7 +2190,8 @@ AstTree *astTreeParseFunction(const ParserNode *parserNode, argument->type = type; argument->name_begin = arg_metadata->name->str_begin; argument->name_end = arg_metadata->name->str_end; - argument->isLazy = true; // all arguments are constants + argument->isConst = arg_metadata->isComptime; + argument->isLazy = arg_metadata->isLazy; if (!pushVariable(&helper, &function->arguments, argument)) { astTreeVariableDelete(argument); @@ -2379,12 +2387,14 @@ AstTree *astTreeParseTypeFunction(const ParserNode *parserNode, if (argument.type == NULL) { return NULL; } + argument.isComptime = variable_metadata->isComptime; } else { argument.type = astTreeParse(node_argument, helper); if (argument.type == NULL) { return NULL; } argument.name_begin = argument.name_end = NULL; + argument.isComptime = false; } if (!typeIsEqual(argument.type->type, &AST_TREE_TYPE_TYPE)) { @@ -2408,9 +2418,8 @@ AstTree *astTreeParseTypeFunction(const ParserNode *parserNode, goto RETURN_ERROR; } - return newAstTree(AST_TREE_TOKEN_TYPE_FUNCTION, typeFunction, - &AST_TREE_TYPE_TYPE, parserNode->str_begin, - parserNode->str_end); + return newAstTree(AST_TREE_TOKEN_TYPE_FUNCTION, typeFunction, NULL, + parserNode->str_begin, parserNode->str_end); RETURN_ERROR: return NULL; @@ -2491,7 +2500,8 @@ AstTree *astTreeParseString(const ParserNode *parserNode, metadata->variables.data[i] = a404m_malloc(sizeof(*metadata->variables.data[i])); - metadata->variables.data[i]->isLazy = true; + metadata->variables.data[i]->isConst = true; + metadata->variables.data[i]->isLazy = false; metadata->variables.data[i]->name_begin = NULL; metadata->variables.data[i]->name_end = NULL; metadata->variables.data[i]->type = copyAstTree(&AST_TREE_U8_TYPE); @@ -2693,6 +2703,11 @@ AstTree *astTreeParseVariable(const ParserNode *parserNode, AstTreeHelper *helper) { ParserNodeVariableMetadata *node_metadata = parserNode->metadata; + if (node_metadata->isComptime) { + printError(parserNode->str_begin, parserNode->str_end, "Bad comptime"); + return NULL; + } + if (node_metadata->value == NULL) { printError(parserNode->str_begin, parserNode->str_end, "Must have a value (or use undefined)"); @@ -3026,7 +3041,11 @@ AstTree *astTreeParseStruct(const ParserNode *parserNode, if (node_variable->value != NULL) { printError(node->str_begin, node->str_end, "Can't have default values"); NOT_IMPLEMENTED; + } else if (node_variable->isComptime) { + printError(node->str_begin, node->str_end, "Bad comptime"); + return NULL; } + variable->value = NULL; variable->initValue = NULL; variable->isConst = false; @@ -3296,7 +3315,10 @@ AstTree *makeTypeOf(AstTree *value) { AstTreeVariable *arg = function->arguments.data[i]; type_metadata->arguments[i].name_begin = arg->name_begin; type_metadata->arguments[i].name_end = arg->name_end; + type_metadata->arguments[i].str_begin = arg->name_begin; + type_metadata->arguments[i].str_end = arg->name_end; type_metadata->arguments[i].type = copyAstTree(arg->type); + type_metadata->arguments[i].isComptime = arg->isConst; } return newAstTree(AST_TREE_TOKEN_TYPE_FUNCTION, type_metadata, @@ -3549,7 +3571,7 @@ bool typeIsEqualBack(const AstTree *type0, const AstTree *type1) { for (size_t i = 0; i < type0_metadata->arguments_size; ++i) { AstTreeTypeFunctionArgument p0 = type0_metadata->arguments[i]; AstTreeTypeFunctionArgument p1 = type1_metadata->arguments[i]; - if (!typeIsEqual(p0.type, p1.type)) { + if (!typeIsEqual(p0.type, p1.type) && p0.isComptime == p1.isComptime) { return false; } } @@ -4868,15 +4890,10 @@ bool setTypesAstVariable(AstTreeVariable *variable, return false; } - if (isConst(variable->type, true)) { - AstTree *type = variable->type; - variable->type = getValue(type); - if (variable->type == NULL) { - return false; - } - if (type != variable->type) { - astTreeDelete(type); - } + if (!isConst(variable->type, true)) { + printError(variable->name_begin, variable->name_end, + "Type must be comptime"); + return false; } } @@ -4918,6 +4935,12 @@ bool setTypesAstVariable(AstTreeVariable *variable, } } + if (!typeIsEqual(variable->type->type, &AST_TREE_TYPE_TYPE)) { + printError(variable->name_begin, variable->name_end, + "Type must have type of `type`"); + return false; + } + return true; } @@ -5188,6 +5211,7 @@ bool setTypesBuiltinCast(AstTree *tree, AstTreeSetTypesHelper helper, .name_end = FROM_STR + FROM_STR_SIZE, .str_begin = NULL, .str_end = NULL, + .isComptime = false, }; type_metadata->arguments[1] = (AstTreeTypeFunctionArgument){ @@ -5196,6 +5220,7 @@ bool setTypesBuiltinCast(AstTree *tree, AstTreeSetTypesHelper helper, .name_end = TO_STR + TO_STR_SIZE, .str_begin = NULL, .str_end = NULL, + .isComptime = false, }; tree->type = newAstTree(AST_TREE_TOKEN_TYPE_FUNCTION, type_metadata, @@ -5257,6 +5282,7 @@ bool setTypesBuiltinTypeOf(AstTree *tree, AstTreeSetTypesHelper helper, .name_end = VARIABLE_STR + VARIABLE_STR_SIZE, .str_begin = NULL, .str_end = NULL, + .isComptime = false, }; tree->type = newAstTree(AST_TREE_TOKEN_TYPE_FUNCTION, type_metadata, @@ -5318,6 +5344,7 @@ bool setTypesBuiltinImport(AstTree *tree, AstTreeSetTypesHelper helper, .name_end = PATH_STR + PATH_STR_SIZE, .str_begin = NULL, .str_end = NULL, + .isComptime = false, }; tree->type = newAstTree(AST_TREE_TOKEN_TYPE_FUNCTION, type_metadata, @@ -5470,6 +5497,7 @@ AFTER_SWITCH: .name_end = VALUE_STR + VALUE_STR_SIZE, .str_begin = NULL, .str_end = NULL, + .isComptime = false, }; tree->type = newAstTree(AST_TREE_TOKEN_TYPE_FUNCTION, type_metadata, @@ -5539,6 +5567,7 @@ bool setTypesBuiltinBinary(AstTree *tree, AstTreeSetTypesHelper helper, .name_end = LEFT_STR + LEFT_STR_SIZE, .str_begin = NULL, .str_end = NULL, + .isComptime = false, }; type_metadata->arguments[1] = (AstTreeTypeFunctionArgument){ @@ -5547,6 +5576,7 @@ bool setTypesBuiltinBinary(AstTree *tree, AstTreeSetTypesHelper helper, .name_end = RIGHT_STR + RIGHT_STR_SIZE, .str_begin = NULL, .str_end = NULL, + .isComptime = false, }; tree->type = newAstTree(AST_TREE_TOKEN_TYPE_FUNCTION, type_metadata, @@ -5617,6 +5647,7 @@ bool setTypesBuiltinBinaryWithRet(AstTree *tree, AstTreeSetTypesHelper helper, .name_end = LEFT_STR + LEFT_STR_SIZE, .str_begin = NULL, .str_end = NULL, + .isComptime = false, }; type_metadata->arguments[1] = (AstTreeTypeFunctionArgument){ @@ -5625,6 +5656,7 @@ bool setTypesBuiltinBinaryWithRet(AstTree *tree, AstTreeSetTypesHelper helper, .name_end = RIGHT_STR + RIGHT_STR_SIZE, .str_begin = NULL, .str_end = NULL, + .isComptime = false, }; tree->type = newAstTree(AST_TREE_TOKEN_TYPE_FUNCTION, type_metadata, @@ -5794,7 +5826,8 @@ AstTreeVariable *setTypesFindVariable(const char *name_begin, AstTreeTypeFunctionArgument arg = function->arguments[j]; if ((size_t)(arg.name_end - arg.name_begin) == param_name_size && strnEquals(arg.name_begin, param.nameBegin, param_name_size)) { - if (!typeIsEqual(arg.type, param.value->type)) { + if (!typeIsEqual(arg.type, param.value->type) || + (arg.isComptime && !isConst(param.value, false))) { goto CONTINUE_OUTER; } initedArguments[j] = param; @@ -5812,7 +5845,8 @@ AstTreeVariable *setTypesFindVariable(const char *name_begin, for (size_t j = 0; j < function->arguments_size; ++j) { AstTreeTypeFunctionArgument arg = function->arguments[j]; if (initedArguments[j].value == NULL) { - if (!typeIsEqual(arg.type, param.value->type)) { + if (!typeIsEqual(arg.type, param.value->type) || + (arg.isComptime && !isConst(param.value, false))) { goto CONTINUE_OUTER; } initedArguments[j] = param; diff --git a/src/compiler/ast-tree.h b/src/compiler/ast-tree.h index c1f0464..9eda3f0 100644 --- a/src/compiler/ast-tree.h +++ b/src/compiler/ast-tree.h @@ -183,6 +183,7 @@ typedef struct AstTreeTypeFunctionArgument { char const *name_begin; char const *name_end; AstTree *type; + bool isComptime; } AstTreeTypeFunctionArgument; typedef struct AstTreeTypeFunction { @@ -312,15 +313,13 @@ AstTreeVariables copyAstTreeVariables(AstTreeVariables variables, AstTreeRoots makeAstTree(const char *filePath #ifdef PRINT_STATISTICS , - Time *lexingTime, - Time *parsingTime + Time *lexingTime, Time *parsingTime #endif ); AstTreeRoot *getAstTreeRoot(char *filePath, AstTreeRoots *roots #ifdef PRINT_STATISTICS , - Time *lexingTime, - Time *parsingTime + Time *lexingTime, Time *parsingTime #endif ); AstTreeRoot *makeAstRoot(const ParserNode *parsedRoot, char *filePath); @@ -342,8 +341,7 @@ AstTree *astTreeParseValue(const ParserNode *parserNode, AstTreeToken token, AstTree *astTreeParseString(const ParserNode *parserNode, AstTreeHelper *helper); AstTree *astTreeParseKeyword(const ParserNode *parserNode, AstTreeToken token); -AstTree *astTreeParsePutc(const ParserNode *parserNode, - AstTreeHelper *helper); +AstTree *astTreeParsePutc(const ParserNode *parserNode, AstTreeHelper *helper); AstTree *astTreeParseReturn(const ParserNode *parserNode, AstTreeHelper *helper); AstTree *astTreeParseBinaryOperator(const ParserNode *parserNode, @@ -375,7 +373,7 @@ AstTree *astTreeParseBracket(const ParserNode *parserNode, AstTreeHelper *helper, AstTreeToken token); bool isFunction(AstTree *value); -bool isConst(AstTree *tree,bool byValue); +bool isConst(AstTree *tree, bool byValue); AstTree *makeTypeOf(AstTree *value); bool typeIsEqual(AstTree *type0, AstTree *type1); bool typeIsEqualBack(const AstTree *type0, const AstTree *type1); diff --git a/src/compiler/parser.c b/src/compiler/parser.c index 388e69a..139a0ff 100644 --- a/src/compiler/parser.c +++ b/src/compiler/parser.c @@ -1881,15 +1881,25 @@ ParserNode *parserVariable(LexerNode *node, LexerNode *begin, LexerNode *end, metadata->value = value; metadata->name = name; metadata->type = type; + metadata->isComptime = false; + metadata->isLazy = false; LexerNode *flagNode = nameNode - 1; - if (flagNode >= begin && flagNode->parserNode == NULL && - flagNode->token == LEXER_TOKEN_KEYWORD_LAZY) { - metadata->isLazy = true; + while (flagNode >= begin && flagNode->parserNode == NULL) { + switch (flagNode->token) { + case LEXER_TOKEN_KEYWORD_LAZY: + metadata->isLazy = true; + break; + case LEXER_TOKEN_KEYWORD_COMPTIME: + metadata->isComptime = true; + break; + default: + goto AFTER_WHILE; + } flagNode->parserNode = variableNode; - } else { - metadata->isLazy = false; + flagNode -= 1; } +AFTER_WHILE: variableNode->metadata = metadata; diff --git a/src/compiler/parser.h b/src/compiler/parser.h index 0e43c34..59bbaaf 100644 --- a/src/compiler/parser.h +++ b/src/compiler/parser.h @@ -134,6 +134,7 @@ typedef struct ParserNodeVariableMetadata { ParserNode *type; ParserNode *value; bool isLazy; + bool isComptime; } ParserNodeVariableMetadata; typedef struct ParserNodeFunctionDefnitionMetadata { diff --git a/src/utils/file.c b/src/utils/file.c index 61165d2..971dd67 100644 --- a/src/utils/file.c +++ b/src/utils/file.c @@ -40,7 +40,7 @@ void filePush(const char *filePath, char *code) { fileCodes[fileCodes_length] = code; fileCodes_names[fileCodes_length] = a404m_malloc((filePath_length + 1) * sizeof(**fileCodes_names)); - for (size_t i = 0; i < filePath_length; ++i) { + for (size_t i = 0; i < filePath_length + 1; ++i) { fileCodes_names[fileCodes_length][i] = filePath[i]; } fileCodes_length += 1; |