diff options
-rw-r--r-- | code/main.felan | 63 | ||||
-rw-r--r-- | src/compiler/ast-tree.c | 386 | ||||
-rw-r--r-- | src/compiler/ast-tree.h | 13 | ||||
-rw-r--r-- | src/compiler/lexer.c | 12 | ||||
-rw-r--r-- | src/compiler/lexer.h | 3 | ||||
-rw-r--r-- | src/compiler/parser.c | 178 | ||||
-rw-r--r-- | src/compiler/parser.h | 11 | ||||
-rw-r--r-- | src/runner/runner.c | 75 |
8 files changed, 678 insertions, 63 deletions
diff --git a/code/main.felan b/code/main.felan index 79a7dd2..a49972b 100644 --- a/code/main.felan +++ b/code/main.felan @@ -1,63 +1,22 @@ -byte :: i8; -ubyte :: u8; - -short :: i16; -ushort :: u16; - -int :: i32; -uint :: u32; - -long :: i64; -ulong :: u64; - -// short_float :: f16; -float :: f32; -double :: f64; -long_double :: f128; - -usize :: u64; - main :: () -> void { - a := 2; - println(@typeOf(a) == i64); -}; - -print_rev :: (value:u64) -> void { - putc 'a'; - value := value; - while { - putc '0' + @cast(value % 10,u8); - value /= 10; - value != 0; - } {} + a : [10]u8 = undefined; + a[0] = 2; + print(123); }; -print_rev :: (value:i64) -> void { - putc 'b'; +print :: (value:i64)->void{ value := value; + a : [20]u8 = undefined; + i := 0; while { - putc '0' + @cast(value % 10,u8); + a[i] = '0' + @cast(value % 10,u8); + i += 1; value /= 10; value != 0; } {} -}; -print :: (value:bool) -> void { - if value { - putc 't'; - putc 'r'; - putc 'u'; - putc 'e'; - } else { - putc 'f'; - putc 'a'; - putc 'l'; - putc 's'; - putc 'e'; + while i > 0 { + putc a[i-1]; + i -= 1; } }; - -println :: (value:bool) -> void { - print(value); - putc '\n'; -}; diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c index 04f8d54..1ac05e1 100644 --- a/src/compiler/ast-tree.c +++ b/src/compiler/ast-tree.c @@ -5,6 +5,7 @@ #include "utils/log.h" #include "utils/memory.h" #include "utils/string.h" +#include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -119,6 +120,7 @@ const char *AST_TREE_TOKEN_STRINGS[] = { "AST_TREE_TOKEN_KEYWORD_STRUCT", "AST_TREE_TOKEN_TYPE_FUNCTION", + "AST_TREE_TOKEN_TYPE_ARRAY", "AST_TREE_TOKEN_TYPE_TYPE", "AST_TREE_TOKEN_TYPE_VOID", "AST_TREE_TOKEN_TYPE_I8", @@ -166,6 +168,7 @@ const char *AST_TREE_TOKEN_STRINGS[] = { "AST_TREE_TOKEN_OPERATOR_ADDRESS", "AST_TREE_TOKEN_OPERATOR_DEREFERENCE", "AST_TREE_TOKEN_OPERATOR_ACCESS", + "AST_TREE_TOKEN_OPERATOR_ARRAY_ACCESS", "AST_TREE_TOKEN_SCOPE", @@ -491,6 +494,28 @@ void astTreePrint(const AstTree *tree, int indent) { printf(" "); } goto RETURN_SUCCESS; + case AST_TREE_TOKEN_TYPE_ARRAY: + case AST_TREE_TOKEN_OPERATOR_ARRAY_ACCESS: { + AstTreeBracket *metadata = tree->metadata; + printf(",\n"); + for (int i = 0; i < indent; ++i) + printf(" "); + printf("operand=\n"); + astTreePrint(metadata->operand, indent + 1); + printf(",\n"); + for (int i = 0; i < indent; ++i) + printf(" "); + printf("paramters=[\n"); + for (size_t i = 0; i < metadata->parameters.size; ++i) { + AstTree *param = metadata->parameters.data[i]; + astTreePrint(param, indent + 2); + printf(",\n"); + } + for (int i = 0; i < indent; ++i) + printf(" "); + printf("]"); + } + goto RETURN_SUCCESS; case AST_TREE_TOKEN_NONE: } UNREACHABLE; @@ -730,6 +755,17 @@ void astTreeDestroy(AstTree tree) { free(metadata); } return; + case AST_TREE_TOKEN_TYPE_ARRAY: + case AST_TREE_TOKEN_OPERATOR_ARRAY_ACCESS: { + AstTreeBracket *metadata = tree.metadata; + astTreeDelete(metadata->operand); + for (size_t i = 0; i < metadata->parameters.size; ++i) { + astTreeDelete(metadata->parameters.data[i]); + } + free(metadata->parameters.data); + free(metadata); + } + return; case AST_TREE_TOKEN_NONE: } printLog("token = %d", tree.token); @@ -905,8 +941,8 @@ AstTree *copyAstTreeBack(AstTree *tree, AstTreeVariables oldVariables[], AstTreeInfix *metadata = tree->metadata; AstTreeInfix *new_metadata = a404m_malloc(sizeof(*new_metadata)); - new_metadata->left = copyAstTreeBack( - metadata->left, oldVariables, newVariables, variables_size); + new_metadata->left = copyAstTreeBack(metadata->left, oldVariables, + newVariables, variables_size); new_metadata->right = copyAstTreeBack(metadata->right, oldVariables, newVariables, variables_size); return newAstTree( @@ -1115,6 +1151,29 @@ AstTree *copyAstTreeBack(AstTree *tree, AstTreeVariables oldVariables[], copyAstTreeBack(tree->type, oldVariables, newVariables, variables_size), tree->str_begin, tree->str_end); } + case AST_TREE_TOKEN_TYPE_ARRAY: + case AST_TREE_TOKEN_OPERATOR_ARRAY_ACCESS: { + AstTreeBracket *metadata = tree->metadata; + AstTreeBracket *new_metadata = a404m_malloc(sizeof(*new_metadata)); + + new_metadata->operand = copyAstTreeBack(metadata->operand, oldVariables, + newVariables, variables_size); + + new_metadata->parameters.size = metadata->parameters.size; + new_metadata->parameters.data = a404m_malloc( + sizeof(*new_metadata->parameters.data) * new_metadata->parameters.size); + + for (size_t i = 0; i < metadata->parameters.size; ++i) { + new_metadata->parameters.data[i] = + copyAstTreeBack(metadata->parameters.data[i], oldVariables, + newVariables, variables_size); + } + + return newAstTree( + tree->token, new_metadata, + copyAstTreeBack(tree->type, oldVariables, newVariables, variables_size), + tree->str_begin, tree->str_end); + } case AST_TREE_TOKEN_NONE: } printLog("Bad token %d", tree->token); @@ -1314,6 +1373,8 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) { case PARSER_TOKEN_OPERATOR_DEREFERENCE: case PARSER_TOKEN_KEYWORD_STRUCT: case PARSER_TOKEN_BUILTIN: + case PARSER_TOKEN_SYMBOL_BRACKET_LEFT: + case PARSER_TOKEN_SYMBOL_BRACKET_RIGHT: goto AFTER_SWITCH; case PARSER_TOKEN_ROOT: case PARSER_TOKEN_KEYWORD_PUTC: @@ -1593,6 +1654,11 @@ AstTree *astTreeParse(ParserNode *parserNode, AstTreeHelper *helper) { return astTreeParseParenthesis(parserNode, helper); case PARSER_TOKEN_KEYWORD_STRUCT: return astTreeParseStruct(parserNode, helper); + case PARSER_TOKEN_SYMBOL_BRACKET_LEFT: + return astTreeParseBracket(parserNode, helper, AST_TREE_TOKEN_TYPE_ARRAY); + case PARSER_TOKEN_SYMBOL_BRACKET_RIGHT: + return astTreeParseBracket(parserNode, helper, + AST_TREE_TOKEN_OPERATOR_ARRAY_ACCESS); case PARSER_TOKEN_CONSTANT: case PARSER_TOKEN_SYMBOL_COMMA: case PARSER_TOKEN_NONE: @@ -1744,6 +1810,8 @@ AstTree *astTreeParseFunction(ParserNode *parserNode, AstTreeHelper *p_helper) { case PARSER_TOKEN_OPERATOR_LOGICAL_AND: case PARSER_TOKEN_OPERATOR_LOGICAL_OR: case PARSER_TOKEN_BUILTIN: + case PARSER_TOKEN_SYMBOL_BRACKET_LEFT: + case PARSER_TOKEN_SYMBOL_BRACKET_RIGHT: printError(node->str_begin, node->str_end, "Unexpected %s", PARSER_TOKEN_STRINGS[node->token]); goto RETURN_ERROR; @@ -2079,8 +2147,11 @@ RETURN_ERROR: AstTree *astTreeParseVariable(ParserNode *parserNode, AstTreeHelper *helper) { ParserNodeVariableMetadata *node_metadata = parserNode->metadata; - if (node_metadata->value == NULL || - node_metadata->name->token != PARSER_TOKEN_IDENTIFIER) { + if (node_metadata->value == NULL) { + printError(parserNode->str_begin, parserNode->str_end, + "Must have a value (or use undefined)"); + return NULL; + } else if (node_metadata->name->token != PARSER_TOKEN_IDENTIFIER) { printError(parserNode->str_begin, parserNode->str_end, "Not supported"); return NULL; } @@ -2279,6 +2350,8 @@ AstTree *astTreeParseCurlyBracket(ParserNode *parserNode, case PARSER_TOKEN_OPERATOR_LOGICAL_AND: case PARSER_TOKEN_OPERATOR_LOGICAL_OR: case PARSER_TOKEN_BUILTIN: + case PARSER_TOKEN_SYMBOL_BRACKET_LEFT: + case PARSER_TOKEN_SYMBOL_BRACKET_RIGHT: printError(node->str_begin, node->str_end, "Unexpected %s", PARSER_TOKEN_STRINGS[node->token]); goto RETURN_ERROR; @@ -2433,6 +2506,32 @@ AstTree *astTreeParseBuiltin(ParserNode *parserNode, AstTreeHelper *helper) { parserNode->str_begin, parserNode->str_end); } +AstTree *astTreeParseBracket(ParserNode *parserNode, AstTreeHelper *helper, + AstTreeToken token) { + ParserNodeBracketMetadata *node_metadata = parserNode->metadata; + + AstTreeBracket *metadata = a404m_malloc(sizeof(*metadata)); + + metadata->operand = astTreeParse(node_metadata->operand, helper); + + metadata->parameters.size = node_metadata->params->size; + metadata->parameters.data = a404m_malloc(sizeof(*metadata->parameters.data) * + metadata->parameters.size); + + for (size_t i = 0; i < node_metadata->params->size; ++i) { + ParserNode *node_param = node_metadata->params->data[i]; + + if (node_param->token == PARSER_TOKEN_SYMBOL_COMMA) { + node_param = (ParserNodeSingleChildMetadata *)node_param->metadata; + } + + metadata->parameters.data[i] = astTreeParse(node_param, helper); + } + + return newAstTree(token, metadata, NULL, parserNode->str_begin, + parserNode->str_end); +} + bool isFunction(AstTree *value) { return value->type->token == AST_TREE_TOKEN_TYPE_FUNCTION; } @@ -2534,6 +2633,16 @@ bool isConst(AstTree *tree) { AstTreeAccess *metadata = tree->metadata; return isConst(metadata->object); } + case AST_TREE_TOKEN_TYPE_ARRAY: + case AST_TREE_TOKEN_OPERATOR_ARRAY_ACCESS: { + AstTreeBracket *metadata = tree->metadata; + for (size_t i = 0; i < metadata->parameters.size; ++i) { + if (!isConst(metadata->parameters.data[i])) { + return false; + } + } + return isConst(metadata->operand); + } case AST_TREE_TOKEN_NONE: } printLog("Unknown token '%d'", tree->token); @@ -2638,6 +2747,16 @@ bool isConstByValue(AstTree *tree) { AstTreeAccess *metadata = tree->metadata; return isConstByValue(metadata->object); } + case AST_TREE_TOKEN_TYPE_ARRAY: + case AST_TREE_TOKEN_OPERATOR_ARRAY_ACCESS: { + AstTreeBracket *metadata = tree->metadata; + for (size_t i = 0; i < metadata->parameters.size; ++i) { + if (!isConstByValue(metadata->parameters.data[i])) { + return false; + } + } + return isConstByValue(metadata->operand); + } case AST_TREE_TOKEN_NONE: } UNREACHABLE; @@ -2665,6 +2784,7 @@ AstTree *makeTypeOf(AstTree *value) { case AST_TREE_TOKEN_TYPE_BOOL: case AST_TREE_TOKEN_OPERATOR_POINTER: case AST_TREE_TOKEN_KEYWORD_STRUCT: + case AST_TREE_TOKEN_TYPE_ARRAY: return &AST_TREE_TYPE_TYPE; case AST_TREE_TOKEN_OPERATOR_ADDRESS: { AstTreeSingleChild *metadata = value->metadata; @@ -2760,6 +2880,11 @@ AstTree *makeTypeOf(AstTree *value) { } UNREACHABLE; } + case AST_TREE_TOKEN_OPERATOR_ARRAY_ACCESS: { + AstTreeBracket *metadata = value->metadata; + + return copyAstTree(metadata->operand); + } case AST_TREE_TOKEN_BUILTIN: case AST_TREE_TOKEN_VALUE_OBJECT: case AST_TREE_TOKEN_VARIABLE_DEFINE: @@ -2835,6 +2960,7 @@ bool typeIsEqualBack(const AstTree *type0, const AstTree *type1) { case AST_TREE_TOKEN_OPERATOR_ACCESS: case AST_TREE_TOKEN_FUNCTION_CALL: case AST_TREE_TOKEN_VARIABLE: + case AST_TREE_TOKEN_OPERATOR_ARRAY_ACCESS: return false; case AST_TREE_TOKEN_TYPE_TYPE: case AST_TREE_TOKEN_TYPE_VOID: @@ -2855,15 +2981,36 @@ bool typeIsEqualBack(const AstTree *type0, const AstTree *type1) { case AST_TREE_TOKEN_TYPE_F128: return type1->token == type0->token; case AST_TREE_TOKEN_OPERATOR_POINTER: { - if (type1->token != AST_TREE_TOKEN_OPERATOR_POINTER) { + if (type1->token != type0->token) { return false; } AstTreeSingleChild *type0_metadata = type0->metadata; AstTreeSingleChild *type1_metadata = type1->metadata; return typeIsEqual(type0_metadata, type1_metadata); } + case AST_TREE_TOKEN_TYPE_ARRAY: { + if (type1->token != type0->token) + return false; + + AstTreeBracket *type0_metadata = type0->metadata; + AstTreeBracket *type1_metadata = type1->metadata; + + if (!typeIsEqual(type0_metadata->operand, type1_metadata->operand) || + type0_metadata->parameters.size != type1_metadata->parameters.size) { + return false; + } + + for (size_t i = 0; i < type0_metadata->parameters.size; ++i) { + if (!isEqual(type0_metadata->parameters.data[i], + type1_metadata->parameters.data[i])) { + return false; + } + } + + return true; + } case AST_TREE_TOKEN_TYPE_FUNCTION: - if (type1->token != AST_TREE_TOKEN_TYPE_FUNCTION) { + if (type1->token != type0->token) { return false; } AstTreeTypeFunction *type0_metadata = type0->metadata; @@ -2882,7 +3029,7 @@ bool typeIsEqualBack(const AstTree *type0, const AstTree *type1) { } return true; case AST_TREE_TOKEN_KEYWORD_STRUCT: { - if (type1->token != AST_TREE_TOKEN_KEYWORD_STRUCT) + if (type1->token != type0->token) return false; AstTreeStruct *type0_metadata = type0->metadata; @@ -2966,7 +3113,9 @@ AstTree *getValue(AstTree *tree) { case AST_TREE_TOKEN_KEYWORD_IF: case AST_TREE_TOKEN_KEYWORD_WHILE: case AST_TREE_TOKEN_KEYWORD_COMPTIME: - case AST_TREE_TOKEN_SCOPE: { + case AST_TREE_TOKEN_SCOPE: + case AST_TREE_TOKEN_TYPE_ARRAY: + case AST_TREE_TOKEN_OPERATOR_ARRAY_ACCESS: { bool shouldRet = false; AstTree *value = runExpression(tree, &shouldRet, false); if (value == NULL) { @@ -2986,6 +3135,147 @@ AstTree *getValue(AstTree *tree) { UNREACHABLE; } +bool isIntType(AstTree *type) { + switch (type->token) { + 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: + return true; + case AST_TREE_TOKEN_FUNCTION: + case AST_TREE_TOKEN_BUILTIN: + case AST_TREE_TOKEN_KEYWORD_PUTC: + 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_KEYWORD_STRUCT: + case AST_TREE_TOKEN_TYPE_FUNCTION: + case AST_TREE_TOKEN_TYPE_ARRAY: + case AST_TREE_TOKEN_TYPE_TYPE: + case AST_TREE_TOKEN_TYPE_VOID: + 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_TYPE_BOOL: + case AST_TREE_TOKEN_VALUE_VOID: + case AST_TREE_TOKEN_FUNCTION_CALL: + case AST_TREE_TOKEN_VARIABLE: + case AST_TREE_TOKEN_VARIABLE_DEFINE: + case AST_TREE_TOKEN_VALUE_NULL: + case AST_TREE_TOKEN_VALUE_UNDEFINED: + case AST_TREE_TOKEN_VALUE_INT: + case AST_TREE_TOKEN_VALUE_FLOAT: + case AST_TREE_TOKEN_VALUE_BOOL: + case AST_TREE_TOKEN_VALUE_OBJECT: + 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_OPERATOR_POINTER: + case AST_TREE_TOKEN_OPERATOR_ADDRESS: + case AST_TREE_TOKEN_OPERATOR_DEREFERENCE: + case AST_TREE_TOKEN_OPERATOR_ACCESS: + case AST_TREE_TOKEN_OPERATOR_LOGICAL_NOT: + case AST_TREE_TOKEN_OPERATOR_LOGICAL_AND: + case AST_TREE_TOKEN_OPERATOR_LOGICAL_OR: + case AST_TREE_TOKEN_OPERATOR_ARRAY_ACCESS: + case AST_TREE_TOKEN_SCOPE: + return false; + case AST_TREE_TOKEN_NONE: + } + UNREACHABLE; +} + +bool isEqual(AstTree *left, AstTree *right) { + if (left->token != right->token) { + return false; + } + switch (left->token) { + case AST_TREE_TOKEN_TYPE_TYPE: + case AST_TREE_TOKEN_TYPE_VOID: + 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_TYPE_BOOL: + case AST_TREE_TOKEN_VALUE_VOID: + return true; + case AST_TREE_TOKEN_VALUE_INT: { + AstTreeInt *left_metadata = left->metadata; + AstTreeInt *right_metadata = right->metadata; + + return *left_metadata == *right_metadata; + } + case AST_TREE_TOKEN_FUNCTION: + case AST_TREE_TOKEN_BUILTIN: + case AST_TREE_TOKEN_KEYWORD_PUTC: + 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_KEYWORD_STRUCT: + case AST_TREE_TOKEN_TYPE_FUNCTION: + case AST_TREE_TOKEN_TYPE_ARRAY: + case AST_TREE_TOKEN_FUNCTION_CALL: + case AST_TREE_TOKEN_VARIABLE: + case AST_TREE_TOKEN_VARIABLE_DEFINE: + case AST_TREE_TOKEN_VALUE_NULL: + case AST_TREE_TOKEN_VALUE_UNDEFINED: + case AST_TREE_TOKEN_VALUE_FLOAT: + case AST_TREE_TOKEN_VALUE_BOOL: + case AST_TREE_TOKEN_VALUE_OBJECT: + 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_OPERATOR_POINTER: + case AST_TREE_TOKEN_OPERATOR_ADDRESS: + case AST_TREE_TOKEN_OPERATOR_DEREFERENCE: + case AST_TREE_TOKEN_OPERATOR_ACCESS: + case AST_TREE_TOKEN_OPERATOR_LOGICAL_NOT: + case AST_TREE_TOKEN_OPERATOR_LOGICAL_AND: + case AST_TREE_TOKEN_OPERATOR_LOGICAL_OR: + case AST_TREE_TOKEN_OPERATOR_ARRAY_ACCESS: + case AST_TREE_TOKEN_SCOPE: + case AST_TREE_TOKEN_NONE: + } + UNREACHABLE; +} + bool setAllTypesRoot(AstTreeRoot *root) { AstTreeSetTypesHelper setTypesHelper = { .lookingType = NULL, @@ -3109,6 +3399,10 @@ bool setAllTypes(AstTree *tree, AstTreeSetTypesHelper helper, return setTypesOperatorAccess(tree, helper); case AST_TREE_TOKEN_BUILTIN: return setTypesBuiltin(tree, helper, functionCall); + case AST_TREE_TOKEN_TYPE_ARRAY: + return setTypesTypeArray(tree, helper); + case AST_TREE_TOKEN_OPERATOR_ARRAY_ACCESS: + return setTypesArrayAccess(tree, helper); case AST_TREE_TOKEN_NONE: } printError(tree->str_begin, tree->str_end, "Unknown token %d", tree->token); @@ -4169,6 +4463,82 @@ bool setTypesBuiltin(AstTree *tree, AstTreeSetTypesHelper helper, UNREACHABLE; } +bool setTypesTypeArray(AstTree *tree, AstTreeSetTypesHelper helper) { + AstTreeBracket *metadata = tree->metadata; + + if (!setAllTypes(metadata->operand, helper, NULL, NULL)) { + return false; + } else if (!typeIsEqual(metadata->operand->type, &AST_TREE_TYPE_TYPE)) { + printError(metadata->operand->str_begin, metadata->operand->str_end, + "Expected type"); + return false; + } + + if (metadata->parameters.size != 1) { + printError(tree->str_begin, tree->str_end, + "Multiple param in array is not yet supported"); + return false; + } + + AstTreeSetTypesHelper newHelper = { + .lookingType = &AST_TREE_U64_TYPE, + .dependencies = helper.dependencies, + }; + + for (size_t i = 0; i < metadata->parameters.size; ++i) { + AstTree *param = metadata->parameters.data[i]; + if (!setAllTypes(param, newHelper, NULL, NULL)) { + return false; + } else if (!isIntType(param->type)) { + printError(param->str_begin, param->str_end, + "Should only be int (for now)"); + return false; + } + } + + tree->type = copyAstTree(&AST_TREE_TYPE_TYPE); + return true; +} + +bool setTypesArrayAccess(AstTree *tree, AstTreeSetTypesHelper _helper) { + AstTreeBracket *metadata = tree->metadata; + + AstTreeSetTypesHelper helper = { + .lookingType = NULL, + .dependencies = _helper.dependencies, + }; + + if (!setAllTypes(metadata->operand, helper, NULL, NULL)) { + return false; + } else if (metadata->operand->type->token != AST_TREE_TOKEN_TYPE_ARRAY) { + printError(metadata->operand->str_begin, metadata->operand->str_end, + "Expected array"); + return false; + } + + if (metadata->parameters.size != 1) { + printError(tree->str_begin, tree->str_end, + "Multiple param in array is not yet supported"); + return false; + } + + for (size_t i = 0; i < metadata->parameters.size; ++i) { + AstTree *param = metadata->parameters.data[i]; + if (!setAllTypes(param, helper, NULL, NULL)) { + return false; + } else if (!isIntType(param->type)) { + printError(param->str_begin, param->str_end, + "Should only be int (for now)"); + return false; + } + } + + AstTreeBracket *operand_metadata = metadata->operand->type->metadata; + + tree->type = copyAstTree(operand_metadata->operand); + return true; +} + bool setTypesAstInfix(AstTreeInfix *infix, AstTreeSetTypesHelper _helper) { AstTreeSetTypesHelper helper = { .lookingType = NULL, diff --git a/src/compiler/ast-tree.h b/src/compiler/ast-tree.h index 1605328..1c39ecb 100644 --- a/src/compiler/ast-tree.h +++ b/src/compiler/ast-tree.h @@ -17,6 +17,7 @@ typedef enum AstTreeToken { AST_TREE_TOKEN_KEYWORD_STRUCT, AST_TREE_TOKEN_TYPE_FUNCTION, + AST_TREE_TOKEN_TYPE_ARRAY, AST_TREE_TOKEN_TYPE_TYPE, AST_TREE_TOKEN_STATIC_VARS_BEGIN = AST_TREE_TOKEN_TYPE_TYPE, AST_TREE_TOKEN_TYPE_VOID, @@ -69,6 +70,7 @@ typedef enum AstTreeToken { AST_TREE_TOKEN_OPERATOR_LOGICAL_NOT, AST_TREE_TOKEN_OPERATOR_LOGICAL_AND, AST_TREE_TOKEN_OPERATOR_LOGICAL_OR, + AST_TREE_TOKEN_OPERATOR_ARRAY_ACCESS, AST_TREE_TOKEN_SCOPE, @@ -235,6 +237,11 @@ typedef struct AstTreeAccess { } member; } AstTreeAccess; +typedef struct AstTreeBracket { + AstTree *operand; + AstTrees parameters; +} AstTreeBracket; + typedef enum AstTreeBuiltinToken { AST_TREE_BUILTIN_TOKEN_CAST, AST_TREE_BUILTIN_TOKEN_TYPE_OF, @@ -307,6 +314,8 @@ AstTree *astTreeParseStruct(ParserNode *parserNode, AstTreeHelper *helper); AstTree *astTreeParseAccessOperator(ParserNode *parserNode, AstTreeHelper *helper, AstTreeToken token); AstTree *astTreeParseBuiltin(ParserNode *parserNode, AstTreeHelper *helper); +AstTree *astTreeParseBracket(ParserNode *parserNode, AstTreeHelper *helper, + AstTreeToken token); bool isFunction(AstTree *value); bool isConst(AstTree *tree); @@ -315,6 +324,8 @@ AstTree *makeTypeOf(AstTree *value); bool typeIsEqual(AstTree *type0, AstTree *type1); bool typeIsEqualBack(const AstTree *type0, const AstTree *type1); AstTree *getValue(AstTree *tree); +bool isIntType(AstTree *type); +bool isEqual(AstTree *left, AstTree *right); bool setAllTypesRoot(AstTreeRoot *root); bool setAllTypes(AstTree *tree, AstTreeSetTypesHelper helper, @@ -359,6 +370,8 @@ bool setTypesStruct(AstTree *tree, AstTreeSetTypesHelper helper); bool setTypesOperatorAccess(AstTree *tree, AstTreeSetTypesHelper helper); bool setTypesBuiltin(AstTree *tree, AstTreeSetTypesHelper helper, AstTreeFunctionCall *functionCall); +bool setTypesTypeArray(AstTree *tree, AstTreeSetTypesHelper helper); +bool setTypesArrayAccess(AstTree *tree, AstTreeSetTypesHelper helper); bool setTypesAstVariable(AstTreeVariable *variable, AstTreeSetTypesHelper helper); diff --git a/src/compiler/lexer.c b/src/compiler/lexer.c index 43502aa..53d9f05 100644 --- a/src/compiler/lexer.c +++ b/src/compiler/lexer.c @@ -12,6 +12,7 @@ const char *LEXER_TOKEN_STRINGS[] = { "LEXER_TOKEN_SYMBOL_CLOSE_CURLY_BRACKET", "LEXER_TOKEN_SYMBOL_CLOSE_PARENTHESIS", + "LEXER_TOKEN_SYMBOL_CLOSE_BRACKET", "LEXER_TOKEN_IDENTIFIER", "LEXER_TOKEN_BUILTIN", "LEXER_TOKEN_KEYWORD_TYPE", @@ -41,6 +42,7 @@ const char *LEXER_TOKEN_STRINGS[] = { "LEXER_TOKEN_SYMBOL_FUNCTION_ARROW", "LEXER_TOKEN_SYMBOL_POINTER", "LEXER_TOKEN_KEYWORD_STRUCT", + "LEXER_TOKEN_SYMBOL_CLOSE_BRACKET_LEFT", "LEXER_TOKEN_SYMBOL_DEREFERENCE", "LEXER_TOKEN_SYMBOL_ACCESS", @@ -90,6 +92,7 @@ const char *LEXER_TOKEN_STRINGS[] = { "LEXER_TOKEN_SYMBOL", "LEXER_TOKEN_SYMBOL_OPEN_PARENTHESIS", + "LEXER_TOKEN_SYMBOL_OPEN_BRACKET", "LEXER_TOKEN_SYMBOL_OPEN_CURLY_BRACKET", "LEXER_TOKEN_NONE", @@ -98,7 +101,7 @@ const char *LEXER_TOKEN_STRINGS[] = { const char *LEXER_SYMBOL_STRINGS[] = { ";", "(", ")", "{", "}", "->", ":", "=", "+=", "-=", "*=", "/=", "%=", ",", "+", "-", "*", "/", "%", "==", "!=", ">", - ">=", "<", "<=", "&", ".*", ".", "!", "&&", "||", + ">=", "<", "<=", "&", ".*", ".", "!", "&&", "||", "[", "]", }; const LexerToken LEXER_SYMBOL_TOKENS[] = { LEXER_TOKEN_SYMBOL_EOL, @@ -132,6 +135,8 @@ const LexerToken LEXER_SYMBOL_TOKENS[] = { LEXER_TOKEN_SYMBOL_LOGICAL_NOT, LEXER_TOKEN_SYMBOL_LOGICAL_AND, LEXER_TOKEN_SYMBOL_LOGICAL_OR, + LEXER_TOKEN_SYMBOL_OPEN_BRACKET, + LEXER_TOKEN_SYMBOL_CLOSE_BRACKET, }; const size_t LEXER_SYMBOL_SIZE = sizeof(LEXER_SYMBOL_TOKENS) / sizeof(*LEXER_SYMBOL_TOKENS); @@ -387,6 +392,8 @@ void lexerPushClear(LexerNodeArray *array, size_t *array_size, char *iter, case LEXER_TOKEN_SYMBOL_LOGICAL_AND: case LEXER_TOKEN_SYMBOL_LOGICAL_OR: case LEXER_TOKEN_BUILTIN: + case LEXER_TOKEN_SYMBOL_CLOSE_BRACKET: + case LEXER_TOKEN_SYMBOL_OPEN_BRACKET: if (*array_size == array->size) { *array_size += 1 + *array_size / 2; array->data = @@ -401,6 +408,7 @@ void lexerPushClear(LexerNodeArray *array, size_t *array_size, char *iter, array->size += 1; // goto RETURN_SUCCESS; + case LEXER_TOKEN_SYMBOL_CLOSE_BRACKET_LEFT: case LEXER_TOKEN_NONE: goto RETURN_SUCCESS; } @@ -436,6 +444,8 @@ bool isSymbol(char c) { case ',': case '(': case ')': + case '[': + case ']': case '{': case '}': return true; diff --git a/src/compiler/lexer.h b/src/compiler/lexer.h index d7145e1..ad82b5a 100644 --- a/src/compiler/lexer.h +++ b/src/compiler/lexer.h @@ -10,6 +10,7 @@ typedef enum LexerToken { LEXER_TOKEN_SYMBOL_CLOSE_PARENTHESIS, LEXER_TOKEN_ORDER1 = LEXER_TOKEN_SYMBOL_CLOSE_PARENTHESIS, + LEXER_TOKEN_SYMBOL_CLOSE_BRACKET, LEXER_TOKEN_IDENTIFIER, LEXER_TOKEN_BUILTIN, LEXER_TOKEN_KEYWORD_TYPE, @@ -40,6 +41,7 @@ typedef enum LexerToken { LEXER_TOKEN_ORDER2 = LEXER_TOKEN_SYMBOL_FUNCTION_ARROW, LEXER_TOKEN_SYMBOL_POINTER, LEXER_TOKEN_KEYWORD_STRUCT, + LEXER_TOKEN_SYMBOL_CLOSE_BRACKET_LEFT, LEXER_TOKEN_SYMBOL_DEREFERENCE, LEXER_TOKEN_ORDER3 = LEXER_TOKEN_SYMBOL_DEREFERENCE, @@ -101,6 +103,7 @@ typedef enum LexerToken { LEXER_TOKEN_SYMBOL, LEXER_TOKEN_SYMBOL_OPEN_PARENTHESIS, + LEXER_TOKEN_SYMBOL_OPEN_BRACKET, LEXER_TOKEN_SYMBOL_OPEN_CURLY_BRACKET, LEXER_TOKEN_NONE, diff --git a/src/compiler/parser.c b/src/compiler/parser.c index ba8f20a..ae2db33 100644 --- a/src/compiler/parser.c +++ b/src/compiler/parser.c @@ -53,6 +53,8 @@ const char *PARSER_TOKEN_STRINGS[] = { "PARSER_TOKEN_SYMBOL_EOL", "PARSER_TOKEN_SYMBOL_CURLY_BRACKET", + "PARSER_TOKEN_SYMBOL_BRACKET_LEFT", + "PARSER_TOKEN_SYMBOL_BRACKET_RIGHT", "PARSER_TOKEN_SYMBOL_PARENTHESIS", "PARSER_TOKEN_SYMBOL_COMMA", @@ -182,7 +184,10 @@ void parserNodePrint(const ParserNode *node, int indent) { case PARSER_TOKEN_SYMBOL_CURLY_BRACKET: case PARSER_TOKEN_SYMBOL_PARENTHESIS: { const ParserNodeArray *metadata = node->metadata; - printf(",children=[\n"); + printf(",\n"); + for (int i = 0; i < indent; ++i) + printf(" "); + printf("children=[\n"); for (size_t i = 0; i < metadata->size; ++i) { parserNodePrint(metadata->data[i], indent + 1); printf(",\n"); @@ -192,6 +197,27 @@ void parserNodePrint(const ParserNode *node, int indent) { printf("]"); } goto RETURN_SUCCESS; + case PARSER_TOKEN_SYMBOL_BRACKET_LEFT: + case PARSER_TOKEN_SYMBOL_BRACKET_RIGHT: { + const ParserNodeBracketMetadata *metadata = node->metadata; + printf(",\n"); + for (int i = 0; i < indent; ++i) + printf(" "); + printf("operand=\n"); + parserNodePrint(metadata->operand, indent + 1); + printf(",\n"); + for (int i = 0; i < indent; ++i) + printf(" "); + printf("params=[\n"); + for (size_t i = 0; i < metadata->params->size; ++i) { + parserNodePrint(metadata->params->data[i], indent + 1); + printf(",\n"); + } + for (int i = 0; i < indent; ++i) + printf(" "); + printf("]"); + } + goto RETURN_SUCCESS; case PARSER_TOKEN_IDENTIFIER: case PARSER_TOKEN_BUILTIN: case PARSER_TOKEN_TYPE_TYPE: @@ -456,6 +482,18 @@ void parserNodeDelete(ParserNode *node) { free(metadata); } goto RETURN_SUCCESS; + case PARSER_TOKEN_SYMBOL_BRACKET_RIGHT: + case PARSER_TOKEN_SYMBOL_BRACKET_LEFT: { + ParserNodeBracketMetadata *metadata = node->metadata; + parserNodeDelete(metadata->operand); + for (size_t i = 0; i < metadata->params->size; ++i) { + parserNodeDelete(metadata->params->data[i]); + } + free(metadata->params->data); + free(metadata->params); + free(metadata); + } + goto RETURN_SUCCESS; case PARSER_TOKEN_IDENTIFIER: case PARSER_TOKEN_BUILTIN: case PARSER_TOKEN_TYPE_TYPE: @@ -747,6 +785,10 @@ ParserNode *parseNode(LexerNode *node, LexerNode *begin, LexerNode *end, return parserParenthesis(node, begin, parent); case LEXER_TOKEN_SYMBOL_CLOSE_CURLY_BRACKET: return parserCurlyBrackets(node, begin, parent); + case LEXER_TOKEN_SYMBOL_CLOSE_BRACKET: + return parserBracketsRight(node, begin, parent, conti); + case LEXER_TOKEN_SYMBOL_CLOSE_BRACKET_LEFT: + return parserBracketsLeft(node, begin, end, parent); case LEXER_TOKEN_SYMBOL_FUNCTION_ARROW: return parserFunction(node, begin, end, parent); case LEXER_TOKEN_SYMBOL_COLON: @@ -865,6 +907,7 @@ ParserNode *parseNode(LexerNode *node, LexerNode *begin, LexerNode *end, case LEXER_TOKEN_SYMBOL: case LEXER_TOKEN_SYMBOL_OPEN_PARENTHESIS: case LEXER_TOKEN_SYMBOL_OPEN_CURLY_BRACKET: + case LEXER_TOKEN_SYMBOL_OPEN_BRACKET: case LEXER_TOKEN_NONE: break; } @@ -1213,6 +1256,131 @@ ParserNode *parserParenthesis(LexerNode *closing, LexerNode *begin, } } +ParserNode *parserBracketsRight(LexerNode *closing, LexerNode *begin, + ParserNode *parent, bool *conti) { + LexerNode *opening = NULL; + + for (LexerNode *iter = closing - 1; iter >= begin; --iter) { + if (iter->parserNode == NULL && + iter->token == LEXER_TOKEN_SYMBOL_OPEN_BRACKET) { + opening = iter; + break; + } + } + + if (opening == NULL) { + printError(closing->str_begin, closing->str_end, "No opening for bracket"); + return NULL; + } + + LexerNode *beforeNode = opening - 1; + ParserNode *before; + if (beforeNode < begin || beforeNode->parserNode == NULL || + (before = getUntilCommonParent(beforeNode->parserNode, parent)) == NULL || + !isExpression(before)) { + closing->token = LEXER_TOKEN_SYMBOL_CLOSE_BRACKET_LEFT; + *conti = true; + return NULL; + } + + ParserNode *parserNode = a404m_malloc(sizeof(*parserNode)); + parserNode->parent = parent; + + before->parent = parserNode; + + for (LexerNode *iter = closing - 1; iter >= begin; --iter) { + if (iter->parserNode != NULL) { + ParserNode *pNode = + getUntilCommonParents(iter->parserNode, parent, parserNode); + if (pNode == NULL) { + printLog(pNode->str_begin, pNode->str_end, "Bad node"); + return NULL; + } else { + pNode->parent = parserNode; + } + } else if (iter == opening) { + break; + } + } + + opening->parserNode = parserNode; + closing->parserNode = parserNode; + + parserNode->token = PARSER_TOKEN_SYMBOL_BRACKET_RIGHT; + parserNode->str_begin = before->str_begin; + parserNode->str_end = closing->str_end; + + if (parserNodeArray(opening + 1, closing, parserNode)) { + ParserNodeBracketMetadata *metadata = malloc(sizeof(*metadata)); + metadata->operand = before; + metadata->params = parserNode->metadata; + parserNode->metadata = metadata; + return parserNode; + } else { + free(parserNode); + return NULL; + } +} + +ParserNode *parserBracketsLeft(LexerNode *closing, LexerNode *begin, + LexerNode *end, ParserNode *parent) { + LexerNode *afterNode = closing + 1; + ParserNode *after; + if (afterNode >= end || afterNode->parserNode == NULL || + (after = getUntilCommonParent(afterNode->parserNode, parent)) == NULL || + !isExpression(after)) { + printLog(closing->str_begin, closing->str_end, + "Bad bracket can't be parsed"); + return NULL; + } + + ParserNode *parserNode = a404m_malloc(sizeof(*parserNode)); + parserNode->parent = parent; + + after->parent = parserNode; + + LexerNode *opening = NULL; + + for (LexerNode *iter = closing - 1; iter >= begin; --iter) { + + if (iter->parserNode != NULL) { + ParserNode *pNode = + getUntilCommonParents(iter->parserNode, parent, parserNode); + if (pNode == NULL) { + printLog(pNode->str_begin, pNode->str_end, "Bad node"); + return NULL; + } else { + pNode->parent = parserNode; + } + } else if (iter->token == LEXER_TOKEN_SYMBOL_OPEN_BRACKET) { + opening = iter; + break; + } + } + + if (opening == NULL) { + printError(closing->str_begin, closing->str_end, "No opening for bracket"); + return NULL; + } + opening->parserNode = parserNode; + closing->parserNode = parserNode; + + parserNode->token = PARSER_TOKEN_SYMBOL_BRACKET_LEFT; + parserNode->str_begin = opening->str_begin; + parserNode->str_end = after->str_end; + + if (parserNodeArray(opening + 1, closing, parserNode)) { + ParserNodeBracketMetadata *metadata = malloc(sizeof(*metadata)); + metadata->operand = after; + metadata->params = parserNode->metadata; + parserNode->metadata = metadata; + return parserNode; + } else { + free(parserNode); + return NULL; + } +} + ParserNode *parserCurlyBrackets(LexerNode *closing, LexerNode *begin, ParserNode *parent) { ParserNode *parserNode = a404m_malloc(sizeof(*parserNode)); @@ -1323,6 +1491,8 @@ ParserNode *parserFunction(LexerNode *node, LexerNode *begin, LexerNode *end, case PARSER_TOKEN_VARIABLE: case PARSER_TOKEN_SYMBOL_CURLY_BRACKET: case PARSER_TOKEN_SYMBOL_PARENTHESIS: + case PARSER_TOKEN_SYMBOL_BRACKET_LEFT: + case PARSER_TOKEN_SYMBOL_BRACKET_RIGHT: case PARSER_TOKEN_SYMBOL_COMMA: case PARSER_TOKEN_OPERATOR_ACCESS: case PARSER_TOKEN_OPERATOR_ASSIGN: @@ -1752,6 +1922,8 @@ bool isExpression(ParserNode *node) { case PARSER_TOKEN_CONSTANT: case PARSER_TOKEN_VARIABLE: case PARSER_TOKEN_SYMBOL_PARENTHESIS: + case PARSER_TOKEN_SYMBOL_BRACKET_LEFT: + case PARSER_TOKEN_SYMBOL_BRACKET_RIGHT: case PARSER_TOKEN_FUNCTION_DEFINITION: case PARSER_TOKEN_FUNCTION_CALL: case PARSER_TOKEN_KEYWORD_PUTC: @@ -1844,6 +2016,8 @@ bool isType(ParserNode *node) { case PARSER_TOKEN_IDENTIFIER: case PARSER_TOKEN_BUILTIN: case PARSER_TOKEN_SYMBOL_PARENTHESIS: + case PARSER_TOKEN_SYMBOL_BRACKET_LEFT: + case PARSER_TOKEN_SYMBOL_BRACKET_RIGHT: case PARSER_TOKEN_FUNCTION_CALL: case PARSER_TOKEN_KEYWORD_IF: case PARSER_TOKEN_KEYWORD_COMPTIME: @@ -1956,6 +2130,8 @@ bool isValue(ParserNode *node) { case PARSER_TOKEN_KEYWORD_IF: case PARSER_TOKEN_KEYWORD_COMPTIME: case PARSER_TOKEN_SYMBOL_PARENTHESIS: + case PARSER_TOKEN_SYMBOL_BRACKET_LEFT: + case PARSER_TOKEN_SYMBOL_BRACKET_RIGHT: case PARSER_TOKEN_KEYWORD_STRUCT: return true; case PARSER_TOKEN_CONSTANT: diff --git a/src/compiler/parser.h b/src/compiler/parser.h index 9464ca2..120ae39 100644 --- a/src/compiler/parser.h +++ b/src/compiler/parser.h @@ -49,6 +49,8 @@ typedef enum ParserToken { PARSER_TOKEN_SYMBOL_EOL, PARSER_TOKEN_SYMBOL_CURLY_BRACKET, + PARSER_TOKEN_SYMBOL_BRACKET_LEFT, + PARSER_TOKEN_SYMBOL_BRACKET_RIGHT, PARSER_TOKEN_SYMBOL_PARENTHESIS, PARSER_TOKEN_SYMBOL_COMMA, @@ -159,6 +161,11 @@ typedef struct ParserNodeWhileMetadata { ParserNode *body; } ParserNodeWhileMetadata; +typedef struct ParserNodeBracketMetadata { + ParserNode *operand; + ParserNodeArray *params; +} ParserNodeBracketMetadata; + void parserNodePrint(const ParserNode *node, int indent); void parserNodeDelete(ParserNode *node); @@ -192,6 +199,10 @@ ParserNode *parserParenthesis(LexerNode *closing, LexerNode *begin, ParserNode *parent); ParserNode *parserCurlyBrackets(LexerNode *closing, LexerNode *begin, ParserNode *parent); +ParserNode *parserBracketsRight(LexerNode *closing, LexerNode *begin, + ParserNode *parent, bool *conti); +ParserNode *parserBracketsLeft(LexerNode *closing, LexerNode *begin, + LexerNode *end, ParserNode *parent); ParserNode *parserFunction(LexerNode *node, LexerNode *begin, LexerNode *end, ParserNode *parent); ParserNode *parserVariable(LexerNode *node, LexerNode *begin, LexerNode *end, diff --git a/src/runner/runner.c b/src/runner/runner.c index 2f4b32f..075e3a4 100644 --- a/src/runner/runner.c +++ b/src/runner/runner.c @@ -438,6 +438,7 @@ AstTree *runExpression(AstTree *expr, bool *shouldRet, bool isLeft) { if (!conti) { break; } + astTreeDelete(ret); ret = runExpression(metadata->body, shouldRet, isLeft); } return ret; @@ -1121,6 +1122,7 @@ AstTree *runExpression(AstTree *expr, bool *shouldRet, bool isLeft) { case AST_TREE_TOKEN_VALUE_OBJECT: case AST_TREE_TOKEN_FUNCTION: case AST_TREE_TOKEN_BUILTIN: + case AST_TREE_TOKEN_TYPE_ARRAY: return copyAstTree(expr); case AST_TREE_TOKEN_OPERATOR_ADDRESS: { AstTreeSingleChild *metadata = expr->metadata; @@ -1160,7 +1162,8 @@ AstTree *runExpression(AstTree *expr, bool *shouldRet, bool isLeft) { case AST_TREE_TOKEN_OPERATOR_ACCESS: { AstTreeAccess *metadata = expr->metadata; AstTree *tree = runExpression(metadata->object, shouldRet, true); - if (tree->type->token != AST_TREE_TOKEN_KEYWORD_STRUCT) { + if (tree->type->token != AST_TREE_TOKEN_KEYWORD_STRUCT && + tree->token != AST_TREE_TOKEN_VARIABLE) { UNREACHABLE; } AstTreeVariable *variable = tree->metadata; @@ -1217,6 +1220,76 @@ AstTree *runExpression(AstTree *expr, bool *shouldRet, bool isLeft) { return newAstTree(AST_TREE_TOKEN_OPERATOR_POINTER, newMetadata, copyAstTree(expr->type), expr->str_begin, expr->str_end); } + case AST_TREE_TOKEN_OPERATOR_ARRAY_ACCESS: { + AstTreeBracket *metadata = expr->metadata; + AstTree *operand = runExpression(metadata->operand, shouldRet, true); + + if (operand->token != AST_TREE_TOKEN_VARIABLE) { + UNREACHABLE; + } else if (metadata->parameters.size != 1) { + UNREACHABLE; + } + + AstTree *array_indexNode = + runExpression(metadata->parameters.data[0], shouldRet, false); + + if (array_indexNode->token != AST_TREE_TOKEN_VALUE_INT) { + UNREACHABLE; + } + + AstTreeInt index = *(AstTreeInt *)array_indexNode->metadata; + astTreeDelete(array_indexNode); + + AstTreeVariable *variable = operand->metadata; + astTreeDelete(operand); + if (variable->value->token == AST_TREE_TOKEN_VALUE_UNDEFINED) { + AstTreeBracket *array_type_metadata = variable->type->metadata; + if (array_type_metadata->parameters.size != 1) { + UNREACHABLE; + } + AstTree *arraySize_tree = runExpression( + array_type_metadata->parameters.data[0], shouldRet, false); + if (arraySize_tree->token != AST_TREE_TOKEN_VALUE_INT) { + UNREACHABLE; + } + AstTreeInt array_size = *(AstTreeInt *)arraySize_tree->metadata; + astTreeDelete(arraySize_tree); + + AstTreeObject *newMetadata = a404m_malloc(sizeof(*newMetadata)); + + newMetadata->variables = (AstTreeVariables){ + .data = + a404m_malloc(array_size * sizeof(*newMetadata->variables.data)), + .size = array_size, + }; + + for (size_t i = 0; i < array_size; ++i) { + AstTreeVariable *member = a404m_malloc(sizeof(*member)); + member->name_begin = member->name_end = NULL; + member->isConst = false; + member->type = copyAstTree(array_type_metadata->operand); + member->value = newAstTree( + AST_TREE_TOKEN_VALUE_UNDEFINED, NULL, copyAstTree(member->type), + variable->value->str_begin, variable->value->str_end); + newMetadata->variables.data[i] = member; + } + + runnerVariableSetValue(variable, newAstTree(AST_TREE_TOKEN_VALUE_OBJECT, + newMetadata, + copyAstTree(variable->type), + variable->value->str_begin, + variable->value->str_end)); + } + AstTreeObject *object = variable->value->metadata; + AstTreeVariable *var = object->variables.data[index]; + + if (isLeft) { + return newAstTree(AST_TREE_TOKEN_VARIABLE, var, copyAstTree(var->type), + var->name_begin, var->name_end); + } else { + return copyAstTree(var->value); + } + } case AST_TREE_TOKEN_NONE: } UNREACHABLE; |