Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions .github/workflows/linting.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,17 @@ on:

jobs:
pre-commit:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
- uses: pre-commit/action@v3.0.1
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6
with:
node-version-file: '.nvmrc'
- uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5
with:
path: node_modules
key: release-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }}
- name: Install dependencies
run: npm ci
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
- uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1
11 changes: 7 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ default_install_hook_types:
- commit-msg
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
rev: v6.0.0
hooks:
# - id: trailing-whitespace # disabled, because it breaks string literals
# - id: end-of-file-fixer # disabled, because it modifies MPS XML files
- id: check-toml
- id: check-yaml
Expand All @@ -16,16 +17,18 @@ repos:
- id: mixed-line-ending
# - id: trailing-whitespace # disabled, because it modifies multiline string literals to invalid values
- repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook
rev: v9.4.0
rev: v9.24.0
hooks:
- id: commitlint
stages: [commit-msg]
additional_dependencies: ["@commitlint/config-angular"]
args: ["--config", "./commitlint.config.js"]
- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
rev: v2.12.0
rev: v2.16.0
hooks:
- id: pretty-format-kotlin
args:
- --ktlint-version=0.50.0
- --ktlint-version=1.8.0
- --autofix
additional_dependencies:
- setuptools
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,4 @@ You can define a custom editor also in the special `modelix` model using the lan

During development on this project you can run the `installMpsDevPlugins` task
to build and install only those plugins that don't contain any MPS modules.
Then open the project in the `mps` folder with MPS to load and edit the MPS modules.
Then open the project in the `mps` folder with MPS to load and edit the MPS modules.
17 changes: 10 additions & 7 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ plugins {
id("com.dorongold.task-tree") version "4.0.1"
alias(libs.plugins.kotlin.multiplatform) apply false
alias(libs.plugins.kotlin.serialization) apply false
alias(libs.plugins.kotlin.rpc) apply false
id("org.jetbrains.intellij") version "1.17.4" apply false
alias(libs.plugins.npm.publish) apply false
}
Expand Down Expand Up @@ -61,7 +62,8 @@ fun computeVersion(): Any {
}

val tsModelApiPath = rootDir.parentFile.resolve("modelix.core").resolve("ts-model-api")
val tsModelApiVersion = libs.versions.modelixCore.get() // if (tsModelApiPath.exists()) "file:${tsModelApiPath.absolutePath}" else libs.versions.modelixCore.get()
val tsModelApiVersion = libs.versions.modelixCore.get()
// if (tsModelApiPath.exists()) "file:${tsModelApiPath.absolutePath}" else libs.versions.modelixCore.get()
ext.set("ts-model-api.version", tsModelApiVersion)

