From ec6f55ef11adafd77780a6590634f20fb465bea7 Mon Sep 17 00:00:00 2001 From: Mike Samuel Date: Tue, 30 Jun 2026 01:00:39 -0600 Subject: [PATCH] generate getters and setters consistently with qnames Signed-off-by: Mike Samuel --- .../lang/temper/be/tmpl/TmpLBackendTest.kt | 61 ++++- .../temper/frontend/define/DefineStage.kt | 11 +- .../frontend/syntax/AttachQNameMetadata.kt | 224 +++++++++++++++--- .../temper/frontend/syntax/ResolveNames.kt | 4 +- .../frontend/typestage/TypeShapeMacro.kt | 223 ++++++++++------- .../temper/frontend/CleanupTemporariesTest.kt | 6 +- .../lang/temper/frontend/DefineStageTest.kt | 74 +++++- .../temper/frontend/GenerateCodeStageTest.kt | 38 ++- .../temper/frontend/SyntaxMacroStageTest.kt | 1 - .../kotlin/lang/temper/log/Debug.kt | 6 +- .../kotlin/lang/temper/log/logger-names.json | 2 + 11 files changed, 506 insertions(+), 144 deletions(-) diff --git a/be/src/commonTest/kotlin/lang/temper/be/tmpl/TmpLBackendTest.kt b/be/src/commonTest/kotlin/lang/temper/be/tmpl/TmpLBackendTest.kt index 88915d2a..a37e11ec 100644 --- a/be/src/commonTest/kotlin/lang/temper/be/tmpl/TmpLBackendTest.kt +++ b/be/src/commonTest/kotlin/lang/temper/be/tmpl/TmpLBackendTest.kt @@ -724,10 +724,10 @@ class TmpLBackendTest { /* this */ this__1.prop__4 = prop__6; return; } - @reach(\none) get.prop -> getprop__8(this = this__9, @impliedThis(C__0) this__9: C__0): Int32 { + @QName("test-library/C.type C.get prop()") @reach(\none) get.prop -> getprop__8(this = this__9, @QName("test-library/C.type C.get prop().(this)") @impliedThis(C__0) this__9: C__0): Int32 { return /* this */ this__9.prop__4; } - @reach(\none) set.prop -> setprop__11(this = this__13, @impliedThis(C__0) this__13: C__0, newProp__12: Int32): Void { + @QName("test-library/C.type C.set prop()") @reach(\none) set.prop -> setprop__11(this = this__13, @QName("test-library/C.type C.set prop().(this)") @impliedThis(C__0) this__13: C__0, @QName("test-library/C.type C.set prop().(newProp)") newProp__12: Int32): Void { /* this */ this__13.prop__4 = newProp__12; return; } @@ -1258,7 +1258,7 @@ class TmpLBackendTest { | /* this */ this__2.x__0 = x__1; | return; | } - | get.x -> getx__0(this = this__3, @impliedThis(C) this__3: C): Int32 { + | @QName("test-library/myClass.type C.get x()") get.x -> getx__0(this = this__3, @QName("test-library/myClass.type C.get x().(this)") @impliedThis(C) this__3: C): Int32 { | return /* this */ this__3.x__0; | } | } @@ -1320,9 +1320,12 @@ class TmpLBackendTest { | //// work//aType/ => aType.tmpl | require temper-core; | let InterfaceTypeSupport#0 = InterfaceTypeSupport; + | let pureVirtual#0 = builtins.pureVirtual; | @QName("test-library/aType.type I") interface I / I { | @QName("test-library/aType.type I.x") let x__0: String; - | get.x -> nym`get.x#0`(this = this#0, this#0: I): String; + | @QName("test-library/aType.type I.get x()") get.x -> getx__0(this = this__0, @QName("test-library/aType.type I.get x().(this)") @impliedThis(I) this__0: I): String { + | pureVirtual#0(); + | } | } | | ``` @@ -1465,10 +1468,10 @@ class TmpLBackendTest { | /* this */ this__0.p__0 = p__1; | return; | } - | get.p -> getp__0(this = this__1, @impliedThis(C__0) this__1: C__0): Int32 { + | @QName("test-library/foo.type C.get p()") get.p -> getp__0(this = this__1, @QName("test-library/foo.type C.get p().(this)") @impliedThis(C__0) this__1: C__0): Int32 { | return /* this */ this__1.p__0; | } - | set.p -> setp__0(this = this__2, @impliedThis(C__0) this__2: C__0, newP__0: Int32): Void { + | @QName("test-library/foo.type C.set p()") set.p -> setp__0(this = this__2, @QName("test-library/foo.type C.set p().(this)") @impliedThis(C__0) this__2: C__0, @QName("test-library/foo.type C.set p().(newP)") newP__0: Int32): Void { | /* this */ this__2.p__0 = newP__0; | return; | } @@ -1664,7 +1667,7 @@ class TmpLBackendTest { | /* this */ this__0.x__0 = x__1; | return; | } - | get.x -> getx__0(this = this__1, @impliedThis(Point) this__1: Point): Int32 { + | @QName("test-library/foo.type Point.get x()") get.x -> getx__0(this = this__1, @QName("test-library/foo.type Point.get x().(this)") @impliedThis(Point) this__1: Point): Int32 { | return /* this */ this__1.x__0; | } | } @@ -2029,7 +2032,7 @@ class TmpLBackendTest { | /* this */ this__0.a__0 = a__2; | return; | } - | get.a -> geta__0(this = this__1, @impliedThis(A) this__1: A): String { + | @QName("test-library/foo.type A.get a()") get.a -> geta__0(this = this__1, @QName("test-library/foo.type A.get a().(this)") @impliedThis(A) this__1: A): String { | return /* this */ this__1.a__0; | } | } @@ -3015,7 +3018,7 @@ class TmpLBackendTest { | ConsoleLog#0(console#0, "Made C"); | return; | } - | get.s -> gets__0(this = this__1, @impliedThis(C__0) this__1: C__0): String { + | @QName("test-library/foo.type C.get s()") get.s -> gets__0(this = this__1, @QName("test-library/foo.type C.get s().(this)") @impliedThis(C__0) this__1: C__0): String { | return /* this */ this__1.s__0; | } | } @@ -3727,7 +3730,7 @@ class TmpLBackendTest { | /* this */ this__0.s__0 = s__1; | return; | } - | get.s -> gets__0(this = this__1, @impliedThis(StringBoxes) this__1: StringBoxes): String { + | @QName("test-library/foo.type StringBoxes.get s()") get.s -> gets__0(this = this__1, @QName("test-library/foo.type StringBoxes.get s().(this)") @impliedThis(StringBoxes) this__1: StringBoxes): String { | return /* this */ this__1.s__0; | } | } @@ -3895,6 +3898,44 @@ class TmpLBackendTest { """.trimMargin(), ) + @Test + fun interfaceWithAbstractProperty() = assertGeneratedCode( + inputFileMapFromJson( + """ + |{ + | foo.temper: + | ``` + | export interface I { + | b: Boolean; + | } + | ``` + |} + """.trimMargin(), + ), + want = """ + |{ + | tmpl: { + | test_library.tmpl: { + | content: ``` + | //// work// => test_library.tmpl + | require temper-core; + | let InterfaceTypeSupport#0 = InterfaceTypeSupport; + | let pureVirtual#0 = builtins.pureVirtual; + | @QName("test-library.type I") interface I / I { + | @QName("test-library.type I.b") let b__0: Boolean; + | @QName("test-library.type I.get b()") get.b -> getb__0(this = this__0, @QName("test-library.type I.get b().(this)") @impliedThis(I) this__0: I): Boolean { + | pureVirtual#0(); + | } + | } + | + | ```, + | }, + | test_library.tmpl.map: "__DO_NOT_CARE__" + | } + |} + """.trimMargin(), + ) + @Ignore // Not yet implemented @Test fun staticInitializersInitializedAfterTypeDeclared() = assertGeneratedCode( diff --git a/frontend/src/commonMain/kotlin/lang/temper/frontend/define/DefineStage.kt b/frontend/src/commonMain/kotlin/lang/temper/frontend/define/DefineStage.kt index a63e3d6d..3a517705 100644 --- a/frontend/src/commonMain/kotlin/lang/temper/frontend/define/DefineStage.kt +++ b/frontend/src/commonMain/kotlin/lang/temper/frontend/define/DefineStage.kt @@ -11,6 +11,7 @@ import lang.temper.frontend.flipDeclaredNames import lang.temper.frontend.interpretiveDanceStage import lang.temper.frontend.json.mixinJsonInterop import lang.temper.frontend.syntax.DotOperationDesugarer +import lang.temper.frontend.syntax.fillInMissingQnameMetadata import lang.temper.log.Debug import lang.temper.log.FailLog import lang.temper.log.LogSink @@ -31,7 +32,7 @@ internal class DefineStage( fun process(callback: (outputs: StageOutputs) -> Unit) { val configKey = root.configurationKey var addTemperTestInstructions = false - val outputs = Debug.Frontend.DefineStage(configKey).group("Debug stage") { + val outputs = Debug.Frontend.DefineStage(configKey).group("Define Stage") { interpretiveDanceStage( stage = Stage.Define, root = root, @@ -98,6 +99,14 @@ internal class DefineStage( .snapshot(configKey, AstSnapshotKey, root) } + Debug.Frontend.DefineStage.FillInMissingQNames(configKey) + .benchmarkIf(BENCHMARK, "FillInMissingQNames") { + fillInMissingQnameMetadata(root) + } + + Debug.Frontend.DefineStage.AfterFillInMissingQNames + .snapshot(configKey, AstSnapshotKey, root) + Debug.Frontend.DefineStage.SimplifyDeclarations(configKey) .benchmarkIf(BENCHMARK, "SimplifyDeclarations") { SimplifyDeclarations().simplify(root) diff --git a/frontend/src/commonMain/kotlin/lang/temper/frontend/syntax/AttachQNameMetadata.kt b/frontend/src/commonMain/kotlin/lang/temper/frontend/syntax/AttachQNameMetadata.kt index d4a92eed..20b12f84 100644 --- a/frontend/src/commonMain/kotlin/lang/temper/frontend/syntax/AttachQNameMetadata.kt +++ b/frontend/src/commonMain/kotlin/lang/temper/frontend/syntax/AttachQNameMetadata.kt @@ -1,8 +1,10 @@ package lang.temper.frontend.syntax +import lang.temper.ast.TreeVisit import lang.temper.common.Log import lang.temper.common.RSuccess import lang.temper.common.putMultiList +import lang.temper.common.soleElementOrNull import lang.temper.frontend.Module import lang.temper.log.FilePath import lang.temper.log.MessageTemplate @@ -12,16 +14,19 @@ import lang.temper.name.LibraryNameLocationKey import lang.temper.name.ModuleName import lang.temper.name.ParsedName import lang.temper.name.QName +import lang.temper.name.ResolvedName import lang.temper.name.ResolvedParsedName +import lang.temper.name.Symbol import lang.temper.name.TemperName import lang.temper.type.NominalType import lang.temper.type.TypeShape import lang.temper.value.BlockTree +import lang.temper.value.DeclParts import lang.temper.value.DeclTree import lang.temper.value.FunTree import lang.temper.value.LinearFlow import lang.temper.value.MetadataMultimapHelpers.get -import lang.temper.value.ReifiedType +import lang.temper.value.NameLeaf import lang.temper.value.TString import lang.temper.value.TSymbol import lang.temper.value.TType @@ -29,6 +34,7 @@ import lang.temper.value.Tree import lang.temper.value.Value import lang.temper.value.constructorSymbol import lang.temper.value.fnSymbol +import lang.temper.value.fromTypeSymbol import lang.temper.value.getterSymbol import lang.temper.value.initSymbol import lang.temper.value.methodSymbol @@ -37,8 +43,77 @@ import lang.temper.value.qNameSymbol import lang.temper.value.setterSymbol import lang.temper.value.staticPropertySymbol import lang.temper.value.typeDeclSymbol +import lang.temper.value.typeDefContained import lang.temper.value.typeDefinedSymbol import lang.temper.value.typeFormalSymbol +import lang.temper.value.vQNameSymbol +import lang.temper.value.valueContained +import lang.temper.value.varSymbol + +private fun buildTentative( + qNameBuilder: QName.Builder, + name: TemperName?, + parts: DeclParts, + isFnFormal: Boolean, + isFunction: Boolean, + inLocalContext: Boolean, +): QName? { + val metadata = parts.metadataSymbolMultimap + var nameKey: Symbol? = null + val kind = when { + getterSymbol in metadata -> { + nameKey = methodSymbol + QName.PartKind.Getter + } + setterSymbol in metadata -> { + nameKey = methodSymbol + QName.PartKind.Setter + } + constructorSymbol in metadata -> { + nameKey = methodSymbol + QName.PartKind.Constructor + } + methodSymbol in metadata -> { + nameKey = methodSymbol + QName.PartKind.FunctionOrMethod + } + typeFormalSymbol in metadata -> { + nameKey = typeFormalSymbol + QName.PartKind.TypeFormal + } + typeDeclSymbol in metadata -> { + QName.PartKind.Type + } + propertySymbol in metadata -> { + nameKey = propertySymbol + QName.PartKind.Decl + } + staticPropertySymbol in metadata -> { + nameKey = staticPropertySymbol + if (fnSymbol in metadata) { + QName.PartKind.FunctionOrMethod + } else { + QName.PartKind.Decl + } + } + + isFnFormal -> QName.PartKind.Input + isFunction -> QName.PartKind.FunctionOrMethod + inLocalContext -> QName.PartKind.Local + else -> QName.PartKind.Decl + } + val parsedName = nameKey?.let { nameKey -> + metadata[nameKey, TSymbol]?.let { metadataSymbolValue -> + ParsedName(metadataSymbolValue.text) + } + } ?: name?.let { parsedNameFor(it) } + return if (parsedName != null) { + qNameBuilder.part(parsedName, kind) + qNameBuilder.toQName() + } else { + null + } +} /** * Attaches [qNameSymbol] to [QName] metadata to [DeclTree]s. @@ -73,33 +148,19 @@ internal fun attachQNameMetadata(module: Module, root: BlockTree) { if (initial is BlockTree && initial.flow is LinearFlow) { initial = initial.children.lastOrNull() } - val kind = when { - getterSymbol in metadata -> QName.PartKind.Getter - setterSymbol in metadata -> QName.PartKind.Setter - constructorSymbol in metadata -> QName.PartKind.Constructor - methodSymbol in metadata -> QName.PartKind.FunctionOrMethod - typeFormalSymbol in metadata -> QName.PartKind.TypeFormal - typeDeclSymbol in metadata -> QName.PartKind.Type - propertySymbol in metadata -> QName.PartKind.Decl - staticPropertySymbol in metadata -> if (fnSymbol in metadata) { - QName.PartKind.FunctionOrMethod - } else { - QName.PartKind.Decl - } - parentFnParts?.formals?.contains(t) == true -> QName.PartKind.Input - initial is FunTree -> QName.PartKind.FunctionOrMethod - inLocalContext -> QName.PartKind.Local - else -> QName.PartKind.Decl - } - var parsedName: ParsedName = name - if (kind == QName.PartKind.Getter || kind == QName.PartKind.Setter) { - metadata[methodSymbol, TSymbol]?.let { - parsedName = ParsedName(it.text) - } + val isFnFormal = parentFnParts?.formals?.contains(t) == true + val isFunction = initial is FunTree && varSymbol !in metadata + val qName = buildTentative( + qNameBuilder, + name, + parts, + isFnFormal = isFnFormal, + isFunction = isFunction, + inLocalContext = inLocalContext, + ) + if (qName != null) { + qNameToDecls.putMultiList(qName, t) } - qNameBuilder.part(parsedName, kind) - val qName = qNameBuilder.toQName() - qNameToDecls.putMultiList(qName, t) } else { // Store existing QNames in case some micro-passes pre-allocate them. val qNameText = metadata[qNameSymbol, TString] @@ -121,7 +182,7 @@ internal fun attachQNameMetadata(module: Module, root: BlockTree) { if (parts != null) { val metadata = parts.metadataSymbolMultimap val typeDefined = metadata[typeDefinedSymbol, TType] - val definition = ((typeDefined as? ReifiedType)?.type as? NominalType)?.definition + val definition = (typeDefined?.type as? NominalType)?.definition if (definition is TypeShape) { val name = parsedNameFor(definition.name) if (name != null) { @@ -171,6 +232,113 @@ internal fun attachQNameMetadata(module: Module, root: BlockTree) { } } +internal fun fillInMissingQnameMetadata(root: BlockTree) { + val nameToQName = mutableMapOf() + // Like above, we tentatively allocate and then disambiguate, so collect the + // same info as above. + val qNameToDecls = mutableMapOf>() + val needsRepair = mutableListOf() + // The declarations with tentative assignments into qNameToDecls above. + val missing = mutableMapOf() + TreeVisit.startingAt(root) + .forEachContinuing { t -> + if (t is DeclTree) { + val parts = t.parts + if (parts != null) { + val name = parts.name.content as ResolvedName + val qNameEdge = parts.metadataSymbolMap[qNameSymbol] + if (qNameEdge != null) { + val qNameStr = TString.unpackOrNull(qNameEdge.target.valueContained) + val qNameResult = qNameStr?.let { QName.fromString(it) } + if (qNameResult is RSuccess) { + val qName = qNameResult.result + nameToQName[name] = qName + qNameToDecls.putMultiList(qName, t) + } + } else { + needsRepair.add(t) + } + } + } + } + .visitPreOrder() + + for (t in needsRepair) { + val parts = t.parts ?: continue + val name = parts.name.content + var parentQName: QName? = null + val parent = t.incoming?.source + val grandParent = parent?.incoming?.source + val fromType = parts.metadataSymbolMap[fromTypeSymbol] + if (fromType != null) { + val typeDefName = fromType.target.typeDefContained()?.name + if (typeDefName != null) { + parentQName = nameToQName[typeDefName] + } + } + if (parentQName == null) { + var owningDecl: DeclTree? = null + if (parent is FunTree) { + if (isAssignment(grandParent) && parent.incoming?.edgeIndex == 2) { + val leftName = grandParent?.childOrNull(0) as? NameLeaf + if (leftName != null) { + val pQName = nameToQName[leftName.content] + owningDecl = qNameToDecls[pQName]?.soleElementOrNull + } + } else if ( + grandParent is DeclTree && + grandParent.parts?.metadataSymbolMap[initSymbol] == parent.incoming + ) { + owningDecl = grandParent + } + } + val owningDeclParts = owningDecl?.parts + if (owningDeclParts != null && varSymbol !in owningDeclParts.metadataSymbolMap) { + val ownerName = owningDeclParts.name.content + parentQName = nameToQName[ownerName] ?: missing[owningDecl] + } + } + + if (parentQName != null) { + val builder = QName.Builder(parentQName) + val tentative = buildTentative( + builder, name, parts, + isFnFormal = parent is FunTree && parent.parts?.formals?.contains(t) == true, + isFunction = fnSymbol in parts.metadataSymbolMap, + inLocalContext = false, + ) + if (tentative != null) { + missing[t] = tentative + qNameToDecls.putMultiList(tentative, t) + } + } + } + + for ((decl, tentativeQName) in missing) { + val ambiguityGroup = qNameToDecls.getValue(tentativeQName) + var disambiguationIndex: Int? = null + val indicesToAvoid = buildSet { + for (ambiguousWith in ambiguityGroup) { + if (ambiguousWith != decl) { + val qName = ambiguousWith.parts?.metadataSymbolMultimap[qNameSymbol, TString] + val result = qName?.let { QName.fromString(it) } + if (result is RSuccess) { + add(result.result.disambiguationIndex) + } + } + } + } + while (disambiguationIndex in indicesToAvoid) { + disambiguationIndex = (disambiguationIndex ?: 0) + 1 + } + val assignedQName = tentativeQName.copy(disambiguationIndex = disambiguationIndex) + decl.insert(decl.size) { + V(decl.pos.rightEdge, vQNameSymbol) + V(decl.pos.rightEdge, Value("$assignedQName", TString)) + } + } +} + val implicitsLibraryName = DashedIdentifier("implicits") private fun parsedNameFor(name: TemperName?): ParsedName? = diff --git a/frontend/src/commonMain/kotlin/lang/temper/frontend/syntax/ResolveNames.kt b/frontend/src/commonMain/kotlin/lang/temper/frontend/syntax/ResolveNames.kt index 9bdaa44f..5446243b 100644 --- a/frontend/src/commonMain/kotlin/lang/temper/frontend/syntax/ResolveNames.kt +++ b/frontend/src/commonMain/kotlin/lang/temper/frontend/syntax/ResolveNames.kt @@ -177,9 +177,9 @@ internal fun resolveNames(root: BlockTree, logSink: LogSink) { 1 } } - return declarations.toList() + declarations.toList() } else { - return emptyList() + emptyList() } } diff --git a/frontend/src/commonMain/kotlin/lang/temper/frontend/typestage/TypeShapeMacro.kt b/frontend/src/commonMain/kotlin/lang/temper/frontend/typestage/TypeShapeMacro.kt index 9738881a..7f7fac3c 100644 --- a/frontend/src/commonMain/kotlin/lang/temper/frontend/typestage/TypeShapeMacro.kt +++ b/frontend/src/commonMain/kotlin/lang/temper/frontend/typestage/TypeShapeMacro.kt @@ -98,9 +98,9 @@ internal fun typeShapeMacro(macroEnv: MacroEnvironment): PartialResult { val bodyIndex = args.size - 1 - // Concrete -> values exist of the type that are not values of a sub-type? + // Concrete -> values exist of the type that are not values of a subtype? var typeAbstractness = Abstractness.Abstract - // Open -> may be overridden in a sub-type. + // Open -> may be overridden in a subtype. var memberOpenness = OpenOrClosed.Open var sawName = false val typeDefinedAsValue = Value(reifiedTypeFor(typeShape)) @@ -313,9 +313,47 @@ internal fun typeShapeMacro(macroEnv: MacroEnvironment): PartialResult { null } - if (propDef == null) { - // Insert a property definition before the earliest getter/setter - val propertyVisibility: Visibility = when { + var propertyTypeEdge: TEdge? = null + + // TODO: maybe capture property type in a temporary if not collapsed to a value yet + fun propertyTypePlanter(): (Planting.() -> TreeTemplate<*>)? { + val propertyTypeEdge = propertyTypeEdge ?: return null + + return { + val propertyTypeTree = propertyTypeEdge.target + val propertyTypePos = propertyTypeTree.pos + val typeValue = macroEnv.evaluateEdge(propertyTypeEdge, InterpMode.Partial) + + val extractedPropertyType = if (typeValue is Value<*>) { + Either.Left(typeValue) + } else { + var sibling = propertyTypeEdge + while (sibling.source != body) { + sibling = sibling.source!!.incoming!! + } + maybeExtractIntoTemporary( + propertyTypeEdge, + treeFollower = sibling, + ) + } + + when (extractedPropertyType) { + is Either.Left -> V(propertyTypePos, extractedPropertyType.item) + is Either.Right -> Rn(propertyTypePos, extractedPropertyType.item) + } + } + } + + fun propertyVisibility(): Visibility { + val propDef = propDef + val getterVisibility = getterVisibility + val setterVisibility = setterVisibility + return when { + propDef != null -> visibilityFor( + propDef.second, + macroEnv, + defaultVisibility = defaultVisibility, + ) getterVisibility == null -> setterVisibility ?: defaultVisibility setterVisibility == null -> getterVisibility else -> if (getterVisibility > setterVisibility) { @@ -324,6 +362,27 @@ internal fun typeShapeMacro(macroEnv: MacroEnvironment): PartialResult { setterVisibility } } + } + + if (propDef == null && macroEnv.stage == Stage.Define) { + // Insert a property definition before the earliest getter/setter + val propertyVisibility = propertyVisibility() + + if (getter != null && propertyTypeEdge == null) { + // Look at the getter return type for a type hint for the property type + val getterParts = getter.second + propertyTypeEdge = getterParts.metadataSymbolMap[typeSymbol] + } + if (setter != null && propertyTypeEdge == null) { + // Look at input parameter for a type hint for the property type + val setterParts = setter.second + val setterFnEdge = setterParts.metadataSymbolMap[initSymbol]?.let { lookThroughDecorations(it) } + val setterFnParts = (setterFnEdge?.target as? FunTree)?.parts + val newValueParam = setterFnParts?.formals?.firstOrNull { + it.parts?.metadataSymbolMap?.containsKey(impliedThisSymbol) == false + } + propertyTypeEdge = newValueParam?.parts?.metadataSymbolMap[typeSymbol] + } val edge0 = sameNameDefs[0].first val pos = edge0.target.pos.leftEdge @@ -334,6 +393,10 @@ internal fun typeShapeMacro(macroEnv: MacroEnvironment): PartialResult { V(symbol) V(visibilitySymbol) V(propertyVisibility.toSymbol()) + propertyTypePlanter()?.let { plantPropertyType -> + V(typeSymbol) + plantPropertyType() + } } } run { @@ -365,59 +428,37 @@ internal fun typeShapeMacro(macroEnv: MacroEnvironment): PartialResult { addVisibilityAnnotationTo(setter.first.target as DeclTree, setterVisibility) } } - val memberName = propDef.second.name.content + if (propertyTypeEdge == null && propDef != null) { + propertyTypeEdge = propDef.second.metadataSymbolMap[typeSymbol] + } + val memberName = propDef?.second?.name?.content + val propertyAbstractness = when { + propDef == null -> Abstractness.Abstract + memberName != null -> typeShape.properties.firstOrNull { it.name == memberName } + ?.abstractness + else -> null + } ?: if ( + typeAbstractness == Abstractness.Concrete && getter == null && setter == null + ) { + Abstractness.Concrete + } else { + Abstractness.Abstract + } // If we've already decided this property is backed, then keep that decision. This allows // adding public getters/setters to expose a public&backed property. - val propertyAbstractness = - typeShape.properties.firstOrNull { it.name == memberName } - ?.abstractness - ?: if ( - typeAbstractness == Abstractness.Concrete && getter == null && setter == null - ) { - Abstractness.Concrete - } else { - Abstractness.Abstract - } - val visibility = visibilityFor( - propDef.second, - macroEnv, - defaultVisibility = defaultVisibility, - ) - val propStay = stayFor(propDef) + val visibility = propertyVisibility() // Infer getters and setters for public&backed properties. // This allows backends to use `private` properties for the storage of backed property's - // values internally, and to channel external access through getters/setters. + // values internally and to channel external access through getters/setters. if ( - macroEnv.stage == Stage.Define && propertyAbstractness == Abstractness.Concrete && - visibility == Visibility.Public && defineImpliedMethod != null + macroEnv.stage == Stage.Define && + visibility == Visibility.Public && + defineImpliedMethod != null ) { - // TODO: maybe capture property type in a temporary if not collapsed to a value yet - val plantPropertyType = propDef.second.type?.let { propertyTypeEdge -> - val propertyTypeTree = propertyTypeEdge.target - val propertyTypePos = propertyTypeTree.pos - val typeValue = macroEnv.evaluateEdge(propertyTypeEdge, InterpMode.Partial) - - val extractedPropertyType = if (typeValue is Value<*>) { - Either.Left(typeValue) - } else { - maybeExtractIntoTemporary( - propertyTypeEdge, - treeFollower = propDef.first, - ) - } - - fun plantPropertyType(p: Planting) { - when (extractedPropertyType) { - is Either.Left -> p.V(propertyTypePos, extractedPropertyType.item) - is Either.Right -> p.Rn(propertyTypePos, extractedPropertyType.item) - } - } - - ::plantPropertyType - } + check(propDef != null) if (getter == null) { getter = defineImpliedGetterOrSetter( macroEnv, @@ -425,7 +466,8 @@ internal fun typeShapeMacro(macroEnv: MacroEnvironment): PartialResult { defineImpliedMethod, propDef, typeDefinedAsValue, - plantPropertyType, + propertyTypePlanter(), + propertyAbstractness, isGetter = true, ) sameNameDefs.add(getter) @@ -437,27 +479,30 @@ internal fun typeShapeMacro(macroEnv: MacroEnvironment): PartialResult { defineImpliedMethod, propDef, typeDefinedAsValue, - plantPropertyType, + propertyTypePlanter(), + propertyAbstractness, isGetter = false, ) sameNameDefs.add(setter) } } - addOrReplaceNamed( - typeShape.properties, - PropertyShape( - typeShape, - memberName, - symbol, - propStay, - visibility, - abstractness = propertyAbstractness, - getter = getter?.second?.name?.content, - setter = setter?.second?.name?.content, - hasSetter = setter != null || varSymbol in propDef.second.metadataSymbolMap, - ), - ) + if (memberName != null) { + addOrReplaceNamed( + typeShape.properties, + PropertyShape( + typeShape, + memberName, + symbol, + stayFor(propDef), + visibility, + abstractness = propertyAbstractness, + getter = getter?.second?.name?.content, + setter = setter?.second?.name?.content, + hasSetter = setter != null || varSymbol in propDef.second.metadataSymbolMap, + ), + ) + } for (accessor in listOfNotNull(getter, setter)) { var accessorVisibility = if (accessor == getter) getterVisibility else setterVisibility @@ -564,7 +609,7 @@ internal fun stayFor( ): StayLeaf? = stayFor(decl.first.target as DeclTree) /** - * Gets the [StayLeaf] associated with a member declarations if present. + * Gets the [StayLeaf] associated with a member declaration if present. * If not present, and we're late enough that stays won't be obsoleted by name resolution, * create one and attach it. */ @@ -698,7 +743,8 @@ private fun defineImpliedGetterOrSetter( defineImpliedMethod: DefineImpliedMethod, propDef: Pair, containingClassAsValue: Value, - plantPropertyType: ((Planting) -> Unit)?, + plantPropertyType: (Planting.() -> TreeTemplate<*>)?, + abstractness: Abstractness, isGetter: Boolean, ): Pair { val getterName = macroEnv.nameMaker.unusedSourceName( @@ -737,7 +783,7 @@ private fun defineImpliedGetterOrSetter( Decl(newValueName) { if (plantPropertyType != null) { V(typeSymbol) - plantPropertyType(this) + plantPropertyType() } } } @@ -751,30 +797,37 @@ private fun defineImpliedGetterOrSetter( } plantPropertyType != null -> { V(typeSymbol) - plantPropertyType(this) + plantPropertyType() } else -> {} } } Block { - if (newValueName != null) { // If a setter, set the property - check(!isGetter) - Call(BuiltinFuns.setpFn) { - Rn(propDef.second.name.content) - Rn(thisName) - Rn(newValueName) + when (abstractness) { + Abstractness.Abstract -> { + Call(BuiltinFuns.vPureVirtual) {} } - } - // Either way, the value of the property is what we return - Call(BuiltinFuns.setLocalFn) { - Ln(returnName) - if (isGetter) { - Call(BuiltinFuns.getpFn) { - Rn(propDef.second.name.content) - Rn(thisName) + Abstractness.Concrete -> { + if (newValueName != null) { // If a setter, set the property + check(!isGetter) + Call(BuiltinFuns.setpFn) { + Rn(propDef.second.name.content) + Rn(thisName) + Rn(newValueName) + } + } + // Either way, the value of the property is what we return + Call(BuiltinFuns.setLocalFn) { + Ln(returnName) + if (isGetter) { + Call(BuiltinFuns.getpFn) { + Rn(propDef.second.name.content) + Rn(thisName) + } + } else { + V(void) + } } - } else { - V(void) } } } diff --git a/frontend/src/commonTest/kotlin/lang/temper/frontend/CleanupTemporariesTest.kt b/frontend/src/commonTest/kotlin/lang/temper/frontend/CleanupTemporariesTest.kt index 34ea1b7a..751f14f9 100644 --- a/frontend/src/commonTest/kotlin/lang/temper/frontend/CleanupTemporariesTest.kt +++ b/frontend/src/commonTest/kotlin/lang/temper/frontend/CleanupTemporariesTest.kt @@ -1251,7 +1251,7 @@ class CleanupTemporariesTest { |// ```, | pseudoCodeAfter: ``` | let return__0; - | @visibility(\public) @stay @fromType(C__0) let p__0; + | @visibility(\public) @stay @fromType(C__0) let p__0: Boolean; | @visibility(\public) @fn @stay @fromType(C__0) let nym`set.p__1`; | nym`set.p__1` = (@stay fn nym`set.p`(@impliedThis(C__0) this__0: C__0, newValue__0 /* aka newValue */: Boolean) /* return__1 */: Void { | return__1 = void; @@ -1261,6 +1261,10 @@ class CleanupTemporariesTest { | constructor__0 = (@stay fn constructor(@impliedThis(C__0) this__1: C__0) /* return__2 */: Void { | return__2 = void | }); + | @fn @visibility(\public) @stay @fromType(C__0) let getp__0; + | getp__0 = fn (@impliedThis(C__0) this__2: C__0) /* return__3 */: Boolean { + | pureVirtual() + | }; | @typeDecl(C__0) @stay let C__0; | C__0 = type (C__0); | let c__0; diff --git a/frontend/src/commonTest/kotlin/lang/temper/frontend/DefineStageTest.kt b/frontend/src/commonTest/kotlin/lang/temper/frontend/DefineStageTest.kt index ca2e3186..979d99ec 100644 --- a/frontend/src/commonTest/kotlin/lang/temper/frontend/DefineStageTest.kt +++ b/frontend/src/commonTest/kotlin/lang/temper/frontend/DefineStageTest.kt @@ -90,11 +90,16 @@ class DefineStageTest { }); I__0 extends AnyValue; @property(\next) @stay @fromType(I__0) let next__7; + @getter @method(\next) @fn @visibility(\public) @stay @fromType(I__0) let getnext__0; + getnext__0 = fn (@impliedThis(I__0) this__0: I__0) /* return__0 */{ + pureVirtual() + }; @typeDecl(I__0) @stay let I__0; I__0 = type (I__0); @typeDecl(C__1) @stay let C__1; C__1 = type (C__1); interface(\word, \I, \concrete, false, @typeDefined(I__0) fn { + do {}; do {}; do {} }); @@ -166,6 +171,7 @@ class DefineStageTest { "C": { supers: ["I__0"], properties: [ + { name: "i__9", abstract: false, visibility: "private" }, { name: "next__12", abstract: true, @@ -173,7 +179,6 @@ class DefineStageTest { setter: "set.next__16", visibility: "public" }, - { name: "i__9", abstract: false, visibility: "private" }, ], methods: [ { name: "get.next__13", @@ -189,8 +194,12 @@ class DefineStageTest { abstract: true, supers: ["AnyValue__0"], properties: [ - { name: "next__7", abstract: true, visibility: "public" } + { name: "next__7", abstract: true, visibility: "public", getter: "getnext__0" } ], + methods: [ + { name: "getnext__0", + symbol: "next", open: true, visibility: "public", kind: "Getter" }, + ] }, "Void": { supers: [] }, "Console": "__DO_NOT_CARE__", @@ -733,6 +742,18 @@ class DefineStageTest { I__0 extends AnyValue; @property(\m) @stay @fromType(I__0) var m__7; @property(\p) @stay @fromType(I__0) let p__8; + @getter @method(\m) @fn @visibility(\public) @stay @fromType(I__0) let getm__0; + getm__0 = fn (@impliedThis(I__0) this__0: I__0) /* return__0 */{ + pureVirtual() + }; + @setter @method(\m) @fn @visibility(\public) @stay @fromType(I__0) let setm__0; + setm__0 = fn (@impliedThis(I__0) this__1: I__0, newM__0) /* return__1 */: Void { + pureVirtual() + }; + @getter @method(\p) @fn @visibility(\public) @stay @fromType(I__0) let getp__0; + getp__0 = fn (@impliedThis(I__0) this__2: I__0) /* return__2 */{ + pureVirtual() + }; @typeDecl(I__0) @stay let I__0; I__0 = type (I__0); @typeDecl(J__1) @stay let J__1; @@ -740,6 +761,9 @@ class DefineStageTest { @typeDecl(K__2) @stay let K__2; K__2 = type (K__2); interface(\word, \I, \concrete, false, @typeDefined(I__0) fn { + do {}; + do {}; + do {}; do {}; do {}; do {} @@ -747,10 +771,15 @@ class DefineStageTest { J__1 extends AnyValue; @property(\n) @visibility(\public) @stay @fromType(J__1) let n__10; @method(\n) @setter @fn @stay @fromType(J__1) let nym`set.n__11`; - nym`set.n__11` = (@stay fn nym`set.n`(@impliedThis(J__1) this__3: J__1) /* return__0 */: Void { + nym`set.n__11` = (@stay fn nym`set.n`(@impliedThis(J__1) this__3: J__1) /* return__11 */: Void { fn__12: do {} }); + @getter @method(\n) @fn @visibility(\public) @stay @fromType(J__1) let getn__0; + getn__0 = fn (@impliedThis(J__1) this__4: J__1) /* return__12 */{ + pureVirtual() + }; interface(\word, \J, \concrete, false, @typeDefined(J__1) fn { + do {}; do {}; do {}; do {} @@ -763,9 +792,29 @@ class DefineStageTest { @property(\p) @stay @fromType(K__2) let p__17; @property(\q) @stay @fromType(K__2) let q__18; @method(\o) @setter @fn @stay @fromType(K__2) let nym`set.o__19`; - nym`set.o__19` = (@stay fn nym`set.o`(@impliedThis(K__2) this__4: K__2) /* return__1 */: Void { + nym`set.o__19` = (@stay fn nym`set.o`(@impliedThis(K__2) this__14: K__2) /* return__15 */: Void { fn__20: do {} }); + @getter @method(\m) @fn @visibility(\public) @stay @fromType(K__2) let getm__1; + getm__1 = fn (@impliedThis(K__2) this__6: K__2) /* return__6 */{ + pureVirtual() + }; + @getter @method(\n) @fn @visibility(\public) @stay @fromType(K__2) let getn__1; + getn__1 = fn (@impliedThis(K__2) this__7: K__2) /* return__7 */{ + pureVirtual() + }; + @getter @method(\o) @fn @visibility(\public) @stay @fromType(K__2) let geto__0; + geto__0 = fn (@impliedThis(K__2) this__8: K__2) /* return__8 */{ + pureVirtual() + }; + @getter @method(\p) @fn @visibility(\public) @stay @fromType(K__2) let getp__1; + getp__1 = fn (@impliedThis(K__2) this__9: K__2) /* return__9 */{ + pureVirtual() + }; + @getter @method(\q) @fn @visibility(\public) @stay @fromType(K__2) let getq__0; + getq__0 = fn (@impliedThis(K__2) this__10: K__2) /* return__10 */{ + pureVirtual() + }; interface(\word, \K, \concrete, false, @typeDefined(K__2) fn { do {}; do {}; @@ -774,6 +823,11 @@ class DefineStageTest { do {}; do {}; do {}; + do {}; + do {}; + do {}; + do {}; + do {}; do {} }); type (K__2) @@ -1208,10 +1262,15 @@ class DefineStageTest { | ``` | I__0 extends AnyValue; | @property(\p) @visibility(\public) @stay @fromType(I__0) let p__3; + | @getter @method(\p) @fn @visibility(\public) @stay @fromType(I__0) let getp__0; + | getp__0 = fn (@impliedThis(I__0) this__0: I__0) /* return__0 */{ + | pureVirtual() + | }; | @typeDecl(I__0) @stay let I__0; | I__0 = type (I__0); | interface(\word, \I, \concrete, false, @typeDefined(I__0) fn { | do {}; + | do {}; | do {} | }); | type (I__0) @@ -2680,7 +2739,7 @@ class DefineStageTest { | T__0 = type (T__0); | I__0 extends AnyValue; | @property(\x) @visibility(\public) @QName("test-code.type I.x") @stay @fromType(I__0) let x__3: T__0; - | @property(\y) @visibility(\public) @QName("test-code.type I.y") @stay @fromType(I__0) let y__1; + | @property(\y) @visibility(\public) @stay @fromType(I__0) @QName("test-code.type I.y") let y__1: Int32; | @method(\y) @getter @visibility(\public) @fn @QName("test-code.type I.get y()") @stay @fromType(I__0) let nym`get.y__2`; | nym`get.y__2` = fn nym`get.y`(@impliedThis(I__0) @QName("test-code.type I.get y().(this)") this__0: I__0) /* return__2 */: Int32 { | fn__2: do { @@ -2706,6 +2765,10 @@ class DefineStageTest { | fn__5: do {} | }); | void; + | @getter @method(\x) @fn @visibility(\public) @stay @fromType(I__0) @QName("test-code.type I.get x()") let getx__0; + | getx__0 = fn (@impliedThis(I__0) @QName("test-code.type I.get x().(this)") this__3: I__0) /* return__6 */: T__0 { + | pureVirtual() + | }; | interface(\word, \I, \concrete, false, @typeDefined(I__0) fn { | do {}; | do {}; @@ -2717,6 +2780,7 @@ class DefineStageTest { | do {}; | do {}; | do {}; + | do {}; | do {} | }); | type (I__0) diff --git a/frontend/src/commonTest/kotlin/lang/temper/frontend/GenerateCodeStageTest.kt b/frontend/src/commonTest/kotlin/lang/temper/frontend/GenerateCodeStageTest.kt index f865e4d9..be2e229b 100644 --- a/frontend/src/commonTest/kotlin/lang/temper/frontend/GenerateCodeStageTest.kt +++ b/frontend/src/commonTest/kotlin/lang/temper/frontend/GenerateCodeStageTest.kt @@ -318,11 +318,15 @@ class GenerateCodeStageTest { | nym`get.superGetter__1` = (@stay fn nym`get.superGetter`(@impliedThis(I) this__0: I) /* return__0 */: Int32 { | return__0 = 10 | }); - | @visibility(\public) @stay @fromType(I) let superSetter__0; + | @visibility(\public) @stay @fromType(I) let superSetter__0: Int32; | @visibility(\public) @fn @stay @fromType(I) let nym`set.superSetter__1`; | nym`set.superSetter__1` = (@stay fn nym`set.superSetter`(@impliedThis(I) this__1: I, i__0 /* aka i */: Int32) /* return__1 */: Void { | return__1 = void | }); + | @fn @visibility(\public) @stay @fromType(I) let getsuperSetter__0; + | getsuperSetter__0 = (@stay fn (@impliedThis(I) this__17: I) /* return__12 */: Int32 { + | pureVirtual() + | }); | @visibility(\public) @stay @fromType(C) let propNotVar__0: Int32; | @visibility(\public) @stay @fromType(C) var propVar__0: Int32; | @visibility(\public) @fn @stay @fromType(C) let constructor__0; @@ -350,7 +354,7 @@ class GenerateCodeStageTest { | setp(propVar__0, this__3, "hi"); | return__3 = void | }); - | @visibility(\public) @stay @fromType(C) let extraSetter__0; + | @visibility(\public) @stay @fromType(C) let extraSetter__0: Int32; | @visibility(\public) @fn @stay @fromType(C) let nym`set.extraSetter__1`; | nym`set.extraSetter__1` = (@stay fn nym`set.extraSetter`(@impliedThis(C) this__4: C, k__0 /* aka k */: Int32) /* return__4 */: Void { | setp(propVar__0, this__4, k__0); @@ -374,6 +378,10 @@ class GenerateCodeStageTest { | setp(propVar__0, this__8, newPropVar__0); | return__8 = void | }); + | @fn @visibility(\public) @stay @fromType(C) let getextraSetter__0; + | getextraSetter__0 = (@stay fn (@impliedThis(C) this__20: C) /* return__20 */: Int32 { + | pureVirtual() + | }); | `test//`.alsoUpdate = (@stay fn alsoUpdate(c__0 /* aka c */: C, j__0 /* aka j */: Int32) /* return__9 */: Void { | var t#5, t#6, t#7, t#8; | let t#9; @@ -401,8 +409,6 @@ class GenerateCodeStageTest { | }, | errors: [ | "No member wrong in C | I!", - | "Wrong number of arguments. Expected 2!", - | "Expected subtype of Type, but got C!", | "Member extraGetter defined in C | I incompatible with usage!", | "Member superGetter defined in C | I incompatible with usage!", | "Member propNotVar defined in C incompatible with usage!", @@ -411,6 +417,8 @@ class GenerateCodeStageTest { | "Expected subtype of Int32, but got String!", | "Member extraGetter defined in C | I incompatible with usage!", | "No member extraWrong in C | I!", + | "Type C must implement get extraSetter from C. Maybe add `public get extraSetter(): Int32`!", + | "Type C must implement get superSetter from I. Maybe add `public get superSetter(): Int32`!" | ], |} """.trimMargin(), @@ -985,7 +993,7 @@ class GenerateCodeStageTest { | body: ``` | let return__0, console#0; | console#0 = getConsole(); - | @property(\p) @visibility(\public) @stay @fromType(C__0) let p__0; + | @property(\p) @visibility(\public) @stay @fromType(C__0) let p__0: Int32; | @method(\p) @setter @visibility(\public) @fn @stay @fromType(C__0) let nym`set.p__1`; | nym`set.p__1` = (@stay fn nym`set.p`(@impliedThis(C__0) this__0: C__0, newValue__0 /* aka newValue */: Int32) /* return__1 */: Void { | var t#0; @@ -997,6 +1005,12 @@ class GenerateCodeStageTest { | constructor__0 = (@stay fn constructor(@impliedThis(C__0) this__1: C__0) /* return__2 */: Void { | return__2 = void | }); + | @getter @method(\p) @fn @visibility(\public) @stay @fromType(C__0) let getp__0; + | getp__0 = (@stay fn (@impliedThis(C__0) this__2: C__0) /* return__3 */: Int32 { + |## TODO: This pureVirtual occurs in a concrete method, so should be flagged as a failure + |## to implement. Set-only properties are not translatable so we insist on a getter. + | pureVirtual() + | }); | @typeDecl(C__0) @stay let C__0; | C__0 = type (C__0); | let c__0; @@ -1008,7 +1022,7 @@ class GenerateCodeStageTest { | ``` | } |} - """.trimMargin(), + """.trimMargin().stripDoubleHashCommentLinesToPutCommentsInlineBelow(), moduleResultNeeded = true, ) { module, _ -> val input = $$""" @@ -1176,15 +1190,19 @@ class GenerateCodeStageTest { | body: ``` | let return__0; | @property(\x) @visibility(\public) @stay @fromType(I__0) let x__0: Int32; + | @getter @method(\x) @fn @visibility(\public) @stay @fromType(I__0) let getx__0; + | getx__0 = (@stay fn (@impliedThis(I__0) this__0: I__0) /* return__1 */: Int32 { + | pureVirtual() + | }); | @typeDecl(I__0) @stay let I__0; | I__0 = type (I__0); | @typeDecl(C__0) @stay let C__0; | C__0 = type (C__0); | @constructorProperty @property(\x) @visibility(\protected) @stay @fromType(C__0) let x__1: Int32; | @fn @method(\constructor) @visibility(\public) @stay @fromType(C__0) let constructor__0; - | constructor__0 = (@stay fn constructor(@impliedThis(C__0) this__0: C__0, x__2 /* aka x */: Int32) /* return__1 */: Void { - | setp(x__1, this__0, x__2); - | return__1 = void + | constructor__0 = (@stay fn constructor(@impliedThis(C__0) this__1: C__0, x__2 /* aka x */: Int32) /* return__2 */: Void { + | setp(x__1, this__1, x__2); + | return__2 = void | }); | return__0 = type (C__0) | @@ -1358,7 +1376,7 @@ class GenerateCodeStageTest { | constructor__0 = (@stay fn constructor(@impliedThis(Something__0) this__0: Something__0) /* return__0 */: Void { | return__0 = void | }); - | @property(\blah) @visibility(\public) @stay @fromType(Something__0) @reach(\none) let blah__0; + | @property(\blah) @visibility(\public) @stay @fromType(Something__0) @reach(\none) let blah__0: Int32; | @method(\blah) @getter @visibility(\public) @fn @stay @fromType(Something__0) @reach(\none) let nym`get.blah__1`; | nym`get.blah__1` = (@stay fn nym`get.blah`(@impliedThis(Something__0) this__1: Something__0) /* return__1 */{ | return__1 = 5 diff --git a/frontend/src/commonTest/kotlin/lang/temper/frontend/SyntaxMacroStageTest.kt b/frontend/src/commonTest/kotlin/lang/temper/frontend/SyntaxMacroStageTest.kt index 6c0f2503..1d1a9c59 100644 --- a/frontend/src/commonTest/kotlin/lang/temper/frontend/SyntaxMacroStageTest.kt +++ b/frontend/src/commonTest/kotlin/lang/temper/frontend/SyntaxMacroStageTest.kt @@ -1887,7 +1887,6 @@ class SyntaxMacroStageTest { | @typeDecl(C__0) @stay let C__0 = type (C__0); | class(\word, \C, \concrete, true, @typeDefined(C__0) fn { | C__0 extends AnyValue; - | @property(\x) @visibility(\public) let x__0; | REM("Returns 1", true, false); | @method(\x) @getter @visibility(\public) @fn let nym`get.x__1` = (@docString(...) fn nym`get.x`(@impliedThis(C__0) this__0: C__0) /* return__0 */: (Int) { | fn__0: do { diff --git a/log/src/commonMain/kotlin/lang/temper/log/Debug.kt b/log/src/commonMain/kotlin/lang/temper/log/Debug.kt index 1a3ad78c..959e7e64 100644 --- a/log/src/commonMain/kotlin/lang/temper/log/Debug.kt +++ b/log/src/commonMain/kotlin/lang/temper/log/Debug.kt @@ -51,7 +51,7 @@ object Debug : LogConfigurations("*", null, listOf("frontend", "backend", "docge object AfterInterpretation : LogConfigurations("frontend.syntaxMacroStage.afterInterpretation", "frontend.syntaxMacroStage", listOf()) object After : LogConfigurations("frontend.syntaxMacroStage.after", "frontend.syntaxMacroStage", listOf()) } - object DefineStage : LogConfigurations("frontend.defineStage", "frontend", listOf("frontend.defineStage.before", "frontend.defineStage.afterInterpretation", "frontend.defineStage.afterInheritPropertyReassignability", "frontend.defineStage.desugarDotOperations", "frontend.defineStage.afterDesugarDotOperations", "frontend.defineStage.linkThis", "frontend.defineStage.afterLinkThis", "frontend.defineStage.convertClasses", "frontend.defineStage.afterConvertClasses", "frontend.defineStage.afterAddTemperTestInstructions", "frontend.defineStage.simplifyDeclarations", "frontend.defineStage.afterSimplifyDeclarations", "frontend.defineStage.convertObjectSyntax", "frontend.defineStage.after")) { + object DefineStage : LogConfigurations("frontend.defineStage", "frontend", listOf("frontend.defineStage.before", "frontend.defineStage.afterInterpretation", "frontend.defineStage.afterInheritPropertyReassignability", "frontend.defineStage.desugarDotOperations", "frontend.defineStage.afterDesugarDotOperations", "frontend.defineStage.linkThis", "frontend.defineStage.afterLinkThis", "frontend.defineStage.convertClasses", "frontend.defineStage.afterConvertClasses", "frontend.defineStage.afterAddTemperTestInstructions", "frontend.defineStage.fillInMissingQNames", "frontend.defineStage.afterFillInMissingQNames", "frontend.defineStage.simplifyDeclarations", "frontend.defineStage.afterSimplifyDeclarations", "frontend.defineStage.convertObjectSyntax", "frontend.defineStage.after")) { object Before : LogConfigurations("frontend.defineStage.before", "frontend.defineStage", listOf()) object AfterInterpretation : LogConfigurations("frontend.defineStage.afterInterpretation", "frontend.defineStage", listOf()) object AfterInheritPropertyReassignability : LogConfigurations("frontend.defineStage.afterInheritPropertyReassignability", "frontend.defineStage", listOf()) @@ -62,6 +62,8 @@ object Debug : LogConfigurations("*", null, listOf("frontend", "backend", "docge object ConvertClasses : LogConfigurations("frontend.defineStage.convertClasses", "frontend.defineStage", listOf()) object AfterConvertClasses : LogConfigurations("frontend.defineStage.afterConvertClasses", "frontend.defineStage", listOf()) object AfterAddTemperTestInstructions : LogConfigurations("frontend.defineStage.afterAddTemperTestInstructions", "frontend.defineStage", listOf()) + object FillInMissingQNames : LogConfigurations("frontend.defineStage.fillInMissingQNames", "frontend.defineStage", listOf()) + object AfterFillInMissingQNames : LogConfigurations("frontend.defineStage.afterFillInMissingQNames", "frontend.defineStage", listOf()) object SimplifyDeclarations : LogConfigurations("frontend.defineStage.simplifyDeclarations", "frontend.defineStage", listOf()) object AfterSimplifyDeclarations : LogConfigurations("frontend.defineStage.afterSimplifyDeclarations", "frontend.defineStage", listOf()) object ConvertObjectSyntax : LogConfigurations("frontend.defineStage.convertObjectSyntax", "frontend.defineStage", listOf()) @@ -162,6 +164,8 @@ val logConfigurationsByName: Map = mapOf( "frontend.defineStage.convertClasses" to Debug.Frontend.DefineStage.ConvertClasses, "frontend.defineStage.afterConvertClasses" to Debug.Frontend.DefineStage.AfterConvertClasses, "frontend.defineStage.afterAddTemperTestInstructions" to Debug.Frontend.DefineStage.AfterAddTemperTestInstructions, + "frontend.defineStage.fillInMissingQNames" to Debug.Frontend.DefineStage.FillInMissingQNames, + "frontend.defineStage.afterFillInMissingQNames" to Debug.Frontend.DefineStage.AfterFillInMissingQNames, "frontend.defineStage.simplifyDeclarations" to Debug.Frontend.DefineStage.SimplifyDeclarations, "frontend.defineStage.afterSimplifyDeclarations" to Debug.Frontend.DefineStage.AfterSimplifyDeclarations, "frontend.defineStage.convertObjectSyntax" to Debug.Frontend.DefineStage.ConvertObjectSyntax, diff --git a/log/src/commonMain/kotlin/lang/temper/log/logger-names.json b/log/src/commonMain/kotlin/lang/temper/log/logger-names.json index fd3e9dee..6104760d 100644 --- a/log/src/commonMain/kotlin/lang/temper/log/logger-names.json +++ b/log/src/commonMain/kotlin/lang/temper/log/logger-names.json @@ -48,6 +48,8 @@ "frontend.defineStage.convertClasses", "frontend.defineStage.afterConvertClasses", "frontend.defineStage.afterAddTemperTestInstructions", + "frontend.defineStage.fillInMissingQNames", + "frontend.defineStage.afterFillInMissingQNames", "frontend.defineStage.simplifyDeclarations", "frontend.defineStage.afterSimplifyDeclarations", "frontend.defineStage.convertObjectSyntax",