Skip to content

Commit 49d9e4e

Browse files
Automated commit of generated code
1 parent 13ff0c5 commit 49d9e4e

File tree

10 files changed

+142
-57
lines changed

10 files changed

+142
-57
lines changed

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/cast.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,5 @@ public fun <C> TransformableColumnSet<*>.cast(): TransformableColumnSet<C> = thi
9999
public fun <C> TransformableSingleColumn<*>.cast(): TransformableSingleColumn<C> = this as TransformableSingleColumn<C>
100100

101101
public fun <C> ColumnReference<*>.cast(): ColumnReference<C> = this as ColumnReference<C>
102+
103+
public fun <T, G> GroupBy<*, *>.cast(): GroupBy<T, G> = this as GroupBy<T, G>

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/CodeGenerator.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public enum class InterfaceGenerationMode {
1515
None,
1616
}
1717

18-
public data class CodeGenResult(val code: CodeWithConverter, val newMarkers: List<Marker>)
18+
public data class CodeGenResult(val code: CodeWithTypeCastGenerator, val newMarkers: List<Marker>)
1919

2020
public interface CodeGenerator : ExtensionsCodeGenerator {
2121

@@ -37,7 +37,7 @@ public interface CodeGenerator : ExtensionsCodeGenerator {
3737
interfaceMode: InterfaceGenerationMode,
3838
extensionProperties: Boolean,
3939
readDfMethod: DefaultReadDfMethod? = null,
40-
): CodeWithConverter
40+
): CodeWithTypeCastGenerator
4141

