aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--code/file.felan136
-rw-r--r--code/main.felan133
-rw-r--r--src/compiler/ast-tree.c68
-rw-r--r--src/compiler/ast-tree.h12
-rw-r--r--src/compiler/parser.c20
-rw-r--r--src/compiler/parser.h1
-rw-r--r--src/utils/file.c2
8 files changed, 214 insertions, 162 deletions
diff --git a/Makefile b/Makefile
index d9f18bf..62214dc 100644
--- a/Makefile
+++ b/Makefile
@@ -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;