subprojects {
Expand All @@ -83,11 +85,12 @@ allprojects {
if (project.hasProperty("artifacts.itemis.cloud.user")) {
maven {
name = "itemis"
url = if (version.toString().contains("SNAPSHOT")) {
uri("https://artifacts.itemis.cloud/repository/maven-mps-snapshots/")
} else {
uri("https://artifacts.itemis.cloud/repository/maven-mps-releases/")
}
url =
if (version.toString().contains("SNAPSHOT")) {
uri("https://artifacts.itemis.cloud/repository/maven-mps-snapshots/")
} else {
uri("https://artifacts.itemis.cloud/repository/maven-mps-releases/")
}
credentials {
username = project.findProperty("artifacts.itemis.cloud.user").toString()
password = project.findProperty("artifacts.itemis.cloud.pw").toString()
Expand Down Expand Up @@ -151,7 +154,7 @@ rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlu
copyMps()

// make all 'packJsPackage' tasks depend on all 'kotlinNodeJsSetup' tasks, because gradle complained about this being missing
tasks.register("setupNodeEverywhere") {
tasks.register<Task>("setupNodeEverywhere") {
dependsOn(":kernelf-apigen:kotlinNodeJsSetup")
dependsOn(":kernelf-editor:kotlinNodeJsSetup")
dependsOn(":parser:kotlinNodeJsSetup")
Expand Down
23 changes: 17 additions & 6 deletions buildSrc/src/main/kotlin/org/modelix/CopyMps.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ import java.util.zip.ZipInputStream
val Project.mpsMajorVersion: String get() {
if (project != rootProject) return rootProject.mpsMajorVersion
return project.findProperty("mps.version.major")?.toString()?.takeIf { it.isNotEmpty() }
?: project.findProperty("mps.version")?.toString()?.takeIf { it.isNotEmpty() }?.replace(Regex("""(20\d\d\.\d+).*"""), "$1")
?: project
.findProperty("mps.version")
?.toString()
?.takeIf { it.isNotEmpty() }
?.replace(Regex("""(20\d\d\.\d+).*"""), "$1")
?: "2024.1"
}

Expand Down Expand Up @@ -65,10 +69,11 @@ val Project.mpsHomeDir: Provider<Directory> get() {
}

val Project.mpsPluginsDir: File? get() {
val candidates = listOfNotNull(
project.findProperty("mps$mpsPlatformVersion.plugins.dir")?.toString()?.let { file(it) },
System.getProperty("user.home")?.let { file(it).resolve("Library/Application Support/JetBrains/MPS$mpsMajorVersion/plugins/") },
)
val candidates =
listOfNotNull(
project.findProperty("mps$mpsPlatformVersion.plugins.dir")?.toString()?.let { file(it) },
System.getProperty("user.home")?.let { file(it).resolve("Library/Application Support/JetBrains/MPS$mpsMajorVersion/plugins/") },
)
return candidates.firstOrNull { it.isDirectory }
}

Expand Down Expand Up @@ -105,7 +110,13 @@ fun Project.copyMps(): File {

// The IntelliJ gradle plugin doesn't search in jar files when reading plugin descriptors, but the IDE does.
// Copy the XML files from the jars to the META-INF folders to fix that.
for (pluginFolder in (mpsHomeDir.get().asFile.resolve("plugins").listFiles() ?: emptyArray())) {
for (pluginFolder in (
mpsHomeDir
.get()
.asFile
.resolve("plugins")
.listFiles() ?: emptyArray()
)) {
val jars = (pluginFolder.resolve("lib").listFiles() ?: emptyArray()).filter { it.extension == "jar" }
for (jar in jars) {
jar.inputStream().use {
Expand Down
11 changes: 6 additions & 5 deletions editor-common-mps/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,12 @@ tasks {

val pluginDir = mpsPluginsDir
if (pluginDir != null) {
val installMpsPlugin = register<Sync>("installMpsPlugin") {
dependsOn(prepareSandbox)
from(project.layout.buildDirectory.dir("idea-sandbox/plugins/${project.name}"))
into(pluginDir.resolve(project.name))
}
val installMpsPlugin =
register<Sync>("installMpsPlugin") {
dependsOn(prepareSandbox)
from(project.layout.buildDirectory.dir("idea-sandbox/plugins/${project.name}"))
into(pluginDir.resolve(project.name))
}
register("installMpsDevPlugins") {
dependsOn(installMpsPlugin)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,25 @@ import io.ktor.server.netty.NettyApplicationEngine
import io.ktor.util.logging.KtorSimpleLogger
import kotlinx.coroutines.GlobalScope

fun embeddedServer(port: Int, classLoader: ClassLoader? = null, module: Application.() -> Unit): EmbeddedServer<NettyApplicationEngine, NettyApplicationEngine.Configuration> {
fun embeddedServer(
port: Int,
classLoader: ClassLoader? = null,
module: Application.() -> Unit,
): EmbeddedServer<NettyApplicationEngine, NettyApplicationEngine.Configuration> {
val portParam = port
val classLoaderParam = classLoader
val moduleParam = module
val environment = applicationEnvironment {
if (classLoaderParam != null) this.classLoader = classLoaderParam
this.log = KtorSimpleLogger("ktor.application")
}
val applicationProperties = serverConfig(environment) {
this.module(moduleParam)
this.parentCoroutineContext = GlobalScope.coroutineContext
this.watchPaths = emptyList()
}
val environment =
applicationEnvironment {
if (classLoaderParam != null) this.classLoader = classLoaderParam
this.log = KtorSimpleLogger("ktor.application")
}
val applicationProperties =
serverConfig(environment) {
this.module(moduleParam)
this.parentCoroutineContext = GlobalScope.coroutineContext
this.watchPaths = emptyList()
}
return io.ktor.server.engine.embeddedServer(Netty, applicationProperties, configure = {
this.connectors += EngineConnectorBuilder().also { it.port = portParam }
})
Expand Down
10 changes: 10 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ modelix-mps-buildtools = { id = "org.modelix.mps.build-tools", version.ref = "mo
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
kotlin-rpc = { id = "org.jetbrains.kotlinx.rpc.plugin", version.ref = "kotlinx-rpc" }

[versions]
modelixCore = "18.2.0"
modelixBuildtools="2.0.1"
kotlin = "2.2.21"
kotlinx-rpc = "0.10.1"

[libraries]
modelix-model-api = { group = "org.modelix", name = "model-api", version.ref = "modelixCore" }
Expand All @@ -31,3 +33,11 @@ slf4j-api = { group = "org.slf4j", name = "slf4j-api", version = "2.0.17" }
kotlin-collections-immutable = { group = "org.jetbrains.kotlinx", name = "kotlinx-collections-immutable", version = "0.4.0" }
playwright = { group = "com.microsoft.playwright", name = "playwright", version = "1.58.0" }
testcontainers = { group = "org.testcontainers", name = "testcontainers", version = "2.0.3" }

# krpc
kotlinx-rpc-core = { module = "org.jetbrains.kotlinx:kotlinx-rpc-core", version.ref = "kotlinx-rpc" }
kotlinx-rpc-krpc-client = { module = "org.jetbrains.kotlinx:kotlinx-rpc-krpc-client", version.ref = "kotlinx-rpc" }
kotlinx-rpc-krpc-server = { module = "org.jetbrains.kotlinx:kotlinx-rpc-krpc-server", version.ref = "kotlinx-rpc" }
kotlinx-rpc-krpc-ktor-client = { module = "org.jetbrains.kotlinx:kotlinx-rpc-krpc-ktor-client", version.ref = "kotlinx-rpc" }
kotlinx-rpc-krpc-ktor-server = { module = "org.jetbrains.kotlinx:kotlinx-rpc-krpc-ktor-server", version.ref = "kotlinx-rpc" }
kotlinx-rpc-krpc-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-rpc-krpc-serialization-json", version.ref = "kotlinx-rpc" }
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package org.modelix.interpreter.vm.core

class CallInstruction(val entryPoint: Instruction, val parameterCount: Int) : Instruction() {

class CallInstruction(
val entryPoint: Instruction,
val parameterCount: Int,
) : Instruction() {
override fun execute(state: VMState): VMState {
var newFrame = StackFrame(returnTo = next)
var newState = state
Expand All @@ -16,7 +18,7 @@ class CallInstruction(val entryPoint: Instruction, val parameterCount: Int) : In
}
}

class ReturnInstruction() : Instruction() {
class ReturnInstruction : Instruction() {
override fun execute(state: VMState): VMState {
val (newCallStack, currentFrame) = state.callStack.popFrame()
check(currentFrame.operandStack.size == 1) { "Operand stack should contain a single value, but was: " + currentFrame.operandStack }
Expand All @@ -26,27 +28,29 @@ class ReturnInstruction() : Instruction() {
}
}

class PushConstantInstruction<E>(val value: E) : Instruction() {
override fun execute(state: VMState): VMState {
return state.pushOperand(value)
}
class PushConstantInstruction<E>(
val value: E,
) : Instruction() {
override fun execute(state: VMState): VMState = state.pushOperand(value)
}

class StoreInstruction<E>(val target: MemoryKey<in E>) : Instruction() {
override fun execute(state: VMState): VMState {
return state.popOperand().let { (value, newState) -> newState.writeMemory(target, value as E) }
}
class StoreInstruction<E>(
val target: MemoryKey<in E>,
) : Instruction() {
override fun execute(state: VMState): VMState = state.popOperand().let { (value, newState) -> newState.writeMemory(target, value as E) }
}

class LoadInstruction<E>(val source: MemoryKey<out E>) : Instruction() {
override fun execute(state: VMState): VMState {
return state.pushOperand(state.readMemory(source))
}
class LoadInstruction<E>(
val source: MemoryKey<out E>,
) : Instruction() {
override fun execute(state: VMState): VMState = state.pushOperand(state.readMemory(source))
}

abstract class BinaryOperationInstruction<Arg1, Arg2, Result>() : Instruction() {

abstract fun apply(arg1: Arg1, arg2: Arg2): Result
abstract class BinaryOperationInstruction<Arg1, Arg2, Result> : Instruction() {
abstract fun apply(
arg1: Arg1,
arg2: Arg2,
): Result

override fun execute(state: VMState): VMState {
var newState: VMState = state
Expand All @@ -65,43 +69,56 @@ abstract class BinaryOperationInstruction<Arg1, Arg2, Result>() : Instruction()
}
}

class AddIntegersInstruction() : BinaryOperationInstruction<Int, Int, Int>() {
override fun apply(arg1: Int, arg2: Int): Int {
return arg1 + arg2
}
class AddIntegersInstruction : BinaryOperationInstruction<Int, Int, Int>() {
override fun apply(
arg1: Int,
arg2: Int,
): Int = arg1 + arg2
}

class MultiplyIntegersInstruction() : BinaryOperationInstruction<Int, Int, Int>() {
override fun apply(arg1: Int, arg2: Int): Int {
return arg1 * arg2
}
class MultiplyIntegersInstruction : BinaryOperationInstruction<Int, Int, Int>() {
override fun apply(
arg1: Int,
arg2: Int,
): Int = arg1 * arg2
}

class JumpInstruction(val target: Instruction) : Instruction() {
override fun execute(state: VMState): VMState {
return state.copy(nextInstruction = target)
}
class JumpInstruction(
val target: Instruction,
) : Instruction() {
override fun execute(state: VMState): VMState = state.copy(nextInstruction = target)
}

class ConditionalJumpInstruction(val condition: MemoryKey<out Boolean>, val target: Instruction) : Instruction() {
override fun execute(state: VMState): VMState {
return if (state.readMemory(condition)) state.copy(nextInstruction = target) else state
}
class ConditionalJumpInstruction(
val condition: MemoryKey<out Boolean>,
val target: Instruction,
) : Instruction() {
override fun execute(state: VMState): VMState = if (state.readMemory(condition)) state.copy(nextInstruction = target) else state
}

class MoveInstruction<E>(val source: MemoryKey<out E>, val target: MemoryKey<in E>) : Instruction() {
override fun execute(state: VMState): VMState {
return state.writeMemory(target, state.readMemory(source))
}
class MoveInstruction<E>(
val source: MemoryKey<out E>,
val target: MemoryKey<in E>,
) : Instruction() {
override fun execute(state: VMState): VMState = state.writeMemory(target, state.readMemory(source))
}

class NoOpInstruction : Instruction() {
override fun execute(state: VMState): VMState {
return state
}
override fun execute(state: VMState): VMState = state
}

data class NamedGlobalVarKey<E>(val name: String) : MemoryKey<E>(MemoryType.GLOBAL, name)
data class NamedLocalVarKey<E>(val name: String) : MemoryKey<E>(MemoryType.LOCAL, name)
data class ParameterKey<E>(val index: Int) : MemoryKey<E>(MemoryType.LOCAL, "parameter" + index)
data class ReturnValueKey<E>(val index: Int) : MemoryKey<E>(MemoryType.LOCAL, "returnValue" + index)
data class NamedGlobalVarKey<E>(
val name: String,
) : MemoryKey<E>(MemoryType.GLOBAL, name)

data class NamedLocalVarKey<E>(
val name: String,
) : MemoryKey<E>(MemoryType.LOCAL, name)

data class ParameterKey<E>(
val index: Int,
) : MemoryKey<E>(MemoryType.LOCAL, "parameter" + index)

data class ReturnValueKey<E>(
val index: Int,
) : MemoryKey<E>(MemoryType.LOCAL, "returnValue" + index)
Loading
Loading