From 5abc1fa23a014103f840acae6e79d70ab4d93e04 Mon Sep 17 00:00:00 2001 From: ASDAlexander77 Date: Mon, 13 Jul 2026 01:29:49 +0100 Subject: [PATCH] Refactor code structure for improved readability and maintainability --- docs/MLIRGen-refactoring-review.md | 2 +- tslang/lib/TypeScript/CMakeLists.txt | 1 + tslang/lib/TypeScript/MLIRGenGenerics.cpp | 1420 ++++++++++++++++++++ tslang/lib/TypeScript/MLIRGenImpl.h | 1432 +-------------------- 4 files changed, 1480 insertions(+), 1375 deletions(-) create mode 100644 tslang/lib/TypeScript/MLIRGenGenerics.cpp diff --git a/docs/MLIRGen-refactoring-review.md b/docs/MLIRGen-refactoring-review.md index 92991faa..8b4d0315 100644 --- a/docs/MLIRGen-refactoring-review.md +++ b/docs/MLIRGen-refactoring-review.md @@ -39,7 +39,7 @@ Benefits: parallel builds (this single TU dominates incremental build time), sma Mechanically safest path: keep `MLIRGenImpl` as-is, move method *bodies* out with no signature changes, verify with the existing test suite after each batch. -*Status: in progress.* First slice landed: the class moved out of MLIRGen.cpp's anonymous namespace into `typescript::mlirgen` in a private header `lib/TypeScript/MLIRGenImpl.h` (bodies still inline; each subsequent slice replaces a family's inline bodies with declarations and moves the definitions to a new TU). `MLIRGenCast.cpp` is the first satellite: the contiguous cast family (`selectFieldsValues` … `createBoundMethodFromExtensionMethod`, 29 methods) defined out-of-line. Enabling fixes: `GenContext`/`PassResult`/`ValueOrLogicalResult` in `MLIRGenContext.h` were in an anonymous namespace **in a header** (each TU got distinct types — worked only because there was one TU); they now live in `namespace typescript`. `ts::print(Node)` in `dump.h` was a non-inline header definition — now `inline`. The TU-static `compileOptionsPtr` stays in MLIRGen.cpp behind a new `setCompileOptions()` so inline code never references a TU-local. Second slice: `MLIRGenTypes.cpp` — the type-resolution family (`getType` … `getNullType`, 134 methods, ~3,400 lines) moved out-of-line; the lone template member (`getIndexedAccessTypeForArray`) stays inline in the header. Third slice: `MLIRGenModule.cpp` — the module/discovery/include/import driver (`report` … `mlirGen(ImportDeclaration)`, 24 methods, ~930 lines); method-level `#ifdef` guards (`GENERATE_IMPORT_INFO_USING_D_TS_FILE`) are kept around both the declarations and the moved definitions. Remaining units to peel off per the table above; header hygiene (§8) comes after the last one. +*Status: in progress.* First slice landed: the class moved out of MLIRGen.cpp's anonymous namespace into `typescript::mlirgen` in a private header `lib/TypeScript/MLIRGenImpl.h` (bodies still inline; each subsequent slice replaces a family's inline bodies with declarations and moves the definitions to a new TU). `MLIRGenCast.cpp` is the first satellite: the contiguous cast family (`selectFieldsValues` … `createBoundMethodFromExtensionMethod`, 29 methods) defined out-of-line. Enabling fixes: `GenContext`/`PassResult`/`ValueOrLogicalResult` in `MLIRGenContext.h` were in an anonymous namespace **in a header** (each TU got distinct types — worked only because there was one TU); they now live in `namespace typescript`. `ts::print(Node)` in `dump.h` was a non-inline header definition — now `inline`. The TU-static `compileOptionsPtr` stays in MLIRGen.cpp behind a new `setCompileOptions()` so inline code never references a TU-local. Second slice: `MLIRGenTypes.cpp` — the type-resolution family (`getType` … `getNullType`, 134 methods, ~3,400 lines) moved out-of-line; the lone template member (`getIndexedAccessTypeForArray`) stays inline in the header. Third slice: `MLIRGenModule.cpp` — the module/discovery/include/import driver (`report` … `mlirGen(ImportDeclaration)`, 24 methods, ~930 lines); method-level `#ifdef` guards (`GENERATE_IMPORT_INFO_USING_D_TS_FILE`) are kept around both the declarations and the moved definitions. Fourth slice: `MLIRGenGenerics.cpp` — generic inference and specialization (`tryInferNamedGeneric` … `mlirGen(ExpressionWithTypeArguments)`: the `tryInfer*` family, `inferType`, `instantiateSpecializedFunction/ClassType/InterfaceType`, `resolveGenericParams*`, `mlirGenSpecialized`; 26 methods, ~1,400 lines); `tryInferTupleFields` stays inline. Remaining units to peel off per the table above; header hygiene (§8) comes after the last one. ## 2. Kill the dangling-`FuncOp` hazard in the symbol maps diff --git a/tslang/lib/TypeScript/CMakeLists.txt b/tslang/lib/TypeScript/CMakeLists.txt index 8ecebaaa..dec78616 100644 --- a/tslang/lib/TypeScript/CMakeLists.txt +++ b/tslang/lib/TypeScript/CMakeLists.txt @@ -18,6 +18,7 @@ add_mlir_dialect_library(MLIRTypeScript DiagnosticHelper.cpp MLIRGen.cpp MLIRGenCast.cpp + MLIRGenGenerics.cpp MLIRGenModule.cpp MLIRGenTypes.cpp LowerToAffineLoops.cpp diff --git a/tslang/lib/TypeScript/MLIRGenGenerics.cpp b/tslang/lib/TypeScript/MLIRGenGenerics.cpp new file mode 100644 index 00000000..511b2c2b --- /dev/null +++ b/tslang/lib/TypeScript/MLIRGenGenerics.cpp @@ -0,0 +1,1420 @@ +// Generic type inference and specialization/instantiation methods of MLIRGenImpl (see MLIRGenImpl.h). + +#include "MLIRGenImpl.h" + +namespace typescript +{ +namespace mlirgen +{ + + bool MLIRGenImpl::tryInferNamedGeneric(mlir::Location location, mlir::Type templateType, mlir::Type concreteType, + StringMap &results) + { + auto namedGenType = dyn_cast(templateType); + if (!namedGenType) + { + return false; + } + + // merge if exists + + auto currentType = concreteType; + auto name = namedGenType.getName().getValue(); + auto existType = results.lookup(name); + if (existType) + { + auto merged = false; + currentType = mth.mergeType(location, existType, currentType, merged); + + LLVM_DEBUG(llvm::dbgs() << "\n!! result type: " << currentType << "\n";); + results[name] = currentType; + } + else + { + // TODO: when u use literal type to validate extends u need to use original type + // currentType = mth.wideStorageType(currentType); + LLVM_DEBUG(llvm::dbgs() << "\n!! type: " << name << " = " << currentType << "\n";); + results.insert({name, currentType}); + } + + assert(results.lookup(name) == currentType); + + return true; + } + + bool MLIRGenImpl::tryInferClass(mlir::Location location, mlir::Type templateType, mlir::Type concreteType, + StringMap &results, const GenContext &genContext) + { + auto tempClass = dyn_cast(templateType); + auto typeClass = dyn_cast(concreteType); + if (!tempClass || !typeClass) + { + return false; + } + + auto typeClassInfo = getClassInfoByFullName(typeClass.getName().getValue()); + if (auto tempClassInfo = getClassInfoByFullName(tempClass.getName().getValue())) + { + for (auto &templateParam : tempClassInfo->typeParamsWithArgs) + { + auto name = templateParam.getValue().first->getName(); + auto found = typeClassInfo->typeParamsWithArgs.find(name); + if (found != typeClassInfo->typeParamsWithArgs.end()) + { + // TODO: convert GenericType -> AnyGenericType, and NamedGenericType -> GenericType, and + // add 2 type Parameters to it Constrain, Default + inferType(location, templateParam.getValue().second, found->getValue().second, results, genContext); + } + } + + return true; + } + else if (auto tempGenericClassInfo = getGenericClassInfoByFullName(tempClass.getName().getValue())) + { + for (auto &templateParam : tempGenericClassInfo->typeParams) + { + auto name = templateParam->getName(); + auto found = typeClassInfo->typeParamsWithArgs.find(name); + if (found != typeClassInfo->typeParamsWithArgs.end()) + { + inferType(location, getNamedGenericType(found->getValue().first->getName()), + found->getValue().second, results, genContext); + } + } + + return true; + } + + return false; + } + + bool MLIRGenImpl::tryInferInterface(mlir::Location location, mlir::Type templateType, mlir::Type concreteType, + StringMap &results, const GenContext &genContext) + { + auto tempInterface = dyn_cast(templateType); + auto typeInterface = dyn_cast(concreteType); + if (!tempInterface || !typeInterface) + { + return false; + } + + auto typeInterfaceInfo = getInterfaceInfoByFullName(typeInterface.getName().getValue()); + if (auto tempInterfaceInfo = getInterfaceInfoByFullName(tempInterface.getName().getValue())) + { + for (auto &templateParam : tempInterfaceInfo->typeParamsWithArgs) + { + auto name = templateParam.getValue().first->getName(); + auto found = typeInterfaceInfo->typeParamsWithArgs.find(name); + if (found != typeInterfaceInfo->typeParamsWithArgs.end()) + { + // TODO: convert GenericType -> AnyGenericType, and NamedGenericType -> GenericType, and + // add 2 type Parameters to it Constrain, Default + inferType(location, templateParam.getValue().second, found->getValue().second, results, genContext); + } + } + + return true; + } + else if (auto tempGenericInterfaceInfo = getGenericInterfaceInfoByFullName(tempInterface.getName().getValue())) + { + for (auto &templateParam : tempGenericInterfaceInfo->typeParams) + { + auto name = templateParam->getName(); + auto found = typeInterfaceInfo->typeParamsWithArgs.find(name); + if (found != typeInterfaceInfo->typeParamsWithArgs.end()) + { + inferType(location, getNamedGenericType(found->getValue().first->getName()), + found->getValue().second, results, genContext); + } + } + + return true; + } + + return false; + } + + bool MLIRGenImpl::tryInferArray(mlir::Location location, mlir::Type templateType, mlir::Type concreteType, + StringMap &results, const GenContext &genContext) + { + auto tempArray = dyn_cast(templateType); + if (!tempArray) + { + return false; + } + + if (auto typeArray = dyn_cast(concreteType)) + { + inferType(location, tempArray.getElementType(), typeArray.getElementType(), results, genContext); + return true; + } + + if (auto typeArray = dyn_cast(concreteType)) + { + inferType(location, tempArray.getElementType(), typeArray.getElementType(), results, genContext); + return true; + } + + return false; + } + + bool MLIRGenImpl::tryInferTuple(mlir::Location location, mlir::Type templateType, mlir::Type concreteType, + StringMap &results, const GenContext &genContext) + { + auto tempTuple = dyn_cast(templateType); + if (!tempTuple) + { + return false; + } + + if (auto typeTuple = dyn_cast(concreteType)) + { + return tryInferTupleFields(location, tempTuple, typeTuple, results, genContext); + } + + if (auto typeTuple = dyn_cast(concreteType)) + { + return tryInferTupleFields(location, tempTuple, typeTuple, results, genContext); + } + + return false; + } + + bool MLIRGenImpl::tryInferOptional(mlir::Location location, mlir::Type templateType, mlir::Type concreteType, + StringMap &results, const GenContext &genContext) + { + auto tempOpt = dyn_cast(templateType); + if (!tempOpt) + { + return false; + } + + if (auto typeOpt = dyn_cast(concreteType)) + { + inferType(location, tempOpt.getElementType(), typeOpt.getElementType(), results, genContext); + return true; + } + + // optional -> value + inferType(location, tempOpt.getElementType(), concreteType, results, genContext); + return true; + } + + bool MLIRGenImpl::tryInferFunction(mlir::Location location, mlir::Type templateType, mlir::Type concreteType, + StringMap &results, const GenContext &genContext) + { + if (!mth.isAnyFunctionType(templateType) || !mth.isAnyFunctionType(concreteType)) + { + return false; + } + + auto tempfuncType = mth.getParamsFromFuncRef(templateType); + if (tempfuncType.size() > 0) + { + auto funcType = mth.getParamsFromFuncRef(concreteType); + if (funcType.size() > 0) + { + inferTypeFuncType(location, tempfuncType, funcType, results, genContext); + + // lambda(return) -> lambda(return) + auto tempfuncRetType = mth.getReturnsFromFuncRef(templateType); + if (tempfuncRetType.size() > 0) + { + auto funcRetType = mth.getReturnsFromFuncRef(concreteType); + if (funcRetType.size() > 0) + { + inferTypeFuncType(location, tempfuncRetType, funcRetType, results, genContext); + } + } + + return true; + } + } + + return false; + } + + bool MLIRGenImpl::tryInferUnion(mlir::Location location, mlir::Type templateType, mlir::Type concreteType, + StringMap &results, const GenContext &genContext) + { + auto tempUnionType = dyn_cast(templateType); + if (!tempUnionType) + { + return false; + } + + if (auto typeUnionType = dyn_cast(concreteType)) + { + auto types = typeUnionType.getTypes(); + if (types.size() != tempUnionType.getTypes().size()) + { + return true; + } + + for (auto [index, tempSubType] : enumerate(tempUnionType.getTypes())) + { + inferType(location, tempSubType, types[index], results, genContext); + } + + return true; + } + + // TODO: review how to call functions such as: "function* Map(a: T[] | Iterable, f: (i: T) => R) { ... }" + // special case when UnionType is used in generic method + for (auto tempSubType : tempUnionType.getTypes()) + { + auto count = results.size(); + inferType(location, tempSubType, concreteType, results, genContext); + if (count < results.size()) + { + return true; + } + } + + return true; + } + + void MLIRGenImpl::inferType(mlir::Location location, mlir::Type templateType, mlir::Type concreteType, StringMap &results, const GenContext &genContext) + { + LLVM_DEBUG(llvm::dbgs() << "\n!! inferring \n\ttemplate type: " << templateType << ", \n\ttype: " << concreteType + << "\n";); + + if (!templateType || !concreteType) + { + // nothing todo here + return; + } + + if (templateType == concreteType) + { + // nothing todo here + return; + } + + if (tryInferNamedGeneric(location, templateType, concreteType, results)) + { + return; + } + + // class -> class + if (tryInferClass(location, templateType, concreteType, results, genContext)) + { + return; + } + + // interface -> interface + if (tryInferInterface(location, templateType, concreteType, results, genContext)) + { + return; + } + + // array -> array + if (tryInferArray(location, templateType, concreteType, results, genContext)) + { + return; + } + + // tuple -> tuple + if (tryInferTuple(location, templateType, concreteType, results, genContext)) + { + return; + } + + // optional -> optional / optional -> value + if (tryInferOptional(location, templateType, concreteType, results, genContext)) + { + return; + } + + // lambda -> lambda + if (tryInferFunction(location, templateType, concreteType, results, genContext)) + { + return; + } + + // union -> union / union -> value + if (tryInferUnion(location, templateType, concreteType, results, genContext)) + { + return; + } + + // conditional type + auto currentTemplateType = templateType; + if (auto templateCondType = dyn_cast(currentTemplateType)) + { + inferType(location, templateCondType.getTrueType(), concreteType, results, genContext); + currentTemplateType = templateCondType.getFalseType(); + inferType(location, currentTemplateType, concreteType, results, genContext); + } + + // typeref -> type; note: intentionally also tests the false branch of a conditional type from above + if (auto tempTypeRefType = dyn_cast(currentTemplateType)) + { + inferType(location, getTypeByTypeReference(location, tempTypeRefType, genContext), concreteType, results, genContext); + } + } + + void MLIRGenImpl::inferTypeFuncType(mlir::Location location, mlir::ArrayRef tempfuncType, mlir::ArrayRef funcType, + StringMap &results, const GenContext &genContext) + { + if (tempfuncType.size() != funcType.size()) + { + return; + } + + for (auto paramIndex = 0; paramIndex < tempfuncType.size(); paramIndex++) + { + auto currentTemplateType = tempfuncType[paramIndex]; + auto currentType = funcType[paramIndex]; + inferType(location, currentTemplateType, currentType, results, genContext); + } + } + + bool MLIRGenImpl::isGenericFunctionReference(mlir::Value functionRefValue) + { + auto currValue = functionRefValue; + if (auto createBoundFunctionOp = currValue.getDefiningOp()) + { + currValue = createBoundFunctionOp.getFunc(); + } + + if (auto symbolOp = currValue.getDefiningOp()) + { + return symbolOp->hasAttrOfType(GENERIC_ATTR_NAME); + } + + return false; + } + + mlir::Type MLIRGenImpl::instantiateSpecializedFunctionTypeHelper(mlir::Location location, mlir::Value functionRefValue, + mlir::Type recieverType, bool discoverReturnType, + const GenContext &genContext) + { + auto currValue = functionRefValue; + if (auto createBoundFunctionOp = currValue.getDefiningOp()) + { + currValue = createBoundFunctionOp.getFunc(); + } + + if (auto symbolOp = currValue.getDefiningOp()) + { + auto functionName = symbolOp.getIdentifier(); + + // it is not generic arrow function + auto functionGenericTypeInfo = getGenericFunctionInfoByFullName(functionName); + + MLIRNamespaceGuard nsGuard(currentNamespace); + currentNamespace = functionGenericTypeInfo->elementNamespace; + + SourceFileScope sourceFileScope(*this, functionGenericTypeInfo->sourceFile, functionGenericTypeInfo->fileName); + + return instantiateSpecializedFunctionTypeHelper(location, functionGenericTypeInfo->functionDeclaration, + recieverType, discoverReturnType, genContext); + } + + llvm_unreachable("not implemented"); + } + + mlir::Type MLIRGenImpl::instantiateSpecializedFunctionTypeHelper(mlir::Location location, FunctionLikeDeclarationBase funcDecl, + mlir::Type recieverType, bool discoverReturnType, + const GenContext &genContext) + { + GenContext funcGenContext(genContext); + funcGenContext.receiverFuncType = recieverType; + + mlir::OpBuilder::InsertionGuard guard(builder); + builder.setInsertionPointToStart(theModule.getBody()); + + auto [result, funcOp] = getFuncArgTypesOfGenericMethod(funcDecl, {}, discoverReturnType, funcGenContext); + if (mlir::failed(result)) + { + if (!genContext.dummyRun) + { + emitError(location) << "can't instantiate specialized arrow function."; + } + + return mlir::Type(); + } + + return funcOp->getFuncType(); + } + + void MLIRGenImpl::rollbackPostponedErrorMessages(mlir::SmallVector> *postponedMessages, size_t size) + { + while (size < postponedMessages->size()) + postponedMessages->pop_back(); + } + + ValueOrLogicalResult MLIRGenImpl::instantiateSpecializedFunction(mlir::Location location, + mlir::Value functionRefValue, mlir::Type recieverType, const GenContext &genContext) + { + auto currValue = functionRefValue; + auto createBoundFunctionOp = currValue.getDefiningOp(); + if (createBoundFunctionOp) + { + currValue = createBoundFunctionOp.getFunc(); + } + + LLVM_DEBUG(llvm::dbgs() << "\n!! spec. func ref: " << currValue << "\n";); + + auto symbolOp = currValue.getDefiningOp(); + if (!symbolOp) + { + emitError(currValue.getLoc()) << "generic function should be used in 'const' variable declaration."; + return mlir::failure(); + } + + auto functionName = symbolOp.getIdentifier(); + + // it is not generic arrow function + auto functionGenericTypeInfo = getGenericFunctionInfoByFullName(functionName); + if (!functionGenericTypeInfo) + { + emitError(location) << "can't find information about generic function. " << functionName; + return mlir::failure(); + } + + GenContext funcGenContext(genContext); + funcGenContext.receiverFuncType = recieverType; + funcGenContext.specialization = true; + funcGenContext.instantiateSpecializedFunction = true; + funcGenContext.typeParamsWithArgs = functionGenericTypeInfo->typeParamsWithArgs; + + auto savedErrorMessagesCount = funcGenContext.postponedMessages->size(); + + if (mlir::failed(processTypeArgumentsFromFunctionParameters( + functionGenericTypeInfo->functionDeclaration, funcGenContext))) + { + emitError(location) << "can't instantiate specialized function from function parameters."; + return mlir::failure(); + } + + rollbackPostponedErrorMessages(funcGenContext.postponedMessages, savedErrorMessagesCount); + + { + mlir::OpBuilder::InsertionGuard guard(builder); + builder.setInsertionPointToStart(theModule.getBody()); + + MLIRNamespaceGuard nsGuard(currentNamespace); + currentNamespace = functionGenericTypeInfo->elementNamespace; + + SourceFileScope sourceFileScope(*this, functionGenericTypeInfo->sourceFile, functionGenericTypeInfo->fileName); + + auto [result, specFuncOp, specFuncName, isGeneric] = + mlirGenFunctionLikeDeclaration(functionGenericTypeInfo->functionDeclaration, funcGenContext); + if (mlir::failed(result)) + { + emitError(location) << "can't instantiate specialized function."; + return mlir::failure(); + } + + LLVM_DEBUG(llvm::dbgs() << "\n!! fixing spec. func: " << specFuncName << " type: [" + << specFuncOp.getFunctionType() << "\n";); + + // update symbolref + currValue.setType(specFuncOp.getFunctionType()); + if (functionName != specFuncName) + { + symbolOp.setIdentifier(specFuncName); + } + + if (createBoundFunctionOp) + { + auto funcType = specFuncOp.getFunctionType(); + // fix create bound if any + mlir::TypeSwitch(createBoundFunctionOp.getType()) + .template Case([&](auto boundFunc) { + functionRefValue.setType(getBoundFunctionType(funcType)); + }) + .template Case([&](auto hybridFuncType) { + functionRefValue.setType( + mlir_ts::HybridFunctionType::get(builder.getContext(), funcType)); + }) + .Default([&](auto type) { llvm_unreachable("not implemented"); }); + } + + symbolOp->removeAttr(GENERIC_ATTR_NAME); + + builder.setInsertionPoint(symbolOp); + + // TODO: append captures vars to generic arrow function + auto newOpWithCapture = resolveFunctionWithCapture( + location, StringRef(specFuncName), specFuncOp.getFunctionType(), mlir::Value(), false, genContext); + if (!newOpWithCapture.getDefiningOp()) + { + // symbolOp will be removed as unsed + LLVM_DEBUG(llvm::dbgs() << "\n!! newOpWithCapture: " << newOpWithCapture << "\n";); + return newOpWithCapture; + } + else + { + // newOpWithCapture will be removed as unsed + } + } + + return mlir::success(); + } + + mlir::LogicalResult MLIRGenImpl::appendInferredTypes(mlir::Location location, + llvm::SmallVector &typeParams, + StringMap &inferredTypes, IsGeneric &anyNamedGenericType, + GenContext &genericTypeGenContext, + bool arrayMerge, bool noExtendsTest) + { + for (auto &pair : inferredTypes) + { + // find typeParam + auto typeParamName = pair.getKey(); + auto inferredType = pair.getValue(); + auto found = std::find_if(typeParams.begin(), typeParams.end(), + [&](auto ¶mItem) { return paramItem->getName() == typeParamName; }); + if (found == typeParams.end()) + { + LLVM_DEBUG(llvm::dbgs() << "\n!! can't find : " << typeParamName << " in type params: " << "\n";); + LLVM_DEBUG(for (auto typeParam : typeParams) llvm::dbgs() << "\t!! type param: " << typeParam->getName() << "\n";); + + // experiment + //auto typeParameterDOM = std::make_shared(typeParamName.str()); + //genericTypeGenContext.typeParamsWithArgs[typeParamName] = {typeParameterDOM, inferredType}; + + //return mlir::failure(); + // just ignore it + continue; + } + + auto typeParam = (*found); + + // we need to find out type and constrains is not allowing to do it + auto [result, hasAnyNamedGenericType] = + zipTypeParameterWithArgument(location, genericTypeGenContext.typeParamsWithArgs, typeParam, + inferredType, noExtendsTest, genericTypeGenContext, true, arrayMerge); + if (mlir::failed(result)) + { + return mlir::failure(); + } + + if (hasAnyNamedGenericType == IsGeneric::True) + { + anyNamedGenericType = hasAnyNamedGenericType; + } + } + + return mlir::success(); + } + + std::pair MLIRGenImpl::resolveGenericParamFromFunctionCall(mlir::Location location, mlir::Type paramType, mlir::Value argOp, int paramIndex, + GenericFunctionInfo::TypePtr functionGenericTypeInfo, IsGeneric &anyNamedGenericType, GenContext &genericTypeGenContext) + { + if (paramType == argOp.getType()) + { + return {mlir::success(), true}; + } + + StringMap inferredTypes; + inferType(location, paramType, argOp.getType(), inferredTypes, genericTypeGenContext); + if (mlir::failed(appendInferredTypes(location, functionGenericTypeInfo->typeParams, inferredTypes, anyNamedGenericType, + genericTypeGenContext, false, true))) + { + return {mlir::failure(), true}; + } + + if (isGenericFunctionReference(argOp)) + { + GenContext typeGenContext(genericTypeGenContext); + typeGenContext.dummyRun = true; + auto recreatedFuncType = instantiateSpecializedFunctionTypeHelper( + location, functionGenericTypeInfo->functionDeclaration, mlir::Type(), false, + typeGenContext); + if (!recreatedFuncType) + { + // next param + return {mlir::failure(), true}; + } + + LLVM_DEBUG(llvm::dbgs() + << "\n!! instantiate specialized type function: '" + << functionGenericTypeInfo->name << "' type: " << recreatedFuncType << "\n";); + + auto recreatedParamType = mth.getParamFromFuncRef(recreatedFuncType, paramIndex); + + LLVM_DEBUG(llvm::dbgs() + << "\n!! param type for arrow func[" << paramIndex << "]: " << recreatedParamType << "\n";); + + auto newArrowFuncType = instantiateSpecializedFunctionTypeHelper(location, argOp, recreatedParamType, + true, genericTypeGenContext); + + LLVM_DEBUG(llvm::dbgs() << "\n!! instantiate specialized arrow type function: " + << newArrowFuncType << "\n";); + + if (!newArrowFuncType) + { + return {mlir::failure(), true}; + } + + // infer second type when ArrowType is fully built + StringMap inferredTypes; + inferType(location, paramType, newArrowFuncType, inferredTypes, genericTypeGenContext); + if (mlir::failed(appendInferredTypes(location, functionGenericTypeInfo->typeParams, inferredTypes, anyNamedGenericType, + genericTypeGenContext, false, true))) + { + return {mlir::failure(), false}; + } + } + + return {mlir::success(), true}; + } + + mlir::LogicalResult MLIRGenImpl::resolveGenericParamsFromFunctionCall(mlir::Location location, + GenericFunctionInfo::TypePtr functionGenericTypeInfo, + NodeArray typeArguments, + bool skipThisParam, + IsGeneric &anyNamedGenericType, + GenContext &genericTypeGenContext) + { + // add provided type arguments, ignoring defaults + auto typeParams = functionGenericTypeInfo->typeParams; + if (typeArguments) + { + auto [result, hasAnyNamedGenericType] = zipTypeParametersWithArgumentsNoDefaults( + location, typeParams, typeArguments, genericTypeGenContext.typeParamsWithArgs, genericTypeGenContext); + if (mlir::failed(result)) + { + return mlir::failure(); + } + + if (hasAnyNamedGenericType == IsGeneric::True) + { + anyNamedGenericType = hasAnyNamedGenericType; + } + } + + // TODO: investigate, in [...].reduce, lambda function does not have funcOp, why? + auto funcOp = functionGenericTypeInfo->funcOp; + assert(funcOp); + if (funcOp) + { + // TODO: we have func params. + for (auto paramInfo : funcOp->getParams()) + { + paramInfo->processed = false; + } + + auto callOpsCount = genericTypeGenContext.callOperands.size(); + auto totalProcessed = 0; + do + { + auto paramIndex = -1; + auto processed = 0; + auto startParamIndex = skipThisParam ? 1 : 0; + auto skipCount = startParamIndex; + for (auto paramInfo : funcOp->getParams()) + { + if (skipCount-- > 0) + { + continue; + } + + paramIndex++; + if (paramInfo->processed) + { + continue; + } + + auto paramType = paramInfo->getType(); + + if (callOpsCount <= paramIndex) + { + // there is no more ops; mark processed so the param is counted once - + // recounting it every round inflated totalProcessed past the termination + // equality below and spun the loop into the "loop detected" guard + if (paramInfo->getIsOptional() || isa(paramType)) + { + paramInfo->processed = true; + processed++; + continue; + } + + if (paramInfo->getIsMultiArgsParam()) + { + paramInfo->processed = true; + processed++; + continue; + } + + break; + } + + auto argOp = genericTypeGenContext.callOperands[paramIndex]; + + LLVM_DEBUG(llvm::dbgs() + << "\n!! resolving param for generic function: '" + << functionGenericTypeInfo->name << "'\n\t parameter #" << paramIndex << " type: [ " << paramType << " ] \n\t argument type: [ " << argOp.getType() << " ]\n";); + + if (!paramInfo->getIsMultiArgsParam()) + { + auto [result, cont] = resolveGenericParamFromFunctionCall( + location, paramType, argOp, paramIndex + startParamIndex, functionGenericTypeInfo, anyNamedGenericType, genericTypeGenContext); + if (mlir::succeeded(result)) + { + paramInfo->processed = true; + processed++; + } + else if (!cont) + { + return mlir::failure(); + } + } + else + { + struct ArrayInfo arrayInfo{}; + for (auto varArgIndex = paramIndex; varArgIndex < callOpsCount; varArgIndex++) + { + auto argOp = genericTypeGenContext.callOperands[varArgIndex]; + + accumulateArrayItemType(location, argOp.getType(), arrayInfo); + } + + mlir::Type arrayType = getArrayType(arrayInfo.accumulatedArrayElementType); + + StringMap inferredTypes; + inferType(location, paramType, arrayType, inferredTypes, genericTypeGenContext); + if (mlir::failed(appendInferredTypes(location, functionGenericTypeInfo->typeParams, inferredTypes, anyNamedGenericType, + genericTypeGenContext, true))) + { + return mlir::failure(); + } + + paramInfo->processed = true; + processed++; + } + } + + if (processed == 0) + { + // no progress in a full round: some params (e.g. a callback typed by a + // type param that only gets its value from a default) can't be inferred + // here; the default zipping and the completeness check below decide + // whether that is an error + break; + } + + totalProcessed += processed; + + if (totalProcessed == funcOp->getParams().size() - startParamIndex) + { + break; + } + + if (totalProcessed > funcOp->getParams().size() + 100) + { + // defensive only: with params counted exactly once this is unreachable + emitError(location) << "loop detected."; + return mlir::failure(); + } + } while (true); + } + + // add default params if not provided + auto [resultDefArg, hasNamedGenericType] = zipTypeParametersWithDefaultArguments( + location, typeParams, typeArguments, genericTypeGenContext.typeParamsWithArgs, genericTypeGenContext); + if (mlir::failed(resultDefArg)) + { + return mlir::failure(); + } + + if (hasNamedGenericType == IsGeneric::True) + { + anyNamedGenericType = hasNamedGenericType; + } + + // TODO: check if all typeParams are there + if (genericTypeGenContext.typeParamsWithArgs.size() < typeParams.size()) + { + // no resolve needed, this type without param + emitError(location) << "not all types could be inferred"; + return mlir::failure(); + } + + return mlir::success(); + } + + std::tuple MLIRGenImpl::instantiateSpecializedFunction( + mlir::Location location, StringRef name, NodeArray typeArguments, bool skipThisParam, + SmallVector &operands, const GenContext &genContext) + { + // local copy so the 'this'-type override below stays scoped to this instantiation + GenContext instantiateGenContext(genContext); + + auto functionGenericTypeInfo = getGenericFunctionInfoByFullName(name); + if (functionGenericTypeInfo) + { + if (functionGenericTypeInfo->functionDeclaration == SyntaxKind::ArrowFunction + || functionGenericTypeInfo->functionDeclaration == SyntaxKind::FunctionExpression) + { + // we need to avoid wrong redeclaration of arrow functions (when thisType is provided it will add THIS parameter as first) + instantiateGenContext.thisType = nullptr; + } + + MLIRNamespaceGuard ng(currentNamespace); + currentNamespace = functionGenericTypeInfo->elementNamespace; + + SourceFileScope sourceFileScope(*this, functionGenericTypeInfo->sourceFile, functionGenericTypeInfo->fileName); + + auto anyNamedGenericType = IsGeneric::False; + + // step 1, add type arguments first + GenContext genericTypeGenContext(instantiateGenContext); + genericTypeGenContext.specialization = true; + genericTypeGenContext.instantiateSpecializedFunction = true; + genericTypeGenContext.typeParamsWithArgs = functionGenericTypeInfo->typeParamsWithArgs; + genericTypeGenContext.thisType = functionGenericTypeInfo->thisType; // to support methods + genericTypeGenContext.thisClassType = functionGenericTypeInfo->thisClassType; // to support methods + + auto typeParams = functionGenericTypeInfo->typeParams; + if (typeArguments && typeParams.size() == typeArguments.size()) + { + // create typeParamsWithArgs from typeArguments + auto [result, hasAnyNamedGenericType] = zipTypeParametersWithArguments( + location, typeParams, typeArguments, genericTypeGenContext.typeParamsWithArgs, instantiateGenContext); + if (mlir::failed(result)) + { + return {mlir::failure(), mlir_ts::FunctionType(), ""}; + } + + if (hasAnyNamedGenericType == IsGeneric::True) + { + anyNamedGenericType = hasAnyNamedGenericType; + } + } + else if (genericTypeGenContext.callOperands.size() > 0 || + functionGenericTypeInfo->functionDeclaration->parameters.size() > 0) + { + auto result = + resolveGenericParamsFromFunctionCall(location, functionGenericTypeInfo, typeArguments, + skipThisParam, anyNamedGenericType, genericTypeGenContext); + if (mlir::failed(result)) + { + return {mlir::failure(), mlir_ts::FunctionType(), ""}; + } + } + else + { + llvm_unreachable("not implemented"); + } + + // we need to wide all types when initializing function + // TODO: add checking constraints + for (auto &typeParam : genericTypeGenContext.typeParamsWithArgs) + { + auto &typeParamValue = typeParam.getValue(); + auto typeInfo = std::get<0>(typeParamValue); + auto name = typeInfo->getName(); + auto type = std::get<1>(typeParamValue); + auto widenType = mth.wideStorageType(type); + genericTypeGenContext.typeParamsWithArgs[name] = std::make_pair(typeInfo, widenType); + + if (typeParam.getValue().first->getConstraint()) + { + auto reason = testConstraint(location, genericTypeGenContext.typeParamsWithArgs, typeParamValue.first, widenType, instantiateGenContext); + if (reason == Reason::Failure) + { + LLVM_DEBUG(llvm::dbgs() << "\n!! skip. failed. should be resolved later\n";); + return {mlir::failure(), mlir_ts::FunctionType(), ""}; + } + + if (reason == Reason::FailedConstraint) + { + if (functionGenericTypeInfo->funcType.getNumResults() > 0 + && mlir::isa(functionGenericTypeInfo->funcType.getResult(0))) + { + return { + mlir::success(), + mlir_ts::FunctionType::get(builder.getContext(), {}, { getBooleanLiteral(false) }, false), + "" + }; + } + + return {mlir::failure(), mlir_ts::FunctionType(), ""}; + } + } + } + + LLVM_DEBUG(llvm::dbgs() << "\n!! instantiate specialized function: " << functionGenericTypeInfo->name + << " "; + for (auto &typeParam + : genericTypeGenContext.typeParamsWithArgs) llvm::dbgs() + << " param: " << std::get<0>(typeParam.getValue())->getName() + << " type: " << std::get<1>(typeParam.getValue()); + llvm::dbgs() << "\n";); + + LLVM_DEBUG(if (genericTypeGenContext.typeAliasMap.size()) llvm::dbgs() << "\n!! type alias: "; + for (auto &typeAlias + : genericTypeGenContext.typeAliasMap) llvm::dbgs() + << " name: " << typeAlias.getKey() << " type: " << typeAlias.getValue(); + llvm::dbgs() << "\n";); + + // revalidate all types + if (anyNamedGenericType == IsGeneric::True) + { + anyNamedGenericType = IsGeneric::False; + for (auto &typeParamWithArg : genericTypeGenContext.typeParamsWithArgs) + { + if (mth.isGenericType(std::get<1>(typeParamWithArg.second))) + { + anyNamedGenericType = IsGeneric::True; + } + } + } + + if (anyNamedGenericType == IsGeneric::False) + { + if (functionGenericTypeInfo->processing) + { + auto [fullName, name] = + getNameOfFunction(functionGenericTypeInfo->functionDeclaration, genericTypeGenContext); + + auto funcType = lookupFunctionTypeMap(fullName); + if (funcType) + { + return {mlir::success(), funcType, fullName}; + } + + if (instantiateGenContext.allowPartialResolve) + { + return {mlir::success(), mlir_ts::FunctionType(), fullName}; + } + + return {mlir::failure(), mlir_ts::FunctionType(), ""}; + } + + // create new instance of function with TypeArguments + functionGenericTypeInfo->processing = true; + auto [result, funcOp, funcName, isGeneric] = + mlirGenFunctionLikeDeclaration(functionGenericTypeInfo->functionDeclaration, genericTypeGenContext); + functionGenericTypeInfo->processing = false; + if (mlir::failed(result)) + { + return {mlir::failure(), mlir_ts::FunctionType(), ""}; + } + + functionGenericTypeInfo->processed = true; + + // instatiate all ArrowFunctions which are not yet instantiated + auto opIndex = skipThisParam ? 0 : -1; + // TODO: this is hack, somehow we have difference between operands and call Operands due to CreateExtentionsFunction call + // review example raytrace.ts function addLight in getNaturalColor (due to captured params) + long operandsShift = static_cast(operands.size()) - static_cast(instantiateGenContext.callOperands.size()); + for (auto [callOpIndex, op] : enumerate(instantiateGenContext.callOperands)) + { + opIndex++; + if (isGenericFunctionReference(op)) + { + LLVM_DEBUG(llvm::dbgs() << "\n!! delayed arrow func instantiation for func type: " + << funcOp.getFunctionType() << "\n";); + auto result = instantiateSpecializedFunction( + location, op, funcOp.getFunctionType().getInput(opIndex), instantiateGenContext); + if (mlir::failed(result)) + { + return {mlir::failure(), mlir_ts::FunctionType(), ""}; + } + + auto resultValue = V(result); + if (resultValue) + { + operands[callOpIndex + operandsShift] = resultValue; + } + } + } + + return {mlir::success(), funcOp.getFunctionType(), funcOp.getName().str()}; + } + + emitError(location) << "can't instantiate specialized function [" << name << "]."; + return {mlir::failure(), mlir_ts::FunctionType(), ""}; + } + + emitError(location) << "can't find generic [" << name << "] function."; + return {mlir::failure(), mlir_ts::FunctionType(), ""}; + } + + std::pair MLIRGenImpl::getFuncArgTypesOfGenericMethod( + FunctionLikeDeclarationBase functionLikeDeclarationAST, ArrayRef typeParams, + bool discoverReturnType, const GenContext &genContext) + { + GenContext funcGenContext(genContext); + funcGenContext.discoverParamsOnly = !discoverReturnType; + + // we need to map generic parameters to generic types to be able to resolve function parameters which + // are not generic + for (auto typeParam : typeParams) + { + funcGenContext.typeAliasMap.insert({typeParam->getName(), getNamedGenericType(typeParam->getName())}); + } + + auto [funcOp, funcProto, result, isGenericType] = + mlirGenFunctionPrototype(functionLikeDeclarationAST, funcGenContext); + if (mlir::failed(result) || !funcOp) + { + return {mlir::failure(), {}}; + } + + LLVM_DEBUG(llvm::dbgs() << "\n!! func name: " << funcProto->getName() + << ", Op type (resolving from operands): " << funcOp.getFunctionType() << "\n";); + + LLVM_DEBUG(llvm::dbgs() << "\n!! func args: "; for (auto [index, paramInfo] + : enumerate(funcProto->getParams())) { + llvm::dbgs() << "\n_ " << paramInfo->getName() << ": " << paramInfo->getType() << " = (" << index << ") "; + if (genContext.callOperands.size() > index) + llvm::dbgs() << genContext.callOperands[index]; + llvm::dbgs() << "\n"; + }); + + return {mlir::success(), funcProto}; + } + + std::pair MLIRGenImpl::instantiateSpecializedClassType(mlir::Location location, + mlir_ts::ClassType genericClassType, + NodeArray typeArguments, + const GenContext &genContext, + bool allowNamedGenerics) + { + auto fullNameGenericClassTypeName = genericClassType.getName().getValue(); + auto genericClassInfo = getGenericClassInfoByFullName(fullNameGenericClassTypeName); + if (genericClassInfo) + { + MLIRNamespaceGuard ng(currentNamespace); + currentNamespace = genericClassInfo->elementNamespace; + + SourceFileScope sourceFileScope(*this, genericClassInfo->sourceFile, genericClassInfo->fileName); + + GenContext genericTypeGenContext(genContext); + genericTypeGenContext.instantiateSpecializedFunction = false; + auto typeParams = genericClassInfo->typeParams; + auto [result, hasAnyNamedGenericType] = zipTypeParametersWithArguments( + location, typeParams, typeArguments, genericTypeGenContext.typeParamsWithArgs, genContext); + if (mlir::failed(result) && hasAnyNamedGenericType == IsGeneric::NoDefaults) + { + // can't instantiate generic type, so check if normal type without generic types exists + return {mlir::success(), mlir::Type()}; + } + + if (mlir::failed(result) || (hasAnyNamedGenericType == IsGeneric::True && !allowNamedGenerics)) + { + return {mlir::failure(), mlir::Type()}; + } + + LLVM_DEBUG(llvm::dbgs() << "\n!! instantiate specialized class: " << fullNameGenericClassTypeName << " "; + for (auto &typeParam + : genericTypeGenContext.typeParamsWithArgs) llvm::dbgs() + << " param: " << std::get<0>(typeParam.getValue())->getName() + << " type: " << std::get<1>(typeParam.getValue()); + llvm::dbgs() << "\n";); + + LLVM_DEBUG(if (genericTypeGenContext.typeAliasMap.size()) llvm::dbgs() << "\n!! type alias: "; + for (auto &typeAlias + : genericTypeGenContext.typeAliasMap) llvm::dbgs() + << " name: " << typeAlias.getKey() << " type: " << typeAlias.getValue(); + llvm::dbgs() << "\n";); + + // create new instance of interface with TypeArguments + if (mlir::failed(std::get<0>(mlirGen(genericClassInfo->classDeclaration, genericTypeGenContext)))) + { + return {mlir::failure(), mlir::Type()}; + } + + // get instance of generic interface type + auto specType = getSpecializationClassType(genericClassInfo, genericTypeGenContext); + return {mlir::success(), specType}; + } + + // special case: Array + // if (fullNameGenericClassTypeName == "Array" && typeArguments.size() == 1) + // { + // auto arraySpecType = getEmbeddedTypeWithParam(fullNameGenericClassTypeName, typeArguments, genContext); + // return {mlir::success(), arraySpecType}; + // } + + // can't find generic instance + return {mlir::success(), mlir::Type()}; + } + + std::pair MLIRGenImpl::instantiateSpecializedClassType(mlir::Location location, + mlir_ts::ClassType genericClassType, + ArrayRef typeArguments, + const GenContext &genContext, + bool allowNamedGenerics) + { + auto fullNameGenericClassTypeName = genericClassType.getName().getValue(); + auto genericClassInfo = getGenericClassInfoByFullName(fullNameGenericClassTypeName); + if (genericClassInfo) + { + MLIRNamespaceGuard ng(currentNamespace); + currentNamespace = genericClassInfo->elementNamespace; + + SourceFileScope sourceFileScope(*this, genericClassInfo->sourceFile, genericClassInfo->fileName); + + GenContext genericTypeGenContext(genContext); + genericTypeGenContext.instantiateSpecializedFunction = false; + auto typeParams = genericClassInfo->typeParams; + auto [result, hasAnyNamedGenericType] = zipTypeParametersWithArguments( + location, typeParams, typeArguments, genericTypeGenContext.typeParamsWithArgs, genContext); + if (mlir::failed(result) || (hasAnyNamedGenericType == IsGeneric::True && !allowNamedGenerics)) + { + return {mlir::failure(), mlir::Type()}; + } + + LLVM_DEBUG(llvm::dbgs() << "\n!! instantiate specialized class: " << fullNameGenericClassTypeName << " "; + for (auto &typeParam + : genericTypeGenContext.typeParamsWithArgs) llvm::dbgs() + << " param: " << std::get<0>(typeParam.getValue())->getName() + << " type: " << std::get<1>(typeParam.getValue()); + llvm::dbgs() << "\n";); + + LLVM_DEBUG(if (genericTypeGenContext.typeAliasMap.size()) llvm::dbgs() << "\n!! type alias: "; + for (auto &typeAlias + : genericTypeGenContext.typeAliasMap) llvm::dbgs() + << " name: " << typeAlias.getKey() << " type: " << typeAlias.getValue(); + llvm::dbgs() << "\n";); + + static auto count = 0; + count++; + if (count > 99) + { + count--; + emitError(location) << "can't instantiate type. '" << genericClassType + << "'. Circular initialization is detected."; + return {mlir::failure(), mlir::Type()}; + + // std::string s; + // s += "can't instantiate type. '"; + // s += fullNameGenericClassTypeName; + // s += "'. Circular initialization is detected."; + // llvm_unreachable(s.c_str()); + } + + auto res = std::get<0>(mlirGen(genericClassInfo->classDeclaration, genericTypeGenContext)); + count--; + + // create new instance of class with TypeArguments + if (mlir::failed(res)) + { + return {mlir::failure(), mlir::Type()}; + } + + // get instance of generic interface type + auto specType = getSpecializationClassType(genericClassInfo, genericTypeGenContext); + return {mlir::success(), specType}; + } + + // can't find generic instance + return {mlir::success(), mlir::Type()}; + } + + std::pair MLIRGenImpl::instantiateSpecializedInterfaceType( + mlir::Location location, mlir_ts::InterfaceType genericInterfaceType, NodeArray typeArguments, + const GenContext &genContext, bool allowNamedGenerics) + { + auto fullNameGenericInterfaceTypeName = genericInterfaceType.getName().getValue(); + auto genericInterfaceInfo = getGenericInterfaceInfoByFullName(fullNameGenericInterfaceTypeName); + if (genericInterfaceInfo) + { + MLIRNamespaceGuard ng(currentNamespace); + currentNamespace = genericInterfaceInfo->elementNamespace; + + SourceFileScope sourceFileScope(*this, genericInterfaceInfo->sourceFile, genericInterfaceInfo->fileName); + + GenContext genericTypeGenContext(genContext); + auto typeParams = genericInterfaceInfo->typeParams; + auto [result, hasAnyNamedGenericType] = zipTypeParametersWithArguments( + location, typeParams, typeArguments, genericTypeGenContext.typeParamsWithArgs, genContext); + if (mlir::failed(result) || (hasAnyNamedGenericType == IsGeneric::True && !allowNamedGenerics)) + { + return {mlir::failure(), mlir::Type()}; + } + + LLVM_DEBUG(llvm::dbgs() << "\n!! instantiate specialized interface: " << fullNameGenericInterfaceTypeName + << " "; + for (auto &typeParam + : genericTypeGenContext.typeParamsWithArgs) llvm::dbgs() + << " param: " << std::get<0>(typeParam.getValue())->getName() + << " type: " << std::get<1>(typeParam.getValue()); + llvm::dbgs() << "\n";); + + LLVM_DEBUG(if (genericTypeGenContext.typeAliasMap.size()) llvm::dbgs() << "\n!! type alias: "; + for (auto &typeAlias + : genericTypeGenContext.typeAliasMap) llvm::dbgs() + << " name: " << typeAlias.getKey() << " type: " << typeAlias.getValue(); + llvm::dbgs() << "\n";); + + // create new instance of interface with TypeArguments + if (mlir::failed(mlirGen(genericInterfaceInfo->interfaceDeclaration, genericTypeGenContext))) + { + // return mlir::Type(); + // type can't be resolved, so return generic base type + //return {mlir::success(), genericInterfaceInfo->interfaceType}; + return {mlir::failure(), mlir::Type()}; + } + + // get instance of generic interface type + auto specType = getSpecializationInterfaceType(genericInterfaceInfo, genericTypeGenContext); + return {mlir::success(), specType}; + } + + // can't find generic instance + return {mlir::success(), mlir::Type()}; + } + + ValueOrLogicalResult MLIRGenImpl::mlirGenSpecialized(mlir::Location location, mlir::Value genResult, + NodeArray typeArguments, SmallVector &operands, + const GenContext &genContext) + { + // in case it is generic arrow function + auto currValue = genResult; + + // in case of this.generic_func(); + if (auto extensFuncRef = currValue.getDefiningOp()) + { + currValue = extensFuncRef.getFunc(); + + SmallVector operandsSpec; + operandsSpec.push_back(extensFuncRef.getThisVal()); + operandsSpec.append(genContext.callOperands.begin(), genContext.callOperands.end()); + + GenContext specGenContext(genContext); + specGenContext.callOperands = operandsSpec; + + auto newFuncRefOrLogicResult = mlirGenSpecialized(location, currValue, typeArguments, operands, specGenContext); + EXIT_IF_FAILED(newFuncRefOrLogicResult) + if (newFuncRefOrLogicResult && currValue != newFuncRefOrLogicResult) + { + mlir::Value newFuncRefValue = newFuncRefOrLogicResult; + + // special case to work with interfaces + // TODO: finish it, bug + auto thisRef = extensFuncRef.getThisVal(); + auto funcType = mlir::cast(newFuncRefValue.getType()); + + mlir::Value newExtensionFuncVal = builder.create( + location, getExtensionFunctionType(funcType), thisRef, newFuncRefValue); + + extensFuncRef.erase(); + + return newExtensionFuncVal; + } + else + { + return genResult; + } + } + + if (currValue.getDefiningOp()->hasAttrOfType(GENERIC_ATTR_NAME)) + { + // create new function instance + GenContext initSpecGenContext(genContext); + initSpecGenContext.forceDiscover = true; + initSpecGenContext.thisType = mlir::Type(); + + auto skipThisParam = false; + mlir::Value thisValue; + StringRef funcName; + if (auto symbolOp = currValue.getDefiningOp()) + { + funcName = symbolOp.getIdentifierAttr().getValue(); + } + else if (auto thisSymbolOp = currValue.getDefiningOp()) + { + funcName = thisSymbolOp.getIdentifierAttr().getValue(); + skipThisParam = true; + thisValue = thisSymbolOp.getThisVal(); + initSpecGenContext.thisType = thisValue.getType(); + } + else + { + llvm_unreachable("not implemented"); + } + + auto [result, funcType, funcSymbolName] = + instantiateSpecializedFunction(location, funcName, typeArguments, skipThisParam, operands, initSpecGenContext); + if (mlir::failed(result)) + { + emitError(location) << "can't instantiate function. '" << funcName + << "' not all generic types can be identified"; + return mlir::failure(); + } + + if (!funcType && genContext.allowPartialResolve) + { + return mlir::success(); + } + + return resolveFunctionWithCapture(location, StringRef(funcSymbolName), funcType, thisValue, false, genContext); + } + + if (auto classOp = genResult.getDefiningOp()) + { + auto classType = classOp.getType(); + auto [result, specType] = instantiateSpecializedClassType(location, classType, typeArguments, genContext); + if (mlir::failed(result)) + { + return mlir::failure(); + } + + if (auto specClassType = dyn_cast_or_null(specType)) + { + return V(builder.create( + location, specClassType, + mlir::FlatSymbolRefAttr::get(builder.getContext(), specClassType.getName().getValue()))); + } + + if (specType) + { + return V(builder.create(location, specType)); + } + + return genResult; + } + + if (auto ifaceOp = genResult.getDefiningOp()) + { + auto interfaceType = ifaceOp.getType(); + auto [result, specType] = + instantiateSpecializedInterfaceType(location, interfaceType, typeArguments, genContext); + if (auto specInterfaceType = dyn_cast_or_null(specType)) + { + return V(builder.create( + location, specInterfaceType, + mlir::FlatSymbolRefAttr::get(builder.getContext(), specInterfaceType.getName().getValue()))); + } + + return genResult; + } + + return genResult; + } + + ValueOrLogicalResult MLIRGenImpl::mlirGen(Expression expression, NodeArray typeArguments, const GenContext &genContext) + { + auto result = mlirGen(expression, genContext); + EXIT_IF_FAILED_OR_NO_VALUE(result) + auto genResult = V(result); + // we can't leave here, template can have all parameters as default + // if (typeArguments.size() == 0) + // { + // return genResult; + // } + + auto location = loc(expression); + + SmallVector emptyOperands; + return mlirGenSpecialized(location, genResult, typeArguments, emptyOperands, genContext); + } + + ValueOrLogicalResult MLIRGenImpl::mlirGen(ExpressionWithTypeArguments expressionWithTypeArgumentsAST, + const GenContext &genContext) + { + return mlirGen(expressionWithTypeArgumentsAST->expression, expressionWithTypeArgumentsAST->typeArguments, + genContext); + } + +} // namespace mlirgen +} // namespace typescript diff --git a/tslang/lib/TypeScript/MLIRGenImpl.h b/tslang/lib/TypeScript/MLIRGenImpl.h index e2fba0d9..d3d725a6 100644 --- a/tslang/lib/TypeScript/MLIRGenImpl.h +++ b/tslang/lib/TypeScript/MLIRGenImpl.h @@ -964,155 +964,16 @@ class MLIRGenImpl // inferType helpers; return true when the template kind matched and inference was handled bool tryInferNamedGeneric(mlir::Location location, mlir::Type templateType, mlir::Type concreteType, - StringMap &results) - { - auto namedGenType = dyn_cast(templateType); - if (!namedGenType) - { - return false; - } - - // merge if exists - - auto currentType = concreteType; - auto name = namedGenType.getName().getValue(); - auto existType = results.lookup(name); - if (existType) - { - auto merged = false; - currentType = mth.mergeType(location, existType, currentType, merged); - - LLVM_DEBUG(llvm::dbgs() << "\n!! result type: " << currentType << "\n";); - results[name] = currentType; - } - else - { - // TODO: when u use literal type to validate extends u need to use original type - // currentType = mth.wideStorageType(currentType); - LLVM_DEBUG(llvm::dbgs() << "\n!! type: " << name << " = " << currentType << "\n";); - results.insert({name, currentType}); - } - - assert(results.lookup(name) == currentType); - - return true; - } + StringMap &results); bool tryInferClass(mlir::Location location, mlir::Type templateType, mlir::Type concreteType, - StringMap &results, const GenContext &genContext) - { - auto tempClass = dyn_cast(templateType); - auto typeClass = dyn_cast(concreteType); - if (!tempClass || !typeClass) - { - return false; - } - - auto typeClassInfo = getClassInfoByFullName(typeClass.getName().getValue()); - if (auto tempClassInfo = getClassInfoByFullName(tempClass.getName().getValue())) - { - for (auto &templateParam : tempClassInfo->typeParamsWithArgs) - { - auto name = templateParam.getValue().first->getName(); - auto found = typeClassInfo->typeParamsWithArgs.find(name); - if (found != typeClassInfo->typeParamsWithArgs.end()) - { - // TODO: convert GenericType -> AnyGenericType, and NamedGenericType -> GenericType, and - // add 2 type Parameters to it Constrain, Default - inferType(location, templateParam.getValue().second, found->getValue().second, results, genContext); - } - } - - return true; - } - else if (auto tempGenericClassInfo = getGenericClassInfoByFullName(tempClass.getName().getValue())) - { - for (auto &templateParam : tempGenericClassInfo->typeParams) - { - auto name = templateParam->getName(); - auto found = typeClassInfo->typeParamsWithArgs.find(name); - if (found != typeClassInfo->typeParamsWithArgs.end()) - { - inferType(location, getNamedGenericType(found->getValue().first->getName()), - found->getValue().second, results, genContext); - } - } - - return true; - } - - return false; - } + StringMap &results, const GenContext &genContext); bool tryInferInterface(mlir::Location location, mlir::Type templateType, mlir::Type concreteType, - StringMap &results, const GenContext &genContext) - { - auto tempInterface = dyn_cast(templateType); - auto typeInterface = dyn_cast(concreteType); - if (!tempInterface || !typeInterface) - { - return false; - } - - auto typeInterfaceInfo = getInterfaceInfoByFullName(typeInterface.getName().getValue()); - if (auto tempInterfaceInfo = getInterfaceInfoByFullName(tempInterface.getName().getValue())) - { - for (auto &templateParam : tempInterfaceInfo->typeParamsWithArgs) - { - auto name = templateParam.getValue().first->getName(); - auto found = typeInterfaceInfo->typeParamsWithArgs.find(name); - if (found != typeInterfaceInfo->typeParamsWithArgs.end()) - { - // TODO: convert GenericType -> AnyGenericType, and NamedGenericType -> GenericType, and - // add 2 type Parameters to it Constrain, Default - inferType(location, templateParam.getValue().second, found->getValue().second, results, genContext); - } - } - - return true; - } - else if (auto tempGenericInterfaceInfo = getGenericInterfaceInfoByFullName(tempInterface.getName().getValue())) - { - for (auto &templateParam : tempGenericInterfaceInfo->typeParams) - { - auto name = templateParam->getName(); - auto found = typeInterfaceInfo->typeParamsWithArgs.find(name); - if (found != typeInterfaceInfo->typeParamsWithArgs.end()) - { - inferType(location, getNamedGenericType(found->getValue().first->getName()), - found->getValue().second, results, genContext); - } - } - - return true; - } - - return false; - } + StringMap &results, const GenContext &genContext); bool tryInferArray(mlir::Location location, mlir::Type templateType, mlir::Type concreteType, - StringMap &results, const GenContext &genContext) - { - auto tempArray = dyn_cast(templateType); - if (!tempArray) - { - return false; - } - - if (auto typeArray = dyn_cast(concreteType)) - { - inferType(location, tempArray.getElementType(), typeArray.getElementType(), results, genContext); - return true; - } - - if (auto typeArray = dyn_cast(concreteType)) - { - inferType(location, tempArray.getElementType(), typeArray.getElementType(), results, genContext); - return true; - } - - return false; - } + StringMap &results, const GenContext &genContext); // TODO: finish it template @@ -1136,1262 +997,85 @@ class MLIRGenImpl } bool tryInferTuple(mlir::Location location, mlir::Type templateType, mlir::Type concreteType, - StringMap &results, const GenContext &genContext) - { - auto tempTuple = dyn_cast(templateType); - if (!tempTuple) - { - return false; - } - - if (auto typeTuple = dyn_cast(concreteType)) - { - return tryInferTupleFields(location, tempTuple, typeTuple, results, genContext); - } - - if (auto typeTuple = dyn_cast(concreteType)) - { - return tryInferTupleFields(location, tempTuple, typeTuple, results, genContext); - } - - return false; - } + StringMap &results, const GenContext &genContext); bool tryInferOptional(mlir::Location location, mlir::Type templateType, mlir::Type concreteType, - StringMap &results, const GenContext &genContext) - { - auto tempOpt = dyn_cast(templateType); - if (!tempOpt) - { - return false; - } - - if (auto typeOpt = dyn_cast(concreteType)) - { - inferType(location, tempOpt.getElementType(), typeOpt.getElementType(), results, genContext); - return true; - } - - // optional -> value - inferType(location, tempOpt.getElementType(), concreteType, results, genContext); - return true; - } + StringMap &results, const GenContext &genContext); bool tryInferFunction(mlir::Location location, mlir::Type templateType, mlir::Type concreteType, - StringMap &results, const GenContext &genContext) - { - if (!mth.isAnyFunctionType(templateType) || !mth.isAnyFunctionType(concreteType)) - { - return false; - } - - auto tempfuncType = mth.getParamsFromFuncRef(templateType); - if (tempfuncType.size() > 0) - { - auto funcType = mth.getParamsFromFuncRef(concreteType); - if (funcType.size() > 0) - { - inferTypeFuncType(location, tempfuncType, funcType, results, genContext); - - // lambda(return) -> lambda(return) - auto tempfuncRetType = mth.getReturnsFromFuncRef(templateType); - if (tempfuncRetType.size() > 0) - { - auto funcRetType = mth.getReturnsFromFuncRef(concreteType); - if (funcRetType.size() > 0) - { - inferTypeFuncType(location, tempfuncRetType, funcRetType, results, genContext); - } - } - - return true; - } - } - - return false; - } + StringMap &results, const GenContext &genContext); bool tryInferUnion(mlir::Location location, mlir::Type templateType, mlir::Type concreteType, - StringMap &results, const GenContext &genContext) - { - auto tempUnionType = dyn_cast(templateType); - if (!tempUnionType) - { - return false; - } - - if (auto typeUnionType = dyn_cast(concreteType)) - { - auto types = typeUnionType.getTypes(); - if (types.size() != tempUnionType.getTypes().size()) - { - return true; - } - - for (auto [index, tempSubType] : enumerate(tempUnionType.getTypes())) - { - inferType(location, tempSubType, types[index], results, genContext); - } - - return true; - } - - // TODO: review how to call functions such as: "function* Map(a: T[] | Iterable, f: (i: T) => R) { ... }" - // special case when UnionType is used in generic method - for (auto tempSubType : tempUnionType.getTypes()) - { - auto count = results.size(); - inferType(location, tempSubType, concreteType, results, genContext); - if (count < results.size()) - { - return true; - } - } - - return true; - } - - void inferType(mlir::Location location, mlir::Type templateType, mlir::Type concreteType, StringMap &results, const GenContext &genContext) - { - LLVM_DEBUG(llvm::dbgs() << "\n!! inferring \n\ttemplate type: " << templateType << ", \n\ttype: " << concreteType - << "\n";); - - if (!templateType || !concreteType) - { - // nothing todo here - return; - } - - if (templateType == concreteType) - { - // nothing todo here - return; - } + StringMap &results, const GenContext &genContext); - if (tryInferNamedGeneric(location, templateType, concreteType, results)) - { - return; - } - - // class -> class - if (tryInferClass(location, templateType, concreteType, results, genContext)) - { - return; - } - - // interface -> interface - if (tryInferInterface(location, templateType, concreteType, results, genContext)) - { - return; - } - - // array -> array - if (tryInferArray(location, templateType, concreteType, results, genContext)) - { - return; - } - - // tuple -> tuple - if (tryInferTuple(location, templateType, concreteType, results, genContext)) - { - return; - } - - // optional -> optional / optional -> value - if (tryInferOptional(location, templateType, concreteType, results, genContext)) - { - return; - } + void inferType(mlir::Location location, mlir::Type templateType, mlir::Type concreteType, StringMap &results, const GenContext &genContext); - // lambda -> lambda - if (tryInferFunction(location, templateType, concreteType, results, genContext)) - { - return; - } + void inferTypeFuncType(mlir::Location location, mlir::ArrayRef tempfuncType, mlir::ArrayRef funcType, + StringMap &results, const GenContext &genContext); - // union -> union / union -> value - if (tryInferUnion(location, templateType, concreteType, results, genContext)) - { - return; - } + bool isGenericFunctionReference(mlir::Value functionRefValue); - // conditional type - auto currentTemplateType = templateType; - if (auto templateCondType = dyn_cast(currentTemplateType)) - { - inferType(location, templateCondType.getTrueType(), concreteType, results, genContext); - currentTemplateType = templateCondType.getFalseType(); - inferType(location, currentTemplateType, concreteType, results, genContext); - } + mlir::Type instantiateSpecializedFunctionTypeHelper(mlir::Location location, mlir::Value functionRefValue, + mlir::Type recieverType, bool discoverReturnType, + const GenContext &genContext); - // typeref -> type; note: intentionally also tests the false branch of a conditional type from above - if (auto tempTypeRefType = dyn_cast(currentTemplateType)) - { - inferType(location, getTypeByTypeReference(location, tempTypeRefType, genContext), concreteType, results, genContext); - } - } + mlir::Type instantiateSpecializedFunctionTypeHelper(mlir::Location location, FunctionLikeDeclarationBase funcDecl, + mlir::Type recieverType, bool discoverReturnType, + const GenContext &genContext); - void inferTypeFuncType(mlir::Location location, mlir::ArrayRef tempfuncType, mlir::ArrayRef funcType, - StringMap &results, const GenContext &genContext) - { - if (tempfuncType.size() != funcType.size()) - { - return; - } + void rollbackPostponedErrorMessages(mlir::SmallVector> *postponedMessages, size_t size); - for (auto paramIndex = 0; paramIndex < tempfuncType.size(); paramIndex++) - { - auto currentTemplateType = tempfuncType[paramIndex]; - auto currentType = funcType[paramIndex]; - inferType(location, currentTemplateType, currentType, results, genContext); - } - } + ValueOrLogicalResult instantiateSpecializedFunction(mlir::Location location, + mlir::Value functionRefValue, mlir::Type recieverType, const GenContext &genContext); - bool isGenericFunctionReference(mlir::Value functionRefValue) - { - auto currValue = functionRefValue; - if (auto createBoundFunctionOp = currValue.getDefiningOp()) - { - currValue = createBoundFunctionOp.getFunc(); - } + mlir::LogicalResult appendInferredTypes(mlir::Location location, + llvm::SmallVector &typeParams, + StringMap &inferredTypes, IsGeneric &anyNamedGenericType, + GenContext &genericTypeGenContext, + bool arrayMerge = false, bool noExtendsTest = false); - if (auto symbolOp = currValue.getDefiningOp()) - { - return symbolOp->hasAttrOfType(GENERIC_ATTR_NAME); - } + std::pair resolveGenericParamFromFunctionCall(mlir::Location location, mlir::Type paramType, mlir::Value argOp, int paramIndex, + GenericFunctionInfo::TypePtr functionGenericTypeInfo, IsGeneric &anyNamedGenericType, GenContext &genericTypeGenContext); - return false; - } + mlir::LogicalResult resolveGenericParamsFromFunctionCall(mlir::Location location, + GenericFunctionInfo::TypePtr functionGenericTypeInfo, + NodeArray typeArguments, + bool skipThisParam, + IsGeneric &anyNamedGenericType, + GenContext &genericTypeGenContext); - mlir::Type instantiateSpecializedFunctionTypeHelper(mlir::Location location, mlir::Value functionRefValue, - mlir::Type recieverType, bool discoverReturnType, - const GenContext &genContext) - { - auto currValue = functionRefValue; - if (auto createBoundFunctionOp = currValue.getDefiningOp()) - { - currValue = createBoundFunctionOp.getFunc(); - } + std::tuple instantiateSpecializedFunction( + mlir::Location location, StringRef name, NodeArray typeArguments, bool skipThisParam, + SmallVector &operands, const GenContext &genContext); - if (auto symbolOp = currValue.getDefiningOp()) - { - auto functionName = symbolOp.getIdentifier(); + std::pair getFuncArgTypesOfGenericMethod( + FunctionLikeDeclarationBase functionLikeDeclarationAST, ArrayRef typeParams, + bool discoverReturnType, const GenContext &genContext); - // it is not generic arrow function - auto functionGenericTypeInfo = getGenericFunctionInfoByFullName(functionName); + std::pair instantiateSpecializedClassType(mlir::Location location, + mlir_ts::ClassType genericClassType, + NodeArray typeArguments, + const GenContext &genContext, + bool allowNamedGenerics = false); - MLIRNamespaceGuard nsGuard(currentNamespace); - currentNamespace = functionGenericTypeInfo->elementNamespace; + std::pair instantiateSpecializedClassType(mlir::Location location, + mlir_ts::ClassType genericClassType, + ArrayRef typeArguments, + const GenContext &genContext, + bool allowNamedGenerics = false); - SourceFileScope sourceFileScope(*this, functionGenericTypeInfo->sourceFile, functionGenericTypeInfo->fileName); + std::pair instantiateSpecializedInterfaceType( + mlir::Location location, mlir_ts::InterfaceType genericInterfaceType, NodeArray typeArguments, + const GenContext &genContext, bool allowNamedGenerics = false); - return instantiateSpecializedFunctionTypeHelper(location, functionGenericTypeInfo->functionDeclaration, - recieverType, discoverReturnType, genContext); - } + ValueOrLogicalResult mlirGenSpecialized(mlir::Location location, mlir::Value genResult, + NodeArray typeArguments, SmallVector &operands, + const GenContext &genContext); - llvm_unreachable("not implemented"); - } - - mlir::Type instantiateSpecializedFunctionTypeHelper(mlir::Location location, FunctionLikeDeclarationBase funcDecl, - mlir::Type recieverType, bool discoverReturnType, - const GenContext &genContext) - { - GenContext funcGenContext(genContext); - funcGenContext.receiverFuncType = recieverType; - - mlir::OpBuilder::InsertionGuard guard(builder); - builder.setInsertionPointToStart(theModule.getBody()); - - auto [result, funcOp] = getFuncArgTypesOfGenericMethod(funcDecl, {}, discoverReturnType, funcGenContext); - if (mlir::failed(result)) - { - if (!genContext.dummyRun) - { - emitError(location) << "can't instantiate specialized arrow function."; - } - - return mlir::Type(); - } - - return funcOp->getFuncType(); - } - - void rollbackPostponedErrorMessages(mlir::SmallVector> *postponedMessages, size_t size) - { - while (size < postponedMessages->size()) - postponedMessages->pop_back(); - } - - ValueOrLogicalResult instantiateSpecializedFunction(mlir::Location location, - mlir::Value functionRefValue, mlir::Type recieverType, const GenContext &genContext) - { - auto currValue = functionRefValue; - auto createBoundFunctionOp = currValue.getDefiningOp(); - if (createBoundFunctionOp) - { - currValue = createBoundFunctionOp.getFunc(); - } - - LLVM_DEBUG(llvm::dbgs() << "\n!! spec. func ref: " << currValue << "\n";); - - auto symbolOp = currValue.getDefiningOp(); - if (!symbolOp) - { - emitError(currValue.getLoc()) << "generic function should be used in 'const' variable declaration."; - return mlir::failure(); - } - - auto functionName = symbolOp.getIdentifier(); - - // it is not generic arrow function - auto functionGenericTypeInfo = getGenericFunctionInfoByFullName(functionName); - if (!functionGenericTypeInfo) - { - emitError(location) << "can't find information about generic function. " << functionName; - return mlir::failure(); - } - - GenContext funcGenContext(genContext); - funcGenContext.receiverFuncType = recieverType; - funcGenContext.specialization = true; - funcGenContext.instantiateSpecializedFunction = true; - funcGenContext.typeParamsWithArgs = functionGenericTypeInfo->typeParamsWithArgs; - - auto savedErrorMessagesCount = funcGenContext.postponedMessages->size(); - - if (mlir::failed(processTypeArgumentsFromFunctionParameters( - functionGenericTypeInfo->functionDeclaration, funcGenContext))) - { - emitError(location) << "can't instantiate specialized function from function parameters."; - return mlir::failure(); - } - - rollbackPostponedErrorMessages(funcGenContext.postponedMessages, savedErrorMessagesCount); - - { - mlir::OpBuilder::InsertionGuard guard(builder); - builder.setInsertionPointToStart(theModule.getBody()); - - MLIRNamespaceGuard nsGuard(currentNamespace); - currentNamespace = functionGenericTypeInfo->elementNamespace; - - SourceFileScope sourceFileScope(*this, functionGenericTypeInfo->sourceFile, functionGenericTypeInfo->fileName); - - auto [result, specFuncOp, specFuncName, isGeneric] = - mlirGenFunctionLikeDeclaration(functionGenericTypeInfo->functionDeclaration, funcGenContext); - if (mlir::failed(result)) - { - emitError(location) << "can't instantiate specialized function."; - return mlir::failure(); - } - - LLVM_DEBUG(llvm::dbgs() << "\n!! fixing spec. func: " << specFuncName << " type: [" - << specFuncOp.getFunctionType() << "\n";); - - // update symbolref - currValue.setType(specFuncOp.getFunctionType()); - if (functionName != specFuncName) - { - symbolOp.setIdentifier(specFuncName); - } - - if (createBoundFunctionOp) - { - auto funcType = specFuncOp.getFunctionType(); - // fix create bound if any - mlir::TypeSwitch(createBoundFunctionOp.getType()) - .template Case([&](auto boundFunc) { - functionRefValue.setType(getBoundFunctionType(funcType)); - }) - .template Case([&](auto hybridFuncType) { - functionRefValue.setType( - mlir_ts::HybridFunctionType::get(builder.getContext(), funcType)); - }) - .Default([&](auto type) { llvm_unreachable("not implemented"); }); - } - - symbolOp->removeAttr(GENERIC_ATTR_NAME); - - builder.setInsertionPoint(symbolOp); - - // TODO: append captures vars to generic arrow function - auto newOpWithCapture = resolveFunctionWithCapture( - location, StringRef(specFuncName), specFuncOp.getFunctionType(), mlir::Value(), false, genContext); - if (!newOpWithCapture.getDefiningOp()) - { - // symbolOp will be removed as unsed - LLVM_DEBUG(llvm::dbgs() << "\n!! newOpWithCapture: " << newOpWithCapture << "\n";); - return newOpWithCapture; - } - else - { - // newOpWithCapture will be removed as unsed - } - } - - return mlir::success(); - } - - mlir::LogicalResult appendInferredTypes(mlir::Location location, - llvm::SmallVector &typeParams, - StringMap &inferredTypes, IsGeneric &anyNamedGenericType, - GenContext &genericTypeGenContext, - bool arrayMerge = false, bool noExtendsTest = false) - { - for (auto &pair : inferredTypes) - { - // find typeParam - auto typeParamName = pair.getKey(); - auto inferredType = pair.getValue(); - auto found = std::find_if(typeParams.begin(), typeParams.end(), - [&](auto ¶mItem) { return paramItem->getName() == typeParamName; }); - if (found == typeParams.end()) - { - LLVM_DEBUG(llvm::dbgs() << "\n!! can't find : " << typeParamName << " in type params: " << "\n";); - LLVM_DEBUG(for (auto typeParam : typeParams) llvm::dbgs() << "\t!! type param: " << typeParam->getName() << "\n";); - - // experiment - //auto typeParameterDOM = std::make_shared(typeParamName.str()); - //genericTypeGenContext.typeParamsWithArgs[typeParamName] = {typeParameterDOM, inferredType}; - - //return mlir::failure(); - // just ignore it - continue; - } - - auto typeParam = (*found); - - // we need to find out type and constrains is not allowing to do it - auto [result, hasAnyNamedGenericType] = - zipTypeParameterWithArgument(location, genericTypeGenContext.typeParamsWithArgs, typeParam, - inferredType, noExtendsTest, genericTypeGenContext, true, arrayMerge); - if (mlir::failed(result)) - { - return mlir::failure(); - } - - if (hasAnyNamedGenericType == IsGeneric::True) - { - anyNamedGenericType = hasAnyNamedGenericType; - } - } - - return mlir::success(); - } - - std::pair resolveGenericParamFromFunctionCall(mlir::Location location, mlir::Type paramType, mlir::Value argOp, int paramIndex, - GenericFunctionInfo::TypePtr functionGenericTypeInfo, IsGeneric &anyNamedGenericType, GenContext &genericTypeGenContext) - { - if (paramType == argOp.getType()) - { - return {mlir::success(), true}; - } - - StringMap inferredTypes; - inferType(location, paramType, argOp.getType(), inferredTypes, genericTypeGenContext); - if (mlir::failed(appendInferredTypes(location, functionGenericTypeInfo->typeParams, inferredTypes, anyNamedGenericType, - genericTypeGenContext, false, true))) - { - return {mlir::failure(), true}; - } - - if (isGenericFunctionReference(argOp)) - { - GenContext typeGenContext(genericTypeGenContext); - typeGenContext.dummyRun = true; - auto recreatedFuncType = instantiateSpecializedFunctionTypeHelper( - location, functionGenericTypeInfo->functionDeclaration, mlir::Type(), false, - typeGenContext); - if (!recreatedFuncType) - { - // next param - return {mlir::failure(), true}; - } - - LLVM_DEBUG(llvm::dbgs() - << "\n!! instantiate specialized type function: '" - << functionGenericTypeInfo->name << "' type: " << recreatedFuncType << "\n";); - - auto recreatedParamType = mth.getParamFromFuncRef(recreatedFuncType, paramIndex); - - LLVM_DEBUG(llvm::dbgs() - << "\n!! param type for arrow func[" << paramIndex << "]: " << recreatedParamType << "\n";); - - auto newArrowFuncType = instantiateSpecializedFunctionTypeHelper(location, argOp, recreatedParamType, - true, genericTypeGenContext); - - LLVM_DEBUG(llvm::dbgs() << "\n!! instantiate specialized arrow type function: " - << newArrowFuncType << "\n";); - - if (!newArrowFuncType) - { - return {mlir::failure(), true}; - } - - // infer second type when ArrowType is fully built - StringMap inferredTypes; - inferType(location, paramType, newArrowFuncType, inferredTypes, genericTypeGenContext); - if (mlir::failed(appendInferredTypes(location, functionGenericTypeInfo->typeParams, inferredTypes, anyNamedGenericType, - genericTypeGenContext, false, true))) - { - return {mlir::failure(), false}; - } - } - - return {mlir::success(), true}; - } - - mlir::LogicalResult resolveGenericParamsFromFunctionCall(mlir::Location location, - GenericFunctionInfo::TypePtr functionGenericTypeInfo, - NodeArray typeArguments, - bool skipThisParam, - IsGeneric &anyNamedGenericType, - GenContext &genericTypeGenContext) - { - // add provided type arguments, ignoring defaults - auto typeParams = functionGenericTypeInfo->typeParams; - if (typeArguments) - { - auto [result, hasAnyNamedGenericType] = zipTypeParametersWithArgumentsNoDefaults( - location, typeParams, typeArguments, genericTypeGenContext.typeParamsWithArgs, genericTypeGenContext); - if (mlir::failed(result)) - { - return mlir::failure(); - } - - if (hasAnyNamedGenericType == IsGeneric::True) - { - anyNamedGenericType = hasAnyNamedGenericType; - } - } - - // TODO: investigate, in [...].reduce, lambda function does not have funcOp, why? - auto funcOp = functionGenericTypeInfo->funcOp; - assert(funcOp); - if (funcOp) - { - // TODO: we have func params. - for (auto paramInfo : funcOp->getParams()) - { - paramInfo->processed = false; - } - - auto callOpsCount = genericTypeGenContext.callOperands.size(); - auto totalProcessed = 0; - do - { - auto paramIndex = -1; - auto processed = 0; - auto startParamIndex = skipThisParam ? 1 : 0; - auto skipCount = startParamIndex; - for (auto paramInfo : funcOp->getParams()) - { - if (skipCount-- > 0) - { - continue; - } - - paramIndex++; - if (paramInfo->processed) - { - continue; - } - - auto paramType = paramInfo->getType(); - - if (callOpsCount <= paramIndex) - { - // there is no more ops; mark processed so the param is counted once - - // recounting it every round inflated totalProcessed past the termination - // equality below and spun the loop into the "loop detected" guard - if (paramInfo->getIsOptional() || isa(paramType)) - { - paramInfo->processed = true; - processed++; - continue; - } - - if (paramInfo->getIsMultiArgsParam()) - { - paramInfo->processed = true; - processed++; - continue; - } - - break; - } - - auto argOp = genericTypeGenContext.callOperands[paramIndex]; - - LLVM_DEBUG(llvm::dbgs() - << "\n!! resolving param for generic function: '" - << functionGenericTypeInfo->name << "'\n\t parameter #" << paramIndex << " type: [ " << paramType << " ] \n\t argument type: [ " << argOp.getType() << " ]\n";); - - if (!paramInfo->getIsMultiArgsParam()) - { - auto [result, cont] = resolveGenericParamFromFunctionCall( - location, paramType, argOp, paramIndex + startParamIndex, functionGenericTypeInfo, anyNamedGenericType, genericTypeGenContext); - if (mlir::succeeded(result)) - { - paramInfo->processed = true; - processed++; - } - else if (!cont) - { - return mlir::failure(); - } - } - else - { - struct ArrayInfo arrayInfo{}; - for (auto varArgIndex = paramIndex; varArgIndex < callOpsCount; varArgIndex++) - { - auto argOp = genericTypeGenContext.callOperands[varArgIndex]; - - accumulateArrayItemType(location, argOp.getType(), arrayInfo); - } - - mlir::Type arrayType = getArrayType(arrayInfo.accumulatedArrayElementType); - - StringMap inferredTypes; - inferType(location, paramType, arrayType, inferredTypes, genericTypeGenContext); - if (mlir::failed(appendInferredTypes(location, functionGenericTypeInfo->typeParams, inferredTypes, anyNamedGenericType, - genericTypeGenContext, true))) - { - return mlir::failure(); - } - - paramInfo->processed = true; - processed++; - } - } - - if (processed == 0) - { - // no progress in a full round: some params (e.g. a callback typed by a - // type param that only gets its value from a default) can't be inferred - // here; the default zipping and the completeness check below decide - // whether that is an error - break; - } - - totalProcessed += processed; - - if (totalProcessed == funcOp->getParams().size() - startParamIndex) - { - break; - } - - if (totalProcessed > funcOp->getParams().size() + 100) - { - // defensive only: with params counted exactly once this is unreachable - emitError(location) << "loop detected."; - return mlir::failure(); - } - } while (true); - } - - // add default params if not provided - auto [resultDefArg, hasNamedGenericType] = zipTypeParametersWithDefaultArguments( - location, typeParams, typeArguments, genericTypeGenContext.typeParamsWithArgs, genericTypeGenContext); - if (mlir::failed(resultDefArg)) - { - return mlir::failure(); - } - - if (hasNamedGenericType == IsGeneric::True) - { - anyNamedGenericType = hasNamedGenericType; - } - - // TODO: check if all typeParams are there - if (genericTypeGenContext.typeParamsWithArgs.size() < typeParams.size()) - { - // no resolve needed, this type without param - emitError(location) << "not all types could be inferred"; - return mlir::failure(); - } - - return mlir::success(); - } - - std::tuple instantiateSpecializedFunction( - mlir::Location location, StringRef name, NodeArray typeArguments, bool skipThisParam, - SmallVector &operands, const GenContext &genContext) - { - // local copy so the 'this'-type override below stays scoped to this instantiation - GenContext instantiateGenContext(genContext); - - auto functionGenericTypeInfo = getGenericFunctionInfoByFullName(name); - if (functionGenericTypeInfo) - { - if (functionGenericTypeInfo->functionDeclaration == SyntaxKind::ArrowFunction - || functionGenericTypeInfo->functionDeclaration == SyntaxKind::FunctionExpression) - { - // we need to avoid wrong redeclaration of arrow functions (when thisType is provided it will add THIS parameter as first) - instantiateGenContext.thisType = nullptr; - } - - MLIRNamespaceGuard ng(currentNamespace); - currentNamespace = functionGenericTypeInfo->elementNamespace; - - SourceFileScope sourceFileScope(*this, functionGenericTypeInfo->sourceFile, functionGenericTypeInfo->fileName); - - auto anyNamedGenericType = IsGeneric::False; - - // step 1, add type arguments first - GenContext genericTypeGenContext(instantiateGenContext); - genericTypeGenContext.specialization = true; - genericTypeGenContext.instantiateSpecializedFunction = true; - genericTypeGenContext.typeParamsWithArgs = functionGenericTypeInfo->typeParamsWithArgs; - genericTypeGenContext.thisType = functionGenericTypeInfo->thisType; // to support methods - genericTypeGenContext.thisClassType = functionGenericTypeInfo->thisClassType; // to support methods - - auto typeParams = functionGenericTypeInfo->typeParams; - if (typeArguments && typeParams.size() == typeArguments.size()) - { - // create typeParamsWithArgs from typeArguments - auto [result, hasAnyNamedGenericType] = zipTypeParametersWithArguments( - location, typeParams, typeArguments, genericTypeGenContext.typeParamsWithArgs, instantiateGenContext); - if (mlir::failed(result)) - { - return {mlir::failure(), mlir_ts::FunctionType(), ""}; - } - - if (hasAnyNamedGenericType == IsGeneric::True) - { - anyNamedGenericType = hasAnyNamedGenericType; - } - } - else if (genericTypeGenContext.callOperands.size() > 0 || - functionGenericTypeInfo->functionDeclaration->parameters.size() > 0) - { - auto result = - resolveGenericParamsFromFunctionCall(location, functionGenericTypeInfo, typeArguments, - skipThisParam, anyNamedGenericType, genericTypeGenContext); - if (mlir::failed(result)) - { - return {mlir::failure(), mlir_ts::FunctionType(), ""}; - } - } - else - { - llvm_unreachable("not implemented"); - } - - // we need to wide all types when initializing function - // TODO: add checking constraints - for (auto &typeParam : genericTypeGenContext.typeParamsWithArgs) - { - auto &typeParamValue = typeParam.getValue(); - auto typeInfo = std::get<0>(typeParamValue); - auto name = typeInfo->getName(); - auto type = std::get<1>(typeParamValue); - auto widenType = mth.wideStorageType(type); - genericTypeGenContext.typeParamsWithArgs[name] = std::make_pair(typeInfo, widenType); - - if (typeParam.getValue().first->getConstraint()) - { - auto reason = testConstraint(location, genericTypeGenContext.typeParamsWithArgs, typeParamValue.first, widenType, instantiateGenContext); - if (reason == Reason::Failure) - { - LLVM_DEBUG(llvm::dbgs() << "\n!! skip. failed. should be resolved later\n";); - return {mlir::failure(), mlir_ts::FunctionType(), ""}; - } - - if (reason == Reason::FailedConstraint) - { - if (functionGenericTypeInfo->funcType.getNumResults() > 0 - && mlir::isa(functionGenericTypeInfo->funcType.getResult(0))) - { - return { - mlir::success(), - mlir_ts::FunctionType::get(builder.getContext(), {}, { getBooleanLiteral(false) }, false), - "" - }; - } - - return {mlir::failure(), mlir_ts::FunctionType(), ""}; - } - } - } - - LLVM_DEBUG(llvm::dbgs() << "\n!! instantiate specialized function: " << functionGenericTypeInfo->name - << " "; - for (auto &typeParam - : genericTypeGenContext.typeParamsWithArgs) llvm::dbgs() - << " param: " << std::get<0>(typeParam.getValue())->getName() - << " type: " << std::get<1>(typeParam.getValue()); - llvm::dbgs() << "\n";); - - LLVM_DEBUG(if (genericTypeGenContext.typeAliasMap.size()) llvm::dbgs() << "\n!! type alias: "; - for (auto &typeAlias - : genericTypeGenContext.typeAliasMap) llvm::dbgs() - << " name: " << typeAlias.getKey() << " type: " << typeAlias.getValue(); - llvm::dbgs() << "\n";); - - // revalidate all types - if (anyNamedGenericType == IsGeneric::True) - { - anyNamedGenericType = IsGeneric::False; - for (auto &typeParamWithArg : genericTypeGenContext.typeParamsWithArgs) - { - if (mth.isGenericType(std::get<1>(typeParamWithArg.second))) - { - anyNamedGenericType = IsGeneric::True; - } - } - } - - if (anyNamedGenericType == IsGeneric::False) - { - if (functionGenericTypeInfo->processing) - { - auto [fullName, name] = - getNameOfFunction(functionGenericTypeInfo->functionDeclaration, genericTypeGenContext); - - auto funcType = lookupFunctionTypeMap(fullName); - if (funcType) - { - return {mlir::success(), funcType, fullName}; - } - - if (instantiateGenContext.allowPartialResolve) - { - return {mlir::success(), mlir_ts::FunctionType(), fullName}; - } - - return {mlir::failure(), mlir_ts::FunctionType(), ""}; - } - - // create new instance of function with TypeArguments - functionGenericTypeInfo->processing = true; - auto [result, funcOp, funcName, isGeneric] = - mlirGenFunctionLikeDeclaration(functionGenericTypeInfo->functionDeclaration, genericTypeGenContext); - functionGenericTypeInfo->processing = false; - if (mlir::failed(result)) - { - return {mlir::failure(), mlir_ts::FunctionType(), ""}; - } - - functionGenericTypeInfo->processed = true; - - // instatiate all ArrowFunctions which are not yet instantiated - auto opIndex = skipThisParam ? 0 : -1; - // TODO: this is hack, somehow we have difference between operands and call Operands due to CreateExtentionsFunction call - // review example raytrace.ts function addLight in getNaturalColor (due to captured params) - long operandsShift = static_cast(operands.size()) - static_cast(instantiateGenContext.callOperands.size()); - for (auto [callOpIndex, op] : enumerate(instantiateGenContext.callOperands)) - { - opIndex++; - if (isGenericFunctionReference(op)) - { - LLVM_DEBUG(llvm::dbgs() << "\n!! delayed arrow func instantiation for func type: " - << funcOp.getFunctionType() << "\n";); - auto result = instantiateSpecializedFunction( - location, op, funcOp.getFunctionType().getInput(opIndex), instantiateGenContext); - if (mlir::failed(result)) - { - return {mlir::failure(), mlir_ts::FunctionType(), ""}; - } - - auto resultValue = V(result); - if (resultValue) - { - operands[callOpIndex + operandsShift] = resultValue; - } - } - } - - return {mlir::success(), funcOp.getFunctionType(), funcOp.getName().str()}; - } - - emitError(location) << "can't instantiate specialized function [" << name << "]."; - return {mlir::failure(), mlir_ts::FunctionType(), ""}; - } - - emitError(location) << "can't find generic [" << name << "] function."; - return {mlir::failure(), mlir_ts::FunctionType(), ""}; - } - - std::pair getFuncArgTypesOfGenericMethod( - FunctionLikeDeclarationBase functionLikeDeclarationAST, ArrayRef typeParams, - bool discoverReturnType, const GenContext &genContext) - { - GenContext funcGenContext(genContext); - funcGenContext.discoverParamsOnly = !discoverReturnType; - - // we need to map generic parameters to generic types to be able to resolve function parameters which - // are not generic - for (auto typeParam : typeParams) - { - funcGenContext.typeAliasMap.insert({typeParam->getName(), getNamedGenericType(typeParam->getName())}); - } - - auto [funcOp, funcProto, result, isGenericType] = - mlirGenFunctionPrototype(functionLikeDeclarationAST, funcGenContext); - if (mlir::failed(result) || !funcOp) - { - return {mlir::failure(), {}}; - } - - LLVM_DEBUG(llvm::dbgs() << "\n!! func name: " << funcProto->getName() - << ", Op type (resolving from operands): " << funcOp.getFunctionType() << "\n";); - - LLVM_DEBUG(llvm::dbgs() << "\n!! func args: "; for (auto [index, paramInfo] - : enumerate(funcProto->getParams())) { - llvm::dbgs() << "\n_ " << paramInfo->getName() << ": " << paramInfo->getType() << " = (" << index << ") "; - if (genContext.callOperands.size() > index) - llvm::dbgs() << genContext.callOperands[index]; - llvm::dbgs() << "\n"; - }); - - return {mlir::success(), funcProto}; - } - - std::pair instantiateSpecializedClassType(mlir::Location location, - mlir_ts::ClassType genericClassType, - NodeArray typeArguments, - const GenContext &genContext, - bool allowNamedGenerics = false) - { - auto fullNameGenericClassTypeName = genericClassType.getName().getValue(); - auto genericClassInfo = getGenericClassInfoByFullName(fullNameGenericClassTypeName); - if (genericClassInfo) - { - MLIRNamespaceGuard ng(currentNamespace); - currentNamespace = genericClassInfo->elementNamespace; - - SourceFileScope sourceFileScope(*this, genericClassInfo->sourceFile, genericClassInfo->fileName); - - GenContext genericTypeGenContext(genContext); - genericTypeGenContext.instantiateSpecializedFunction = false; - auto typeParams = genericClassInfo->typeParams; - auto [result, hasAnyNamedGenericType] = zipTypeParametersWithArguments( - location, typeParams, typeArguments, genericTypeGenContext.typeParamsWithArgs, genContext); - if (mlir::failed(result) && hasAnyNamedGenericType == IsGeneric::NoDefaults) - { - // can't instantiate generic type, so check if normal type without generic types exists - return {mlir::success(), mlir::Type()}; - } - - if (mlir::failed(result) || (hasAnyNamedGenericType == IsGeneric::True && !allowNamedGenerics)) - { - return {mlir::failure(), mlir::Type()}; - } - - LLVM_DEBUG(llvm::dbgs() << "\n!! instantiate specialized class: " << fullNameGenericClassTypeName << " "; - for (auto &typeParam - : genericTypeGenContext.typeParamsWithArgs) llvm::dbgs() - << " param: " << std::get<0>(typeParam.getValue())->getName() - << " type: " << std::get<1>(typeParam.getValue()); - llvm::dbgs() << "\n";); - - LLVM_DEBUG(if (genericTypeGenContext.typeAliasMap.size()) llvm::dbgs() << "\n!! type alias: "; - for (auto &typeAlias - : genericTypeGenContext.typeAliasMap) llvm::dbgs() - << " name: " << typeAlias.getKey() << " type: " << typeAlias.getValue(); - llvm::dbgs() << "\n";); - - // create new instance of interface with TypeArguments - if (mlir::failed(std::get<0>(mlirGen(genericClassInfo->classDeclaration, genericTypeGenContext)))) - { - return {mlir::failure(), mlir::Type()}; - } - - // get instance of generic interface type - auto specType = getSpecializationClassType(genericClassInfo, genericTypeGenContext); - return {mlir::success(), specType}; - } - - // special case: Array - // if (fullNameGenericClassTypeName == "Array" && typeArguments.size() == 1) - // { - // auto arraySpecType = getEmbeddedTypeWithParam(fullNameGenericClassTypeName, typeArguments, genContext); - // return {mlir::success(), arraySpecType}; - // } - - // can't find generic instance - return {mlir::success(), mlir::Type()}; - } - - std::pair instantiateSpecializedClassType(mlir::Location location, - mlir_ts::ClassType genericClassType, - ArrayRef typeArguments, - const GenContext &genContext, - bool allowNamedGenerics = false) - { - auto fullNameGenericClassTypeName = genericClassType.getName().getValue(); - auto genericClassInfo = getGenericClassInfoByFullName(fullNameGenericClassTypeName); - if (genericClassInfo) - { - MLIRNamespaceGuard ng(currentNamespace); - currentNamespace = genericClassInfo->elementNamespace; - - SourceFileScope sourceFileScope(*this, genericClassInfo->sourceFile, genericClassInfo->fileName); - - GenContext genericTypeGenContext(genContext); - genericTypeGenContext.instantiateSpecializedFunction = false; - auto typeParams = genericClassInfo->typeParams; - auto [result, hasAnyNamedGenericType] = zipTypeParametersWithArguments( - location, typeParams, typeArguments, genericTypeGenContext.typeParamsWithArgs, genContext); - if (mlir::failed(result) || (hasAnyNamedGenericType == IsGeneric::True && !allowNamedGenerics)) - { - return {mlir::failure(), mlir::Type()}; - } - - LLVM_DEBUG(llvm::dbgs() << "\n!! instantiate specialized class: " << fullNameGenericClassTypeName << " "; - for (auto &typeParam - : genericTypeGenContext.typeParamsWithArgs) llvm::dbgs() - << " param: " << std::get<0>(typeParam.getValue())->getName() - << " type: " << std::get<1>(typeParam.getValue()); - llvm::dbgs() << "\n";); - - LLVM_DEBUG(if (genericTypeGenContext.typeAliasMap.size()) llvm::dbgs() << "\n!! type alias: "; - for (auto &typeAlias - : genericTypeGenContext.typeAliasMap) llvm::dbgs() - << " name: " << typeAlias.getKey() << " type: " << typeAlias.getValue(); - llvm::dbgs() << "\n";); - - static auto count = 0; - count++; - if (count > 99) - { - count--; - emitError(location) << "can't instantiate type. '" << genericClassType - << "'. Circular initialization is detected."; - return {mlir::failure(), mlir::Type()}; - - // std::string s; - // s += "can't instantiate type. '"; - // s += fullNameGenericClassTypeName; - // s += "'. Circular initialization is detected."; - // llvm_unreachable(s.c_str()); - } - - auto res = std::get<0>(mlirGen(genericClassInfo->classDeclaration, genericTypeGenContext)); - count--; - - // create new instance of class with TypeArguments - if (mlir::failed(res)) - { - return {mlir::failure(), mlir::Type()}; - } - - // get instance of generic interface type - auto specType = getSpecializationClassType(genericClassInfo, genericTypeGenContext); - return {mlir::success(), specType}; - } - - // can't find generic instance - return {mlir::success(), mlir::Type()}; - } - - std::pair instantiateSpecializedInterfaceType( - mlir::Location location, mlir_ts::InterfaceType genericInterfaceType, NodeArray typeArguments, - const GenContext &genContext, bool allowNamedGenerics = false) - { - auto fullNameGenericInterfaceTypeName = genericInterfaceType.getName().getValue(); - auto genericInterfaceInfo = getGenericInterfaceInfoByFullName(fullNameGenericInterfaceTypeName); - if (genericInterfaceInfo) - { - MLIRNamespaceGuard ng(currentNamespace); - currentNamespace = genericInterfaceInfo->elementNamespace; - - SourceFileScope sourceFileScope(*this, genericInterfaceInfo->sourceFile, genericInterfaceInfo->fileName); - - GenContext genericTypeGenContext(genContext); - auto typeParams = genericInterfaceInfo->typeParams; - auto [result, hasAnyNamedGenericType] = zipTypeParametersWithArguments( - location, typeParams, typeArguments, genericTypeGenContext.typeParamsWithArgs, genContext); - if (mlir::failed(result) || (hasAnyNamedGenericType == IsGeneric::True && !allowNamedGenerics)) - { - return {mlir::failure(), mlir::Type()}; - } - - LLVM_DEBUG(llvm::dbgs() << "\n!! instantiate specialized interface: " << fullNameGenericInterfaceTypeName - << " "; - for (auto &typeParam - : genericTypeGenContext.typeParamsWithArgs) llvm::dbgs() - << " param: " << std::get<0>(typeParam.getValue())->getName() - << " type: " << std::get<1>(typeParam.getValue()); - llvm::dbgs() << "\n";); - - LLVM_DEBUG(if (genericTypeGenContext.typeAliasMap.size()) llvm::dbgs() << "\n!! type alias: "; - for (auto &typeAlias - : genericTypeGenContext.typeAliasMap) llvm::dbgs() - << " name: " << typeAlias.getKey() << " type: " << typeAlias.getValue(); - llvm::dbgs() << "\n";); - - // create new instance of interface with TypeArguments - if (mlir::failed(mlirGen(genericInterfaceInfo->interfaceDeclaration, genericTypeGenContext))) - { - // return mlir::Type(); - // type can't be resolved, so return generic base type - //return {mlir::success(), genericInterfaceInfo->interfaceType}; - return {mlir::failure(), mlir::Type()}; - } - - // get instance of generic interface type - auto specType = getSpecializationInterfaceType(genericInterfaceInfo, genericTypeGenContext); - return {mlir::success(), specType}; - } - - // can't find generic instance - return {mlir::success(), mlir::Type()}; - } - - ValueOrLogicalResult mlirGenSpecialized(mlir::Location location, mlir::Value genResult, - NodeArray typeArguments, SmallVector &operands, - const GenContext &genContext) - { - // in case it is generic arrow function - auto currValue = genResult; - - // in case of this.generic_func(); - if (auto extensFuncRef = currValue.getDefiningOp()) - { - currValue = extensFuncRef.getFunc(); - - SmallVector operandsSpec; - operandsSpec.push_back(extensFuncRef.getThisVal()); - operandsSpec.append(genContext.callOperands.begin(), genContext.callOperands.end()); - - GenContext specGenContext(genContext); - specGenContext.callOperands = operandsSpec; - - auto newFuncRefOrLogicResult = mlirGenSpecialized(location, currValue, typeArguments, operands, specGenContext); - EXIT_IF_FAILED(newFuncRefOrLogicResult) - if (newFuncRefOrLogicResult && currValue != newFuncRefOrLogicResult) - { - mlir::Value newFuncRefValue = newFuncRefOrLogicResult; - - // special case to work with interfaces - // TODO: finish it, bug - auto thisRef = extensFuncRef.getThisVal(); - auto funcType = mlir::cast(newFuncRefValue.getType()); - - mlir::Value newExtensionFuncVal = builder.create( - location, getExtensionFunctionType(funcType), thisRef, newFuncRefValue); - - extensFuncRef.erase(); - - return newExtensionFuncVal; - } - else - { - return genResult; - } - } - - if (currValue.getDefiningOp()->hasAttrOfType(GENERIC_ATTR_NAME)) - { - // create new function instance - GenContext initSpecGenContext(genContext); - initSpecGenContext.forceDiscover = true; - initSpecGenContext.thisType = mlir::Type(); - - auto skipThisParam = false; - mlir::Value thisValue; - StringRef funcName; - if (auto symbolOp = currValue.getDefiningOp()) - { - funcName = symbolOp.getIdentifierAttr().getValue(); - } - else if (auto thisSymbolOp = currValue.getDefiningOp()) - { - funcName = thisSymbolOp.getIdentifierAttr().getValue(); - skipThisParam = true; - thisValue = thisSymbolOp.getThisVal(); - initSpecGenContext.thisType = thisValue.getType(); - } - else - { - llvm_unreachable("not implemented"); - } - - auto [result, funcType, funcSymbolName] = - instantiateSpecializedFunction(location, funcName, typeArguments, skipThisParam, operands, initSpecGenContext); - if (mlir::failed(result)) - { - emitError(location) << "can't instantiate function. '" << funcName - << "' not all generic types can be identified"; - return mlir::failure(); - } - - if (!funcType && genContext.allowPartialResolve) - { - return mlir::success(); - } - - return resolveFunctionWithCapture(location, StringRef(funcSymbolName), funcType, thisValue, false, genContext); - } - - if (auto classOp = genResult.getDefiningOp()) - { - auto classType = classOp.getType(); - auto [result, specType] = instantiateSpecializedClassType(location, classType, typeArguments, genContext); - if (mlir::failed(result)) - { - return mlir::failure(); - } - - if (auto specClassType = dyn_cast_or_null(specType)) - { - return V(builder.create( - location, specClassType, - mlir::FlatSymbolRefAttr::get(builder.getContext(), specClassType.getName().getValue()))); - } - - if (specType) - { - return V(builder.create(location, specType)); - } - - return genResult; - } - - if (auto ifaceOp = genResult.getDefiningOp()) - { - auto interfaceType = ifaceOp.getType(); - auto [result, specType] = - instantiateSpecializedInterfaceType(location, interfaceType, typeArguments, genContext); - if (auto specInterfaceType = dyn_cast_or_null(specType)) - { - return V(builder.create( - location, specInterfaceType, - mlir::FlatSymbolRefAttr::get(builder.getContext(), specInterfaceType.getName().getValue()))); - } - - return genResult; - } - - return genResult; - } - - ValueOrLogicalResult mlirGen(Expression expression, NodeArray typeArguments, const GenContext &genContext) - { - auto result = mlirGen(expression, genContext); - EXIT_IF_FAILED_OR_NO_VALUE(result) - auto genResult = V(result); - // we can't leave here, template can have all parameters as default - // if (typeArguments.size() == 0) - // { - // return genResult; - // } - - auto location = loc(expression); - - SmallVector emptyOperands; - return mlirGenSpecialized(location, genResult, typeArguments, emptyOperands, genContext); - } + ValueOrLogicalResult mlirGen(Expression expression, NodeArray typeArguments, const GenContext &genContext); ValueOrLogicalResult mlirGen(ExpressionWithTypeArguments expressionWithTypeArgumentsAST, - const GenContext &genContext) - { - return mlirGen(expressionWithTypeArgumentsAST->expression, expressionWithTypeArgumentsAST->typeArguments, - genContext); - } + const GenContext &genContext); ValueOrLogicalResult registerVariableInThisContext(mlir::Location location, StringRef name, mlir::Type type, const GenContext &genContext)