4242
public companion object {
4343
public fun create(useFqNames: Boolean = true): CodeGenerator =
@@ -54,7 +54,7 @@ internal fun CodeGenerator.generate(
5454
markerClass: KClass<*>,
5555
interfaceMode: InterfaceGenerationMode,
5656
extensionProperties: Boolean,
57-
): CodeWithConverter =
57+
): CodeWithTypeCastGenerator =
5858
generate(
5959
MarkersExtractor.get(markerClass),
6060
interfaceMode,
@@ -64,4 +64,4 @@ internal fun CodeGenerator.generate(
6464
public inline fun <reified T> CodeGenerator.generate(
6565
interfaceMode: InterfaceGenerationMode,
6666
extensionProperties: Boolean,
67-
): CodeWithConverter = generate(T::class, interfaceMode, extensionProperties)
67+
): CodeWithTypeCastGenerator = generate(T::class, interfaceMode, extensionProperties)

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/CodeWithConverter.kt

Lines changed: 0 additions & 30 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package org.jetbrains.kotlinx.dataframe.codeGen
2+
3+
import org.jetbrains.kotlinx.dataframe.api.cast
4+
5+
/**
6+
* Class representing generated code declarations for a [Marker].
7+
*
8+
* @param declarations The generated code.
9+
* @param typeCastGenerator Optional [TypeCastGenerator] for the [Marker], see [TypeCastGenerator] for
10+
* more information.
11+
*/
12+
public data class CodeWithTypeCastGenerator(
13+
val declarations: Code,
14+
val typeCastGenerator: TypeCastGenerator = TypeCastGenerator.Empty,
15+
) {
16+
17+
public companion object {
18+
public const val EMPTY_DECLARATIONS: Code = ""
19+
20+
@Deprecated("", ReplaceWith("TypeCastGenerator.Empty"))
21+
public val EMPTY_CONVERTER: (Expression) -> Code = { it }
22+
public val EMPTY: CodeWithTypeCastGenerator = CodeWithTypeCastGenerator(EMPTY_DECLARATIONS)
23+
}
24+
25+
val hasDeclarations: Boolean get() = declarations.isNotBlank()
26+
27+
val hasCaster: Boolean
28+
get() = typeCastGenerator !is TypeCastGenerator.Empty &&
29+
typeCastGenerator("it").trim() != "it"
30+
31+
public fun declarationsWithCastExpression(expression: Expression): Code =
32+
when {
33+
!hasCaster -> declarations
34+
!hasDeclarations -> typeCastGenerator(expression)
35+
else -> declarations + "\n" + typeCastGenerator(expression)
36+
}
37+
}
38+
39+
public typealias Code = String
40+
public typealias Expression = String
41+
42+
/**
43+
* A [TypeCastGenerator] can generate [Code] given an [Expression] that casts or converts
44+
* it to a predefined target type.
45+
*
46+
* To create a [TypeCastGenerator] that, for instance, casts everything you pass to [Any?][Any]:
47+
* ```kt
48+
* val myCastGenerator = TypeCastGenerator { expression -> "($expression as Any?)" }
49+
*
50+
* myCastGenerator.addCastTo("myVariable") == "(myVariable as Any?)"
51+
* ```
52+
*
53+
* @see TypeCastGenerator.Empty
54+
* @see TypeCastGenerator.DataFrameApi
55+
*/
56+
public fun interface TypeCastGenerator {
57+
public fun addCastTo(expression: Expression): Code
58+
59+
public operator fun invoke(expression: Expression): Code = addCastTo(expression)
60+
61+
public object Empty : TypeCastGenerator by (TypeCastGenerator { it })
62+
63+
/**
64+
* [TypeCastGenerator] that uses the [cast] functions of the DataFrame API.
65+
*
66+
* NOTE: This generator assumes there's a `.cast<>()` function available that can be called on your
67+
* specific [Expression]. It will cause runtime errors when there isn't one.
68+
*/
69+
public class DataFrameApi private constructor(public val types: Array<out String>) : TypeCastGenerator {
70+
override fun addCastTo(expression: Expression): Code =
71+
if (types.isEmpty()) {
72+
"$expression.cast()"
73+
} else {
74+
"$expression.cast<${types.joinToString()}>()"
75+
}
76+
77+
public companion object {
78+
public operator fun invoke(vararg types: String): TypeCastGenerator = DataFrameApi(types)
79+
}
80+
}
81+
}

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/ExtensionsCodeGenerator.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import org.jetbrains.kotlinx.dataframe.impl.codeGen.ExtensionsCodeGeneratorImpl
44
import org.jetbrains.kotlinx.dataframe.impl.codeGen.ShortNames
55

66
public interface ExtensionsCodeGenerator {
7-
public fun generate(marker: IsolatedMarker): CodeWithConverter
7+
public fun generate(marker: IsolatedMarker): CodeWithTypeCastGenerator
88

99
public companion object {
1010
public fun create(): ExtensionsCodeGenerator = ExtensionsCodeGeneratorImpl(ShortNames)

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/codeGen/CodeGeneratorImpl.kt

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ import org.jetbrains.kotlinx.dataframe.DataRow
99
import org.jetbrains.kotlinx.dataframe.annotations.DataSchema
1010
import org.jetbrains.kotlinx.dataframe.api.ColumnSelectionDsl
1111
import org.jetbrains.kotlinx.dataframe.api.DataSchemaEnum
12+
import org.jetbrains.kotlinx.dataframe.api.cast
1213
import org.jetbrains.kotlinx.dataframe.codeGen.BaseField
1314
import org.jetbrains.kotlinx.dataframe.codeGen.Code
1415
import org.jetbrains.kotlinx.dataframe.codeGen.CodeGenResult
1516
import org.jetbrains.kotlinx.dataframe.codeGen.CodeGenerator
16-
import org.jetbrains.kotlinx.dataframe.codeGen.CodeWithConverter
17+
import org.jetbrains.kotlinx.dataframe.codeGen.CodeWithTypeCastGenerator
1718
import org.jetbrains.kotlinx.dataframe.codeGen.DefaultReadDfMethod
1819
import org.jetbrains.kotlinx.dataframe.codeGen.ExtensionsCodeGenerator
1920
import org.jetbrains.kotlinx.dataframe.codeGen.FieldType
@@ -28,6 +29,7 @@ import org.jetbrains.kotlinx.dataframe.codeGen.Marker
2829
import org.jetbrains.kotlinx.dataframe.codeGen.MarkerVisibility
2930
import org.jetbrains.kotlinx.dataframe.codeGen.NameNormalizer
3031
import org.jetbrains.kotlinx.dataframe.codeGen.SchemaProcessor
32+
import org.jetbrains.kotlinx.dataframe.codeGen.TypeCastGenerator
3133
import org.jetbrains.kotlinx.dataframe.codeGen.ValidFieldName
3234
import org.jetbrains.kotlinx.dataframe.codeGen.toNullable
3335
import org.jetbrains.kotlinx.dataframe.columns.ColumnGroup
@@ -44,8 +46,12 @@ internal fun Iterable<Marker>.filterRequiredForSchema(schema: DataFrameSchema) =
4446

4547
internal val charsToQuote = """[ `(){}\[\].<>'"/|\\!?@:;%^&*#$-]""".toRegex()
4648

47-
internal fun createCodeWithConverter(code: String, markerName: String) =
48-
CodeWithConverter(code) { "$it.cast<$markerName>()" }
49+
/**
50+
* Simple utility function that creates a [CodeWithTypeCastGenerator] using [code] and [TypeCastGenerator.DataFrameApi],
51+
* meaning it uses the [cast] functions of DataFrame.
52+
*/
53+
internal fun createCodeWithTypeCastGenerator(code: String, vararg targetTypeNames: String) =
54+
CodeWithTypeCastGenerator(code, TypeCastGenerator.DataFrameApi(*targetTypeNames))
4955

5056
private val letterCategories = setOf(
5157
CharCategory.UPPERCASE_LETTER,
@@ -365,9 +371,9 @@ internal open class ExtensionsCodeGeneratorImpl(private val typeRendering: TypeR
365371
return declarations.joinToString("\n")
366372
}
367373

368-
override fun generate(marker: IsolatedMarker): CodeWithConverter {
374+
override fun generate(marker: IsolatedMarker): CodeWithTypeCastGenerator {
369375
val code = generateExtensionProperties(marker)
370-
return createCodeWithConverter(code, marker.name)
376+
return createCodeWithTypeCastGenerator(code, marker.name)
371377
}
372378

373379
protected fun renderTopLevelDeclarationVisibility(marker: IsolatedMarker) =
@@ -393,7 +399,7 @@ internal class CodeGeneratorImpl(typeRendering: TypeRenderingStrategy = FullyQua
393399
interfaceMode: InterfaceGenerationMode,
394400
extensionProperties: Boolean,
395401
readDfMethod: DefaultReadDfMethod?,
396-
): CodeWithConverter {
402+
): CodeWithTypeCastGenerator {
397403
val code = when (interfaceMode) {
398404
NoFields, WithFields ->
399405
generateInterface(
@@ -409,7 +415,7 @@ internal class CodeGeneratorImpl(typeRendering: TypeRenderingStrategy = FullyQua
409415
None -> if (extensionProperties) generateExtensionProperties(marker) else ""
410416
}
411417

412-
return createCodeWithConverter(code, marker.name)
418+
return createCodeWithTypeCastGenerator(code, marker.name)
413419
}
414420

415421
private fun generateTypeAlias(marker: Marker): Code {
@@ -479,7 +485,7 @@ internal class CodeGeneratorImpl(typeRendering: TypeRenderingStrategy = FullyQua
479485
declarations.add(generateExtensionProperties(itMarker, withNullable = false))
480486
}
481487
}
482-
val code = createCodeWithConverter(declarations.joinToString("\n\n"), marker.name)
488+
val code = createCodeWithTypeCastGenerator(declarations.joinToString("\n\n"), marker.name)
483489
return CodeGenResult(code, context.generatedMarkers)
484490
}
485491

@@ -558,7 +564,7 @@ internal class CodeGeneratorImpl(typeRendering: TypeRenderingStrategy = FullyQua
558564
}
559565
}
560566

561-
public fun CodeWithConverter.toStandaloneSnippet(packageName: String, additionalImports: List<String>): String =
567+
public fun CodeWithTypeCastGenerator.toStandaloneSnippet(packageName: String, additionalImports: List<String>): String =
562568
declarations.toStandaloneSnippet(packageName, additionalImports)
563569

564570
public fun Code.toStandaloneSnippet(packageName: String, additionalImports: List<String>): String =

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/codeGen/ReplCodeGenerator.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,19 @@ package org.jetbrains.kotlinx.dataframe.impl.codeGen
22

33
import org.jetbrains.kotlinx.dataframe.AnyFrame
44
import org.jetbrains.kotlinx.dataframe.AnyRow
5+
import org.jetbrains.kotlinx.dataframe.api.GroupBy
56
import org.jetbrains.kotlinx.dataframe.codeGen.Code
6-
import org.jetbrains.kotlinx.dataframe.codeGen.CodeWithConverter
7+
import org.jetbrains.kotlinx.dataframe.codeGen.CodeWithTypeCastGenerator
78
import kotlin.reflect.KClass
89
import kotlin.reflect.KProperty
910

1011
internal interface ReplCodeGenerator {
1112

12-
fun process(df: AnyFrame, property: KProperty<*>? = null): CodeWithConverter
13+
fun process(df: AnyFrame, property: KProperty<*>? = null): CodeWithTypeCastGenerator
1314

14-
fun process(row: AnyRow, property: KProperty<*>? = null): CodeWithConverter
15+
fun process(row: AnyRow, property: KProperty<*>? = null): CodeWithTypeCastGenerator
16+
17+
fun process(groupBy: GroupBy<*, *>): CodeWithTypeCastGenerator
1518

1619
fun process(markerClass: KClass<*>): Code
1720

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/codeGen/ReplCodeGeneratorImpl.kt

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@ import org.jetbrains.kotlinx.dataframe.AnyRow
55
import org.jetbrains.kotlinx.dataframe.DataFrame
66
import org.jetbrains.kotlinx.dataframe.DataRow
77
import org.jetbrains.kotlinx.dataframe.annotations.DataSchema
8+
import org.jetbrains.kotlinx.dataframe.api.GroupBy
89
import org.jetbrains.kotlinx.dataframe.api.schema
910
import org.jetbrains.kotlinx.dataframe.codeGen.Code
1011
import org.jetbrains.kotlinx.dataframe.codeGen.CodeGenerator
11-
import org.jetbrains.kotlinx.dataframe.codeGen.CodeWithConverter
12+
import org.jetbrains.kotlinx.dataframe.codeGen.CodeWithTypeCastGenerator
1213
import org.jetbrains.kotlinx.dataframe.codeGen.InterfaceGenerationMode
1314
import org.jetbrains.kotlinx.dataframe.codeGen.Marker
1415
import org.jetbrains.kotlinx.dataframe.codeGen.MarkerVisibility
1516
import org.jetbrains.kotlinx.dataframe.codeGen.MarkersExtractor
17+
import org.jetbrains.kotlinx.dataframe.codeGen.TypeCastGenerator
1618
import org.jetbrains.kotlinx.dataframe.schema.DataFrameSchema
1719
import kotlin.reflect.KClass
1820
import kotlin.reflect.KProperty
@@ -43,9 +45,9 @@ internal class ReplCodeGeneratorImpl : ReplCodeGenerator {
4345
else -> null
4446
}
4547

46-
override fun process(row: AnyRow, property: KProperty<*>?): CodeWithConverter = process(row.df(), property)
48+
override fun process(row: AnyRow, property: KProperty<*>?): CodeWithTypeCastGenerator = process(row.df(), property)
4749

48-
override fun process(df: AnyFrame, property: KProperty<*>?): CodeWithConverter {
50+
override fun process(df: AnyFrame, property: KProperty<*>?): CodeWithTypeCastGenerator {
4951
var targetSchema = df.schema()
5052

5153
if (property != null) {
@@ -65,7 +67,7 @@ internal class ReplCodeGeneratorImpl : ReplCodeGenerator {
6567
// property scheme is valid for current data frame, but we should also check that all compatible open markers are implemented by it
6668
val requiredBaseMarkers = registeredMarkers.values.filterRequiredForSchema(columnSchema)
6769
if (requiredBaseMarkers.any() && requiredBaseMarkers.all { currentMarker.implements(it) }) {
68-
return CodeWithConverter.EMPTY
70+
return CodeWithTypeCastGenerator.EMPTY
6971
}
7072
// use current marker scheme as a target for generation of new marker interface, so that available properties won't change
7173
targetSchema = columnSchema
@@ -77,7 +79,28 @@ internal class ReplCodeGeneratorImpl : ReplCodeGenerator {
7779
return generate(schema = targetSchema, name = markerInterfacePrefix, isOpen = true)
7880
}
7981

80-
fun generate(schema: DataFrameSchema, name: String, isOpen: Boolean): CodeWithConverter {
82+
override fun process(groupBy: GroupBy<*, *>): CodeWithTypeCastGenerator {
83+
val key = generate(
84+
schema = groupBy.keys.schema(),
85+
name = markerInterfacePrefix + "Keys",
86+
isOpen = false,
87+
)
88+
val group = generate(
89+
schema = groupBy.groups.schema.value,
90+
name = markerInterfacePrefix + "Groups",
91+
isOpen = false,
92+
)
93+
94+
val keyTypeName = (key.typeCastGenerator as TypeCastGenerator.DataFrameApi).types.single()
95+
val groupTypeName = (group.typeCastGenerator as TypeCastGenerator.DataFrameApi).types.single()
96+
97+
return CodeWithTypeCastGenerator(
98+
declarations = key.declarations + "\n" + group.declarations,
99+
typeCastGenerator = TypeCastGenerator.DataFrameApi(keyTypeName, groupTypeName),
100+
)
101+
}
102+
103+
fun generate(schema: DataFrameSchema, name: String, isOpen: Boolean): CodeWithTypeCastGenerator {
81104
val result = generator.generate(
82105
schema = schema,
83106
name = name,

core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/CodeGenerationTests.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,11 @@ class CodeGenerationTests : BaseTest() {
115115
val expectedConverter = "it.cast<$typeName>()"
116116

117117
generated.declarations shouldBe expectedDeclaration
118-
generated.converter("it") shouldBe expectedConverter
118+
generated.typeCastGenerator("it") shouldBe expectedConverter
119119

120120
val rowGenerated = codeGen.process(df[0], ::typedRow)
121121
rowGenerated.hasDeclarations shouldBe true
122-
rowGenerated.hasConverter shouldBe true
122+
rowGenerated.hasCaster shouldBe true
123123
}
124124

125125
val row: AnyRow? = null
@@ -146,7 +146,7 @@ class CodeGenerationTests : BaseTest() {
146146
val expectedConverter = "it.cast<$typeName>()"
147147

148148
generated.declarations shouldBe expectedDeclaration
149-
generated.converter("it") shouldBe expectedConverter
149+
generated.typeCastGenerator("it") shouldBe expectedConverter
150150
}
151151

152152
@Test
@@ -191,7 +191,7 @@ class CodeGenerationTests : BaseTest() {
191191
val expectedConverter = "it.cast<$type2>()"
192192

193193
generated.declarations shouldBe declaration1 + "\n" + declaration2
194-
generated.converter("it") shouldBe expectedConverter
194+
generated.typeCastGenerator("it") shouldBe expectedConverter
195195
}
196196

197197
@Test

core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/MatchSchemeTests.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ class MatchSchemeTests {
8989
fun `marker is reused`() {
9090
val codeGen = ReplCodeGenerator.create()
9191
codeGen.process(DataRecord::class)
92-
codeGen.process(typed, ::typed).hasConverter shouldBe false
92+
codeGen.process(typed, ::typed).hasCaster shouldBe false
9393
val generated = codeGen.process(df, ::df)
9494
generated.declarations.split("\n").size shouldBe 1
9595
}

0 commit comments

Comments
 (0)