diff --git a/lionweb-gen-gradle/README.md b/lionweb-gen-gradle/README.md index acdf1d15..628bf96c 100644 --- a/lionweb-gen-gradle/README.md +++ b/lionweb-gen-gradle/README.md @@ -1,2 +1,5 @@ -Gradle plugin to generate Kotlin classes from LionWeb languages. -Depends on lionweb-gen. \ No newline at end of file +This plugin introduce support for LIonWeb in Kolasu projects. + +It permits to: +* Generate Kolasu AST classes froma LIonWeb language definition. This is useful when using a language defined by a LIonweb compatible tool different from Kolasu +* Generate a LIonWeb language definition from Kolasu AST classes. This is useful to make a language defined in Kolasu available to other LIonWeb compatible tools. diff --git a/lionweb-gen-gradle/build.gradle b/lionweb-gen-gradle/build.gradle index ee857e35..0cc09513 100644 --- a/lionweb-gen-gradle/build.gradle +++ b/lionweb-gen-gradle/build.gradle @@ -1,6 +1,5 @@ plugins { id("java-gradle-plugin") - //id("org.gradle.kotlin.kotlin-dsl") version "4.0.14" id 'org.jetbrains.kotlin.jvm' id("com.github.gmazzo.buildconfig") version "3.1.0" id("maven-publish") @@ -18,7 +17,6 @@ dependencies { testImplementation("org.junit.jupiter:junit-jupiter:5.7.1") implementation("com.google.code.gson:gson:$gson_version") implementation("com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin:$kotlin_version-$kspVersion") - } buildConfig { @@ -46,4 +44,4 @@ tasks.named("compileKotlin") { test { useJUnitPlatform() -} \ No newline at end of file +} diff --git a/lionweb-gen/README.md b/lionweb-gen/README.md index 0751cfdf..87f44091 100644 --- a/lionweb-gen/README.md +++ b/lionweb-gen/README.md @@ -1 +1 @@ -Logic to generate Kotlin classes from LionWeb languages. \ No newline at end of file +Logic to generate Kolasu AST classes from LionWeb languages. \ No newline at end of file diff --git a/lionweb-gen/build.gradle b/lionweb-gen/build.gradle index 06fc06c7..13cf44cc 100644 --- a/lionweb-gen/build.gradle +++ b/lionweb-gen/build.gradle @@ -36,16 +36,9 @@ dependencies { } } - implementation("com.google.devtools.ksp:symbol-processing-api:$kotlin_version-$kspVersion") - + // We use the embeddable version because it avoids issues with conflicting versions of dependencies + // that we have when using the normal one implementation("org.jetbrains.kotlin:kotlin-compiler-embeddable:$kotlin_version") - -// implementation("org.jetbrains.kotlin:kotlin-compiler:$kotlin_version") { -// exclude group: "org.jetbrains.kotlin", module: "kotlin-build-common" -// exclude group: "org.jetbrains.kotlin", module: "kotlin-stdlib" -// exclude group: "org.jetbrains.kotlin", module: "kotlin-stdlib-jdk8" -// } - } publishing { diff --git a/lionweb-gen/src/main/kotlin/com/strumenta/kolasu/lionweb/ASTGenerator.kt b/lionweb-gen/src/main/kotlin/com/strumenta/kolasu/lionweb/ASTGenerator.kt index 55e6588b..f7689f01 100644 --- a/lionweb-gen/src/main/kotlin/com/strumenta/kolasu/lionweb/ASTGenerator.kt +++ b/lionweb-gen/src/main/kotlin/com/strumenta/kolasu/lionweb/ASTGenerator.kt @@ -21,36 +21,11 @@ import io.lionweb.lioncore.java.language.Reference data class KotlinFile(val path: String, val code: String) +/** + * This class generates Kotlin code for a given LIonWeb Language. + */ class ASTGenerator(val packageName: String, val language: Language) { - private fun typeName(featuresContainer: FeaturesContainer<*>): TypeName { - return when { - featuresContainer.id == StarLasuLWLanguage.ASTNode.id -> { - Node::class.java.asTypeName() - } - featuresContainer.language == this.language -> { - ClassName.bestGuess("$packageName.${featuresContainer.name}") - } - else -> { - TODO() - } - } - } - - private fun typeName(dataType: DataType<*>): TypeName { - return when (dataType) { - LionCoreBuiltins.getString() -> { - ClassName.bestGuess("kotlin.String") - } - LionCoreBuiltins.getBoolean() -> { - Boolean::class.java.asTypeName() - } - else -> { - TODO("DataType: $dataType") - } - } - } - fun generateClasses(existingKotlinClasses: Set = emptySet()): Set { val fileSpecBuilder = FileSpec.builder(packageName, "${language.name}AST.kt") language.elements.forEach { element -> @@ -116,4 +91,32 @@ class ASTGenerator(val packageName: String, val language: Language) { val file = KotlinFile(path = "ast.kt", fileSpecBuilder.build().toString()) return setOf(file) } + + private fun typeName(featuresContainer: FeaturesContainer<*>): TypeName { + return when { + featuresContainer.id == StarLasuLWLanguage.ASTNode.id -> { + Node::class.java.asTypeName() + } + featuresContainer.language == this.language -> { + ClassName.bestGuess("$packageName.${featuresContainer.name}") + } + else -> { + TODO() + } + } + } + + private fun typeName(dataType: DataType<*>): TypeName { + return when (dataType) { + LionCoreBuiltins.getString() -> { + ClassName.bestGuess("kotlin.String") + } + LionCoreBuiltins.getBoolean() -> { + Boolean::class.java.asTypeName() + } + else -> { + TODO("DataType: $dataType") + } + } + } } diff --git a/lionweb-gen/src/main/kotlin/com/strumenta/kolasu/lionweb/KotlinCodeProcessor.kt b/lionweb-gen/src/main/kotlin/com/strumenta/kolasu/lionweb/KotlinCodeProcessor.kt index 9f670036..0eee12d6 100644 --- a/lionweb-gen/src/main/kotlin/com/strumenta/kolasu/lionweb/KotlinCodeProcessor.kt +++ b/lionweb-gen/src/main/kotlin/com/strumenta/kolasu/lionweb/KotlinCodeProcessor.kt @@ -20,6 +20,10 @@ private val KtDeclaration.fqName: String "$packageName.$name" } } + +/** + * This class finds Kotlin classes definitions. + */ class KotlinCodeProcessor { fun astClassesDeclaredInFile(code: String): Set { diff --git a/lionweb-gen/src/main/kotlin/com/strumenta/kolasu/lionweb/LanguageExporter.kt b/lionweb-gen/src/main/kotlin/com/strumenta/kolasu/lionweb/LanguageExporter.kt deleted file mode 100644 index 0f4a6453..00000000 --- a/lionweb-gen/src/main/kotlin/com/strumenta/kolasu/lionweb/LanguageExporter.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.strumenta.kolasu.lionweb - -import com.google.devtools.ksp.processing.Resolver -import com.google.devtools.ksp.processing.SymbolProcessor -import com.google.devtools.ksp.processing.SymbolProcessorEnvironment -import com.google.devtools.ksp.processing.SymbolProcessorProvider -import com.google.devtools.ksp.symbol.KSAnnotated - -class LionWebSymbolProcessor : SymbolProcessor { - override fun process(resolver: Resolver): List { - println("executing LionWebSymbolProcessor") - resolver.getAllFiles().forEach { - println("PROCESSING FILE ${it.fileName}") - } - return emptyList() - } -} - -class LanguageExporter : SymbolProcessorProvider { - override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor { - println("CREATING LionWebSymbolProcessor") - return LionWebSymbolProcessor() - } -} diff --git a/lionweb-ksp/README.md b/lionweb-ksp/README.md new file mode 100644 index 00000000..07908143 --- /dev/null +++ b/lionweb-ksp/README.md @@ -0,0 +1,31 @@ +This is a ksp processor (i.e., a lightweight compiler plugin) that find all AST classes and generate the Kotlin code +for the corresponding Language definition. + +For example, it could generate something like this: + +``` +package com.strumenta.math + +import com.strumenta.kolasu.lionweb.LanguageGeneratorCommand +import com.strumenta.kolasu.lionweb.KolasuLanguage +import com.strumenta.kolasu.lionweb.LionWebLanguageExporter +import io.lionweb.lioncore.java.language.Language + +val kLanguage = KolasuLanguage("com.strumenta.math").apply { + addClass(Expression::class) + addClass(BinaryExpression::class) + addClass(SumExpression::class) + addClass(SubExpression::class) + addClass(IntLiteralExpr::class) +} + +val lwLanguage: Language by lazy { + val importer = LionWebLanguageExporter() + importer.export(kLanguage) +} + +fun main(args: Array) { + LanguageGeneratorCommand(lwLanguage).main(args) +} + +``` \ No newline at end of file