From b30cc334a4e365b039f28dd6fb34d6e227dc304b Mon Sep 17 00:00:00 2001 From: Marc Auberer Date: Sat, 8 Oct 2022 03:09:41 +0200 Subject: [PATCH] Fix #193 (#208) * Rename arg to param * Fix #193 --- media/specs/generics.md | 2 +- media/test-project/os-test.spice | 29 +++-- src/analyzer/AnalyzerVisitor.cpp | 68 ++++++----- src/ast/AstNodes.h | 9 ++ src/generator/GeneratorVisitor.cpp | 12 +- src/symbol/Function.cpp | 113 +++++++++--------- src/symbol/Function.h | 20 ++-- src/symbol/SymbolTable.cpp | 8 +- src/symbol/SymbolTableEntry.cpp | 2 +- .../exception.out | 1 + .../source.spice | 26 ++++ 11 files changed, 173 insertions(+), 117 deletions(-) create mode 100644 test/test-files/analyzer/functions/errror-function-param-dyn-sized/exception.out create mode 100644 test/test-files/analyzer/functions/errror-function-param-dyn-sized/source.spice diff --git a/media/specs/generics.md b/media/specs/generics.md index 7e3310fc6..0bbda6534 100644 --- a/media/specs/generics.md +++ b/media/specs/generics.md @@ -61,7 +61,7 @@ While running the analyzer, Spice will check which concrete manifestations gener within the code base. It will generate IR for exactly those manifestations. ### Detailed technical description -After a call to `substantiateOptionalArgs()`, the optional arguments are substantiated, but the generic types are not. When `match()` is called, +After a call to `substantiateOptionalParams()`, the optional arguments are substantiated, but the generic types are not. When `match()` is called, it also checks if the call matches to a generic function. If yes, the generic function is duplicated in the function registry, the duplicate gets the concrete types by the `match()` method and the new function gets returned to the caller of `match()`. At the end of the analyzer run, all functions that are not fully substantiated (optional types as well as generic types) get removed from the diff --git a/media/test-project/os-test.spice b/media/test-project/os-test.spice index 321b760ac..bdd5d425a 100644 --- a/media/test-project/os-test.spice +++ b/media/test-project/os-test.spice @@ -1,13 +1,28 @@ -import "std/data/vector" as vec; -import "std/data/pair" as pair; +const int SIZE = 9; + +p print(int[][] grid) { + for int i = 0; i < size; i++ { + for int j = 0; j < size; j++ { + printf("%d ", grid[i][j]); + } + printf("\n"); + } +} f main() { - vec::Vector> pairVector = vec.Vector>(); - pairVector.pushBack(pair.Pair(0, "Hello")); - pairVector.pushBack(pair.Pair(1, "World")); + int[SIZE][SIZE] grid = { + { 3, 0, 6, 5, 0, 8, 4, 0, 0 }, + { 5, 2, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 8, 7, 0, 0, 0, 0, 3, 1 }, + { 0, 0, 3, 0, 1, 0, 0, 8, 0 }, + { 9, 0, 0, 8, 6, 3, 0, 0, 5 }, + { 0, 5, 0, 0, 9, 0, 6, 0, 0 }, + { 1, 3, 0, 0, 0, 0, 2, 5, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 7, 4 }, + { 0, 0, 5, 2, 0, 6, 3, 0, 0 } + }; - pair::Pair p1 = pairVector.get(1); - printf("Hello %s!\n", p1.getSecond()); + print(grid); } /*import "std/net/http" as http; diff --git a/src/analyzer/AnalyzerVisitor.cpp b/src/analyzer/AnalyzerVisitor.cpp index 6843c0274..164160a8b 100644 --- a/src/analyzer/AnalyzerVisitor.cpp +++ b/src/analyzer/AnalyzerVisitor.cpp @@ -155,25 +155,25 @@ std::any AnalyzerVisitor::visitFctDef(FctDefNode *node) { } } - // Visit arguments in new scope - std::vector argNames; - ArgList argTypes; + // Visit parameters in new scope + std::vector paramNames; + ParamList paramTypes; if (node->hasParams) { - auto namedArgList = any_cast(visit(node->paramLst())); - for (const auto &namedArg : namedArgList) { - std::string argName = std::get<0>(namedArg); - SymbolType argType = std::get<1>(namedArg); - bool argOptional = std::get<2>(namedArg); + auto namedParamList = any_cast(visit(node->paramLst())); + for (const auto &namedParam : namedParamList) { + const std::string paramName = std::get<0>(namedParam); + const SymbolType paramType = std::get<1>(namedParam); + bool isOptional = std::get<2>(namedParam); // Check if the type is present in the template for generic types - if (argType.is(TY_GENERIC)) { - if (std::none_of(templateTypes.begin(), templateTypes.end(), [&](const GenericType &t) { return t == argType; })) + if (paramType.is(TY_GENERIC)) { + if (std::none_of(templateTypes.begin(), templateTypes.end(), [&](const GenericType &t) { return t == paramType; })) throw SemanticError(node->paramLst()->codeLoc, GENERIC_TYPE_NOT_IN_TEMPLATE, "Generic arg type not included in function template"); } - argNames.push_back(argName); - argTypes.push_back({argType, argOptional}); + paramNames.push_back(paramName); + paramTypes.push_back({paramType, isOptional}); } } @@ -211,11 +211,11 @@ std::any AnalyzerVisitor::visitFctDef(FctDefNode *node) { } // Insert function into the symbol table - Function spiceFunc(node->functionName, fctSymbolSpecifiers, thisType, returnType, argTypes, templateTypes, node); + Function spiceFunc(node->functionName, fctSymbolSpecifiers, thisType, returnType, paramTypes, templateTypes, node); currentScope->insertFunction(spiceFunc); // Rename / duplicate the original child block to reflect the substantiated versions of the function - std::vector substantiatedFunctions = spiceFunc.substantiateOptionalArgs(); + std::vector substantiatedFunctions = spiceFunc.substantiateOptionalParams(); currentScope->renameChildBlock(node->getScopeId(), substantiatedFunctions.front().getSignature()); for (int i = 1; i < substantiatedFunctions.size(); i++) currentScope->copyChildBlock(substantiatedFunctions.front().getSignature(), substantiatedFunctions[i].getSignature()); @@ -280,7 +280,7 @@ std::any AnalyzerVisitor::visitFctDef(FctDefNode *node) { } // Morph the generic types to the replacements - std::vector newArgTypes = spiceFunc.getArgTypes(); + std::vector newArgTypes = spiceFunc.getParamTypes(); for (int i = 0; i < newArgTypes.size(); i++) { SymbolTableEntry *argEntry = currentScope->lookup(args[i].first); argEntry->updateType(newArgTypes[i], true); @@ -362,25 +362,25 @@ std::any AnalyzerVisitor::visitProcDef(ProcDefNode *node) { if (node->hasParams && node->procedureName == "dtor") throw SemanticError(node->codeLoc, DTOR_WITH_PARAMS, "It is not allowed to specify parameters for destructors"); - // Visit arguments in new scope - std::vector argNames; - ArgList argTypes; + // Visit parameters in new scope + std::vector paramNames; + ParamList paramTypes; if (node->hasParams) { - auto namedArgList = any_cast(visit(node->paramLst())); - for (const auto &namedArg : namedArgList) { - std::string argName = std::get<0>(namedArg); - SymbolType argType = std::get<1>(namedArg); - bool argOptional = std::get<2>(namedArg); + auto namedParamList = any_cast(visit(node->paramLst())); + for (const auto &namedParam : namedParamList) { + const std::string paramName = std::get<0>(namedParam); + const SymbolType paramType = std::get<1>(namedParam); + bool isOptional = std::get<2>(namedParam); // Check if the type is present in the template for generic types - if (argType.is(TY_GENERIC)) { - if (std::none_of(templateTypes.begin(), templateTypes.end(), [&](const GenericType &t) { return t == argType; })) + if (paramType.is(TY_GENERIC)) { + if (std::none_of(templateTypes.begin(), templateTypes.end(), [&](const GenericType &t) { return t == paramType; })) throw SemanticError(node->paramLst()->codeLoc, GENERIC_TYPE_NOT_IN_TEMPLATE, "Generic arg type not included in procedure template"); } - argNames.push_back(argName); - argTypes.push_back({argType, argOptional}); + paramNames.push_back(paramName); + paramTypes.push_back({paramType, isOptional}); } } @@ -409,11 +409,11 @@ std::any AnalyzerVisitor::visitProcDef(ProcDefNode *node) { } // Insert function into the symbol table - Function spiceProc(node->procedureName, procSymbolSpecifiers, thisType, SymbolType(TY_DYN), argTypes, templateTypes, node); + Function spiceProc(node->procedureName, procSymbolSpecifiers, thisType, SymbolType(TY_DYN), paramTypes, templateTypes, node); currentScope->insertFunction(spiceProc); // Rename / duplicate the original child block to reflect the substantiated versions of the function - std::vector substantiatedProcedures = spiceProc.substantiateOptionalArgs(); + std::vector substantiatedProcedures = spiceProc.substantiateOptionalParams(); currentScope->renameChildBlock(node->getScopeId(), substantiatedProcedures.front().getSignature()); for (int i = 1; i < substantiatedProcedures.size(); i++) currentScope->copyChildBlock(substantiatedProcedures.front().getSignature(), substantiatedProcedures[i].getSignature()); @@ -468,7 +468,7 @@ std::any AnalyzerVisitor::visitProcDef(ProcDefNode *node) { } // Morph the generic types to the replacements - std::vector newArgTypes = spiceProc.getArgTypes(); + std::vector newArgTypes = spiceProc.getParamTypes(); for (int i = 0; i < newArgTypes.size(); i++) { SymbolTableEntry *argEntry = currentScope->lookup(params[i].first); argEntry->updateType(newArgTypes[i], true); @@ -758,7 +758,7 @@ std::any AnalyzerVisitor::visitExtDecl(ExtDeclNode *node) { if (runNumber > 1) return nullptr; - ArgList argTypes; + ParamList argTypes; if (node->hasArgs) { // Check if an argument is dyn for (const auto &arg : node->argTypeLst()->dataTypes()) { @@ -1976,7 +1976,7 @@ std::any AnalyzerVisitor::visitFunctionCall(FunctionCallNode *node) { // Build dummy function to get a better error message SymbolSpecifiers specifiers = SymbolSpecifiers(SymbolType(TY_FUNCTION)); - ArgList errArgTypes; + ParamList errArgTypes; for (const auto &argType : argTypes) errArgTypes.emplace_back(argType, false); @@ -2180,6 +2180,10 @@ std::any AnalyzerVisitor::visitDataType(DataTypeNode *node) { if (typeModifier.hardcodedSize <= 1) throw SemanticError(node->codeLoc, ARRAY_SIZE_INVALID, "The size of an array must be > 1 and explicitly stated"); } else { + // Do not allow dynamic sized types in parameter lists + if (node->isParamType()) + throw SemanticError(node->codeLoc, ARRAY_SIZE_INVALID, "Types in parameter lists may not be dynamically sized"); + auto sizeType = any_cast(visit(arraySizeExpr[assignExprCounter++])); if (!sizeType.isOneOf({TY_INT, TY_LONG, TY_SHORT})) throw SemanticError(node->codeLoc, ARRAY_SIZE_INVALID, "The array size must be of type int, long or short"); diff --git a/src/ast/AstNodes.h b/src/ast/AstNodes.h index 0f242f94f..9ccd1e4ce 100644 --- a/src/ast/AstNodes.h +++ b/src/ast/AstNodes.h @@ -625,6 +625,9 @@ class DeclStmtNode : public AstNode { [[nodiscard]] DataTypeNode *dataType() const { return getChild(); } [[nodiscard]] AssignExprNode *assignExpr() const { return getChild(); } + // Util methods + [[nodiscard]] bool isParam() const { return dynamic_cast(parent); } + // Public members std::string varName; bool hasAssignment = false; @@ -1237,6 +1240,12 @@ class DataTypeNode : public AstNode { [[nodiscard]] BaseDataTypeNode *baseDataType() const { return getChild(); } [[nodiscard]] std::vector arraySizeExpr() const { return getChildren(); } + // Util methods + [[nodiscard]] bool isParamType() const { + auto declStmt = dynamic_cast(parent); + return declStmt && declStmt->isParam(); + } + // Public members std::queue tmQueue; }; diff --git a/src/generator/GeneratorVisitor.cpp b/src/generator/GeneratorVisitor.cpp index 5a2b41b9a..b567c40f3 100644 --- a/src/generator/GeneratorVisitor.cpp +++ b/src/generator/GeneratorVisitor.cpp @@ -367,7 +367,7 @@ std::any GeneratorVisitor::visitFctDef(FctDefNode *node) { // Arguments unsigned int currentArgIndex = 0; if (node->hasParams) { - std::vector argSymbolTypes = spiceFunc.getArgTypes(); + std::vector argSymbolTypes = spiceFunc.getParamTypes(); for (; currentArgIndex < argSymbolTypes.size(); currentArgIndex++) { currentVarName = node->paramLst()->params()[currentArgIndex]->varName; argNames.push_back(currentVarName); @@ -558,7 +558,7 @@ std::any GeneratorVisitor::visitProcDef(ProcDefNode *node) { // Arguments unsigned int currentArgIndex = 0; if (node->paramLst()) { - std::vector argSymbolTypes = spiceProc.getArgTypes(); + std::vector argSymbolTypes = spiceProc.getParamTypes(); for (; currentArgIndex < argSymbolTypes.size(); currentArgIndex++) { currentVarName = node->paramLst()->params()[currentArgIndex]->varName; argNames.push_back(currentVarName); @@ -820,7 +820,7 @@ std::any GeneratorVisitor::visitExtDecl(ExtDeclNode *node) { argTypes.push_back(argType); } } - std::vector argSymbolTypes = spiceFunc.getArgTypes(); + std::vector argSymbolTypes = spiceFunc.getParamTypes(); symbolTypes.insert(std::end(symbolTypes), std::begin(argSymbolTypes), std::end(argSymbolTypes)); // Declare function @@ -2641,7 +2641,7 @@ std::any GeneratorVisitor::visitFunctionCall(FunctionCallNode *node) { if (!functionFound) { // Not found => Declare function, which will be linked in SymbolType returnSymbolType = spiceFunc->getReturnType(); - std::vector argSymbolTypes = spiceFunc->getArgTypes(); + std::vector argSymbolTypes = spiceFunc->getParamTypes(); llvm::Type *returnType = returnSymbolType.is(TY_DYN) ? llvm::Type::getVoidTy(*context) : returnSymbolType.toLLVMType(*context, accessScope); @@ -2671,7 +2671,7 @@ std::any GeneratorVisitor::visitFunctionCall(FunctionCallNode *node) { if (node->argLst()) { for (const auto &arg : node->argLst()->args()) { // Get expected arg type - SymbolType expectedArgSymbolType = spiceFunc->getArgTypes()[isMethod ? argIndex - 1 : argIndex]; + SymbolType expectedArgSymbolType = spiceFunc->getParamTypes()[isMethod ? argIndex - 1 : argIndex]; llvm::Type *expectedArgType = fctType->getParamType(argIndex); // Get the actual arg value SymbolType actualArgSymbolType = arg->getEvaluatedSymbolType(); @@ -3299,7 +3299,7 @@ void GeneratorVisitor::generateFunctionDebugInfo(llvm::Function *llvmFunction, c // Create function type std::vector argTypes; argTypes.push_back(getDITypeForSymbolType(spiceFunc->getReturnType())); // Add result type - for (const auto &argType : spiceFunc->getArgTypes()) // Add arg types + for (const auto &argType : spiceFunc->getParamTypes()) // Add arg types argTypes.push_back(getDITypeForSymbolType(argType)); llvm::DISubroutineType *functionTy = diBuilder->createSubroutineType(diBuilder->getOrCreateTypeArray(argTypes)); diff --git a/src/symbol/Function.cpp b/src/symbol/Function.cpp index 5e468e037..6e82aed67 100644 --- a/src/symbol/Function.cpp +++ b/src/symbol/Function.cpp @@ -36,23 +36,23 @@ SymbolType Function::getThisType() const { return thisType; } SymbolType Function::getReturnType() const { return returnType; } /** - * Retrieve the argument types of the current function + * Retrieve the parameter types of the current function * - * @return Vector of argument types + * @return Vector of parameter types */ -std::vector Function::getArgTypes() const { - std::vector newArgTypes; - for (const auto &argType : argList) - newArgTypes.push_back(argType.first); - return newArgTypes; +std::vector Function::getParamTypes() const { + std::vector newParamTypes; + for (const auto ¶mType : paramList) + newParamTypes.push_back(paramType.first); + return newParamTypes; } /** - * Retrieve the argument list of the current function + * Retrieve the parameter list of the current function * - * @return Argument list + * @return Parameter list */ -ArgList Function::getArgList() const { return argList; } +ParamList Function::getParamList() const { return paramList; } /** * Mange the function and return the mangled string @@ -85,14 +85,14 @@ std::string Function::getMangledName() const { thisTyStr += "_" + templateType.getName(false, true); } - // Arg type string - std::string argTyStr; - for (const auto &argType : argList) { - if (!argTyStr.empty()) - argTyStr += "_"; - argTyStr += argType.first.getName(false, true); - if (argType.second) - argTyStr += "?"; + // Param type string + std::string paramTyStr; + for (const auto ¶mType : paramList) { + if (!paramTyStr.empty()) + paramTyStr += "_"; + paramTyStr += paramType.first.getName(false, true); + if (paramType.second) + paramTyStr += "?"; } // Template type string @@ -108,8 +108,8 @@ std::string Function::getMangledName() const { if (!templateTyStr.empty()) mangledName += "__" + templateTyStr; mangledName += "__" + name; - if (!argTyStr.empty()) - mangledName += "__" + argTyStr; + if (!paramTyStr.empty()) + mangledName += "__" + paramTyStr; return mangledName; } @@ -128,14 +128,14 @@ std::string Function::getSignature() const { if (!returnType.is(TY_DYN)) returnTyStr = ": " + returnType.getName(); - // Argument type string - std::string argTyStr; - for (const auto &argType : argList) { - if (!argTyStr.empty()) - argTyStr += ","; - argTyStr += argType.first.getName(); - if (argType.second) - argTyStr += "?"; + // Parameter type string + std::string paramTyStr; + for (const auto ¶mType : paramList) { + if (!paramTyStr.empty()) + paramTyStr += ","; + paramTyStr += paramType.first.getName(); + if (paramType.second) + paramTyStr += "?"; } // Template type string @@ -148,7 +148,7 @@ std::string Function::getSignature() const { if (!templateTyStr.empty()) templateTyStr = "<" + templateTyStr + ">"; - return thisTyStr + name + templateTyStr + "(" + argTyStr + ")" + returnTyStr; + return thisTyStr + name + templateTyStr + "(" + paramTyStr + ")" + returnTyStr; } /** @@ -187,32 +187,33 @@ bool Function::isMethodProcedure() const { return returnType.is(TY_DYN) && !this SymbolType Function::getSymbolType() const { return SymbolType(isFunction() || isMethodFunction() ? TY_FUNCTION : TY_PROCEDURE); } /** - * Convert the current ambiguous function with potential optional arguments to a vector of - * definite functions without optional arguments + * Convert the current ambiguous function with potential optional parameters to a vector of + * definite functions without optional parameters * * @return List of definite functions */ -std::vector Function::substantiateOptionalArgs() const { +std::vector Function::substantiateOptionalParams() const { std::vector definiteFunctions; - std::vector> currentFunctionArgTypes; - bool metFirstOptionalArg = false; - - for (const auto &argType : argList) { - if (argType.second) { // Met optional argument - if (!metFirstOptionalArg) { // Add substantiation without the optional argument - definiteFunctions.emplace_back(name, specifiers, thisType, returnType, currentFunctionArgTypes, templateTypes, declNode); - metFirstOptionalArg = true; + std::vector> currentFunctionParamTypes; + bool metFirstOptionalParam = false; + + for (const auto ¶mType : paramList) { + if (paramType.second) { // Met optional parameter + if (!metFirstOptionalParam) { // Add substantiation without the optional parameter + definiteFunctions.emplace_back(name, specifiers, thisType, returnType, currentFunctionParamTypes, templateTypes, + declNode); + metFirstOptionalParam = true; } - // Add substantiation with the optional argument - currentFunctionArgTypes.emplace_back(argType.first, false); - definiteFunctions.emplace_back(name, specifiers, thisType, returnType, currentFunctionArgTypes, templateTypes, declNode); - } else { // Met mandatory argument - currentFunctionArgTypes.emplace_back(argType.first, false); + // Add substantiation with the optional parameter + currentFunctionParamTypes.emplace_back(paramType.first, false); + definiteFunctions.emplace_back(name, specifiers, thisType, returnType, currentFunctionParamTypes, templateTypes, declNode); + } else { // Met mandatory parameter + currentFunctionParamTypes.emplace_back(paramType.first, false); } } if (definiteFunctions.empty()) - definiteFunctions.emplace_back(name, specifiers, thisType, returnType, currentFunctionArgTypes, templateTypes, declNode); + definiteFunctions.emplace_back(name, specifiers, thisType, returnType, currentFunctionParamTypes, templateTypes, declNode); return definiteFunctions; } @@ -220,24 +221,24 @@ std::vector Function::substantiateOptionalArgs() const { /** * Convert the current ambiguous function with potential generic types to a definite function without generic types * - * @return Substantiated function with concrete arg types and without template types + * @return Substantiated function with concrete param types and without template types */ -Function Function::substantiateGenerics(const ArgList &concreteArgList, const SymbolType &concreteThisType, +Function Function::substantiateGenerics(const ParamList &concreteParamList, const SymbolType &concreteThisType, const std::map &concreteGenericTypes) const { // Substantiate return type SymbolType newReturnType = returnType.is(TY_GENERIC) ? concreteGenericTypes.at(returnType.getSubType()) : returnType; - return Function(name, specifiers, concreteThisType, newReturnType, concreteArgList, {}, declNode); + return Function(name, specifiers, concreteThisType, newReturnType, concreteParamList, {}, declNode); } /** - * Checks if a function contains optional arguments. - * This would imply that the function is not substantiated by its optional arguments yet. + * Checks if a function contains optional parameters. + * This would imply that the function is not substantiated by its optional parameters yet. * - * @return Substantiated args or not + * @return Substantiated params or not */ -bool Function::hasSubstantiatedArgs() const { - return std::none_of(argList.begin(), argList.end(), [](auto t) { return t.second; }); +bool Function::hasSubstantiatedParams() const { + return std::none_of(paramList.begin(), paramList.end(), [](auto t) { return t.second; }); } /** @@ -251,12 +252,12 @@ bool Function::hasSubstantiatedGenerics() const { } /** - * Checks if a function contains optional arguments or has generic types present. + * Checks if a function contains optional parameters or has generic types present. * This would imply that the function is not fully substantiated yet. * * @return Fully substantiated or not */ -bool Function::isFullySubstantiated() const { return hasSubstantiatedArgs() && hasSubstantiatedGenerics(); } +bool Function::isFullySubstantiated() const { return hasSubstantiatedParams() && hasSubstantiatedGenerics(); } /** * Retrieve the declaration node of this function diff --git a/src/symbol/Function.h b/src/symbol/Function.h index ce092fa40..42cfbd08c 100644 --- a/src/symbol/Function.h +++ b/src/symbol/Function.h @@ -11,25 +11,25 @@ // Forward declarations struct AstNode; -typedef std::vector> ArgList; +typedef std::vector> ParamList; typedef std::vector> NamedParamList; class Function { public: // Constructors explicit Function(std::string name, SymbolSpecifiers specifiers, const SymbolType &thisType, const SymbolType &returnType, - std::vector> argTypes, std::vector templateTypes, + std::vector> paramTypes, std::vector templateTypes, const AstNode *declNode) - : name(std::move(name)), specifiers(specifiers), thisType(thisType), returnType(returnType), argList(std::move(argTypes)), - templateTypes(std::move(templateTypes)), declNode(declNode) {} + : name(std::move(name)), specifiers(specifiers), thisType(thisType), returnType(returnType), + paramList(std::move(paramTypes)), templateTypes(std::move(templateTypes)), declNode(declNode) {} // Public methods [[nodiscard]] std::string getName() const; [[nodiscard]] SymbolSpecifiers getSpecifiers() const; [[nodiscard]] SymbolType getThisType() const; [[nodiscard]] SymbolType getReturnType() const; - [[nodiscard]] std::vector getArgTypes() const; - [[nodiscard]] ArgList getArgList() const; + [[nodiscard]] std::vector getParamTypes() const; + [[nodiscard]] ParamList getParamList() const; [[nodiscard]] std::string getMangledName() const; [[nodiscard]] std::string getSignature() const; [[nodiscard]] bool isFunction() const; @@ -37,10 +37,10 @@ class Function { [[nodiscard]] bool isMethodFunction() const; [[nodiscard]] bool isMethodProcedure() const; [[nodiscard]] SymbolType getSymbolType() const; - [[nodiscard]] std::vector substantiateOptionalArgs() const; - [[nodiscard]] Function substantiateGenerics(const ArgList &concreteArgList, const SymbolType &concreteThisType, + [[nodiscard]] std::vector substantiateOptionalParams() const; + [[nodiscard]] Function substantiateGenerics(const ParamList &concreteParamList, const SymbolType &concreteThisType, const std::map &concreteGenericTypes) const; - [[nodiscard]] bool hasSubstantiatedArgs() const; + [[nodiscard]] bool hasSubstantiatedParams() const; [[nodiscard]] bool hasSubstantiatedGenerics() const; [[nodiscard]] bool isFullySubstantiated() const; [[nodiscard]] const AstNode *getDeclNode() const; @@ -56,7 +56,7 @@ class Function { SymbolSpecifiers specifiers; SymbolType thisType = SymbolType(TY_DYN); SymbolType returnType = SymbolType(TY_DYN); - std::vector> argList; + std::vector> paramList; std::vector templateTypes; const AstNode *declNode; }; \ No newline at end of file diff --git a/src/symbol/SymbolTable.cpp b/src/symbol/SymbolTable.cpp index 1cacb5df1..e5278d6dc 100644 --- a/src/symbol/SymbolTable.cpp +++ b/src/symbol/SymbolTable.cpp @@ -358,13 +358,13 @@ void SymbolTable::insertFunction(const Function &function) { functions.insert({codeLocStr, std::make_shared>()}); // Check if function is already substantiated - if (function.hasSubstantiatedArgs()) { + if (function.hasSubstantiatedParams()) { insertSubstantiatedFunction(function, declNode); return; } // Substantiate the function and insert the substantiated instances - for (const auto &fct : function.substantiateOptionalArgs()) + for (const auto &fct : function.substantiateOptionalParams()) insertSubstantiatedFunction(fct, declNode); } @@ -412,7 +412,7 @@ Function *SymbolTable::matchFunction(SymbolTable *currentScope, const std::strin } // Check arg types requirement - auto argList = f.getArgList(); + auto argList = f.getParamList(); if (argList.size() != callArgTypes.size()) continue; bool differentArgTypes = false; // Note: This is a workaround for a break from an inner loop @@ -542,7 +542,7 @@ Function *SymbolTable::getFunctionAccessPointer(const CodeLoc &codeLoc, const st * @param codeLoc Code location */ void SymbolTable::insertSubstantiatedFunction(const Function &function, const AstNode *declNode) { - if (!function.hasSubstantiatedArgs()) + if (!function.hasSubstantiatedParams()) throw std::runtime_error("Internal compiler error: Expected substantiated function"); // Check if the function exists already diff --git a/src/symbol/SymbolTableEntry.cpp b/src/symbol/SymbolTableEntry.cpp index 850d4e5d1..806c5a1d6 100644 --- a/src/symbol/SymbolTableEntry.cpp +++ b/src/symbol/SymbolTableEntry.cpp @@ -7,7 +7,7 @@ #include /** - * Update the type of a symbol. This is used for substantiateOptionalArgs types in the process of type inference + * Update the type of a symbol. This is used for substantiateOptionalParams types in the process of type inference * * @param newType New type of the current symbol */ diff --git a/test/test-files/analyzer/functions/errror-function-param-dyn-sized/exception.out b/test/test-files/analyzer/functions/errror-function-param-dyn-sized/exception.out new file mode 100644 index 000000000..3685d09a0 --- /dev/null +++ b/test/test-files/analyzer/functions/errror-function-param-dyn-sized/exception.out @@ -0,0 +1 @@ +Semantic error in ./test-files/analyzer/functions/errror-function-param-dyn-sized/source.spice:3:9: Array size invalid: Types in parameter lists may not be dynamically sized \ No newline at end of file diff --git a/test/test-files/analyzer/functions/errror-function-param-dyn-sized/source.spice b/test/test-files/analyzer/functions/errror-function-param-dyn-sized/source.spice new file mode 100644 index 000000000..c40f7a25b --- /dev/null +++ b/test/test-files/analyzer/functions/errror-function-param-dyn-sized/source.spice @@ -0,0 +1,26 @@ +const int SIZE = 9; + +p print(int[SIZE][SIZE] grid) { + foreach int[SIZE] row : grid { + foreach int cell : row { + printf("%d ", cell); + } + printf("\n"); + } +} + +f main() { + int[SIZE][SIZE] grid = { + { 3, 0, 6, 5, 0, 8, 4, 0, 0 }, + { 5, 2, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 8, 7, 0, 0, 0, 0, 3, 1 }, + { 0, 0, 3, 0, 1, 0, 0, 8, 0 }, + { 9, 0, 0, 8, 6, 3, 0, 0, 5 }, + { 0, 5, 0, 0, 9, 0, 6, 0, 0 }, + { 1, 3, 0, 0, 0, 0, 2, 5, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 7, 4 }, + { 0, 0, 5, 2, 0, 6, 3, 0, 0 } + }; + + print(grid); +} \ No newline at end of file