From ca6f2ec64941953f0111a64b7acf4cf6fb31929a Mon Sep 17 00:00:00 2001 From: A404M Date: Sat, 31 May 2025 15:09:23 +0330 Subject: add array access support to arrays --- src/compiler/ast-tree.c | 31 +++++++++--- src/compiler/parser.c | 6 +++ src/runner/runner.c | 125 +++++++++++++++++++++++++++++++++--------------- src/runner/runner.h | 15 +++--- 4 files changed, 126 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c index 0563086..e9d6430 100644 --- a/src/compiler/ast-tree.c +++ b/src/compiler/ast-tree.c @@ -8,6 +8,7 @@ #include "utils/string.h" #include "utils/time.h" #include "utils/type.h" +#include #include #include @@ -691,12 +692,13 @@ void astTreePrint(const AstTree *tree, int indent) { printf("]"); } goto RETURN_SUCCESS; - case AST_TREE_TOKEN_NONE: case AST_TREE_TOKEN_VALUE_NAMESPACE: case AST_TREE_TOKEN_VALUE_SHAPE_SHIFTER: case AST_TREE_TOKEN_SHAPE_SHIFTER_ELEMENT: case AST_TREE_TOKEN_VALUE_C_LIBRARY: case AST_TREE_TOKEN_VALUE_C_FUNCTION: + goto RETURN_SUCCESS; + case AST_TREE_TOKEN_NONE: } UNREACHABLE; @@ -2968,7 +2970,7 @@ AstTree *astTreeParseIntValue(const ParserNode *parserNode) { case PARSER_NODE_INT_TYPE_U8: { u8 *metadata = a404m_malloc(sizeof(*metadata)); *metadata = node_metadata->value; - return newAstTree(AST_TREE_TOKEN_RAW_VALUE, metadata, &AST_TREE_I8_TYPE, + return newAstTree(AST_TREE_TOKEN_RAW_VALUE, metadata, &AST_TREE_U8_TYPE, parserNode->str_begin, parserNode->str_end); } case PARSER_NODE_INT_TYPE_I16: { @@ -2980,7 +2982,7 @@ AstTree *astTreeParseIntValue(const ParserNode *parserNode) { case PARSER_NODE_INT_TYPE_U16: { u16 *metadata = a404m_malloc(sizeof(*metadata)); *metadata = node_metadata->value; - return newAstTree(AST_TREE_TOKEN_RAW_VALUE, metadata, &AST_TREE_I16_TYPE, + return newAstTree(AST_TREE_TOKEN_RAW_VALUE, metadata, &AST_TREE_U16_TYPE, parserNode->str_begin, parserNode->str_end); } case PARSER_NODE_INT_TYPE_I32: { @@ -2992,7 +2994,7 @@ AstTree *astTreeParseIntValue(const ParserNode *parserNode) { case PARSER_NODE_INT_TYPE_U32: { u32 *metadata = a404m_malloc(sizeof(*metadata)); *metadata = node_metadata->value; - return newAstTree(AST_TREE_TOKEN_RAW_VALUE, metadata, &AST_TREE_I32_TYPE, + return newAstTree(AST_TREE_TOKEN_RAW_VALUE, metadata, &AST_TREE_U32_TYPE, parserNode->str_begin, parserNode->str_end); } case PARSER_NODE_INT_TYPE_I64: { @@ -3004,7 +3006,7 @@ AstTree *astTreeParseIntValue(const ParserNode *parserNode) { case PARSER_NODE_INT_TYPE_U64: { u64 *metadata = a404m_malloc(sizeof(*metadata)); *metadata = node_metadata->value; - return newAstTree(AST_TREE_TOKEN_RAW_VALUE, metadata, &AST_TREE_I64_TYPE, + return newAstTree(AST_TREE_TOKEN_RAW_VALUE, metadata, &AST_TREE_U64_TYPE, parserNode->str_begin, parserNode->str_end); } } @@ -6411,10 +6413,21 @@ bool setTypesOperatorAccess(AstTree *tree, AstTreeSetTypesHelper helper) { static const char LENGTH_STR[] = "length"; static const size_t LENGTH_STR_SIZE = sizeof(LENGTH_STR) / sizeof(*LENGTH_STR) - sizeof(*LENGTH_STR); + static const char PTR_STR[] = "ptr"; + static const size_t PTR_STR_SIZE = + sizeof(PTR_STR) / sizeof(*PTR_STR) - sizeof(*PTR_STR); + if (LENGTH_STR_SIZE == size && strnEquals(LENGTH_STR, str, size)) { - metadata->member.index = 0; + metadata->member.index = 1; tree->type = copyAstTree(&AST_TREE_U64_TYPE); return true; + } else if (PTR_STR_SIZE == size && strnEquals(PTR_STR, str, size)) { + metadata->member.index = 0; + AstTreeBracket *arrayType = metadata->object->type->metadata; + tree->type = newAstTree(AST_TREE_TOKEN_OPERATOR_POINTER, + copyAstTree(arrayType->operand), + &AST_TREE_TYPE_TYPE, NULL, NULL); + return true; } printError(metadata->member.name.begin, metadata->member.name.end, @@ -7516,8 +7529,14 @@ bool setTypesTypeArray(AstTree *tree, AstTreeSetTypesHelper helper) { printError(metadata->operand->str_begin, metadata->operand->str_end, "Expected type"); return false; + } else if (!isConst(metadata->operand)) { + printError(metadata->operand->str_begin, metadata->operand->str_end, + "Epxected const"); + return false; } + metadata->operand = getValue(metadata->operand, false); + if (metadata->parameters.size == 0) { // left empty } else if (metadata->parameters.size == 1) { diff --git a/src/compiler/parser.c b/src/compiler/parser.c index 903a8af..97edae4 100644 --- a/src/compiler/parser.c +++ b/src/compiler/parser.c @@ -1307,6 +1307,11 @@ ParserNode *parserNumber(LexerNode *node, ParserNode *parent) { parserNode = newParserNode(PARSER_TOKEN_VALUE_INT, node->str_begin, node->str_end, metadata, parent); break; + case 'i': + case 'I': + case 'u': + case 'U': + goto DEFAULT; default: NOT_IMPLEMENTED; } @@ -1314,6 +1319,7 @@ ParserNode *parserNumber(LexerNode *node, ParserNode *parent) { } // fall through default: { + DEFAULT: ParserNodeIntType type = getIntType(node->str_begin, node->str_end); u64 value = decimalToU64(node->str_begin, node->str_end - getIntTypeSize(type), &success); diff --git a/src/runner/runner.c b/src/runner/runner.c index 432a750..59e1889 100644 --- a/src/runner/runner.c +++ b/src/runner/runner.c @@ -124,20 +124,22 @@ } #endif -void runnerVariableSetValue(AstTreeVariable *variable, AstTree *value) { +void runnerVariableSetValue(AstTreeVariable *variable, AstTree *value, + AstTreeScope *scope) { if (variable->isConst) { printLog("Can't assign to const"); UNREACHABLE; } - runnerVariableSetValueWihtoutConstCheck(variable, value); + runnerVariableSetValueWihtoutConstCheck(variable, value, scope); } void runnerVariableSetValueWihtoutConstCheck(AstTreeVariable *variable, - AstTree *value) { + AstTree *value, + AstTreeScope *scope) { if (variable->value != NULL) { astTreeDelete(variable->value); } - AstTree *raw = toRawValue(value); + AstTree *raw = toRawValue(value, scope); if (raw == NULL) { variable->value = value; } else { @@ -153,6 +155,16 @@ bool runAstTree(AstTreeRoots roots) { AstTreeVariable *mainVariable = NULL; + AstTreeScope *scope = a404m_malloc(sizeof(*scope)); + *scope = (AstTreeScope){ + .expressions = a404m_malloc(0), + .expressions_size = 0, + .variables.data = a404m_malloc(0), + .variables.size = 0, + .stackAllocation = a404m_malloc(0), + .stackAllocation_size = 0, + }; + for (size_t i = 0; i < roots.size; ++i) { AstTreeRoot *root = roots.data[i]; for (size_t i = 0; i < root->variables.size; ++i) { @@ -168,7 +180,8 @@ bool runAstTree(AstTreeRoots roots) { mainVariable = variable; } if (!variable->isConst) { - runnerVariableSetValueWihtoutConstCheck(variable, variable->initValue); + runnerVariableSetValueWihtoutConstCheck(variable, variable->initValue, + scope); } } } @@ -186,21 +199,24 @@ bool runAstTree(AstTreeRoots roots) { return false; } - AstTree *res = runAstTreeFunction(main, NULL, 0, false); + AstTree *res = runAstTreeFunction(main, NULL, 0, scope, false); const bool ret = res == &AST_TREE_VOID_VALUE; astTreeDelete(res); astTreeDelete(main); + astTreeDelete( + newAstTree(AST_TREE_TOKEN_SCOPE, scope, &AST_TREE_VOID_TYPE, NULL, NULL)); return ret; } AstTree *runAstTreeFunction(AstTree *tree, AstTree **arguments, - size_t arguments_size, bool isComptime) { + size_t arguments_size, AstTreeScope *scope, + bool isComptime) { AstTreeFunction *function = tree->metadata; for (size_t i = 0; i < arguments_size; ++i) { AstTree *param = arguments[i]; AstTreeVariable *arg = function->arguments.data[i]; - runnerVariableSetValueWihtoutConstCheck(arg, param); + runnerVariableSetValueWihtoutConstCheck(arg, param, scope); } bool shouldRet = false; @@ -627,6 +643,7 @@ AstTree *runAstTreeBuiltin(AstTree *tree, AstTreeScope *scope, *(AstTreeBool *)ret->metadata = typeIsEqual(left, right); break; default: + printLog("%s", AST_TREE_TOKEN_STRINGS[left->token]); UNREACHABLE; } return ret; @@ -1376,7 +1393,7 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, return args[i]; } } - result = runAstTreeFunction(function, args, args_size, isComptime); + result = runAstTreeFunction(function, args, args_size, scope, isComptime); } else if (function->token >= AST_TREE_TOKEN_BUILTIN_BEGIN && function->token <= AST_TREE_TOKEN_BUILTIN_END) { for (size_t i = 0; i < args_size; ++i) { @@ -1443,7 +1460,7 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, if (right->token != AST_TREE_TOKEN_RAW_VALUE) { UNREACHABLE; } - if (l->token != AST_TREE_TOKEN_RAW_VALUE || + if (l->token != AST_TREE_TOKEN_RAW_VALUE && l->type->token != AST_TREE_TOKEN_OPERATOR_POINTER) { UNREACHABLE; } @@ -1466,7 +1483,7 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, astTreeDelete(l); return right; } - runnerVariableSetValue(left, right); + runnerVariableSetValue(left, right, scope); astTreeDelete(l); return copyAstTree(left->value); } else if (l->token == AST_TREE_TOKEN_RAW_VALUE) { @@ -1512,7 +1529,7 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, return value; } } - runnerVariableSetValue(variable, value); + runnerVariableSetValue(variable, value, scope); return &AST_TREE_VOID_VALUE; } case AST_TREE_TOKEN_KEYWORD_IF: { @@ -1720,7 +1737,7 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, AstTree *value = runExpression(variable->value, scope, shouldRet, false, isComptime, breakCount, shouldContinue, false); - runnerVariableSetValue(variable, value); + runnerVariableSetValue(variable, value, scope); } return copyAstTree(variable->value); } @@ -1728,7 +1745,7 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, case AST_TREE_TOKEN_OPERATOR_ACCESS: { AstTreeAccess *metadata = expr->metadata; AstTree *tree = - runExpression(metadata->object, scope, shouldRet, true, isComptime, + runExpression(metadata->object, scope, shouldRet, false, isComptime, breakCount, shouldContinue, false); if (discontinue(*shouldRet, *breakCount)) { return tree; @@ -1779,7 +1796,8 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, newAstTree(AST_TREE_TOKEN_VALUE_UNDEFINED, NULL, copyAstTree(member->type), variable->value->str_begin, - variable->value->str_end)); + variable->value->str_end), + scope); } } @@ -1787,7 +1805,8 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, variable, newAstTree(AST_TREE_TOKEN_VALUE_OBJECT, newMetadata, copyAstTree(variable->type), - variable->value->str_begin, variable->value->str_end)); + variable->value->str_begin, variable->value->str_end), + scope); } AstTreeObject *object = variable->value->metadata; AstTreeVariable *var = object->variables.data[metadata->member.index]; @@ -1802,24 +1821,13 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, UNREACHABLE; } else if (tree->token == AST_TREE_TOKEN_RAW_VALUE) { if (tree->type->token == AST_TREE_TOKEN_TYPE_ARRAY) { - AstTreeBracket *array_metadata = tree->type->metadata; - if (metadata->member.index != 0) { - UNREACHABLE; - } else { - if (array_metadata->parameters.size == 1) { - AstTree *sizeTree = runExpression( - array_metadata->parameters.data[0], scope, shouldRet, false, - isComptime, breakCount, shouldContinue, false); - astTreeDelete(tree); - return sizeTree; - } else { - u64 *value = a404m_malloc(sizeof(*value)); - *value = a404m_malloc_usable_size(tree->metadata); - astTreeDelete(tree); - return newAstTree(AST_TREE_TOKEN_RAW_VALUE, value, - &AST_TREE_U64_TYPE, NULL, NULL); - } - } + u64 *tree_value = tree->metadata; + + u64 *value = a404m_malloc(sizeof(*value)); + *value = tree_value[metadata->member.index]; + astTreeDelete(tree); + return newAstTree(AST_TREE_TOKEN_RAW_VALUE, value, copyAstTree(expr->type), + NULL, NULL); } size_t index = 0; AstTreeStruct *type = tree->type->metadata; @@ -1922,7 +1930,7 @@ bool discontinue(bool shouldRet, u32 breakCount) { return shouldRet || breakCount > 0; } -AstTree *toRawValue(AstTree *value) { +AstTree *toRawValue(AstTree *value, AstTreeScope *scope) { switch (value->token) { case AST_TREE_TOKEN_VALUE_VOID: case AST_TREE_TOKEN_VALUE_NULL: { @@ -1934,9 +1942,48 @@ AstTree *toRawValue(AstTree *value) { value->str_end); } case AST_TREE_TOKEN_VALUE_UNDEFINED: { - const size_t size = getSizeOfType(value->type); - AstTreeRawValue *rawValue = a404m_malloc(size); - memset(rawValue, 0, size); + size_t size; + AstTreeRawValue *rawValue; + if (value->type->token == AST_TREE_TOKEN_TYPE_ARRAY) { + struct Array { + void *data; + size_t size; + }; + size = sizeof(struct Array); + rawValue = a404m_malloc(size); + struct Array *array = (void *)rawValue; + + AstTreeBracket *bracket = value->type->metadata; + + size_t stackAllocation_capacity = + a404m_malloc_usable_size(scope->stackAllocation) / + sizeof(*scope->stackAllocation); + if (scope->stackAllocation_size == stackAllocation_capacity) { + stackAllocation_capacity += stackAllocation_capacity / 2 + 1; + scope->stackAllocation = a404m_realloc( + scope->stackAllocation, + stackAllocation_capacity * sizeof(*scope->stackAllocation)); + } + + if (bracket->parameters.size != 1) { + UNREACHABLE; + } + + const size_t sizeOfType = getSizeOfType(bracket->operand); + const size_t size = + *(u64 *)bracket->parameters.data[0]->metadata * sizeOfType; + scope->stackAllocation[scope->stackAllocation_size] = a404m_malloc(size); + // memset(scope->stackAllocation[scope->stackAllocation_size], 0, size); + + array->data = scope->stackAllocation[scope->stackAllocation_size]; + array->size = *(u64 *)bracket->parameters.data[0]->metadata; + + scope->stackAllocation_size += 1; + } else { + size = getSizeOfType(value->type); + rawValue = a404m_malloc(size); + memset(rawValue, 0, size); + } return newAstTree(AST_TREE_TOKEN_RAW_VALUE, rawValue, copyAstTree(value->type), value->str_begin, value->str_end); @@ -1981,7 +2028,7 @@ AstTree *toRawValue(AstTree *value) { size_t filledSize = 0; for (size_t i = 0; i < object->variables.size; ++i) { AstTreeVariable *variable = object->variables.data[i]; - AstTree *variableValue = toRawValue(variable->value); + AstTree *variableValue = toRawValue(variable->value, scope); size_t variableValueSize = getSizeOfType(variableValue); if (variableValue == NULL) { NOT_IMPLEMENTED; diff --git a/src/runner/runner.h b/src/runner/runner.h index 66ad757..16103cc 100644 --- a/src/runner/runner.h +++ b/src/runner/runner.h @@ -3,15 +3,18 @@ #include "compiler/ast-tree.h" #include -void runnerVariableSetValue(AstTreeVariable *variable, AstTree *value); +void runnerVariableSetValue(AstTreeVariable *variable, AstTree *value, + AstTreeScope *scope); void runnerVariableSetValueWihtoutConstCheck(AstTreeVariable *variable, - AstTree *value); + AstTree *value, + AstTreeScope *scope); AstTree *runnerVariableGetValue(AstTreeVariable *variable); bool runAstTree(AstTreeRoots roots); AstTree *runAstTreeFunction(AstTree *tree, AstTree **arguments, - size_t arguments_size, bool isComptime); + size_t arguments_size, AstTreeScope *scope, + bool isComptime); AstTree *runAstTreeBuiltin(AstTree *tree, AstTreeScope *scope, AstTree **arguments); @@ -21,15 +24,15 @@ AstTree *runAstTreeCFunction(AstTree *tree, AstTree **arguments, AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, bool isLeft, bool isComptime, u32 *breakCount, - bool *shouldContinue,bool needOwnership); + bool *shouldContinue, bool needOwnership); AstTree *getForVariable(AstTree *expr, AstTreeScope *scope, bool *shouldRet, bool isLeft, bool isComptime, u32 *breakCount, - bool *shouldContinue, bool isLazy,bool needOwnership); + bool *shouldContinue, bool isLazy, bool needOwnership); bool discontinue(bool shouldRet, u32 breakCount); -AstTree *toRawValue(AstTree *value); +AstTree *toRawValue(AstTree *value, AstTreeScope *scope); AstTree *castTo(AstTree *value, AstTree *to); -- cgit v1.2.3