Skip to content

Commit

Permalink
feat: packages, calls and more in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
nathanfallet committed Jun 23, 2024
1 parent 0825444 commit ebb191d
Show file tree
Hide file tree
Showing 19 changed files with 192 additions and 52 deletions.
1 change: 0 additions & 1 deletion kode-kotlin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ kotlin {
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
implementation(libs.tests.mockk)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
package software.guimauve.kode.kotlin

import software.guimauve.kode.dsl.Class
import software.guimauve.kode.dsl.File
import software.guimauve.kode.dsl.KodeGenerator
import software.guimauve.kode.dsl.shift
import software.guimauve.kode.dsl.*

object KotlinVisitor {

fun visit(generator: KodeGenerator): String = when (generator) {
is Text -> generator.text
is File -> visitFile(generator)
is Class -> visitClass(generator)
is software.guimauve.kode.dsl.Function -> visitFunction(generator)
is Variable -> visitVariable(generator)
is Type -> visitType(generator)
is Call -> visitCall(generator)
}

private fun visitFile(file: File): String = """
|package ${file.`package`}
|
|${file.imports.joinToString("\n") { "import $it" }}
|
|${file.declarations.joinToString("\n\n") { visit(it) }}
""".trimMargin()
private fun visitFile(file: File): String = listOf(
"package ${file.`package`}\n",
file.imports.joinToString("\n") { "import $it" }.takeIf { it.isNotEmpty() }?.let { "\n$it\n" } ?: "",
file.declarations.joinToString("\n\n") { visit(it) }.takeIf { it.isNotEmpty() }?.let { "\n$it\n" } ?: ""
).joinToString("")

private fun visitClass(`class`: Class): String = """
|${if (`class`.data) "data " else ""}class ${`class`.name} {
Expand All @@ -28,9 +27,21 @@ object KotlinVisitor {
""".trimMargin()

private fun visitFunction(function: software.guimauve.kode.dsl.Function): String = """
|fun ${function.name}() {
|${function.declarations.joinToString("\n") { visit(it) }.shift(4)}
|fun ${function.name}(${function.arguments.joinToString(", ") { "${it.name}: ${visit(it.type)}" }}) {
|${function.instructions.joinToString("\n") { visit(it) }.shift(4)}
|}
""".trimMargin()

private fun visitVariable(variable: Variable): String = """
|val ${variable.name}: ${visit(variable.type)}
""".trimMargin()

private fun visitType(type: Type): String = """
|${type.name}${if (type.parameters.isNotEmpty()) "<${type.parameters.joinToString(", ") { visit(it) }}>" else ""}
""".trimMargin()

private fun visitCall(call: Call): String = """
|${call.name}(${call.parameters.joinToString(", ") { visit(it) }})
""".trimMargin()

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package software.guimauve.kode.usecases

import software.guimauve.kode.dsl.KodeGenerator
import software.guimauve.kode.kotlin.KotlinVisitor

class GenerateKotlinUseCase : IGenerateCodeUseCase {

override fun invoke(input: KodeGenerator): String = KotlinVisitor.visit(input)

}
Original file line number Diff line number Diff line change
@@ -1,34 +1,57 @@
package software.guimauve.kode.kotlin

import software.guimauve.kode.dsl.`class`
import software.guimauve.kode.dsl.dataClass
import software.guimauve.kode.dsl.file
import software.guimauve.kode.dsl.function
import software.guimauve.kode.dsl.Package
import software.guimauve.kode.dsl.`package`
import software.guimauve.kode.dsl.type
import software.guimauve.kode.dsl.unaryPlus
import kotlin.test.Test

class KotlinVisitorTest {

@Test
fun main() {
file {
`package`("com.example")
imports("java.util.*", "kotlin.*")
`class`("MyClass") {
function("myFunction") {
fun testPackage() {
fun printPackage(pkg: Package) {
println(pkg.name)
println("files: " + pkg.files.map { it.key + " -> " + KotlinVisitor.visit(it.value) })
pkg.packages.forEach { printPackage(it) }
}

val basePackage = "com.example"
`package`(basePackage) {
file("Application.kt") {
import("$basePackage.plugins")
import("io.ktor.server.application.*")
import("io.ktor.server.netty.*")

function("main") {
argument("args", type("Array") {
parameter(type("String"))
})
call("EngineMain.main") {
parameters(+"args")
}
}
}
dataClass("MyDataClass") {
function("myDataFunction") {

function("Application.module") {
call("configureI18n")
// ...
}
}
function("main") {
`package`("plugins") {
file("I18n.kt") {
import("dev.kaccelero.plugins.I18n")
import("io.ktor.server.application.*")
import("java.util.*")

function("Application.configureI18n") {
call("install") {
parameter(+"I18n")
}
}
}
}
}.let {
println(KotlinVisitor.visit(it))
}

}.let(::printPackage)
}

}
13 changes: 13 additions & 0 deletions kode/src/commonMain/kotlin/software/guimauve/kode/dsl/Call.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package software.guimauve.kode.dsl

@KodeDsl
class Call internal constructor(
val name: String,
) : Instruction {

val parameters = mutableListOf<Instruction>()

fun parameter(instruction: Instruction) = parameters.add(instruction)
fun parameters(vararg instructions: Instruction) = this.parameters.addAll(instructions)

}
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package software.guimauve.kode.dsl

@KodeDsl
class Class(
class Class internal constructor(
val name: String,
val data: Boolean = false,
) : Declaration, DeclarationContainer {

override val declarations = mutableListOf<Declaration>()
val declarations = mutableListOf<Declaration>()

override fun declaration(declaration: Declaration) {
declarations.add(declaration)
}

}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package software.guimauve.kode.dsl

sealed interface Declaration : KodeGenerator
sealed interface Declaration : Instruction
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,18 @@ package software.guimauve.kode.dsl

interface DeclarationContainer {

val declarations: MutableList<Declaration>
fun declaration(declaration: Declaration)

fun declaration(declaration: Declaration) = declarations.add(declaration)
fun `class`(name: String, init: Class.() -> Unit = {}) =
declaration(Class(name).apply(init))

fun dataClass(name: String, init: Class.() -> Unit = {}) =
declaration(Class(name, data = true).apply(init))

fun function(name: String, init: Function.() -> Unit = {}) =
declaration(Function(name).apply(init))

fun variable(name: String, type: Type) =
declaration(Variable(name, type))

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@ package software.guimauve.kode.dsl
fun String.shift(spaces: Int) =
split("\n").joinToString("\n") { " ".repeat(spaces) + it }

fun file(init: File.() -> Unit) =
File().apply(init)
operator fun String.unaryPlus() = Text(this)

fun DeclarationContainer.`class`(name: String, init: Class.() -> Unit) =
declaration(Class(name).apply(init))
fun type(name: String, init: Type.() -> Unit = {}) =
Type(name).apply(init)

fun DeclarationContainer.dataClass(name: String, init: Class.() -> Unit) =
declaration(Class(name, data = true).apply(init))
fun `package`(name: String, init: Package.() -> Unit = {}) =
Package(name).apply(init)

fun DeclarationContainer.function(name: String, init: Function.() -> Unit) =
declaration(Function(name).apply(init))
fun file(init: File.() -> Unit) =
File().apply(init)
8 changes: 6 additions & 2 deletions kode/src/commonMain/kotlin/software/guimauve/kode/dsl/File.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package software.guimauve.kode.dsl

@KodeDsl
class File : KodeGenerator, DeclarationContainer {
class File internal constructor() : KodeGenerator, DeclarationContainer {

var `package` = ""
val imports = mutableListOf<String>()
override val declarations = mutableListOf<Declaration>()
val declarations = mutableListOf<Declaration>()

fun `package`(name: String) {
`package` = name
Expand All @@ -14,4 +14,8 @@ class File : KodeGenerator, DeclarationContainer {
fun import(import: String) = imports.add(import)
fun imports(vararg imports: String) = this.imports.addAll(imports)

override fun declaration(declaration: Declaration) {
declarations.add(declaration)
}

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
package software.guimauve.kode.dsl

@KodeDsl
class Function(val name: String) : Declaration, DeclarationContainer {
class Function internal constructor(val name: String) : Declaration, InstructionContainer {

override val declarations = mutableListOf<Declaration>()
val arguments = mutableListOf<Variable>()
val instructions = mutableListOf<Instruction>()

override fun instruction(instruction: Instruction) {
instructions.add(instruction)
}

fun argument(name: String, type: Type) = arguments.add(Variable(name, type))

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package software.guimauve.kode.dsl

sealed interface Instruction : KodeGenerator
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package software.guimauve.kode.dsl

interface InstructionContainer : DeclarationContainer {

fun instruction(instruction: Instruction)

override fun declaration(declaration: Declaration) =
instruction(declaration)

fun call(name: String, init: Call.() -> Unit = {}) =
instruction(Call(name).apply(init))

}
17 changes: 17 additions & 0 deletions kode/src/commonMain/kotlin/software/guimauve/kode/dsl/Package.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package software.guimauve.kode.dsl

@KodeDsl
class Package internal constructor(
val name: String,
) {

val packages = mutableListOf<Package>()
val files = mutableMapOf<String, File>()

fun `package`(name: String, init: Package.() -> Unit = {}) =
packages.add(Package("${this.name}.$name").apply(init))

fun file(name: String, init: File.() -> Unit = {}) =
files.put(name, File().apply(init).apply { `package`(this@Package.name) })

}
5 changes: 5 additions & 0 deletions kode/src/commonMain/kotlin/software/guimauve/kode/dsl/Text.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package software.guimauve.kode.dsl

class Text internal constructor(
val text: String,
) : Instruction
13 changes: 13 additions & 0 deletions kode/src/commonMain/kotlin/software/guimauve/kode/dsl/Type.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package software.guimauve.kode.dsl

@KodeDsl
class Type internal constructor(
val name: String,
) : KodeGenerator {

val parameters = mutableListOf<Type>()

fun parameter(type: Type) = parameters.add(type)
fun parameters(vararg types: Type) = this.parameters.addAll(types)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package software.guimauve.kode.dsl

@KodeDsl
class Variable internal constructor(
val name: String,
val type: Type,
) : Declaration
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package software.guimauve.kode.usecases

import dev.kaccelero.usecases.IUseCase
import software.guimauve.kode.dsl.KodeGenerator

interface IGenerateCodeUseCase : IUseCase<KodeGenerator, String>
4 changes: 0 additions & 4 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ dependencyResolutionManagement {
// Kaccelero
version("kaccelero", "0.2.0")
library("kaccelero-core", "dev.kaccelero", "core").versionRef("kaccelero")

// Tests
library("tests-mockk", "io.mockk:mockk:1.13.11")
library("tests-h2", "com.h2database:h2:2.2.224")
}
}
}
Expand Down

0 comments on commit ebb191d

Please sign in to comment.