Skip to content

Commit ef95e61

Browse files
authored
Add FieldRef and ArrayAccess in CFG DSL (#352)
1 parent d3e9720 commit ef95e61

File tree

9 files changed

+155
-44
lines changed

9 files changed

+155
-44
lines changed

jacodb-ets/src/main/kotlin/org/jacodb/ets/dsl/BlockStmt.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ sealed interface BlockStmt
2424
data object BlockNop : BlockStmt
2525

2626
data class BlockAssign(
27-
val target: Local,
27+
val target: LValue,
2828
val expr: Expr,
2929
) : BlockStmt
3030

jacodb-ets/src/main/kotlin/org/jacodb/ets/dsl/DSL.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,21 @@ private fun main() {
6262
}
6363

6464
// x.foo := 35
65+
assign(local("x").field("foo"), const(35))
66+
67+
// arr[i] := 42
68+
assign(local("arr")[local("i")], const(42))
69+
70+
// MyClass.staticField := "hello"
71+
assign(staticFieldRef("MyClass", "staticField"), const("hello"))
72+
73+
// obj.field1.field2 := 100
74+
assign(local("obj").field("field1").field("field2"), const(100))
75+
76+
// objects[0].value := 99
77+
assign(local("objects")[const(0)].field("value"), const(99))
78+
79+
// x.foo := 35 (using CustomStmt approach)
6580
customStmt { loc ->
6681
EtsAssignStmt(
6782
location = loc,

jacodb-ets/src/main/kotlin/org/jacodb/ets/dsl/Expr.kt

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ package org.jacodb.ets.dsl
1818

1919
sealed interface Expr
2020

21-
data class Local(val name: String) : Expr {
21+
data class Local(val name: String) : LValue {
2222
override fun toString() = name
2323
}
2424

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

33+
data class ConstantInt(val value: Int) : Expr {
34+
override fun toString() = "const($value)"
35+
}
36+
3337
data class ConstantNumber(val value: Double) : Expr {
3438
override fun toString() = "const($value)"
3539
}
@@ -79,3 +83,26 @@ data class UnaryExpr(
7983
) : Expr {
8084
override fun toString() = "${operator.name.lowercase()}($expr)"
8185
}
86+
87+
sealed interface LValue : Expr
88+
89+
data class FieldRef(
90+
val instance: Expr,
91+
val fieldName: String,
92+
) : LValue {
93+
override fun toString() = "$instance.$fieldName"
94+
}
95+
96+
data class StaticFieldRef(
97+
val className: String,
98+
val fieldName: String,
99+
) : LValue {
100+
override fun toString() = "$className.$fieldName"
101+
}
102+
103+
data class ArrayAccess(
104+
val array: Expr,
105+
val index: Expr,
106+
) : LValue {
107+
override fun toString() = "$array[$index]"
108+
}

jacodb-ets/src/main/kotlin/org/jacodb/ets/dsl/Node.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ sealed interface Node
2424
data object Nop : Node
2525

2626
data class Assign(
27-
val target: Local,
27+
val target: LValue,
2828
val expr: Expr,
2929
) : Node
3030

jacodb-ets/src/main/kotlin/org/jacodb/ets/dsl/ProgramBuilder.kt

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import org.jacodb.ets.model.EtsStmtLocation
2424

2525
interface ProgramBuilder {
2626
fun nop()
27-
fun assign(target: Local, expr: Expr)
27+
fun assign(target: LValue, expr: Expr)
2828
fun ret(expr: Expr)
2929
fun label(name: String)
3030
fun goto(label: String)
@@ -36,11 +36,18 @@ interface ProgramBuilder {
3636
fun ProgramBuilder.local(name: String) = Local(name)
3737
fun ProgramBuilder.param(index: Int) = Parameter(index)
3838
fun ProgramBuilder.thisRef() = ThisRef
39-
fun ProgramBuilder.const(value: Int) = ConstantNumber(value.toDouble())
39+
fun ProgramBuilder.const(value: Int) = ConstantInt(value)
4040
fun ProgramBuilder.const(value: Double) = ConstantNumber(value)
4141
fun ProgramBuilder.const(value: Boolean) = ConstantBoolean(value)
4242
fun ProgramBuilder.const(value: String) = ConstantString(value)
4343

44+
fun ProgramBuilder.fieldRef(instance: Expr, fieldName: String) = FieldRef(instance, fieldName)
45+
fun ProgramBuilder.staticFieldRef(className: String, fieldName: String) = StaticFieldRef(className, fieldName)
46+
fun ProgramBuilder.arrayAccess(array: Expr, index: Expr) = ArrayAccess(array, index)
47+
48+
fun Expr.field(name: String) = FieldRef(this, name)
49+
operator fun Expr.get(index: Expr) = ArrayAccess(this, index)
50+
4451
fun ProgramBuilder.and(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.AND, left, right)
4552
fun ProgramBuilder.or(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.OR, left, right)
4653
fun ProgramBuilder.eq(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.EQ, left, right)
@@ -89,7 +96,7 @@ class ProgramBuilderImpl : ProgramBuilder {
8996
_nodes += Nop
9097
}
9198

92-
override fun assign(target: Local, expr: Expr) {
99+
override fun assign(target: LValue, expr: Expr) {
93100
_nodes += Assign(target, expr)
94101
}
95102

@@ -140,7 +147,7 @@ class IfBuilder : ProgramBuilder {
140147
thenBuilder.ifStmt(condition, block)
141148

142149
override fun nop() = thenBuilder.nop()
143-
override fun assign(target: Local, expr: Expr) = thenBuilder.assign(target, expr)
150+
override fun assign(target: LValue, expr: Expr) = thenBuilder.assign(target, expr)
144151
override fun ret(expr: Expr) = thenBuilder.ret(expr)
145152
override fun label(name: String) = thenBuilder.label(name)
146153
override fun goto(label: String) = thenBuilder.goto(label)

jacodb-ets/src/main/kotlin/org/jacodb/ets/dsl/Stmt.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ data class NopStmt(
3131

3232
data class AssignStmt(
3333
override val location: StmtLocation,
34-
val target: Local,
34+
val target: LValue,
3535
val expr: Expr,
3636
) : Stmt
3737

jacodb-ets/src/main/kotlin/org/jacodb/ets/dsl/ToDot.kt

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,19 @@
1616

1717
package org.jacodb.ets.dsl
1818

19-
import org.jacodb.ets.utils.toDotLabel
2019
import java.util.IdentityHashMap
2120

22-
private fun Node.toDotLabel() = when (this) {
23-
is Nop -> "nop"
24-
is Assign -> "$target := $expr"
25-
is Return -> "return $expr"
26-
is If -> "if ($condition)"
27-
is Label -> "label $name"
28-
is Goto -> "goto $targetLabel"
29-
is CustomEts -> "???"
21+
private fun Node.toDotLabel(): String {
22+
val label = when (this) {
23+
is Nop -> "nop"
24+
is Assign -> "$target := $expr"
25+
is Return -> "return $expr"
26+
is If -> "if ($condition)"
27+
is Label -> "label $name"
28+
is Goto -> "goto $targetLabel"
29+
is CustomEts -> "???"
30+
}
31+
return label.replace("\"", "\\\"")
3032
}
3133

3234
fun Program.toDot(): String {
@@ -99,12 +101,15 @@ fun Program.toDot(): String {
99101
return lines.joinToString("\n")
100102
}
101103

102-
private fun BlockStmt.toDotLabel() = when (this) {
103-
is BlockAssign -> "$target := $expr"
104-
is BlockReturn -> "return $expr"
105-
is BlockIf -> "if ($condition)"
106-
is BlockNop -> "nop"
107-
is BlockCustomEts -> "???"
104+
private fun BlockStmt.toDotLabel(): String {
105+
val label = when (this) {
106+
is BlockAssign -> "$target := $expr"
107+
is BlockReturn -> "return $expr"
108+
is BlockIf -> "if ($condition)"
109+
is BlockNop -> "nop"
110+
is BlockCustomEts -> "???"
111+
}
112+
return label.replace("\"", "\\\"")
108113
}
109114

110115
fun BlockCfg.toDot(): String {
@@ -136,12 +141,15 @@ fun BlockCfg.toDot(): String {
136141
return lines.joinToString("\n")
137142
}
138143

139-
private fun Stmt.toDotLabel() = when (this) {
140-
is NopStmt -> "nop"
141-
is AssignStmt -> "$target := $expr"
142-
is ReturnStmt -> "return $expr"
143-
is IfStmt -> "if ($condition)"
144-
is CustomEtsStmt -> "???"
144+
private fun Stmt.toDotLabel(): String {
145+
val label = when (this) {
146+
is NopStmt -> "nop"
147+
is AssignStmt -> "$target := $expr"
148+
is ReturnStmt -> "return $expr"
149+
is IfStmt -> "if ($condition)"
150+
is CustomEtsStmt -> "???"
151+
}
152+
return label.replace("\"", "\\\"")
145153
}
146154

147155
fun LinearizedCfg.toDot(): String {

jacodb-ets/src/main/kotlin/org/jacodb/ets/model/Modifiers.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ interface WithModifiers {
5252
val isDeclare: Boolean get() = hasModifier(EtsModifier.DECLARE)
5353

5454
fun hasModifier(modifier: EtsModifier): Boolean
55+
56+
val modifiersList: List<EtsModifier>
57+
get() = EtsModifier.entries.filter { hasModifier(it) }
5558
}
5659

5760
@JvmInline
@@ -64,8 +67,5 @@ value class EtsModifiers(val mask: Int) : WithModifiers {
6467
}
6568
}
6669

67-
val modifiers: List<EtsModifier>
68-
get() = EtsModifier.entries.filter { hasModifier(it) }
69-
7070
override fun hasModifier(modifier: EtsModifier): Boolean = (mask and modifier.value) != 0
7171
}

0 commit comments

Comments
 (0)