diff --git a/SKIE/acceptance-tests b/SKIE/acceptance-tests index 56ec4dc8..d07f141f 160000 --- a/SKIE/acceptance-tests +++ b/SKIE/acceptance-tests @@ -1 +1 @@ -Subproject commit 56ec4dc88ec50f72fa1eadffa2d254bcc84841c4 +Subproject commit d07f141f913bbc3728b9780a8cd5574f02f3a1c4 diff --git a/SKIE/kotlin-compiler/core/src/commonMain/kotlin/co/touchlab/skie/sir/element/SirFunction.kt b/SKIE/kotlin-compiler/core/src/commonMain/kotlin/co/touchlab/skie/sir/element/SirFunction.kt index 1d2c8adb..4c4b6e2f 100644 --- a/SKIE/kotlin-compiler/core/src/commonMain/kotlin/co/touchlab/skie/sir/element/SirFunction.kt +++ b/SKIE/kotlin-compiler/core/src/commonMain/kotlin/co/touchlab/skie/sir/element/SirFunction.kt @@ -1,6 +1,7 @@ package co.touchlab.skie.sir.element import co.touchlab.skie.sir.signature.Signature +import co.touchlab.skie.util.collisionFreeIdentifier import co.touchlab.skie.util.swift.escapeSwiftIdentifier import io.outfoxx.swiftpoet.CodeBlock import io.outfoxx.swiftpoet.FunctionSpec @@ -76,4 +77,31 @@ fun SirFunction.copyValueParametersFrom(valueParameters: List inout = it.inout, ) } + + fixValueParameterCollisions() +} + +fun SirFunction.fixValueParameterCollisions() { + fixValueParameterNameCollisions() + fixValueParameterLabelCollisions() +} + +private fun SirFunction.fixValueParameterNameCollisions() { + val usedNames = mutableSetOf() + + valueParameters.forEach { parameter -> + parameter.name = parameter.name.collisionFreeIdentifier(usedNames) + + usedNames.add(parameter.name) + } +} + +private fun SirFunction.fixValueParameterLabelCollisions() { + val usedNames = mutableSetOf() + + valueParameters.forEach { parameter -> + parameter.label = parameter.labelOrName.collisionFreeIdentifier(usedNames) + + usedNames.add(parameter.labelOrName) + } } diff --git a/SKIE/kotlin-compiler/core/src/commonMain/kotlin/co/touchlab/skie/sir/element/SirTypeParameterParent.kt b/SKIE/kotlin-compiler/core/src/commonMain/kotlin/co/touchlab/skie/sir/element/SirTypeParameterParent.kt index c3fbd0fa..44ac8d8d 100644 --- a/SKIE/kotlin-compiler/core/src/commonMain/kotlin/co/touchlab/skie/sir/element/SirTypeParameterParent.kt +++ b/SKIE/kotlin-compiler/core/src/commonMain/kotlin/co/touchlab/skie/sir/element/SirTypeParameterParent.kt @@ -13,12 +13,28 @@ sealed interface SirTypeParameterParent { } } -fun SirTypeParameterParent.copyTypeParametersFrom(other: SirClass) { - val copiesWithOriginal = other.typeParameters.map { +fun SirTypeParameterParent.copyTypeParametersFrom(other: SirTypeParameterParent) { + copyTypeParametersFrom(other.typeParameters) +} + +fun SirTypeParameterParent.copyTypeParametersFrom( + copiedTypeParameters: List, + allTypeParameters: List = copiedTypeParameters, +) { + val copiesWithOriginal = copiedTypeParameters.map { it to SirTypeParameter(it.name) } - val substitutions = copiesWithOriginal.toMap() + val nonCopiedTypeParameters = allTypeParameters - copiedTypeParameters.toSet() + + val nonCopiedSubstitutions = nonCopiedTypeParameters.map { nonCopiedTypeParameter -> + val existingTypeParameter = (typeParameters.firstOrNull { it.name == nonCopiedTypeParameter.name } + ?: error("Type parameter ${nonCopiedTypeParameter.name} not found in parent scope")) + + nonCopiedTypeParameter to existingTypeParameter + } + + val substitutions = (copiesWithOriginal + nonCopiedSubstitutions).toMap() copiesWithOriginal.forEach { (original, copy) -> // TODO This is not entirely correct, because we don't substitute type parameters from parent scope as nested scopes are not implemented yet.