diff --git a/tslang/lib/TypeScript/MLIRGen.cpp b/tslang/lib/TypeScript/MLIRGen.cpp index 8096b3a6..906d191f 100644 --- a/tslang/lib/TypeScript/MLIRGen.cpp +++ b/tslang/lib/TypeScript/MLIRGen.cpp @@ -1862,310 +1862,373 @@ class MLIRGenImpl llvm_unreachable("unknown expression"); } - void inferType(mlir::Location location, mlir::Type templateType, mlir::Type concreteType, StringMap &results, const GenContext &genContext) + // 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 currentTemplateType = templateType; - auto currentType = concreteType; + auto namedGenType = dyn_cast(templateType); + if (!namedGenType) + { + return false; + } - LLVM_DEBUG(llvm::dbgs() << "\n!! inferring \n\ttemplate type: " << templateType << ", \n\ttype: " << concreteType - << "\n";); + // merge if exists - if (!currentTemplateType || !currentType) + auto currentType = concreteType; + auto name = namedGenType.getName().getValue(); + auto existType = results.lookup(name); + if (existType) { - // nothing todo here - return; - } + auto merged = false; + currentType = mth.mergeType(location, existType, currentType, merged); - if (currentTemplateType == currentType) + LLVM_DEBUG(llvm::dbgs() << "\n!! result type: " << currentType << "\n";); + results[name] = currentType; + } + else { - // nothing todo here - return; + // 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}); } - if (auto namedGenType = dyn_cast(currentTemplateType)) - { - // merge if exists + assert(results.lookup(name) == currentType); - auto name = namedGenType.getName().getValue(); - auto existType = results.lookup(name); - if (existType) - { - auto merged = false; - currentType = mth.mergeType(location, existType, currentType, merged); + return true; + } - LLVM_DEBUG(llvm::dbgs() << "\n!! result type: " << currentType << "\n";); - results[name] = currentType; - } - else + 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) { - // 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}); + 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); + } } - assert(results.lookup(name) == currentType); - - return; + return true; } - - // class -> class - if (auto tempClass = dyn_cast(currentTemplateType)) + else if (auto tempGenericClassInfo = getGenericClassInfoByFullName(tempClass.getName().getValue())) { - if (auto typeClass = dyn_cast(concreteType)) + for (auto &templateParam : tempGenericClassInfo->typeParams) { - auto typeClassInfo = getClassInfoByFullName(typeClass.getName().getValue()); - if (auto tempClassInfo = getClassInfoByFullName(tempClass.getName().getValue())) + auto name = templateParam->getName(); + auto found = typeClassInfo->typeParamsWithArgs.find(name); + if (found != typeClassInfo->typeParamsWithArgs.end()) { - 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 - currentTemplateType = templateParam.getValue().second; - currentType = found->getValue().second; + inferType(location, getNamedGenericType(found->getValue().first->getName()), + found->getValue().second, results, genContext); + } + } - inferType(location, currentTemplateType, currentType, results, genContext); - } - } + return true; + } - return; - } - 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()) - { - currentTemplateType = getNamedGenericType(found->getValue().first->getName()); - currentType = found->getValue().second; + return false; + } - inferType(location, currentTemplateType, currentType, results, 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; + } - return; + 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); } } - } - // interface -> interface - if (auto tempInterface = dyn_cast(currentTemplateType)) + return true; + } + else if (auto tempGenericInterfaceInfo = getGenericInterfaceInfoByFullName(tempInterface.getName().getValue())) { - if (auto typeInterface = dyn_cast(concreteType)) + for (auto &templateParam : tempGenericInterfaceInfo->typeParams) { - auto typeInterfaceInfo = getInterfaceInfoByFullName(typeInterface.getName().getValue()); - if (auto tempInterfaceInfo = getInterfaceInfoByFullName(tempInterface.getName().getValue())) + auto name = templateParam->getName(); + auto found = typeInterfaceInfo->typeParamsWithArgs.find(name); + if (found != typeInterfaceInfo->typeParamsWithArgs.end()) { - 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 - currentTemplateType = templateParam.getValue().second; - currentType = found->getValue().second; + inferType(location, getNamedGenericType(found->getValue().first->getName()), + found->getValue().second, results, genContext); + } + } - inferType(location, currentTemplateType, currentType, results, genContext); - } - } + return true; + } - return; - } - 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()) - { - currentTemplateType = getNamedGenericType(found->getValue().first->getName()); - currentType = found->getValue().second; + return false; + } - inferType(location, currentTemplateType, currentType, results, 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; + } - return; - } - } + if (auto typeArray = dyn_cast(concreteType)) + { + inferType(location, tempArray.getElementType(), typeArray.getElementType(), results, genContext); + return true; } - // array -> array - if (auto tempArray = dyn_cast(currentTemplateType)) + if (auto typeArray = dyn_cast(concreteType)) + { + inferType(location, tempArray.getElementType(), typeArray.getElementType(), results, genContext); + return true; + } + + return false; + } + + // TODO: finish it + template + bool tryInferTupleFields(mlir::Location location, mlir_ts::TupleType tempTuple, T typeTuple, + StringMap &results, const GenContext &genContext) + { + for (auto tempFieldInfo : tempTuple.getFields()) { - if (auto typeArray = dyn_cast(concreteType)) + auto index = typeTuple.getIndex(tempFieldInfo.id); + if (index >= 0) { - currentTemplateType = tempArray.getElementType(); - currentType = typeArray.getElementType(); - inferType(location, currentTemplateType, currentType, results, genContext); - return; + inferType(location, tempFieldInfo.type, typeTuple.getFieldInfo(index).type, results, genContext); } - - if (auto typeArray = dyn_cast(concreteType)) + else { - currentTemplateType = tempArray.getElementType(); - currentType = typeArray.getElementType(); - inferType(location, currentTemplateType, currentType, results, genContext); - return; + return true; } } - // TODO: finish it - // tuple -> tuple - if (auto tempTuple = dyn_cast(currentTemplateType)) + return true; + } + + 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; + } + + 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; + } + + bool tryInferFunction(mlir::Location location, mlir::Type templateType, mlir::Type concreteType, + StringMap &results, const GenContext &genContext) + { + if (!mth.isAnyFunctionType(templateType) || !mth.isAnyFunctionType(concreteType)) { - if (auto typeTuple = dyn_cast(concreteType)) + return false; + } + + auto tempfuncType = mth.getParamsFromFuncRef(templateType); + if (tempfuncType.size() > 0) + { + auto funcType = mth.getParamsFromFuncRef(concreteType); + if (funcType.size() > 0) { - for (auto tempFieldInfo : tempTuple.getFields()) + inferTypeFuncType(location, tempfuncType, funcType, results, genContext); + + // lambda(return) -> lambda(return) + auto tempfuncRetType = mth.getReturnsFromFuncRef(templateType); + if (tempfuncRetType.size() > 0) { - currentTemplateType = tempFieldInfo.type; - auto index = typeTuple.getIndex(tempFieldInfo.id); - if (index >= 0) + auto funcRetType = mth.getReturnsFromFuncRef(concreteType); + if (funcRetType.size() > 0) { - currentType = typeTuple.getFieldInfo(index).type; - inferType(location, currentTemplateType, currentType, results, genContext); - } - else - { - return; + inferTypeFuncType(location, tempfuncRetType, funcRetType, results, genContext); } } - return; + return true; } + } - if (auto typeTuple = dyn_cast(concreteType)) + return false; + } + + 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()) { - for (auto tempFieldInfo : tempTuple.getFields()) - { - currentTemplateType = tempFieldInfo.type; - auto index = typeTuple.getIndex(tempFieldInfo.id); - if (index >= 0) - { - currentType = typeTuple.getFieldInfo(index).type; - inferType(location, currentTemplateType, currentType, results, genContext); - } - else - { - return; - } - } + return true; + } - return; + for (auto [index, tempSubType] : enumerate(tempUnionType.getTypes())) + { + inferType(location, tempSubType, types[index], results, genContext); } - } - // optional -> optional - if (auto tempOpt = dyn_cast(currentTemplateType)) + 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()) { - if (auto typeOpt = dyn_cast(concreteType)) + auto count = results.size(); + inferType(location, tempSubType, concreteType, results, genContext); + if (count < results.size()) { - currentTemplateType = tempOpt.getElementType(); - currentType = typeOpt.getElementType(); - inferType(location, currentTemplateType, currentType, results, genContext); - return; + return true; } + } - // optional -> value - currentTemplateType = tempOpt.getElementType(); - currentType = concreteType; - inferType(location, currentTemplateType, currentType, results, genContext); + 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; } - // lambda -> lambda - if (mth.isAnyFunctionType(currentTemplateType) && mth.isAnyFunctionType(concreteType)) + if (templateType == concreteType) { - auto tempfuncType = mth.getParamsFromFuncRef(currentTemplateType); - if (tempfuncType.size() > 0) - { - auto funcType = mth.getParamsFromFuncRef(concreteType); - if (funcType.size() > 0) - { - inferTypeFuncType(location, tempfuncType, funcType, results, genContext); + // nothing todo here + return; + } - // lambda(return) -> lambda(return) - auto tempfuncRetType = mth.getReturnsFromFuncRef(currentTemplateType); - if (tempfuncRetType.size() > 0) - { - auto funcRetType = mth.getReturnsFromFuncRef(concreteType); - if (funcRetType.size() > 0) - { - inferTypeFuncType(location, tempfuncRetType, funcRetType, results, genContext); - } - } + if (tryInferNamedGeneric(location, templateType, concreteType, results)) + { + return; + } - return; - } - } + // class -> class + if (tryInferClass(location, templateType, concreteType, results, genContext)) + { + return; } - // union -> union - if (auto tempUnionType = dyn_cast(currentTemplateType)) + // interface -> interface + if (tryInferInterface(location, templateType, concreteType, results, genContext)) { - if (auto typeUnionType = dyn_cast(concreteType)) - { - auto types = typeUnionType.getTypes(); - if (types.size() != tempUnionType.getTypes().size()) - { - return; - } + return; + } - for (auto [index, tempSubType] : enumerate(tempUnionType.getTypes())) - { - auto typeSubType = types[index]; + // array -> array + if (tryInferArray(location, templateType, concreteType, results, genContext)) + { + return; + } - currentTemplateType = tempSubType; - currentType = typeSubType; - inferType(location, currentTemplateType, currentType, results, genContext); - } + // tuple -> tuple + if (tryInferTuple(location, templateType, concreteType, results, genContext)) + { + return; + } - return; - } - else - { - // 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()) - { - currentTemplateType = tempSubType; - currentType = concreteType; + // optional -> optional / optional -> value + if (tryInferOptional(location, templateType, concreteType, results, genContext)) + { + return; + } - auto count = results.size(); - inferType(location, currentTemplateType, currentType, results, genContext); - if (count < results.size()) - { - return; - } - } + // lambda -> lambda + if (tryInferFunction(location, templateType, concreteType, results, genContext)) + { + return; + } - return; - } + // union -> union / union -> value + if (tryInferUnion(location, templateType, concreteType, results, genContext)) + { + return; } // conditional type + auto currentTemplateType = templateType; if (auto templateCondType = dyn_cast(currentTemplateType)) { - currentTemplateType = templateCondType.getTrueType(); - inferType(location, currentTemplateType, currentType, results, genContext); + inferType(location, templateCondType.getTrueType(), concreteType, results, genContext); currentTemplateType = templateCondType.getFalseType(); - inferType(location, currentTemplateType, currentType, results, genContext); + inferType(location, currentTemplateType, concreteType, results, genContext); } - // typeref -> type + // typeref -> type; note: intentionally also tests the false branch of a conditional type from above if (auto tempTypeRefType = dyn_cast(currentTemplateType)) { - currentTemplateType = getTypeByTypeReference(location, tempTypeRefType, genContext); - inferType(location, currentTemplateType, currentType, results, genContext); + inferType(location, getTypeByTypeReference(location, tempTypeRefType, genContext), concreteType, results, genContext); } }