diff --git a/core/api/core.api b/core/api/core.api index df69027a41..a802ba2219 100644 --- a/core/api/core.api +++ b/core/api/core.api @@ -673,6 +673,7 @@ public final class org/jetbrains/kotlinx/dataframe/api/CastKt { public static final fun cast (Lorg/jetbrains/kotlinx/dataframe/DataColumn;)Lorg/jetbrains/kotlinx/dataframe/DataColumn; public static final fun cast (Lorg/jetbrains/kotlinx/dataframe/DataFrame;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static final fun cast (Lorg/jetbrains/kotlinx/dataframe/DataRow;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun cast (Lorg/jetbrains/kotlinx/dataframe/api/GroupBy;)Lorg/jetbrains/kotlinx/dataframe/api/GroupBy; public static final fun cast (Lorg/jetbrains/kotlinx/dataframe/columns/ColumnAccessor;)Lorg/jetbrains/kotlinx/dataframe/columns/ColumnAccessor; public static final fun cast (Lorg/jetbrains/kotlinx/dataframe/columns/ColumnGroup;)Lorg/jetbrains/kotlinx/dataframe/columns/ColumnGroup; public static final fun cast (Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference; @@ -4770,13 +4771,13 @@ public abstract interface class org/jetbrains/kotlinx/dataframe/codeGen/BaseFiel } public final class org/jetbrains/kotlinx/dataframe/codeGen/CodeGenResult { - public fun (Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithConverter;Ljava/util/List;)V - public final fun component1 ()Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithConverter; + public fun (Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithTypeCastGenerator;Ljava/util/List;)V + public final fun component1 ()Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithTypeCastGenerator; public final fun component2 ()Ljava/util/List; - public final fun copy (Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithConverter;Ljava/util/List;)Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeGenResult; - public static synthetic fun copy$default (Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeGenResult;Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithConverter;Ljava/util/List;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeGenResult; + public final fun copy (Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithTypeCastGenerator;Ljava/util/List;)Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeGenResult; + public static synthetic fun copy$default (Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeGenResult;Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithTypeCastGenerator;Ljava/util/List;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeGenResult; public fun equals (Ljava/lang/Object;)Z - public final fun getCode ()Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithConverter; + public final fun getCode ()Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithTypeCastGenerator; public final fun getNewMarkers ()Ljava/util/List; public fun hashCode ()I public fun toString ()Ljava/lang/String; @@ -4784,9 +4785,9 @@ public final class org/jetbrains/kotlinx/dataframe/codeGen/CodeGenResult { public abstract interface class org/jetbrains/kotlinx/dataframe/codeGen/CodeGenerator : org/jetbrains/kotlinx/dataframe/codeGen/ExtensionsCodeGenerator { public static final field Companion Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeGenerator$Companion; - public abstract fun generate (Lorg/jetbrains/kotlinx/dataframe/codeGen/Marker;Lorg/jetbrains/kotlinx/dataframe/codeGen/InterfaceGenerationMode;ZLorg/jetbrains/kotlinx/dataframe/codeGen/DefaultReadDfMethod;)Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithConverter; + public abstract fun generate (Lorg/jetbrains/kotlinx/dataframe/codeGen/Marker;Lorg/jetbrains/kotlinx/dataframe/codeGen/InterfaceGenerationMode;ZLorg/jetbrains/kotlinx/dataframe/codeGen/DefaultReadDfMethod;)Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithTypeCastGenerator; public abstract fun generate (Lorg/jetbrains/kotlinx/dataframe/schema/DataFrameSchema;Ljava/lang/String;ZZZLorg/jetbrains/kotlinx/dataframe/codeGen/MarkerVisibility;Ljava/lang/Iterable;Lorg/jetbrains/kotlinx/dataframe/codeGen/DefaultReadDfMethod;Lorg/jetbrains/kotlinx/dataframe/codeGen/NameNormalizer;Z)Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeGenResult; - public static synthetic fun generate$default (Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeGenerator;Lorg/jetbrains/kotlinx/dataframe/codeGen/Marker;Lorg/jetbrains/kotlinx/dataframe/codeGen/InterfaceGenerationMode;ZLorg/jetbrains/kotlinx/dataframe/codeGen/DefaultReadDfMethod;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithConverter; + public static synthetic fun generate$default (Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeGenerator;Lorg/jetbrains/kotlinx/dataframe/codeGen/Marker;Lorg/jetbrains/kotlinx/dataframe/codeGen/InterfaceGenerationMode;ZLorg/jetbrains/kotlinx/dataframe/codeGen/DefaultReadDfMethod;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithTypeCastGenerator; public static synthetic fun generate$default (Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeGenerator;Lorg/jetbrains/kotlinx/dataframe/schema/DataFrameSchema;Ljava/lang/String;ZZZLorg/jetbrains/kotlinx/dataframe/codeGen/MarkerVisibility;Ljava/lang/Iterable;Lorg/jetbrains/kotlinx/dataframe/codeGen/DefaultReadDfMethod;Lorg/jetbrains/kotlinx/dataframe/codeGen/NameNormalizer;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeGenResult; } @@ -4796,30 +4797,30 @@ public final class org/jetbrains/kotlinx/dataframe/codeGen/CodeGenerator$Compani } public final class org/jetbrains/kotlinx/dataframe/codeGen/CodeGeneratorKt { - public static final fun generate (Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeGenerator;Lkotlin/reflect/KClass;Lorg/jetbrains/kotlinx/dataframe/codeGen/InterfaceGenerationMode;Z)Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithConverter; + public static final fun generate (Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeGenerator;Lkotlin/reflect/KClass;Lorg/jetbrains/kotlinx/dataframe/codeGen/InterfaceGenerationMode;Z)Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithTypeCastGenerator; } -public final class org/jetbrains/kotlinx/dataframe/codeGen/CodeWithConverter { - public static final field Companion Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithConverter$Companion; +public final class org/jetbrains/kotlinx/dataframe/codeGen/CodeWithTypeCastGenerator { + public static final field Companion Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithTypeCastGenerator$Companion; public static final field EMPTY_DECLARATIONS Ljava/lang/String; - public fun (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V - public synthetic fun (Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Ljava/lang/String;Lorg/jetbrains/kotlinx/dataframe/codeGen/TypeCastGenerator;)V + public synthetic fun (Ljava/lang/String;Lorg/jetbrains/kotlinx/dataframe/codeGen/TypeCastGenerator;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun component1 ()Ljava/lang/String; - public final fun component2 ()Lkotlin/jvm/functions/Function1; - public final fun copy (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithConverter; - public static synthetic fun copy$default (Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithConverter;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithConverter; + public final fun component2 ()Lorg/jetbrains/kotlinx/dataframe/codeGen/TypeCastGenerator; + public final fun copy (Ljava/lang/String;Lorg/jetbrains/kotlinx/dataframe/codeGen/TypeCastGenerator;)Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithTypeCastGenerator; + public static synthetic fun copy$default (Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithTypeCastGenerator;Ljava/lang/String;Lorg/jetbrains/kotlinx/dataframe/codeGen/TypeCastGenerator;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithTypeCastGenerator; + public final fun declarationsWithCastExpression (Ljava/lang/String;)Ljava/lang/String; public fun equals (Ljava/lang/Object;)Z - public final fun getConverter ()Lkotlin/jvm/functions/Function1; public final fun getDeclarations ()Ljava/lang/String; - public final fun getHasConverter ()Z + public final fun getHasCaster ()Z public final fun getHasDeclarations ()Z + public final fun getTypeCastGenerator ()Lorg/jetbrains/kotlinx/dataframe/codeGen/TypeCastGenerator; public fun hashCode ()I public fun toString ()Ljava/lang/String; - public final fun with (Ljava/lang/String;)Ljava/lang/String; } -public final class org/jetbrains/kotlinx/dataframe/codeGen/CodeWithConverter$Companion { - public final fun getEMPTY ()Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithConverter; +public final class org/jetbrains/kotlinx/dataframe/codeGen/CodeWithTypeCastGenerator$Companion { + public final fun getEMPTY ()Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithTypeCastGenerator; public final fun getEMPTY_CONVERTER ()Lkotlin/jvm/functions/Function1; } @@ -4830,7 +4831,7 @@ public abstract interface class org/jetbrains/kotlinx/dataframe/codeGen/DefaultR public abstract interface class org/jetbrains/kotlinx/dataframe/codeGen/ExtensionsCodeGenerator { public static final field Companion Lorg/jetbrains/kotlinx/dataframe/codeGen/ExtensionsCodeGenerator$Companion; - public abstract fun generate (Lorg/jetbrains/kotlinx/dataframe/codeGen/IsolatedMarker;)Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithConverter; + public abstract fun generate (Lorg/jetbrains/kotlinx/dataframe/codeGen/IsolatedMarker;)Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithTypeCastGenerator; } public final class org/jetbrains/kotlinx/dataframe/codeGen/ExtensionsCodeGenerator$Companion { @@ -4976,6 +4977,28 @@ public final class org/jetbrains/kotlinx/dataframe/codeGen/NameNormalizer : kotl public final class org/jetbrains/kotlinx/dataframe/codeGen/NameNormalizer$Companion { } +public abstract interface class org/jetbrains/kotlinx/dataframe/codeGen/TypeCastGenerator { + public abstract fun addCastTo (Ljava/lang/String;)Ljava/lang/String; + public fun invoke (Ljava/lang/String;)Ljava/lang/String; +} + +public final class org/jetbrains/kotlinx/dataframe/codeGen/TypeCastGenerator$DataFrameApi : org/jetbrains/kotlinx/dataframe/codeGen/TypeCastGenerator { + public static final field Companion Lorg/jetbrains/kotlinx/dataframe/codeGen/TypeCastGenerator$DataFrameApi$Companion; + public synthetic fun ([Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun addCastTo (Ljava/lang/String;)Ljava/lang/String; + public final fun getTypes ()[Ljava/lang/String; +} + +public final class org/jetbrains/kotlinx/dataframe/codeGen/TypeCastGenerator$DataFrameApi$Companion { + public final fun invoke ([Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/codeGen/TypeCastGenerator; +} + +public final class org/jetbrains/kotlinx/dataframe/codeGen/TypeCastGenerator$Empty : org/jetbrains/kotlinx/dataframe/codeGen/TypeCastGenerator { + public static final field INSTANCE Lorg/jetbrains/kotlinx/dataframe/codeGen/TypeCastGenerator$Empty; + public fun addCastTo (Ljava/lang/String;)Ljava/lang/String; + public fun invoke (Ljava/lang/String;)Ljava/lang/String; +} + public final class org/jetbrains/kotlinx/dataframe/codeGen/ValidFieldName { public static final field Companion Lorg/jetbrains/kotlinx/dataframe/codeGen/ValidFieldName$Companion; public synthetic fun (Ljava/lang/String;ZLkotlin/jvm/internal/DefaultConstructorMarker;)V @@ -5850,7 +5873,7 @@ public final class org/jetbrains/kotlinx/dataframe/impl/codeGen/CodeGeneratorImp public static final fun quoteIfNeeded (Ljava/lang/String;)Ljava/lang/String; public static final fun toStandaloneSnippet (Ljava/lang/String;Ljava/lang/String;Ljava/util/List;)Ljava/lang/String; public static final fun toStandaloneSnippet (Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeGenResult;Ljava/lang/String;Ljava/util/List;)Ljava/lang/String; - public static final fun toStandaloneSnippet (Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithConverter;Ljava/lang/String;Ljava/util/List;)Ljava/lang/String; + public static final fun toStandaloneSnippet (Lorg/jetbrains/kotlinx/dataframe/codeGen/CodeWithTypeCastGenerator;Ljava/lang/String;Ljava/util/List;)Ljava/lang/String; } public abstract interface class org/jetbrains/kotlinx/dataframe/impl/codeGen/DfReadResult { diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/cast.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/cast.kt index bf282b2491..63ad00bbd9 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/cast.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/cast.kt @@ -99,3 +99,5 @@ public fun TransformableColumnSet<*>.cast(): TransformableColumnSet = thi public fun TransformableSingleColumn<*>.cast(): TransformableSingleColumn = this as TransformableSingleColumn public fun ColumnReference<*>.cast(): ColumnReference = this as ColumnReference + +public fun GroupBy<*, *>.cast(): GroupBy = this as GroupBy diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/CodeGenerator.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/CodeGenerator.kt index f5c95ee4d7..b3b2016709 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/CodeGenerator.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/CodeGenerator.kt @@ -15,7 +15,7 @@ public enum class InterfaceGenerationMode { None, } -public data class CodeGenResult(val code: CodeWithConverter, val newMarkers: List) +public data class CodeGenResult(val code: CodeWithTypeCastGenerator, val newMarkers: List) public interface CodeGenerator : ExtensionsCodeGenerator { @@ -37,7 +37,7 @@ public interface CodeGenerator : ExtensionsCodeGenerator { interfaceMode: InterfaceGenerationMode, extensionProperties: Boolean, readDfMethod: DefaultReadDfMethod? = null, - ): CodeWithConverter + ): CodeWithTypeCastGenerator public companion object { public fun create(useFqNames: Boolean = true): CodeGenerator = @@ -54,7 +54,7 @@ internal fun CodeGenerator.generate( markerClass: KClass<*>, interfaceMode: InterfaceGenerationMode, extensionProperties: Boolean, -): CodeWithConverter = +): CodeWithTypeCastGenerator = generate( MarkersExtractor.get(markerClass), interfaceMode, @@ -64,4 +64,4 @@ internal fun CodeGenerator.generate( public inline fun CodeGenerator.generate( interfaceMode: InterfaceGenerationMode, extensionProperties: Boolean, -): CodeWithConverter = generate(T::class, interfaceMode, extensionProperties) +): CodeWithTypeCastGenerator = generate(T::class, interfaceMode, extensionProperties) diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/CodeWithConverter.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/CodeWithConverter.kt deleted file mode 100644 index a6f3443f6b..0000000000 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/CodeWithConverter.kt +++ /dev/null @@ -1,30 +0,0 @@ -package org.jetbrains.kotlinx.dataframe.codeGen - -/** - * Class representing generated code declarations for a [Marker]. - * - * @param declarations The generated code. - * @param converter Optional converter for the [Marker], such as a [org.jetbrains.kotlinx.dataframe.api.cast], often used for Jupyter. - */ -public data class CodeWithConverter(val declarations: Code, val converter: (VariableName) -> Code = EMPTY_CONVERTER) { - - public companion object { - public const val EMPTY_DECLARATIONS: Code = "" - public val EMPTY_CONVERTER: (VariableName) -> Code = { it } - public val EMPTY: CodeWithConverter = CodeWithConverter(EMPTY_DECLARATIONS, EMPTY_CONVERTER) - } - - val hasDeclarations: Boolean get() = declarations.isNotBlank() - - val hasConverter: Boolean get() = converter("it").trim() != "it" - - public fun with(name: VariableName): Code = - when { - !hasConverter -> declarations - !hasDeclarations -> converter(name) - else -> declarations + "\n" + converter(name) - } -} - -public typealias Code = String -public typealias VariableName = String diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/CodeWithTypeCastGenerator.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/CodeWithTypeCastGenerator.kt new file mode 100644 index 0000000000..49c55a6f86 --- /dev/null +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/CodeWithTypeCastGenerator.kt @@ -0,0 +1,81 @@ +package org.jetbrains.kotlinx.dataframe.codeGen + +import org.jetbrains.kotlinx.dataframe.api.cast + +/** + * Class representing generated code declarations for a [Marker]. + * + * @param declarations The generated code. + * @param typeCastGenerator Optional [TypeCastGenerator] for the [Marker], see [TypeCastGenerator] for + * more information. + */ +public data class CodeWithTypeCastGenerator( + val declarations: Code, + val typeCastGenerator: TypeCastGenerator = TypeCastGenerator.Empty, +) { + + public companion object { + public const val EMPTY_DECLARATIONS: Code = "" + + @Deprecated("", ReplaceWith("TypeCastGenerator.Empty")) + public val EMPTY_CONVERTER: (Expression) -> Code = { it } + public val EMPTY: CodeWithTypeCastGenerator = CodeWithTypeCastGenerator(EMPTY_DECLARATIONS) + } + + val hasDeclarations: Boolean get() = declarations.isNotBlank() + + val hasCaster: Boolean + get() = typeCastGenerator !is TypeCastGenerator.Empty && + typeCastGenerator("it").trim() != "it" + + public fun declarationsWithCastExpression(expression: Expression): Code = + when { + !hasCaster -> declarations + !hasDeclarations -> typeCastGenerator(expression) + else -> declarations + "\n" + typeCastGenerator(expression) + } +} + +public typealias Code = String +public typealias Expression = String + +/** + * A [TypeCastGenerator] can generate [Code] given an [Expression] that casts or converts + * it to a predefined target type. + * + * To create a [TypeCastGenerator] that, for instance, casts everything you pass to [Any?][Any]: + * ```kt + * val myCastGenerator = TypeCastGenerator { expression -> "(\$expression as Any?)" } + * + * myCastGenerator.addCastTo("myVariable") == "(myVariable as Any?)" + * ``` + * + * @see TypeCastGenerator.Empty + * @see TypeCastGenerator.DataFrameApi + */ +public fun interface TypeCastGenerator { + public fun addCastTo(expression: Expression): Code + + public operator fun invoke(expression: Expression): Code = addCastTo(expression) + + public object Empty : TypeCastGenerator by (TypeCastGenerator { it }) + + /** + * [TypeCastGenerator] that uses the [cast] functions of the DataFrame API. + * + * NOTE: This generator assumes there's a `.cast<>()` function available that can be called on your + * specific [Expression]. It will cause runtime errors when there isn't one. + */ + public class DataFrameApi private constructor(public val types: Array) : TypeCastGenerator { + override fun addCastTo(expression: Expression): Code = + if (types.isEmpty()) { + "$expression.cast()" + } else { + "$expression.cast<${types.joinToString()}>()" + } + + public companion object { + public operator fun invoke(vararg types: String): TypeCastGenerator = DataFrameApi(types) + } + } +} diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/ExtensionsCodeGenerator.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/ExtensionsCodeGenerator.kt index de874282f1..6d625547c1 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/ExtensionsCodeGenerator.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/ExtensionsCodeGenerator.kt @@ -4,7 +4,7 @@ import org.jetbrains.kotlinx.dataframe.impl.codeGen.ExtensionsCodeGeneratorImpl import org.jetbrains.kotlinx.dataframe.impl.codeGen.ShortNames public interface ExtensionsCodeGenerator { - public fun generate(marker: IsolatedMarker): CodeWithConverter + public fun generate(marker: IsolatedMarker): CodeWithTypeCastGenerator public companion object { public fun create(): ExtensionsCodeGenerator = ExtensionsCodeGeneratorImpl(ShortNames) diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/codeGen/CodeGeneratorImpl.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/codeGen/CodeGeneratorImpl.kt index dcc48bda23..87ebde289c 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/codeGen/CodeGeneratorImpl.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/codeGen/CodeGeneratorImpl.kt @@ -9,11 +9,12 @@ import org.jetbrains.kotlinx.dataframe.DataRow import org.jetbrains.kotlinx.dataframe.annotations.DataSchema import org.jetbrains.kotlinx.dataframe.api.ColumnSelectionDsl import org.jetbrains.kotlinx.dataframe.api.DataSchemaEnum +import org.jetbrains.kotlinx.dataframe.api.cast import org.jetbrains.kotlinx.dataframe.codeGen.BaseField import org.jetbrains.kotlinx.dataframe.codeGen.Code import org.jetbrains.kotlinx.dataframe.codeGen.CodeGenResult import org.jetbrains.kotlinx.dataframe.codeGen.CodeGenerator -import org.jetbrains.kotlinx.dataframe.codeGen.CodeWithConverter +import org.jetbrains.kotlinx.dataframe.codeGen.CodeWithTypeCastGenerator import org.jetbrains.kotlinx.dataframe.codeGen.DefaultReadDfMethod import org.jetbrains.kotlinx.dataframe.codeGen.ExtensionsCodeGenerator import org.jetbrains.kotlinx.dataframe.codeGen.FieldType @@ -28,6 +29,7 @@ import org.jetbrains.kotlinx.dataframe.codeGen.Marker import org.jetbrains.kotlinx.dataframe.codeGen.MarkerVisibility import org.jetbrains.kotlinx.dataframe.codeGen.NameNormalizer import org.jetbrains.kotlinx.dataframe.codeGen.SchemaProcessor +import org.jetbrains.kotlinx.dataframe.codeGen.TypeCastGenerator import org.jetbrains.kotlinx.dataframe.codeGen.ValidFieldName import org.jetbrains.kotlinx.dataframe.codeGen.toNullable import org.jetbrains.kotlinx.dataframe.columns.ColumnGroup @@ -44,8 +46,12 @@ internal fun Iterable.filterRequiredForSchema(schema: DataFrameSchema) = internal val charsToQuote = """[ `(){}\[\].<>'"/|\\!?@:;%^&*#$-]""".toRegex() -internal fun createCodeWithConverter(code: String, markerName: String) = - CodeWithConverter(code) { "$it.cast<$markerName>()" } +/** + * Simple utility function that creates a [CodeWithTypeCastGenerator] using [code] and [TypeCastGenerator.DataFrameApi], + * meaning it uses the [cast] functions of DataFrame. + */ +internal fun createCodeWithTypeCastGenerator(code: String, vararg targetTypeNames: String) = + CodeWithTypeCastGenerator(code, TypeCastGenerator.DataFrameApi(*targetTypeNames)) private val letterCategories = setOf( CharCategory.UPPERCASE_LETTER, @@ -365,9 +371,9 @@ internal open class ExtensionsCodeGeneratorImpl(private val typeRendering: TypeR return declarations.joinToString("\n") } - override fun generate(marker: IsolatedMarker): CodeWithConverter { + override fun generate(marker: IsolatedMarker): CodeWithTypeCastGenerator { val code = generateExtensionProperties(marker) - return createCodeWithConverter(code, marker.name) + return createCodeWithTypeCastGenerator(code, marker.name) } protected fun renderTopLevelDeclarationVisibility(marker: IsolatedMarker) = @@ -393,7 +399,7 @@ internal class CodeGeneratorImpl(typeRendering: TypeRenderingStrategy = FullyQua interfaceMode: InterfaceGenerationMode, extensionProperties: Boolean, readDfMethod: DefaultReadDfMethod?, - ): CodeWithConverter { + ): CodeWithTypeCastGenerator { val code = when (interfaceMode) { NoFields, WithFields -> generateInterface( @@ -409,7 +415,7 @@ internal class CodeGeneratorImpl(typeRendering: TypeRenderingStrategy = FullyQua None -> if (extensionProperties) generateExtensionProperties(marker) else "" } - return createCodeWithConverter(code, marker.name) + return createCodeWithTypeCastGenerator(code, marker.name) } private fun generateTypeAlias(marker: Marker): Code { @@ -479,7 +485,7 @@ internal class CodeGeneratorImpl(typeRendering: TypeRenderingStrategy = FullyQua declarations.add(generateExtensionProperties(itMarker, withNullable = false)) } } - val code = createCodeWithConverter(declarations.joinToString("\n\n"), marker.name) + val code = createCodeWithTypeCastGenerator(declarations.joinToString("\n\n"), marker.name) return CodeGenResult(code, context.generatedMarkers) } @@ -558,7 +564,7 @@ internal class CodeGeneratorImpl(typeRendering: TypeRenderingStrategy = FullyQua } } -public fun CodeWithConverter.toStandaloneSnippet(packageName: String, additionalImports: List): String = +public fun CodeWithTypeCastGenerator.toStandaloneSnippet(packageName: String, additionalImports: List): String = declarations.toStandaloneSnippet(packageName, additionalImports) public fun Code.toStandaloneSnippet(packageName: String, additionalImports: List): String = diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/codeGen/ReplCodeGenerator.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/codeGen/ReplCodeGenerator.kt index 71d080e4fa..99a57903ce 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/codeGen/ReplCodeGenerator.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/codeGen/ReplCodeGenerator.kt @@ -2,16 +2,19 @@ package org.jetbrains.kotlinx.dataframe.impl.codeGen import org.jetbrains.kotlinx.dataframe.AnyFrame import org.jetbrains.kotlinx.dataframe.AnyRow +import org.jetbrains.kotlinx.dataframe.api.GroupBy import org.jetbrains.kotlinx.dataframe.codeGen.Code -import org.jetbrains.kotlinx.dataframe.codeGen.CodeWithConverter +import org.jetbrains.kotlinx.dataframe.codeGen.CodeWithTypeCastGenerator import kotlin.reflect.KClass import kotlin.reflect.KProperty internal interface ReplCodeGenerator { - fun process(df: AnyFrame, property: KProperty<*>? = null): CodeWithConverter + fun process(df: AnyFrame, property: KProperty<*>? = null): CodeWithTypeCastGenerator - fun process(row: AnyRow, property: KProperty<*>? = null): CodeWithConverter + fun process(row: AnyRow, property: KProperty<*>? = null): CodeWithTypeCastGenerator + + fun process(groupBy: GroupBy<*, *>): CodeWithTypeCastGenerator fun process(markerClass: KClass<*>): Code diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/codeGen/ReplCodeGeneratorImpl.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/codeGen/ReplCodeGeneratorImpl.kt index 01a91fa62f..4e1a434bc9 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/codeGen/ReplCodeGeneratorImpl.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/codeGen/ReplCodeGeneratorImpl.kt @@ -5,14 +5,16 @@ import org.jetbrains.kotlinx.dataframe.AnyRow import org.jetbrains.kotlinx.dataframe.DataFrame import org.jetbrains.kotlinx.dataframe.DataRow import org.jetbrains.kotlinx.dataframe.annotations.DataSchema +import org.jetbrains.kotlinx.dataframe.api.GroupBy import org.jetbrains.kotlinx.dataframe.api.schema import org.jetbrains.kotlinx.dataframe.codeGen.Code import org.jetbrains.kotlinx.dataframe.codeGen.CodeGenerator -import org.jetbrains.kotlinx.dataframe.codeGen.CodeWithConverter +import org.jetbrains.kotlinx.dataframe.codeGen.CodeWithTypeCastGenerator import org.jetbrains.kotlinx.dataframe.codeGen.InterfaceGenerationMode import org.jetbrains.kotlinx.dataframe.codeGen.Marker import org.jetbrains.kotlinx.dataframe.codeGen.MarkerVisibility import org.jetbrains.kotlinx.dataframe.codeGen.MarkersExtractor +import org.jetbrains.kotlinx.dataframe.codeGen.TypeCastGenerator import org.jetbrains.kotlinx.dataframe.schema.DataFrameSchema import kotlin.reflect.KClass import kotlin.reflect.KProperty @@ -43,9 +45,9 @@ internal class ReplCodeGeneratorImpl : ReplCodeGenerator { else -> null } - override fun process(row: AnyRow, property: KProperty<*>?): CodeWithConverter = process(row.df(), property) + override fun process(row: AnyRow, property: KProperty<*>?): CodeWithTypeCastGenerator = process(row.df(), property) - override fun process(df: AnyFrame, property: KProperty<*>?): CodeWithConverter { + override fun process(df: AnyFrame, property: KProperty<*>?): CodeWithTypeCastGenerator { var targetSchema = df.schema() if (property != null) { @@ -65,7 +67,7 @@ internal class ReplCodeGeneratorImpl : ReplCodeGenerator { // property scheme is valid for current data frame, but we should also check that all compatible open markers are implemented by it val requiredBaseMarkers = registeredMarkers.values.filterRequiredForSchema(columnSchema) if (requiredBaseMarkers.any() && requiredBaseMarkers.all { currentMarker.implements(it) }) { - return CodeWithConverter.EMPTY + return CodeWithTypeCastGenerator.EMPTY } // use current marker scheme as a target for generation of new marker interface, so that available properties won't change targetSchema = columnSchema @@ -77,7 +79,28 @@ internal class ReplCodeGeneratorImpl : ReplCodeGenerator { return generate(schema = targetSchema, name = markerInterfacePrefix, isOpen = true) } - fun generate(schema: DataFrameSchema, name: String, isOpen: Boolean): CodeWithConverter { + override fun process(groupBy: GroupBy<*, *>): CodeWithTypeCastGenerator { + val key = generate( + schema = groupBy.keys.schema(), + name = markerInterfacePrefix + "Keys", + isOpen = false, + ) + val group = generate( + schema = groupBy.groups.schema.value, + name = markerInterfacePrefix + "Groups", + isOpen = false, + ) + + val keyTypeName = (key.typeCastGenerator as TypeCastGenerator.DataFrameApi).types.single() + val groupTypeName = (group.typeCastGenerator as TypeCastGenerator.DataFrameApi).types.single() + + return CodeWithTypeCastGenerator( + declarations = key.declarations + "\n" + group.declarations, + typeCastGenerator = TypeCastGenerator.DataFrameApi(keyTypeName, groupTypeName), + ) + } + + fun generate(schema: DataFrameSchema, name: String, isOpen: Boolean): CodeWithTypeCastGenerator { val result = generator.generate( schema = schema, name = name, diff --git a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/CodeGenerationTests.kt b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/CodeGenerationTests.kt index 1cfe07482d..8398f7c0d9 100644 --- a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/CodeGenerationTests.kt +++ b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/CodeGenerationTests.kt @@ -115,11 +115,11 @@ class CodeGenerationTests : BaseTest() { val expectedConverter = "it.cast<$typeName>()" generated.declarations shouldBe expectedDeclaration - generated.converter("it") shouldBe expectedConverter + generated.typeCastGenerator("it") shouldBe expectedConverter val rowGenerated = codeGen.process(df[0], ::typedRow) rowGenerated.hasDeclarations shouldBe true - rowGenerated.hasConverter shouldBe true + rowGenerated.hasCaster shouldBe true } val row: AnyRow? = null @@ -146,7 +146,7 @@ class CodeGenerationTests : BaseTest() { val expectedConverter = "it.cast<$typeName>()" generated.declarations shouldBe expectedDeclaration - generated.converter("it") shouldBe expectedConverter + generated.typeCastGenerator("it") shouldBe expectedConverter } @Test @@ -191,7 +191,7 @@ class CodeGenerationTests : BaseTest() { val expectedConverter = "it.cast<$type2>()" generated.declarations shouldBe declaration1 + "\n" + declaration2 - generated.converter("it") shouldBe expectedConverter + generated.typeCastGenerator("it") shouldBe expectedConverter } @Test diff --git a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/MatchSchemeTests.kt b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/MatchSchemeTests.kt index 598c0aa057..96ad16e289 100644 --- a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/MatchSchemeTests.kt +++ b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/MatchSchemeTests.kt @@ -89,7 +89,7 @@ class MatchSchemeTests { fun `marker is reused`() { val codeGen = ReplCodeGenerator.create() codeGen.process(DataRecord::class) - codeGen.process(typed, ::typed).hasConverter shouldBe false + codeGen.process(typed, ::typed).hasCaster shouldBe false val generated = codeGen.process(df, ::df) generated.declarations.split("\n").size shouldBe 1 } diff --git a/dataframe-geo/src/main/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/IntegrationGeo.kt b/dataframe-geo/src/main/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/IntegrationGeo.kt index e1c4f1718f..45e0c5bbec 100644 --- a/dataframe-geo/src/main/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/IntegrationGeo.kt +++ b/dataframe-geo/src/main/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/IntegrationGeo.kt @@ -65,8 +65,8 @@ internal class IntegrationGeo : JupyterIntegration() { val execution = FieldHandlerFactory.createUpdateExecution> { geo, kProperty -> // TODO rewrite better val generatedDf = execute( - codeWithConverter = replCodeGeneratorImpl.process(geo.df, kProperty), - "(${kProperty.name}.df as DataFrame<*>)", + codeWithTypeCastGenerator = replCodeGeneratorImpl.process(geo.df, kProperty), + expression = "(${kProperty.name}.df as DataFrame<*>)", ) val name = execute("GeoDataFrame($generatedDf, ${kProperty.name}.crs)").name name diff --git a/dataframe-jupyter/src/main/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/Integration.kt b/dataframe-jupyter/src/main/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/Integration.kt index d46b8a3e18..9b8a1ce916 100644 --- a/dataframe-jupyter/src/main/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/Integration.kt +++ b/dataframe-jupyter/src/main/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/Integration.kt @@ -30,7 +30,6 @@ import org.jetbrains.kotlinx.dataframe.api.asDataFrame import org.jetbrains.kotlinx.dataframe.api.columnsCount import org.jetbrains.kotlinx.dataframe.api.isColumnGroup import org.jetbrains.kotlinx.dataframe.codeGen.CodeGenerator -import org.jetbrains.kotlinx.dataframe.codeGen.CodeWithConverter import org.jetbrains.kotlinx.dataframe.columns.ColumnGroup import org.jetbrains.kotlinx.dataframe.columns.ColumnReference import org.jetbrains.kotlinx.dataframe.dataTypes.IFRAME @@ -108,7 +107,7 @@ internal class Integration(private val notebook: Notebook, private val options: codeGen: ReplCodeGenerator, ): VariableName? = execute( - codeWithConverter = codeGen.process(df, property), + codeWithTypeCastGenerator = codeGen.process(df, property), property = property, type = DataFrame::class.createStarProjectedType(false), ) @@ -119,7 +118,7 @@ internal class Integration(private val notebook: Notebook, private val options: codeGen: ReplCodeGenerator, ): VariableName? = execute( - codeWithConverter = codeGen.process(row, property), + codeWithTypeCastGenerator = codeGen.process(row, property), property = property, type = DataRow::class.createStarProjectedType(false), ) @@ -130,7 +129,7 @@ internal class Integration(private val notebook: Notebook, private val options: codeGen: ReplCodeGenerator, ): VariableName? = execute( - codeWithConverter = codeGen.process(col.asDataFrame(), property), + codeWithTypeCastGenerator = codeGen.process(col.asDataFrame(), property), property = property, type = ColumnGroup::class.createStarProjectedType(false), ) @@ -141,11 +140,12 @@ internal class Integration(private val notebook: Notebook, private val options: codeGen: ReplCodeGenerator, ): VariableName? = if (col.isColumnGroup()) { - val codeWithConverter = codeGen.process(col.asDataFrame(), property).let { c -> - CodeWithConverter(c.declarations) { c.converter("$it.asColumnGroup()") } + val codeWithDfCaster = codeGen.process(col.asDataFrame(), property) + val codeWithColumnGroupCaster = codeWithDfCaster.copy { + codeWithDfCaster.typeCastGenerator("$it.asColumnGroup()") } execute( - codeWithConverter = codeWithConverter, + codeWithTypeCastGenerator = codeWithColumnGroupCaster, property = property, type = DataColumn::class.createStarProjectedType(false), ) @@ -153,6 +153,17 @@ internal class Integration(private val notebook: Notebook, private val options: null } + private fun KotlinKernelHost.updateGroupByVariable( + instance: GroupBy<*, *>, + property: KProperty<*>, + codeGen: ReplCodeGenerator, + ): VariableName? = + execute( + codeWithTypeCastGenerator = codeGen.process(instance), + property = property, + type = GroupBy::class.createStarProjectedType(false), + ) + override fun Builder.onLoaded() { if (version != null) { if (enableExperimentalCsv?.toBoolean() == true) { @@ -282,13 +293,16 @@ internal class Integration(private val notebook: Notebook, private val options: import("org.jetbrains.kotlinx.dataframe.impl.codeGen.urlCodeGenReader") addTypeConverter(object : FieldHandler { + override val execution = FieldHandlerFactory.createUpdateExecution { instance, property -> + // TODO check property type first, then instance, Issue #1245 when (instance) { is AnyCol -> updateAnyColVariable(instance, property, codeGen) is ColumnGroup<*> -> updateColumnGroupVariable(instance, property, codeGen) is AnyRow -> updateAnyRowVariable(instance, property, codeGen) is AnyFrame -> updateAnyFrameVariable(instance, property, codeGen) is ImportDataSchema -> updateImportDataSchemaVariable(instance, property) + is GroupBy<*, *> -> updateGroupByVariable(instance, property, codeGen) else -> error("${instance::class} should not be handled by Dataframe field handler") } } @@ -298,7 +312,8 @@ internal class Integration(private val notebook: Notebook, private val options: value is ColumnGroup<*> || value is AnyRow || value is AnyFrame || - value is ImportDataSchema + value is ImportDataSchema || + value is GroupBy<*, *> }) fun KotlinKernelHost.addDataSchemas(classes: List>) { diff --git a/dataframe-jupyter/src/main/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/execute.kt b/dataframe-jupyter/src/main/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/execute.kt index def44d63a9..ff34bc37c5 100644 --- a/dataframe-jupyter/src/main/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/execute.kt +++ b/dataframe-jupyter/src/main/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/execute.kt @@ -1,16 +1,19 @@ package org.jetbrains.kotlinx.dataframe.jupyter -import org.jetbrains.kotlinx.dataframe.codeGen.CodeWithConverter +import org.jetbrains.kotlinx.dataframe.codeGen.CodeWithTypeCastGenerator import org.jetbrains.kotlinx.jupyter.api.KotlinKernelHost import org.jetbrains.kotlinx.jupyter.api.VariableName import kotlin.reflect.KProperty import kotlin.reflect.KType -internal fun KotlinKernelHost.execute(codeWithConverter: CodeWithConverter, argument: String): VariableName? { - val code = codeWithConverter.with(argument) +internal fun KotlinKernelHost.execute( + codeWithTypeCastGenerator: CodeWithTypeCastGenerator, + expression: String, +): VariableName? { + val code = codeWithTypeCastGenerator.declarationsWithCastExpression(expression) return if (code.isNotBlank()) { val result = execute(code) - if (codeWithConverter.hasConverter) { + if (codeWithTypeCastGenerator.hasCaster) { result.name } else { null @@ -21,10 +24,10 @@ internal fun KotlinKernelHost.execute(codeWithConverter: CodeWithConverter, argu } internal fun KotlinKernelHost.execute( - codeWithConverter: CodeWithConverter, + codeWithTypeCastGenerator: CodeWithTypeCastGenerator, property: KProperty<*>, type: KType, ): VariableName? { val variableName = "(${property.name}${if (property.returnType.isMarkedNullable) "!!" else ""} as $type)" - return execute(codeWithConverter, variableName) + return execute(codeWithTypeCastGenerator, variableName) } diff --git a/dataframe-jupyter/src/test/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/CodeGenerationTests.kt b/dataframe-jupyter/src/test/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/CodeGenerationTests.kt index 90b7ccb6e9..636b27aa73 100644 --- a/dataframe-jupyter/src/test/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/CodeGenerationTests.kt +++ b/dataframe-jupyter/src/test/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/CodeGenerationTests.kt @@ -1,5 +1,3 @@ -@file:Suppress("LocalVariableName") - package org.jetbrains.kotlinx.dataframe.jupyter import org.intellij.lang.annotations.Language @@ -56,7 +54,8 @@ class CodeGenerationTests : DataFrameJupyterTest() { @Test fun `interface without body compiled correctly`() { - """ + @Language("kts") + val a = """ val a = dataFrameOf("a")(1, 2, 3) val b = dataFrameOf("b")(1, 2, 3) val ab = dataFrameOf("a", "b")(1, 2) @@ -66,30 +65,78 @@ class CodeGenerationTests : DataFrameJupyterTest() { @Test fun `nested schema with isOpen = false is ignored in marker generation`() { - """ - val df = dataFrameOf("col" to listOf("a"), "leaf" to listOf(dataFrameOf("a", "b")(1, 2).first())) - val df1 = df.convert { leaf }.asFrame { it.add("c") { 3 } } - df1.leaf.c + @Language("kts") + val a = """ + val df = dataFrameOf("col" to listOf("a"), "leaf" to listOf(dataFrameOf("a", "b")(1, 2).first())) + val df1 = df.convert { leaf }.asFrame { it.add("c") { 3 } } + df1.leaf.c """.checkCompilation() } // Issue #1222 @Test fun `do not reuse marker with non-matching sub-schema`() { - @Language("kt") - val _1 = """ + @Language("kts") + val a = """ val df1 = dataFrameOf("group" to columnOf("a" to columnOf(1, null, 3))) val df2 = dataFrameOf("group" to columnOf("a" to columnOf(1, 2, 3))) df1.group.a df2.group.a """.checkCompilation() - @Language("kt") - val _2 = """ + @Language("kts") + val b = """ val df1 = dataFrameOf("group" to columnOf("a" to columnOf(1, 2, 3))) val df2 = dataFrameOf("group" to columnOf("a" to columnOf(1, null, 3))) df1.group.a df2.group.a """.checkCompilation() } + + // Issue #1221, #663 + @Test + fun `GroupBy code generation`() { + @Language("kts") + val a = """ + val ab = dataFrameOf("a", "b")(1, 2) + ab.groupBy { a }.aggregate { sum { b } into "bSum" } + """.checkCompilation() + + @Language("kts") + val b = """ + val ab = dataFrameOf("a", "b")(1, 2) + val grouped = ab.groupBy { a } + grouped.aggregate { sum { b } into "bSum" } + """.checkCompilation() + + @Language("kts") + val c = """ + val grouped = dataFrameOf("a", "b")(1, 2).groupBy("a") + grouped.aggregate { sum { b } into "bSum" } + """.checkCompilation() + + @Language("kts") + val d = """ + val grouped = dataFrameOf("a", "b")(1, 2).groupBy("a") + grouped.keys.a + """.checkCompilation() + + @Language("kts") + val e = """ + val grouped = dataFrameOf("a", "b")(1, 2).groupBy { "a"() named "k" } + grouped.keys.k + """.checkCompilation() + + @Language("kts") + val f = """ + val groupBy = dataFrameOf("a")("1", "11", "2", "22").groupBy { expr { "a"().length } named "k" } + groupBy.keys.k + """.checkCompilation() + + @Language("kts") + val g = """ + val groupBy = dataFrameOf("a")("1", "11", "2", "22").groupBy { expr { "a"().length } named "k" }.add("newCol") { 42 } + groupBy.aggregate { newCol into "newCol" } + """.checkCompilation() + } } diff --git a/docs/StardustDocs/resources/api/generate_docs/notebook_test_generate_docs_1.html b/docs/StardustDocs/resources/api/generate_docs/notebook_test_generate_docs_1.html index 99654215e6..837c2a4463 100644 --- a/docs/StardustDocs/resources/api/generate_docs/notebook_test_generate_docs_1.html +++ b/docs/StardustDocs/resources/api/generate_docs/notebook_test_generate_docs_1.html @@ -177,7 +177,7 @@ -
+

@@ -458,23 +458,23 @@ /**/ /**/ /**/ -call_DataFrame(function() { DataFrame.renderTable(-553648128) }); +call_DataFrame(function() { DataFrame.renderTable(-637534208) }); function sendHeight() { const table = document.querySelector('table.dataframe'); diff --git a/docs/StardustDocs/resources/api/rename/notebook_test_rename_3.html b/docs/StardustDocs/resources/api/rename/notebook_test_rename_3.html index 965d0f1659..93878a0dac 100644 --- a/docs/StardustDocs/resources/api/rename/notebook_test_rename_3.html +++ b/docs/StardustDocs/resources/api/rename/notebook_test_rename_3.html @@ -177,7 +177,7 @@ -
+

@@ -460,10 +460,10 @@ call_DataFrame(function() { DataFrame.addTable({ cols: [{ name: "ColumnA", children: [], rightAlign: true, values: ["1","2"] }, { name: "column_b", children: [], rightAlign: false, values: ["a","b"] }, { name: "COLUMN-C", children: [], rightAlign: false, values: ["true","false"] }, -], id: -553648125, rootId: -553648125, totalRows: 2 } ) }); +], id: -637534205, rootId: -637534205, totalRows: 2 } ) }); /*-->*/ -call_DataFrame(function() { DataFrame.renderTable(-553648125) }); +call_DataFrame(function() { DataFrame.renderTable(-637534205) }); function sendHeight() { const table = document.querySelector('table.dataframe'); diff --git a/docs/StardustDocs/resources/api/rename/notebook_test_rename_4.html b/docs/StardustDocs/resources/api/rename/notebook_test_rename_4.html index fd4d1bcb79..fc44637d33 100644 --- a/docs/StardustDocs/resources/api/rename/notebook_test_rename_4.html +++ b/docs/StardustDocs/resources/api/rename/notebook_test_rename_4.html @@ -177,7 +177,7 @@ -
+

@@ -460,10 +460,10 @@ call_DataFrame(function() { DataFrame.addTable({ cols: [{ name: "columnA", children: [], rightAlign: true, values: ["1","2"] }, { name: "column_b", children: [], rightAlign: false, values: ["a","b"] }, { name: "columnC", children: [], rightAlign: false, values: ["true","false"] }, -], id: -553648124, rootId: -553648124, totalRows: 2 } ) }); +], id: -637534204, rootId: -637534204, totalRows: 2 } ) }); /*-->*/ -call_DataFrame(function() { DataFrame.renderTable(-553648124) }); +call_DataFrame(function() { DataFrame.renderTable(-637534204) }); function sendHeight() { const table = document.querySelector('table.dataframe'); diff --git a/docs/StardustDocs/resources/api/rename/notebook_test_rename_5.html b/docs/StardustDocs/resources/api/rename/notebook_test_rename_5.html index aaac896cf0..a4d810538a 100644 --- a/docs/StardustDocs/resources/api/rename/notebook_test_rename_5.html +++ b/docs/StardustDocs/resources/api/rename/notebook_test_rename_5.html @@ -177,7 +177,7 @@ -
+

@@ -460,10 +460,10 @@ call_DataFrame(function() { DataFrame.addTable({ cols: [{ name: "columnA", children: [], rightAlign: true, values: ["1","2"] }, { name: "columnB", children: [], rightAlign: false, values: ["a","b"] }, { name: "columnC", children: [], rightAlign: false, values: ["true","false"] }, -], id: -553648123, rootId: -553648123, totalRows: 2 } ) }); +], id: -637534203, rootId: -637534203, totalRows: 2 } ) }); /*-->*/ -call_DataFrame(function() { DataFrame.renderTable(-553648123) }); +call_DataFrame(function() { DataFrame.renderTable(-637534203) }); function sendHeight() { const table = document.querySelector('table.dataframe'); diff --git a/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_10.html b/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_10.html index e9f9bd31c2..94e9292230 100644 --- a/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_10.html +++ b/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_10.html @@ -177,7 +177,7 @@ -
+

... showing only top 20 of 24 rows

@@ -461,10 +461,10 @@ { name: "starsCount", children: [], rightAlign: true, values: ["6120","1241","12926","1066","39402","1737","5688","1074","1181","1072","1110","1058","1815","1017","7101","2424","2836","2628","6059","1133"] }, { name: "\">topics", children: [], rightAlign: false, values: ["[ideavim, intellij, intellij-pl..., ...]","[domain-specific-language, dsl]","[code-editor, ide, intellij, i..., i...]","[intellij-idea, intellij-plugin, scala]","[compiler, gradle-plugin, intel..., ...]","[]","[dao, kotlin, orm, sql]","[kotlin]","[gitignore, ignore-files, intellij, ...]","[]","[]","[gradle, gradle-intellij-plugin, ...]","[sprite, svg, svg-sprite, svg-s..., ...]","[hacktoberfest, jetbrains, plugin, ...]","[c, compiler, kotlin, llvm, objective-c]","[create-react-app, jetbrains-ui, ...]","[components, jetbrains-ui, react]","[]","[coding-font, font, ligatures, ...]","[intellij, intellij-idea, intel..., ...]"] }, { name: "isIntellij", children: [], rightAlign: false, values: ["true","false","true","true","false","true","false","false","true","false","false","true","false","false","false","false","false","false","false","true"] }, -], id: -553648116, rootId: -553648116, totalRows: 24 } ) }); +], id: -637534196, rootId: -637534196, totalRows: 24 } ) }); /*-->*/ -call_DataFrame(function() { DataFrame.renderTable(-553648116) }); +call_DataFrame(function() { DataFrame.renderTable(-637534196) }); function sendHeight() { const table = document.querySelector('table.dataframe'); diff --git a/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_11.html b/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_11.html index d082e15136..d6a0b1122c 100644 --- a/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_11.html +++ b/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_11.html @@ -177,7 +177,7 @@ -
+

@@ -458,8 +458,8 @@ /**/ /**/ /**/ -call_DataFrame(function() { DataFrame.renderTable(-553648115) }); +call_DataFrame(function() { DataFrame.renderTable(-637534195) }); function sendHeight() { const table = document.querySelector('table.dataframe'); diff --git a/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_12.html b/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_12.html index d1dd5256ef..1c16493b23 100644 --- a/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_12.html +++ b/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_12.html @@ -177,7 +177,7 @@ -
+

@@ -459,10 +459,10 @@ /**/ -call_DataFrame(function() { DataFrame.renderTable(-553648112) }); +call_DataFrame(function() { DataFrame.renderTable(-637534192) }); function sendHeight() { const table = document.querySelector('table.dataframe'); diff --git a/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_13.html b/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_13.html index 638120234d..bed746e6ea 100644 --- a/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_13.html +++ b/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_13.html @@ -177,7 +177,7 @@ -
+

@@ -460,10 +460,10 @@ call_DataFrame(function() { DataFrame.addTable({ cols: [{ name: "isIntellij", children: [], rightAlign: false, values: ["true","false"] }, { name: "sumStars", children: [], rightAlign: true, values: ["25221","85392"] }, { name: "maxStars", children: [], rightAlign: true, values: ["12926","39402"] }, -], id: -553648111, rootId: -553648111, totalRows: 2 } ) }); +], id: -637534191, rootId: -637534191, totalRows: 2 } ) }); /*-->*/ -call_DataFrame(function() { DataFrame.renderTable(-553648111) }); +call_DataFrame(function() { DataFrame.renderTable(-637534191) }); function sendHeight() { const table = document.querySelector('table.dataframe'); diff --git a/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_14.html b/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_14.html index cbd6378f27..b6f078ad1b 100644 --- a/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_14.html +++ b/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_14.html @@ -177,7 +177,7 @@ -
+

@@ -461,10 +461,10 @@ { name: "starsCount", children: [], rightAlign: true, values: ["39402","12926","7101","6805","6120","6059","5688","2836","2628","2424"] }, { name: "\">topics", children: [], rightAlign: false, values: ["[compiler, gradle-plugin, intel..., ...]","[code-editor, ide, intellij, i..., i...]","[c, compiler, kotlin, llvm, objective-c]","[android, awt, compose, declara..., ...]","[ideavim, intellij, intellij-pl..., ...]","[coding-font, font, ligatures, ...]","[dao, kotlin, orm, sql]","[components, jetbrains-ui, react]","[]","[create-react-app, jetbrains-ui, ...]"] }, { name: "isIntellij", children: [], rightAlign: false, values: ["false","true","false","false","true","false","false","false","false","false"] }, -], id: -553648110, rootId: -553648110, totalRows: 10 } ) }); +], id: -637534190, rootId: -637534190, totalRows: 10 } ) }); /*-->*/ -call_DataFrame(function() { DataFrame.renderTable(-553648110) }); +call_DataFrame(function() { DataFrame.renderTable(-637534190) }); function sendHeight() { const table = document.querySelector('table.dataframe'); diff --git a/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_3.html b/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_3.html index f44d1342c6..f4f1429b4f 100644 --- a/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_3.html +++ b/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_3.html @@ -177,7 +177,7 @@ -
+

... showing only top 20 of 562 rows

@@ -462,10 +462,10 @@ { name: "stargazers_count", children: [], rightAlign: true, values: ["23","115","290","6120","5","8","47","11","41","534","6","218","1241","12926","39","118","1066","125","27","39402"] }, { name: "topics", children: [], rightAlign: false, values: ["[]","[jetbrains, jetbrains-youtrack, youtr...","[]","[ideavim, intellij, intellij-platform...","[]","[]","[]","[]","[nuget, nuget-feed, teamcity, teamcit...","[]","[]","[]","[domain-specific-language, dsl]","[code-editor, ide, intellij, intellij...","[c-sharp, teamcity, teamcity-service-...","[]","[intellij-idea, intellij-plugin, scala]","[]","[]","[compiler, gradle-plugin, intellij-pl..."] }, { name: "watchers", children: [], rightAlign: true, values: ["23","115","290","6120","5","8","47","11","41","534","6","218","1241","12926","39","118","1066","125","27","39402"] }, -], id: -553648122, rootId: -553648122, totalRows: 562 } ) }); +], id: -637534202, rootId: -637534202, totalRows: 562 } ) }); /*-->*/ -call_DataFrame(function() { DataFrame.renderTable(-553648122) }); +call_DataFrame(function() { DataFrame.renderTable(-637534202) }); function sendHeight() { const table = document.querySelector('table.dataframe'); diff --git a/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_4.html b/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_4.html index da0a3bb8be..d03056111a 100644 --- a/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_4.html +++ b/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_4.html @@ -177,7 +177,7 @@ -
+

@@ -471,10 +471,10 @@ { name: "?\">median", children: [], rightAlign: false, values: ["JetBrains/lightbeam","null","8","[]","8"] }, { name: "?\">p75", children: [], rightAlign: false, values: ["JetBrains/teamcity-bazel-plugin","null","48","[awt, swing]","48"] }, { name: "?\">max", children: [], rightAlign: false, values: ["JetBrains/ztools","null","39402","[youtrack, youtrack-workflow]","39402"] }, -], id: -553648121, rootId: -553648121, totalRows: 5 } ) }); +], id: -637534201, rootId: -637534201, totalRows: 5 } ) }); /*-->*/ -call_DataFrame(function() { DataFrame.renderTable(-553648121) }); +call_DataFrame(function() { DataFrame.renderTable(-637534201) }); function sendHeight() { const table = document.querySelector('table.dataframe'); diff --git a/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_5.html b/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_5.html index 9743054374..b2438a387a 100644 --- a/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_5.html +++ b/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_5.html @@ -177,7 +177,7 @@ -
+

... showing only top 20 of 562 rows

@@ -460,10 +460,10 @@ call_DataFrame(function() { DataFrame.addTable({ cols: [{ name: "full_name", children: [], rightAlign: false, values: ["JetBrains/JPS","JetBrains/YouTrackSharp","JetBrains/colorSchemeTool","JetBrains/ideavim","JetBrains/youtrack-vcs-hooks","JetBrains/youtrack-rest-ruby-library","JetBrains/emacs4ij","JetBrains/codereview4intellij","JetBrains/teamcity-nuget-support","JetBrains/Grammar-Kit","JetBrains/intellij-starteam-plugin","JetBrains/la-clojure","JetBrains/MPS","JetBrains/intellij-community","JetBrains/TeamCity.ServiceMessages","JetBrains/youtrack-rest-python-library","JetBrains/intellij-scala","JetBrains/teamcity-messages","JetBrains/teamcity-cpp","JetBrains/kotlin"] }, { name: "stargazers_count", children: [], rightAlign: true, values: ["23","115","290","6120","5","8","47","11","41","534","6","218","1241","12926","39","118","1066","125","27","39402"] }, { name: "topics", children: [], rightAlign: false, values: ["[]","[jetbrains, jetbrains-youtrack, youtr...","[]","[ideavim, intellij, intellij-platform...","[]","[]","[]","[]","[nuget, nuget-feed, teamcity, teamcit...","[]","[]","[]","[domain-specific-language, dsl]","[code-editor, ide, intellij, intellij...","[c-sharp, teamcity, teamcity-service-...","[]","[intellij-idea, intellij-plugin, scala]","[]","[]","[compiler, gradle-plugin, intellij-pl..."] }, -], id: -553648120, rootId: -553648120, totalRows: 562 } ) }); +], id: -637534200, rootId: -637534200, totalRows: 562 } ) }); /*-->*/ -call_DataFrame(function() { DataFrame.renderTable(-553648120) }); +call_DataFrame(function() { DataFrame.renderTable(-637534200) }); function sendHeight() { const table = document.querySelector('table.dataframe'); diff --git a/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_6.html b/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_6.html index 6468fb7827..8ba1fc220b 100644 --- a/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_6.html +++ b/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_6.html @@ -177,7 +177,7 @@ -
+

... showing only top 20 of 24 rows

@@ -460,10 +460,10 @@ call_DataFrame(function() { DataFrame.addTable({ cols: [{ name: "full_name", children: [], rightAlign: false, values: ["JetBrains/ideavim","JetBrains/MPS","JetBrains/intellij-community","JetBrains/intellij-scala","JetBrains/kotlin","JetBrains/intellij-plugins","JetBrains/Exposed","JetBrains/kotlin-web-site","JetBrains/idea-gitignore","JetBrains/swot","JetBrains/phpstorm-stubs","JetBrains/gradle-intellij-plugin","JetBrains/svg-sprite-loader","JetBrains/resharper-unity","JetBrains/kotlin-native","JetBrains/create-react-kotlin-app","JetBrains/ring-ui","JetBrains/kotlinconf-app","JetBrains/JetBrainsMono","JetBrains/intellij-platform-plugin-te..."] }, { name: "stargazers_count", children: [], rightAlign: true, values: ["6120","1241","12926","1066","39402","1737","5688","1074","1181","1072","1110","1058","1815","1017","7101","2424","2836","2628","6059","1133"] }, { name: "topics", children: [], rightAlign: false, values: ["[ideavim, intellij, intellij-platform...","[domain-specific-language, dsl]","[code-editor, ide, intellij, intellij...","[intellij-idea, intellij-plugin, scala]","[compiler, gradle-plugin, intellij-pl...","[]","[dao, kotlin, orm, sql]","[kotlin]","[gitignore, ignore-files, intellij, i...","[]","[]","[gradle, gradle-intellij-plugin, grad...","[sprite, svg, svg-sprite, svg-stack, ...","[hacktoberfest, jetbrains, plugin, re...","[c, compiler, kotlin, llvm, objective-c]","[create-react-app, jetbrains-ui, kotl...","[components, jetbrains-ui, react]","[]","[coding-font, font, ligatures, monosp...","[intellij, intellij-idea, intellij-id..."] }, -], id: -553648119, rootId: -553648119, totalRows: 24 } ) }); +], id: -637534199, rootId: -637534199, totalRows: 24 } ) }); /*-->*/ -call_DataFrame(function() { DataFrame.renderTable(-553648119) }); +call_DataFrame(function() { DataFrame.renderTable(-637534199) }); function sendHeight() { const table = document.querySelector('table.dataframe'); diff --git a/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_7.html b/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_7.html index e6429b1e52..075003d964 100644 --- a/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_7.html +++ b/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_7.html @@ -177,7 +177,7 @@ -
+

... showing only top 20 of 24 rows

@@ -460,10 +460,10 @@ call_DataFrame(function() { DataFrame.addTable({ cols: [{ name: "name", children: [], rightAlign: false, values: ["JetBrains/ideavim","JetBrains/MPS","JetBrains/intellij-community","JetBrains/intellij-scala","JetBrains/kotlin","JetBrains/intellij-plugins","JetBrains/Exposed","JetBrains/kotlin-web-site","JetBrains/idea-gitignore","JetBrains/swot","JetBrains/phpstorm-stubs","JetBrains/gradle-intellij-plugin","JetBrains/svg-sprite-loader","JetBrains/resharper-unity","JetBrains/kotlin-native","JetBrains/create-react-kotlin-app","JetBrains/ring-ui","JetBrains/kotlinconf-app","JetBrains/JetBrainsMono","JetBrains/intellij-platform-plugin-te..."] }, { name: "starsCount", children: [], rightAlign: true, values: ["6120","1241","12926","1066","39402","1737","5688","1074","1181","1072","1110","1058","1815","1017","7101","2424","2836","2628","6059","1133"] }, { name: "topics", children: [], rightAlign: false, values: ["[ideavim, intellij, intellij-platform...","[domain-specific-language, dsl]","[code-editor, ide, intellij, intellij...","[intellij-idea, intellij-plugin, scala]","[compiler, gradle-plugin, intellij-pl...","[]","[dao, kotlin, orm, sql]","[kotlin]","[gitignore, ignore-files, intellij, i...","[]","[]","[gradle, gradle-intellij-plugin, grad...","[sprite, svg, svg-sprite, svg-stack, ...","[hacktoberfest, jetbrains, plugin, re...","[c, compiler, kotlin, llvm, objective-c]","[create-react-app, jetbrains-ui, kotl...","[components, jetbrains-ui, react]","[]","[coding-font, font, ligatures, monosp...","[intellij, intellij-idea, intellij-id..."] }, -], id: -553648118, rootId: -553648118, totalRows: 24 } ) }); +], id: -637534198, rootId: -637534198, totalRows: 24 } ) }); /*-->*/ -call_DataFrame(function() { DataFrame.renderTable(-553648118) }); +call_DataFrame(function() { DataFrame.renderTable(-637534198) }); function sendHeight() { const table = document.querySelector('table.dataframe'); diff --git a/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_8.html b/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_8.html index 37e35daa59..898b28197a 100644 --- a/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_8.html +++ b/docs/StardustDocs/resources/guides/quickstart/notebook_test_quickstart_8.html @@ -177,7 +177,7 @@ -
+

... showing only top 20 of 24 rows

@@ -460,10 +460,10 @@ call_DataFrame(function() { DataFrame.addTable({ cols: [{ name: "name", children: [], rightAlign: false, values: ["ideavim","MPS","intellij-community","intellij-scala","kotlin","intellij-plugins","Exposed","kotlin-web-site","idea-gitignore","swot","phpstorm-stubs","gradle-intellij-plugin","svg-sprite-loader","resharper-unity","kotlin-native","create-react-kotlin-app","ring-ui","kotlinconf-app","JetBrainsMono","intellij-platform-plugin-template"] }, { name: "starsCount", children: [], rightAlign: true, values: ["6120","1241","12926","1066","39402","1737","5688","1074","1181","1072","1110","1058","1815","1017","7101","2424","2836","2628","6059","1133"] }, { name: "\">topics", children: [], rightAlign: false, values: ["[ideavim, intellij, intellij-pl..., ...]","[domain-specific-language, dsl]","[code-editor, ide, intellij, i..., i...]","[intellij-idea, intellij-plugin, scala]","[compiler, gradle-plugin, intel..., ...]","[]","[dao, kotlin, orm, sql]","[kotlin]","[gitignore, ignore-files, intellij, ...]","[]","[]","[gradle, gradle-intellij-plugin, ...]","[sprite, svg, svg-sprite, svg-s..., ...]","[hacktoberfest, jetbrains, plugin, ...]","[c, compiler, kotlin, llvm, objective-c]","[create-react-app, jetbrains-ui, ...]","[components, jetbrains-ui, react]","[]","[coding-font, font, ligatures, ...]","[intellij, intellij-idea, intel..., ...]"] }, -], id: -553648117, rootId: -553648117, totalRows: 24 } ) }); +], id: -637534197, rootId: -637534197, totalRows: 24 } ) }); /*-->*/ -call_DataFrame(function() { DataFrame.renderTable(-553648117) }); +call_DataFrame(function() { DataFrame.renderTable(-637534197) }); function sendHeight() { const table = document.querySelector('table.dataframe');