Skip to content
Merged
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
2 changes: 1 addition & 1 deletion jacodb-ets/src/main/kotlin/org/jacodb/ets/dsl/BlockStmt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ sealed interface BlockStmt
data object BlockNop : BlockStmt

data class BlockAssign(
val target: Local,
val target: LValue,
val expr: Expr,
) : BlockStmt

Expand Down
15 changes: 15 additions & 0 deletions jacodb-ets/src/main/kotlin/org/jacodb/ets/dsl/DSL.kt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,21 @@ private fun main() {
}

// x.foo := 35
assign(local("x").field("foo"), const(35))

// arr[i] := 42
assign(local("arr")[local("i")], const(42))

// MyClass.staticField := "hello"
assign(staticFieldRef("MyClass", "staticField"), const("hello"))

// obj.field1.field2 := 100
assign(local("obj").field("field1").field("field2"), const(100))

// objects[0].value := 99
assign(local("objects")[const(0)].field("value"), const(99))

// x.foo := 35 (using CustomStmt approach)
customStmt { loc ->
EtsAssignStmt(
location = loc,
Expand Down
29 changes: 28 additions & 1 deletion jacodb-ets/src/main/kotlin/org/jacodb/ets/dsl/Expr.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ package org.jacodb.ets.dsl

sealed interface Expr

data class Local(val name: String) : Expr {
data class Local(val name: String) : LValue {
override fun toString() = name
}

Expand All @@ -30,6 +30,10 @@ object ThisRef : Expr {
override fun toString() = "this"
}

data class ConstantInt(val value: Int) : Expr {
override fun toString() = "const($value)"
}

data class ConstantNumber(val value: Double) : Expr {
override fun toString() = "const($value)"
}
Expand Down Expand Up @@ -79,3 +83,26 @@ data class UnaryExpr(
) : Expr {
override fun toString() = "${operator.name.lowercase()}($expr)"
}

sealed interface LValue : Expr

data class FieldRef(
val instance: Expr,
val fieldName: String,
) : LValue {
override fun toString() = "$instance.$fieldName"
}

data class StaticFieldRef(
val className: String,
val fieldName: String,
) : LValue {
override fun toString() = "$className.$fieldName"
}

data class ArrayAccess(
val array: Expr,
val index: Expr,
) : LValue {
override fun toString() = "$array[$index]"
}
2 changes: 1 addition & 1 deletion jacodb-ets/src/main/kotlin/org/jacodb/ets/dsl/Node.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ sealed interface Node
data object Nop : Node

data class Assign(
val target: Local,
val target: LValue,
val expr: Expr,
) : Node

Expand Down
15 changes: 11 additions & 4 deletions jacodb-ets/src/main/kotlin/org/jacodb/ets/dsl/ProgramBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import org.jacodb.ets.model.EtsStmtLocation

interface ProgramBuilder {
fun nop()
fun assign(target: Local, expr: Expr)
fun assign(target: LValue, expr: Expr)
fun ret(expr: Expr)
fun label(name: String)
fun goto(label: String)
Expand All @@ -36,11 +36,18 @@ interface ProgramBuilder {
fun ProgramBuilder.local(name: String) = Local(name)
fun ProgramBuilder.param(index: Int) = Parameter(index)
fun ProgramBuilder.thisRef() = ThisRef
fun ProgramBuilder.const(value: Int) = ConstantNumber(value.toDouble())
fun ProgramBuilder.const(value: Int) = ConstantInt(value)
fun ProgramBuilder.const(value: Double) = ConstantNumber(value)
fun ProgramBuilder.const(value: Boolean) = ConstantBoolean(value)
fun ProgramBuilder.const(value: String) = ConstantString(value)

fun ProgramBuilder.fieldRef(instance: Expr, fieldName: String) = FieldRef(instance, fieldName)
fun ProgramBuilder.staticFieldRef(className: String, fieldName: String) = StaticFieldRef(className, fieldName)
fun ProgramBuilder.arrayAccess(array: Expr, index: Expr) = ArrayAccess(array, index)

fun Expr.field(name: String) = FieldRef(this, name)
operator fun Expr.get(index: Expr) = ArrayAccess(this, index)

fun ProgramBuilder.and(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.AND, left, right)
fun ProgramBuilder.or(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.OR, left, right)
fun ProgramBuilder.eq(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.EQ, left, right)
Expand Down Expand Up @@ -89,7 +96,7 @@ class ProgramBuilderImpl : ProgramBuilder {
_nodes += Nop
}

override fun assign(target: Local, expr: Expr) {
override fun assign(target: LValue, expr: Expr) {
_nodes += Assign(target, expr)
}

Expand Down Expand Up @@ -140,7 +147,7 @@ class IfBuilder : ProgramBuilder {
thenBuilder.ifStmt(condition, block)

override fun nop() = thenBuilder.nop()
override fun assign(target: Local, expr: Expr) = thenBuilder.assign(target, expr)
override fun assign(target: LValue, expr: Expr) = thenBuilder.assign(target, expr)
override fun ret(expr: Expr) = thenBuilder.ret(expr)
override fun label(name: String) = thenBuilder.label(name)
override fun goto(label: String) = thenBuilder.goto(label)
Expand Down
2 changes: 1 addition & 1 deletion jacodb-ets/src/main/kotlin/org/jacodb/ets/dsl/Stmt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ data class NopStmt(

data class AssignStmt(
override val location: StmtLocation,
val target: Local,
val target: LValue,
val expr: Expr,
) : Stmt

Expand Down
50 changes: 29 additions & 21 deletions jacodb-ets/src/main/kotlin/org/jacodb/ets/dsl/ToDot.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,19 @@

package org.jacodb.ets.dsl

import org.jacodb.ets.utils.toDotLabel
import java.util.IdentityHashMap

private fun Node.toDotLabel() = when (this) {
is Nop -> "nop"
is Assign -> "$target := $expr"
is Return -> "return $expr"
is If -> "if ($condition)"
is Label -> "label $name"
is Goto -> "goto $targetLabel"
is CustomEts -> "???"
private fun Node.toDotLabel(): String {
val label = when (this) {
is Nop -> "nop"
is Assign -> "$target := $expr"
is Return -> "return $expr"
is If -> "if ($condition)"
is Label -> "label $name"
is Goto -> "goto $targetLabel"
is CustomEts -> "???"
}
return label.replace("\"", "\\\"")
}

fun Program.toDot(): String {
Expand Down Expand Up @@ -99,12 +101,15 @@ fun Program.toDot(): String {
return lines.joinToString("\n")
}

private fun BlockStmt.toDotLabel() = when (this) {
is BlockAssign -> "$target := $expr"
is BlockReturn -> "return $expr"
is BlockIf -> "if ($condition)"
is BlockNop -> "nop"
is BlockCustomEts -> "???"
private fun BlockStmt.toDotLabel(): String {
val label = when (this) {
is BlockAssign -> "$target := $expr"
is BlockReturn -> "return $expr"
is BlockIf -> "if ($condition)"
is BlockNop -> "nop"
is BlockCustomEts -> "???"
}
return label.replace("\"", "\\\"")
}

fun BlockCfg.toDot(): String {
Expand Down Expand Up @@ -136,12 +141,15 @@ fun BlockCfg.toDot(): String {
return lines.joinToString("\n")
}

private fun Stmt.toDotLabel() = when (this) {
is NopStmt -> "nop"
is AssignStmt -> "$target := $expr"
is ReturnStmt -> "return $expr"
is IfStmt -> "if ($condition)"
is CustomEtsStmt -> "???"
private fun Stmt.toDotLabel(): String {
val label = when (this) {
is NopStmt -> "nop"
is AssignStmt -> "$target := $expr"
is ReturnStmt -> "return $expr"
is IfStmt -> "if ($condition)"
is CustomEtsStmt -> "???"
}
return label.replace("\"", "\\\"")
}

fun LinearizedCfg.toDot(): String {
Expand Down
6 changes: 3 additions & 3 deletions jacodb-ets/src/main/kotlin/org/jacodb/ets/model/Modifiers.kt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ interface WithModifiers {
val isDeclare: Boolean get() = hasModifier(EtsModifier.DECLARE)

fun hasModifier(modifier: EtsModifier): Boolean

val modifiersList: List<EtsModifier>
get() = EtsModifier.entries.filter { hasModifier(it) }
}

@JvmInline
Expand All @@ -64,8 +67,5 @@ value class EtsModifiers(val mask: Int) : WithModifiers {
}
}

val modifiers: List<EtsModifier>
get() = EtsModifier.entries.filter { hasModifier(it) }

override fun hasModifier(modifier: EtsModifier): Boolean = (mask and modifier.value) != 0
}
Loading
Loading