Revert IDL2K Multiple constructors (via secondary constructors when needed)

This commit is contained in:
Sergey Mashkov
2015-06-15 20:17:23 +03:00
parent 6d9413f02e
commit 4949624a2a
7 changed files with 73 additions and 171 deletions
+33 -64
View File
@@ -26,7 +26,7 @@ fun String.dropNullable() = when {
else -> this
}
fun String.copyNullabilityFrom(type: String) = when {
fun String.copyNullabilityFrom(type : String) = when {
type.isNullable() -> ensureNullable()
else -> this
}
@@ -94,85 +94,54 @@ fun generateAttribute(putNoImpl: Boolean, repository: Repository, attribute: Att
)
private fun InterfaceDefinition.superTypes(repository: Repository) = superTypes.map { repository.interfaces[it] }.filterNotNull()
private fun resolveDefinitionKind(repository: Repository, iface: InterfaceDefinition, constructors: List<ExtendedAttribute> = iface.findConstructors()): GenerateDefinitionKind =
if (iface.dictionary || constructors.isNotEmpty() || iface.superTypes(repository).any { resolveDefinitionKind(repository, it) == GenerateDefinitionKind.CLASS }) {
private fun resolveDefinitionKind(repository: Repository, iface: InterfaceDefinition, constructor: ExtendedAttribute? = iface.findConstructor()): GenerateDefinitionKind =
if (iface.dictionary || constructor != null || iface.superTypes(repository).any { resolveDefinitionKind(repository, it) == GenerateDefinitionKind.CLASS }) {
GenerateDefinitionKind.CLASS
} else {
}
else {
GenerateDefinitionKind.TRAIT
}
private fun InterfaceDefinition.mapAttributes(repository: Repository) = attributes.map { generateAttribute(!dictionary, repository, it) }
private fun InterfaceDefinition.mapOperations(repository: Repository) = operations.flatMap { generateFunctions(repository, it) }
private fun Constant.mapConstant(repository: Repository) = GenerateAttribute(name, mapType(repository, type), value, false, true, false, false)
private fun emptyConstructor() = ExtendedAttribute(null, "Constructor", emptyList())
private fun Constant.mapConstant(repository : Repository) = GenerateAttribute(name, mapType(repository, type), value, false, true, false, false)
fun generateTrait(repository: Repository, iface: InterfaceDefinition): GenerateTraitOrClass {
val superClasses = iface.superTypes
val constructor = iface.findConstructor()
val constructorFunction = generateFunction(repository, Operation("", "Unit", constructor?.arguments ?: emptyList(), emptyList()), functionName = "", nativeGetterOrSetter = NativeGetterOrSetter.NONE)
val constructorArgumentNames = constructorFunction.arguments.map { it.name }.toSet()
val constructorSuperCalls = iface.superTypes
.map { repository.interfaces[it] }
.filterNotNull()
.filter { resolveDefinitionKind(repository, it) == GenerateDefinitionKind.CLASS }
.map {
val superConstructor = it.findConstructor()
GenerateFunctionCall(
name = it.name,
arguments = if (superConstructor == null) {
emptyList()
} else {
superConstructor.arguments.map { arg ->
if (arg.name in constructorArgumentNames) arg.name else "noImpl"
}
}
)
}
assert(superClasses.size() <= 1) { "Type ${iface.name} should have one or zero super classes but found ${superClasses.map { it.name }}" }
val superClass = superClasses.singleOrNull()
val superConstructor = superClass?.findConstructors()?.firstOrNull()
val declaredConstructors = iface.findConstructors()
val entityKind = resolveDefinitionKind(repository, iface, declaredConstructors)
val entityKind = resolveDefinitionKind(repository, iface, constructor)
val extensions = repository.externals[iface.name]?.map { repository.interfaces[it] }?.filterNotNull() ?: emptyList()
val primaryConstructor = when {
declaredConstructors.size() == 1 -> declaredConstructors.single()
declaredConstructors.isEmpty() && entityKind == GenerateDefinitionKind.CLASS -> emptyConstructor()
else -> declaredConstructors.firstOrNull { it.arguments.isEmpty() }
}
val secondaryConstructors = declaredConstructors.filter { it != primaryConstructor }
val primaryConstructorWithCall = if (primaryConstructor != null) {
val constructorAsFunction = generateConstructorAsFunction(repository, primaryConstructor)
val superCall = when {
superClass != null -> superOrPrimaryConstructorCall(constructorAsFunction, superClass.name, superConstructor ?: emptyConstructor())
else -> null
}
ConstructorWithSuperTypeCall(constructorAsFunction, primaryConstructor, superCall)
} else null
val secondaryConstructorsWithCall = secondaryConstructors.map { secondaryConstructor ->
val constructorAsFunction = generateConstructorAsFunction(repository, secondaryConstructor)
val initCall = when {
primaryConstructorWithCall != null -> superOrPrimaryConstructorCall(constructorAsFunction, "this", primaryConstructorWithCall.constructorAttribute)
else -> superOrPrimaryConstructorCall(constructorAsFunction, "super", superConstructor ?: emptyConstructor())
}
ConstructorWithSuperTypeCall(constructorAsFunction, secondaryConstructor, initCall)
}
return GenerateTraitOrClass(iface.name, iface.namespace, entityKind, iface.superTypes,
memberAttributes = (iface.mapAttributes(repository) + extensions.flatMap { it.mapAttributes(repository) }).distinct().toList(),
memberFunctions = (iface.mapOperations(repository) + extensions.flatMap { it.mapOperations(repository) }).distinct().toList(),
constants = (iface.constants.map { it.mapConstant(repository) } + extensions.flatMap { it.constants.map { it.mapConstant(repository) } }.distinct().toList()),
primaryConstructor = primaryConstructorWithCall,
secondaryConstructors = secondaryConstructorsWithCall
constants = (iface.constants.map {it.mapConstant(repository)} + extensions.flatMap { it.constants.map {it.mapConstant(repository)} }.distinct().toList()),
constructor = constructorFunction,
superConstructorCalls = constructorSuperCalls
)
}
fun generateConstructorAsFunction(repository: Repository, constructor: ExtendedAttribute) = generateFunction(
repository,
Operation("", "Unit", constructor.arguments, emptyList()),
functionName = "",
nativeGetterOrSetter = NativeGetterOrSetter.NONE)
fun superOrPrimaryConstructorCall(constructorAsFunction: GenerateFunction, superClassName: String, superOrPrimaryConstructor: ExtendedAttribute): GenerateFunctionCall {
val constructorArgumentNames = constructorAsFunction.arguments.map { it.name }.toSet()
return GenerateFunctionCall(
name = superClassName,
arguments = superOrPrimaryConstructor.arguments.map { arg ->
if (arg.name in constructorArgumentNames) arg.name else "noImpl"
}
)
}
fun mapUnionType(it: UnionType) = GenerateTraitOrClass(
fun mapUnionType(it : UnionType) = GenerateTraitOrClass(
name = it.name,
namespace = it.namespace,
kind = GenerateDefinitionKind.TRAIT,
@@ -180,16 +149,16 @@ fun mapUnionType(it: UnionType) = GenerateTraitOrClass(
memberAttributes = emptyList(),
memberFunctions = emptyList(),
constants = emptyList(),
primaryConstructor = null,
secondaryConstructors = emptyList()
constructor = null,
superConstructorCalls = emptyList()
)
fun generateUnionTypeTraits(allUnionTypes: Iterable<UnionType>): List<GenerateTraitOrClass> = allUnionTypes.map(::mapUnionType)
fun generateUnionTypeTraits(allUnionTypes : Iterable<UnionType>): List<GenerateTraitOrClass> = allUnionTypes.map(::mapUnionType)
fun mapDefinitions(repository: Repository, definitions: Iterable<InterfaceDefinition>) =
definitions.filter { "NoInterfaceObject" !in it.extendedAttributes.map { it.call } }.map { generateTrait(repository, it) }
fun generateUnions(ifaces: List<GenerateTraitOrClass>, typedefs: Iterable<TypedefDefinition>): GenerateUnionTypes {
fun generateUnions(ifaces: List<GenerateTraitOrClass>, typedefs: Iterable<TypedefDefinition>) : GenerateUnionTypes {
val declaredTypes = ifaces.toMap { it.name }
val anonymousUnionTypes = collectUnionTypes(declaredTypes)
+11 -8
View File
@@ -41,7 +41,6 @@ val GenerateAttribute.signature: String
get() = "$name:${type.typeSignature}"
fun GenerateAttribute.dynamicIfUnknownType(allTypes : Set<String>, standardTypes : Set<String> = standardTypes()) = copy(type = type.dynamicIfUnknownType(allTypes, standardTypes))
fun List<GenerateAttribute>.dynamicIfUnknownType(allTypes : Set<String>, standardTypes : Set<String> = standardTypes()) = map { it.dynamicIfUnknownType(allTypes, standardTypes) }
enum class NativeGetterOrSetter {
NONE,
@@ -73,7 +72,6 @@ data class GenerateFunction(
val nativeGetterOrSetter: NativeGetterOrSetter
)
data class ConstructorWithSuperTypeCall(val constructor: GenerateFunction, val constructorAttribute: ExtendedAttribute, val initTypeCall: GenerateFunctionCall?)
data class GenerateTraitOrClass(
val name: String,
val namespace: String,
@@ -82,9 +80,14 @@ data class GenerateTraitOrClass(
val memberAttributes: List<GenerateAttribute>,
val memberFunctions: List<GenerateFunction>,
val constants: List<GenerateAttribute>,
val primaryConstructor: ConstructorWithSuperTypeCall?,
val secondaryConstructors: List<ConstructorWithSuperTypeCall>
)
val constructor: GenerateFunction?,
val superConstructorCalls: List<GenerateFunctionCall>
) {
init {
assert(superConstructorCalls.size() <= 1, "It shoould be zero or one super constructors")
}
}
val GenerateFunction.signature: String
get() = arguments.map { it.type.typeSignature }.joinToString(", ", "$name(", ")")
@@ -93,9 +96,9 @@ fun GenerateFunction.dynamicIfUnknownType(allTypes : Set<String>) = standardType
copy(returnType = returnType.dynamicIfUnknownType(allTypes, standardTypes), arguments = arguments.map { it.dynamicIfUnknownType(allTypes, standardTypes) })
}
fun InterfaceDefinition.findExtendedAttributes(name: String) = extendedAttributes.filter { it.call == name }
fun InterfaceDefinition?.hasExtendedAttribute(name: String) = this?.findExtendedAttributes(name)?.isNotEmpty() ?: false
fun InterfaceDefinition.findConstructors() = findExtendedAttributes("Constructor")
fun InterfaceDefinition.findExtendedAttribute(name: String) = extendedAttributes.firstOrNull { it.call == name }
fun InterfaceDefinition?.hasExtendedAttribute(name: String) = this?.findExtendedAttribute(name) ?: null != null
fun InterfaceDefinition.findConstructor() = findExtendedAttribute("Constructor")
data class GenerateUnionTypes(
val typeNamesToUnionsMap: Map<String, List<String>>,
+10 -27
View File
@@ -94,23 +94,20 @@ fun Appendable.render(allTypes: Map<String, GenerateTraitOrClass>, typeNamesToUn
GenerateDefinitionKind.TRAIT -> append("interface ")
}
append(iface.name)
if (iface.constructor != null && iface.constructor.arguments.isNotEmpty()) {
append("(")
renderArgumentsDeclaration(iface.constructor.arguments.map { it.dynamicIfUnknownType(allTypes.keySet()) }, false)
append(")")
}
val allSuperTypes = iface.allSuperTypes(allTypes)
val allSuperTypesNames = allSuperTypes.map { it.name }.toSet()
append(iface.name)
val primary = iface.primaryConstructor
if (primary != null) {
if (primary.constructor.arguments.isNotEmpty() || iface.secondaryConstructors.isNotEmpty()) {
append("(")
renderArgumentsDeclaration(primary.constructor.arguments.dynamicIfUnknownType(allTypes.keySet()), false)
append(")")
}
}
val superCallName = primary?.initTypeCall?.name
val superCalls = iface.superConstructorCalls.map { it.name }.toSet()
val superTypesWithCalls =
listOf(primary?.initTypeCall).filterNotNull().map { renderCall(it) } +
iface.superTypes.filter { it != superCallName && it in allSuperTypesNames } +
iface.superConstructorCalls.map { renderCall(it) } +
iface.superTypes.filter { it !in superCalls && it in allSuperTypesNames } +
(typeNamesToUnions[iface.name] ?: emptyList())
if (superTypesWithCalls.isNotEmpty()) {
@@ -119,20 +116,6 @@ fun Appendable.render(allTypes: Map<String, GenerateTraitOrClass>, typeNamesToUn
appendln (" {")
iface.secondaryConstructors.forEach { secondary ->
indent(1)
append("constructor(")
renderArgumentsDeclaration(secondary.constructor.arguments.dynamicIfUnknownType(allTypes.keySet()), false)
append(")")
if (secondary.initTypeCall != null) {
append(" : ")
append(renderCall(secondary.initTypeCall))
}
appendln()
}
val superAttributes = allSuperTypes.flatMap { it.memberAttributes }.distinct()
val superFunctions = allSuperTypes.flatMap { it.memberFunctions }.distinct()
val superSignatures = superAttributes.map { it.signature } merge superFunctions.map { it.signature }
@@ -60,7 +60,7 @@ data class FunctionType(val parameterTypes : List<Attribute>, val returnType : S
val FunctionType.arity : Int
get() = parameterTypes.size()
val FunctionType.text : String
get() = "(${parameterTypes.map { it.formatFunctionTypePart() }.join(", ")}) -> $returnType"
get() = "(${parameterTypes.map { it.formatFunctionTypePart() }.join(", ")}) -> ${returnType}"
fun FunctionType(text : String) : FunctionType {
val (parameters, returnType) = text.split("->".toRegex()).map { it.trim() }.filter { it != "" }
@@ -135,13 +135,12 @@ private fun mapTypedef(repository: Repository, type: String): String {
private fun splitUnionType(unionType: String) =
unionType.replace("Union<".toRegex(), "").replace("[>]+".toRegex(), "").split("\\s*,\\s*".toRegex()).distinct().map {it.replace("\\?$".toRegex(), "")}
private fun GenerateFunction.allTypes() = sequenceOf(returnType) + arguments.asSequence().map { it.type }
private fun GenerateFunction?.allTypes() = if (this != null) sequenceOf(returnType) + arguments.asSequence().map { it.type } else emptySequence()
private fun collectUnionTypes(allTypes: Map<String, GenerateTraitOrClass>) =
allTypes.values().asSequence()
.flatMap {
it.secondaryConstructors.asSequence().flatMap { it.constructor.allTypes() } +
sequenceOf(it.primaryConstructor).filterNotNull().flatMap { it.constructor.allTypes() } +
it.constructor.allTypes() +
it.memberAttributes.asSequence().map { it.type } +
it.memberFunctions.asSequence().flatMap { it.allTypes() }
}