diff options
author | A404M <ahmadmahmoudiprogrammer@gmail.com> | 2025-01-24 04:12:03 +0330 |
---|---|---|
committer | A404M <ahmadmahmoudiprogrammer@gmail.com> | 2025-01-24 04:12:03 +0330 |
commit | 5d46c19b25a05a289ccecfa38bc0be849af87877 (patch) | |
tree | 04498dd1e3ece62449f96864c0c8d1bd7ebc37f4 | |
parent | 76272a881916b466f42f78ba16c696a843628d08 (diff) |
add types and type checking (not complete)
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | src/compiler/ast-tree.c | 245 | ||||
-rw-r--r-- | src/compiler/ast-tree.h | 29 | ||||
-rw-r--r-- | src/compiler/code-generator.c | 7 | ||||
-rw-r--r-- | src/compiler/lexer.c | 7 | ||||
-rw-r--r-- | src/compiler/parser.c | 101 | ||||
-rw-r--r-- | test/main.felan | 7 |
7 files changed, 318 insertions, 81 deletions
@@ -56,6 +56,9 @@ test: $(EXEC_FILE) val-test: $(EXEC_FILE) valgrind --log-file="val.log" --leak-check=full --track-origins=yes --show-leak-kinds=all -s $(EXEC_FILE) test/main.felan build/out +gdb-test: $(EXEC_FILE) + gdb $(EXEC_FILE) test/main.felan build/out + # $@ = left hand of : # $< = right hand of : first one of them # $^ = right hand of : all diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c index 3fe867e..76ee706 100644 --- a/src/compiler/ast-tree.c +++ b/src/compiler/ast-tree.c @@ -6,9 +6,9 @@ #include <stdlib.h> const char *AST_TREE_TOKEN_STRINGS[] = { - "AST_TREE_TOKEN_FUNCTION", - "AST_TREE_TOKEN_KEYWORD_PRINT", - "AST_TREE_TOKEN_NONE", + "AST_TREE_TOKEN_FUNCTION", "AST_TREE_TOKEN_KEYWORD_PRINT", + "AST_TREE_TOKEN_NONE", "AST_TREE_TOKEN_TYPE_FUNCTION", + "AST_TREE_TOKEN_TYPE_VOID", }; void astTreePrint(const AstTree *tree, int indent) { @@ -16,20 +16,48 @@ void astTreePrint(const AstTree *tree, int indent) { printf(" "); printf("{token=\"%s\"", AST_TREE_TOKEN_STRINGS[tree->token]); switch (tree->token) { - case AST_TREE_TOKEN_FUNCTION: - AstTreeScope *metadata = tree->metadata; + case AST_TREE_TOKEN_FUNCTION: { + AstTreeFunction *metadata = tree->metadata; printf(",\n"); for (int i = 0; i < indent; ++i) printf(" "); + printf("arguments=[\n"); + for (size_t i = 0; i < metadata->arguments_size; ++i) { + // astTreePrint(metadata->arguments[i], indent + 1); // TODO: do it + printf(",\n"); + } + for (int i = 0; i < indent; ++i) + printf(" "); + printf("],\n"); + for (int i = 0; i < indent; ++i) + printf(" "); printf("expressions=[\n"); - for (size_t i = 0; i < metadata->expressions_size; ++i) { - astTreePrint(&metadata->expressions[i], indent + 1); + for (size_t i = 0; i < metadata->scope.expressions_size; ++i) { + astTreePrint(&metadata->scope.expressions[i], indent + 1); printf(",\n"); } for (int i = 0; i < indent; ++i) printf(" "); printf("]"); + } + goto RETURN_SUCCESS; case AST_TREE_TOKEN_KEYWORD_PRINT: + case AST_TREE_TOKEN_TYPE_VOID: + goto RETURN_SUCCESS; + case AST_TREE_TOKEN_TYPE_FUNCTION: { + AstTreeTypeFunction *metadata = tree->metadata; + printf(",\n"); + for (int i = 0; i < indent; ++i) + printf(" "); + printf("arguments=[\n"); + for (size_t i = 0; i < metadata->arguments_size; ++i) { + astTreePrint(metadata->arguments[i], indent + 1); + printf(",\n"); + } + for (int i = 0; i < indent; ++i) + printf(" "); + printf("]"); + } goto RETURN_SUCCESS; case AST_TREE_TOKEN_NONE: } @@ -54,16 +82,30 @@ void astTreeRootPrint(const AstTreeRoot *root) { void astTreeDestroy(AstTree tree) { switch (tree.token) { - case AST_TREE_TOKEN_FUNCTION: + case AST_TREE_TOKEN_FUNCTION: { AstTreeScope *metadata = tree.metadata; for (size_t i = 0; i < metadata->expressions_size; ++i) { astTreeDestroy(metadata->expressions[i]); } free(metadata->expressions); free(metadata); + } + return; case AST_TREE_TOKEN_KEYWORD_PRINT: + case AST_TREE_TOKEN_TYPE_VOID: + return; + case AST_TREE_TOKEN_TYPE_FUNCTION: { + AstTreeTypeFunction *metadata = tree.metadata; + for (size_t i = 0; i < metadata->arguments_size; ++i) { + astTreeDelete(metadata->arguments[i]); + } + free(metadata->arguments); + free(metadata->returnType); + free(metadata); + } return; case AST_TREE_TOKEN_NONE: + break; } printLog("Bad token '%d'", tree.token); exit(1); @@ -128,13 +170,23 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) { ParserNode *node = (ParserNodeEOLMetadata *)nodes->data[i]->metadata; ParserNodeVariableMetadata *node_metadata = node->metadata; - // TODO: check type - AstTree *tree = astTreeParse(node_metadata->value, &root->variables, 1); - if (tree == NULL) { + AstTree *type = astTreeParse(node_metadata->type, &root->variables, 1); + if (type == NULL) { + goto RETURN_ERROR; + } + + AstTree *value = astTreeParse(node_metadata->value, &root->variables, 1); + if (value == NULL) { goto RETURN_ERROR; } - root->variables.data[i]->value = tree; + if (!hasTypeOf(value, type)) { + printLog("Type mismatch"); + goto RETURN_ERROR; + } + + root->variables.data[i]->type = type; + root->variables.data[i]->value = value; } return root; @@ -163,14 +215,16 @@ AstTree *astTreeParse(ParserNode *parserNode, AstTreeVariables *variables, return newAstTree(AST_TREE_TOKEN_KEYWORD_PRINT, NULL); case PARSER_TOKEN_FUNCTION_DEFINITION: return astTreeParseFunction(parserNode, variables, variables_size); + case PARSER_TOKEN_TYPE_FUNCTION: + return astTreeParseTypeFunction(parserNode, variables, variables_size); + case PARSER_TOKEN_TYPE_VOID: + return newAstTree(AST_TREE_TOKEN_TYPE_VOID, NULL); case PARSER_TOKEN_SYMBOL_EOL: case PARSER_TOKEN_SYMBOL_PARENTHESIS: case PARSER_TOKEN_SYMBOL_CURLY_BRACKET: case PARSER_TOKEN_SYMBOL_COMMA: case PARSER_TOKEN_CONSTANT: case PARSER_TOKEN_IDENTIFIER: - case PARSER_TOKEN_TYPE_VOID: - case PARSER_TOKEN_TYPE_FUNCTION: case PARSER_TOKEN_NONE: case PARSER_TOKEN_ROOT: } @@ -182,14 +236,55 @@ AstTree *astTreeParseFunction(ParserNode *parserNode, AstTreeVariables *variables, size_t variables_size) { ParserNodeFunctionDefnitionMetadata *node_metadata = parserNode->metadata; + ParserNodeArray *node_arguments = node_metadata->arguments->metadata; ParserNodeArray *body = node_metadata->body->metadata; - AstTreeScope *scope = a404m_malloc(sizeof(*scope)); - size_t expressions_size = 0; - scope->expressions = - a404m_malloc(expressions_size * sizeof(*scope->expressions)); - scope->expressions_size = 0; + AstTreeScope scope = { + .expressions = + a404m_malloc(expressions_size * sizeof(*scope.expressions)), + .expressions_size = 0, + .variables = NULL, + .variables_size = 0, + }; + + AstTreeFunction *function = a404m_malloc(sizeof(*function)); + + size_t arguments_size = 0; + function->arguments = + a404m_malloc(arguments_size * sizeof(*function->arguments)); + function->arguments_size = 0; + + if ((function->returnType = astTreeParse(node_metadata->returnType, variables, + variables_size)) == NULL) { + goto RETURN_ERROR; + } + + for (size_t i = 0; i < node_arguments->size; ++i) { + ParserNode *arg = node_arguments->data[i]; + ParserNodeVariableMetadata *arg_metadata = arg->metadata; + if (arg_metadata->value != NULL) { + printLog("arguments can't have default values (for now)"); + goto RETURN_ERROR; + } + + AstTree *type = astTreeParse(arg_metadata->type, variables, variables_size); + if (type == NULL) { + goto RETURN_ERROR; + } + + if (function->arguments_size == arguments_size) { + arguments_size += arguments_size / 2 + 1; + function->arguments = a404m_realloc( + function->arguments, arguments_size * sizeof(*function->arguments)); + } + + function->arguments[function->arguments_size].value = NULL; + function->arguments[function->arguments_size].type = type; + function->arguments[function->arguments_size].name_begin = arg_metadata->name->str_begin; + function->arguments[function->arguments_size].name_end = arg_metadata->name->str_end; + function->arguments_size += 1; + } for (size_t i = 0; i < body->size; ++i) { ParserNode *eol = body->data[i]; @@ -204,27 +299,117 @@ AstTree *astTreeParseFunction(ParserNode *parserNode, goto RETURN_ERROR; } - if (expressions_size == scope->expressions_size) { + if (expressions_size == scope.expressions_size) { expressions_size += expressions_size / 2 + 1; - scope->expressions = a404m_realloc( - scope->expressions, expressions_size * sizeof(*scope->expressions)); + scope.expressions = a404m_realloc( + scope.expressions, expressions_size * sizeof(*scope.expressions)); } - scope->expressions[scope->expressions_size] = *tree; - scope->expressions_size += 1; + scope.expressions[scope.expressions_size] = *tree; + scope.expressions_size += 1; free(tree); } - scope->expressions = - a404m_realloc(scope->expressions, - scope->expressions_size * sizeof(*scope->expressions)); + scope.expressions = a404m_realloc( + scope.expressions, scope.expressions_size * sizeof(*scope.expressions)); + + function->scope = scope; - AstTree *result = newAstTree(AST_TREE_TOKEN_FUNCTION, scope); + AstTree *result = newAstTree(AST_TREE_TOKEN_FUNCTION, function); return result; RETURN_ERROR: - free(scope->expressions); - free(scope); + free(function); + free(scope.expressions); + return NULL; +} + +AstTree *astTreeParseTypeFunction(ParserNode *parserNode, + AstTreeVariables *variables, + size_t variables_size) { + ParserNodeTypeFunctionMetadata *metadata = parserNode->metadata; + ParserNodeArray *node_arguments = metadata->arguments->metadata; + + AstTreeTypeFunction *typeFunction = a404m_malloc(sizeof(*typeFunction)); + + size_t arguments_size = 0; + typeFunction->arguments = + a404m_malloc(arguments_size * sizeof(*typeFunction->arguments)); + typeFunction->arguments_size = 0; + + for (size_t i = 0; i < node_arguments->size; ++i) { + ParserNodeVariableMetadata *arg_metadata = + node_arguments->data[i]->metadata; + if (arg_metadata->value != NULL) { + printLog("arguments can't have default values (for now)"); + goto RETURN_ERROR; + } + + AstTree *type = astTreeParse(arg_metadata->type, variables, variables_size); + if (type == NULL) { + goto RETURN_ERROR; + } + + if (typeFunction->arguments_size == arguments_size) { + arguments_size += arguments_size / 2 + 1; + typeFunction->arguments = + a404m_realloc(typeFunction->arguments, + arguments_size * sizeof(*typeFunction->arguments)); + } + + typeFunction->arguments[typeFunction->arguments_size] = type; + typeFunction->arguments_size += 1; + } + + if ((typeFunction->returnType = astTreeParse(metadata->returnType, variables, + variables_size)) == NULL) { + goto RETURN_ERROR; + } + + AstTree *tree = a404m_malloc(sizeof(*tree)); + tree->metadata = typeFunction; + tree->token = AST_TREE_TOKEN_TYPE_FUNCTION; + return tree; + +RETURN_ERROR: return NULL; } + +bool hasTypeOf(AstTree *value, AstTree *type) { + switch (type->token) { + case AST_TREE_TOKEN_TYPE_FUNCTION: + AstTreeTypeFunction *typeMetadata = type->metadata; + switch (value->token) { + case AST_TREE_TOKEN_FUNCTION: { + AstTreeFunction *valueMetadata = value->metadata; + if (typeMetadata->arguments_size != valueMetadata->arguments_size) { + return false; + } + for (size_t i = 0; i < typeMetadata->arguments_size; ++i) { + if (!typeIsEqual(typeMetadata->arguments[i], + valueMetadata->arguments[i].type)) { + return false; + } + } + return typeIsEqual(typeMetadata->returnType, valueMetadata->returnType); + } + case AST_TREE_TOKEN_KEYWORD_PRINT: + case AST_TREE_TOKEN_TYPE_FUNCTION: + case AST_TREE_TOKEN_TYPE_VOID: + return false; + case AST_TREE_TOKEN_NONE: + } + goto ERROR; + case AST_TREE_TOKEN_FUNCTION: + case AST_TREE_TOKEN_KEYWORD_PRINT: + case AST_TREE_TOKEN_TYPE_VOID: + return false; + case AST_TREE_TOKEN_NONE: + } +ERROR: + printLog("Bad token '%d'", type->token); + exit(1); +} + +bool typeIsEqual(AstTree *type0, AstTree *type1) { return true; } diff --git a/src/compiler/ast-tree.h b/src/compiler/ast-tree.h index 758d113..23f0b9c 100644 --- a/src/compiler/ast-tree.h +++ b/src/compiler/ast-tree.h @@ -6,12 +6,11 @@ typedef enum AstTreeToken { AST_TREE_TOKEN_FUNCTION, AST_TREE_TOKEN_KEYWORD_PRINT, + AST_TREE_TOKEN_TYPE_FUNCTION, + AST_TREE_TOKEN_TYPE_VOID, AST_TREE_TOKEN_NONE, } AstTreeToken; -typedef struct AstTreeType { -} AstTreeType; - typedef struct AstTree { AstTreeToken token; void *metadata; @@ -20,7 +19,7 @@ typedef struct AstTree { typedef struct AstTreeVariable { char *name_begin; char *name_end; - AstTreeType type; + AstTree *type; AstTree *value; } AstTreeVariable; @@ -40,9 +39,22 @@ typedef struct AstTreeScope { size_t expressions_size; } AstTreeScope; +typedef struct AstTreeFunction { + AstTreeVariable *arguments; + size_t arguments_size; + AstTreeScope scope; + AstTree *returnType; +} AstTreeFunction; + +typedef struct AstTreeTypeFunction { + AstTree **arguments; + size_t arguments_size; + AstTree *returnType; +} AstTreeTypeFunction; + extern const char *AST_TREE_TOKEN_STRINGS[]; -void astTreePrint(const AstTree *tree,int indent); +void astTreePrint(const AstTree *tree, int indent); void astTreeRootPrint(const AstTreeRoot *root); void astTreeDestroy(AstTree tree); @@ -62,3 +74,10 @@ AstTree *astTreeParse(ParserNode *parserNode, AstTreeVariables *variables, AstTree *astTreeParseFunction(ParserNode *parserNode, AstTreeVariables *variables, size_t variables_size); + +AstTree *astTreeParseTypeFunction(ParserNode *parserNode, + AstTreeVariables *variables, + size_t variables_size); + +bool hasTypeOf(AstTree *value, AstTree *type); +bool typeIsEqual(AstTree *type0, AstTree *type1); diff --git a/src/compiler/code-generator.c b/src/compiler/code-generator.c index 67fba4c..932202a 100644 --- a/src/compiler/code-generator.c +++ b/src/compiler/code-generator.c @@ -73,10 +73,11 @@ CodeGeneratorCodes *codeGenerator(AstTreeRoot *astTreeRoot) { bool codeGeneratorAstTreeFunction(char *label_begin, char *label_end, AstTree astTree, CodeGeneratorCodes *codes) { - AstTreeScope *scope = astTree.metadata; + AstTreeFunction *metadata = astTree.metadata; + AstTreeScope scope = metadata->scope; - for (size_t i = 0; i < scope->expressions_size; ++i) { - AstTree tree = scope->expressions[i]; + for (size_t i = 0; i < scope.expressions_size; ++i) { + AstTree tree = scope.expressions[i]; switch (tree.token) { case AST_TREE_TOKEN_KEYWORD_PRINT: generateCodePushCode( diff --git a/src/compiler/lexer.c b/src/compiler/lexer.c index f248641..8994bce 100644 --- a/src/compiler/lexer.c +++ b/src/compiler/lexer.c @@ -123,14 +123,11 @@ LexerNodeArray lexer(char *str) { lexerPushClear(&result, &result_size, iter, &node_str_begin, &node_token, LEXER_TOKEN_NUMBER); } - } else if (isSymbol(c)) { - if (node_token != LEXER_TOKEN_SYMBOL) { + } else if (isSymbol(c) || isSingleSymbol(c)) { + if (node_token != LEXER_TOKEN_SYMBOL || isSingleSymbol(*node_str_begin)) { lexerPushClear(&result, &result_size, iter, &node_str_begin, &node_token, LEXER_TOKEN_SYMBOL); } - } else if (isSingleSymbol(c)) { - lexerPushClear(&result, &result_size, iter, &node_str_begin, &node_token, - LEXER_TOKEN_SYMBOL); } else { RETURN_ERROR: free(result.data); diff --git a/src/compiler/parser.c b/src/compiler/parser.c index 12c7ca9..7ec9e1c 100644 --- a/src/compiler/parser.c +++ b/src/compiler/parser.c @@ -166,7 +166,23 @@ void parserNodePrint(const ParserNode *node, int indent) { printf(" "); } goto RETURN_SUCCESS; - case PARSER_TOKEN_TYPE_FUNCTION: + case PARSER_TOKEN_TYPE_FUNCTION: { + const ParserNodeTypeFunctionMetadata *metadata = node->metadata; + printf(",\n"); + for (int i = 0; i < indent; ++i) + printf(" "); + printf("arguments=\n"); + parserNodePrint(metadata->arguments, indent + 1); + printf(",\n"); + for (int i = 0; i < indent; ++i) + printf(" "); + printf("returnType=\n"); + parserNodePrint(metadata->returnType, indent + 1); + printf("\n"); + for (int i = 0; i < indent; ++i) + printf(" "); + } + goto RETURN_SUCCESS; case PARSER_TOKEN_NONE: } printLog("Bad token '%d'", node->token); @@ -218,7 +234,14 @@ void parserNodeDelete(ParserNode *node) { free(metadata); } goto RETURN_SUCCESS; - case PARSER_TOKEN_TYPE_FUNCTION: + case PARSER_TOKEN_TYPE_FUNCTION: { + ParserNodeTypeFunctionMetadata *metadata = node->metadata; + parserNodeDelete(metadata->arguments); + parserNodeDelete(metadata->returnType); + free(metadata); + } + goto RETURN_SUCCESS; + case PARSER_TOKEN_NONE: } printLog("Bad token '%d'", node->token); @@ -416,7 +439,6 @@ ParserNode *parserComma(LexerNode *node, LexerNode *begin, ParserNode *parent) { return NULL; } } - printLog("%s", PARSER_TOKEN_STRINGS[parserNodeBefore->token]); return node->parserNode = parserNodeBefore->parent = newParserNode( PARSER_TOKEN_SYMBOL_COMMA, node->str_begin, node->str_end, (ParserNodeEOLMetadata *)parserNodeBefore, parent); @@ -504,11 +526,6 @@ ParserNode *parserFunction(LexerNode *node, LexerNode *begin, LexerNode *end, if (bodyNode >= end || bodyNode->parserNode == NULL) { body = NULL; - // TODO: implement - // if body is not there then it is a function type not a function - // definition - printLog("Not implemented"); - return NULL; } else { body = getUntilCommonParent(bodyNode->parserNode, parent); if (body == NULL || body->token != PARSER_TOKEN_SYMBOL_CURLY_BRACKET) { @@ -534,16 +551,28 @@ ParserNode *parserFunction(LexerNode *node, LexerNode *begin, LexerNode *end, return NULL; } - ParserNodeFunctionDefnitionMetadata *metadata = - a404m_malloc(sizeof(*metadata)); + if (body != NULL) { + ParserNodeFunctionDefnitionMetadata *metadata = + a404m_malloc(sizeof(*metadata)); - metadata->body = body; - metadata->arguments = params; - metadata->returnType = retType; + metadata->body = body; + metadata->arguments = params; + metadata->returnType = retType; - return params->parent = retType->parent = body->parent = node->parserNode = - newParserNode(PARSER_TOKEN_FUNCTION_DEFINITION, params->str_begin, - body->str_end, metadata, parent); + return params->parent = retType->parent = body->parent = node->parserNode = + newParserNode(PARSER_TOKEN_FUNCTION_DEFINITION, + params->str_begin, body->str_end, metadata, + parent); + } else { + ParserNodeTypeFunctionMetadata *metadata = a404m_malloc(sizeof(*metadata)); + + metadata->arguments = params; + metadata->returnType = retType; + + return params->parent = retType->parent = node->parserNode = + newParserNode(PARSER_TOKEN_TYPE_FUNCTION, params->str_begin, + retType->str_end, metadata, parent); + } } ParserNode *parserVariable(LexerNode *node, LexerNode *begin, LexerNode *end, @@ -561,7 +590,8 @@ ParserNode *parserVariable(LexerNode *node, LexerNode *begin, LexerNode *end, ParserNode *name = getUntilCommonParent(nameNode->parserNode, parent); if (name->token != PARSER_TOKEN_IDENTIFIER) { - printLog("Name should be identifier"); + printLog("Name should be identifier but got '%s'", + PARSER_TOKEN_STRINGS[name->token]); return NULL; } else { name->parent = variableNode; @@ -570,6 +600,7 @@ ParserNode *parserVariable(LexerNode *node, LexerNode *begin, LexerNode *end, LexerNode *node1 = node + 1; ParserNode *type; + ParserNode *value; if (node1 >= end) { printLog("Bad variable definition"); @@ -588,21 +619,31 @@ ParserNode *parserVariable(LexerNode *node, LexerNode *begin, LexerNode *end, return NULL; } type->parent = variableNode; - printLog("Here is"); + for (++node1; node1 < end && getUntilCommonParent(node1->parserNode, + parent) == variableNode; + ++node1) { + } + if (node1 < end && node1->token == LEXER_TOKEN_SYMBOL_COLON) { + node1->parserNode = variableNode; + } else { + node1 = NULL; + value = NULL; + } } - LexerNode *valueNode = node + 2; - ParserNode *value; - - if (valueNode >= end || valueNode->parserNode == NULL) { - value = NULL; - } else { - value = getUntilCommonParent(valueNode->parserNode, parent); - if (!isValue(value)) { + if (node1 != NULL) { + LexerNode *valueNode = node1 + 1; + if (valueNode >= end || valueNode->parserNode == NULL) { printLog("No value"); return NULL; + } else { + value = getUntilCommonParent(valueNode->parserNode, parent); + if (!isValue(value)) { + printLog("No value"); + return NULL; + } + value->parent = variableNode; } - value->parent = variableNode; } ParserNodeVariableMetadata *metadata = a404m_malloc(sizeof(*metadata)); @@ -626,13 +667,9 @@ RETURN_ERROR: } bool isAllArguments(const ParserNodeArray *nodes) { - printLog("%d", nodes->size); for (size_t i = 0; i < nodes->size; ++i) { const ParserNode *node = nodes->data[i]; if (node->token != PARSER_TOKEN_SYMBOL_COMMA && i + 1 != nodes->size) { - printLog("%d %s %d %.*s", i, PARSER_TOKEN_STRINGS[node->token], - node->token, (int)(node->str_end - node->str_begin), - node->str_begin); return false; } } @@ -663,6 +700,7 @@ bool isExpression(ParserNode *node) { bool isType(ParserNode *node) { switch (node->token) { case PARSER_TOKEN_TYPE_VOID: + case PARSER_TOKEN_TYPE_FUNCTION: return true; case PARSER_TOKEN_IDENTIFIER: case PARSER_TOKEN_CONSTANT: @@ -670,7 +708,6 @@ bool isType(ParserNode *node) { case PARSER_TOKEN_FUNCTION_DEFINITION: case PARSER_TOKEN_KEYWORD_PRINT: case PARSER_TOKEN_ROOT: - case PARSER_TOKEN_TYPE_FUNCTION: case PARSER_TOKEN_SYMBOL_EOL: case PARSER_TOKEN_SYMBOL_CURLY_BRACKET: case PARSER_TOKEN_SYMBOL_COMMA: diff --git a/test/main.felan b/test/main.felan index 6d26e52..92881c9 100644 --- a/test/main.felan +++ b/test/main.felan @@ -1,8 +1,3 @@ -main :: () -> void { - print; -}; - -a :: (b:void,c:void) -> void { - print; +main : ()->void : () -> void { print; }; |