Skip to content

Commit 213f9a1

Browse files
authored
Add CustomValue, add bool/int/string constants, improve ifStmt builder in CFG DSL (#340)
1 parent c12d7e5 commit 213f9a1

4 files changed

Lines changed: 278 additions & 162 deletions

File tree

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

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,26 +22,26 @@ private fun main() {
2222
val prog = program {
2323
assign(local("i"), param(0))
2424

25-
ifStmt(gt(local("i"), const(10.0))) {
26-
ifStmt(eq(local("i"), const(42.0))) {
25+
ifStmt(gt(local("i"), const(10))) {
26+
ifStmt(eq(local("i"), const(42))) {
2727
ret(local("i"))
28-
`else` {
29-
assign(local("i"), const(10.0))
30-
}
28+
}.elseIf(eq(local("i"), const(20))) {
29+
ret(local("i"))
30+
}.`else` {
31+
assign(local("i"), const(10))
3132
}
3233
nop()
3334
}
3435

3536
label("loop")
36-
ifStmt(gt(local("i"), const(0.0))) {
37-
assign(local("i"), sub(local("i"), const(1.0)))
37+
ifStmt(gt(local("i"), const(0))) {
38+
assign(local("i"), sub(local("i"), const(1)))
3839
goto("loop")
39-
`else` {
40-
ret(local("i"))
41-
}
40+
}.`else` {
41+
ret(local("i"))
4242
}
4343

44-
ret(const(42.0)) // unreachable
44+
ret(const(100)) // unreachable
4545
}
4646

4747
val doView = false

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

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,35 @@ object ThisRef : Expr {
3030
override fun toString() = "this"
3131
}
3232

33-
data class Constant(val value: Double) : Expr {
33+
data class ConstantNumber(val value: Double) : Expr {
3434
override fun toString() = "const($value)"
3535
}
3636

37+
data class ConstantBoolean(val value: Boolean) : Expr {
38+
override fun toString() = "const($value)"
39+
}
40+
41+
data class ConstantString(val value: String) : Expr {
42+
override fun toString() = "const(\"$value\")"
43+
}
44+
3745
enum class BinaryOperator {
38-
AND, OR,
39-
EQ, NEQ, LT, LTE, GT, GTE,
40-
ADD, SUB, MUL, DIV
46+
AND, // &&
47+
OR, // ||
48+
EQ, // ==
49+
NEQ, // !=
50+
EQQ, // ===
51+
NEQQ, // !==
52+
LT, // <
53+
LTE, // <=
54+
GT, // >
55+
GTE, // >=
56+
ADD, // +
57+
SUB, // -
58+
MUL, // *
59+
DIV, // /
60+
REM, // %
61+
// TODO: shift
4162
}
4263

4364
data class BinaryExpr(

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

Lines changed: 69 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -18,35 +18,60 @@
1818

1919
package org.jacodb.ets.dsl
2020

21+
import org.jacodb.ets.model.EtsEntity
22+
2123
interface ProgramBuilder {
24+
fun nop()
2225
fun assign(target: Local, expr: Expr)
2326
fun ret(expr: Expr)
24-
fun ifStmt(condition: Expr, block: IfBuilder.() -> Unit)
25-
fun nop()
2627
fun label(name: String)
2728
fun goto(label: String)
29+
fun ifStmt(condition: Expr, block: ProgramBuilder.() -> Unit): IfBuilder
30+
}
31+
32+
fun ProgramBuilder.local(name: String) = Local(name)
33+
fun ProgramBuilder.param(index: Int) = Parameter(index)
34+
fun ProgramBuilder.thisRef() = ThisRef
35+
fun ProgramBuilder.const(value: Int) = ConstantNumber(value.toDouble())
36+
fun ProgramBuilder.const(value: Double) = ConstantNumber(value)
37+
fun ProgramBuilder.const(value: Boolean) = ConstantBoolean(value)
38+
fun ProgramBuilder.const(value: String) = ConstantString(value)
39+
40+
fun ProgramBuilder.and(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.AND, left, right)
41+
fun ProgramBuilder.or(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.OR, left, right)
42+
fun ProgramBuilder.eq(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.EQ, left, right)
43+
fun ProgramBuilder.neq(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.NEQ, left, right)
44+
fun ProgramBuilder.eqq(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.EQQ, left, right)
45+
fun ProgramBuilder.neqq(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.NEQQ, left, right)
46+
fun ProgramBuilder.lt(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.LT, left, right)
47+
fun ProgramBuilder.leq(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.LTE, left, right)
48+
fun ProgramBuilder.gt(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.GT, left, right)
49+
fun ProgramBuilder.geq(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.GTE, left, right)
50+
fun ProgramBuilder.add(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.ADD, left, right)
51+
fun ProgramBuilder.sub(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.SUB, left, right)
52+
fun ProgramBuilder.mul(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.MUL, left, right)
53+
fun ProgramBuilder.div(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.DIV, left, right)
54+
fun ProgramBuilder.rem(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.REM, left, right)
55+
56+
fun ProgramBuilder.not(expr: Expr) = UnaryExpr(UnaryOperator.NOT, expr)
57+
fun ProgramBuilder.neg(expr: Expr) = UnaryExpr(UnaryOperator.NEG, expr)
58+
59+
class CustomValue(
60+
val toEts: () -> EtsEntity,
61+
) : Expr {
62+
constructor(value: EtsEntity) : this({ value })
2863
}
2964

30-
fun ProgramBuilder.local(name: String): Local = Local(name)
31-
fun ProgramBuilder.param(index: Int): Parameter = Parameter(index)
32-
fun ProgramBuilder.thisRef(): Expr = ThisRef
33-
fun ProgramBuilder.const(value: Double): Constant = Constant(value)
34-
35-
fun ProgramBuilder.and(left: Expr, right: Expr): Expr = BinaryExpr(BinaryOperator.AND, left, right)
36-
fun ProgramBuilder.or(left: Expr, right: Expr): Expr = BinaryExpr(BinaryOperator.OR, left, right)
37-
fun ProgramBuilder.eq(left: Expr, right: Expr): Expr = BinaryExpr(BinaryOperator.EQ, left, right)
38-
fun ProgramBuilder.neq(left: Expr, right: Expr): Expr = BinaryExpr(BinaryOperator.NEQ, left, right)
39-
fun ProgramBuilder.lt(left: Expr, right: Expr): Expr = BinaryExpr(BinaryOperator.LT, left, right)
40-
fun ProgramBuilder.leq(left: Expr, right: Expr): Expr = BinaryExpr(BinaryOperator.LTE, left, right)
41-
fun ProgramBuilder.gt(left: Expr, right: Expr): Expr = BinaryExpr(BinaryOperator.GT, left, right)
42-
fun ProgramBuilder.geq(left: Expr, right: Expr): Expr = BinaryExpr(BinaryOperator.GTE, left, right)
43-
fun ProgramBuilder.add(left: Expr, right: Expr): Expr = BinaryExpr(BinaryOperator.ADD, left, right)
44-
fun ProgramBuilder.sub(left: Expr, right: Expr): Expr = BinaryExpr(BinaryOperator.SUB, left, right)
45-
fun ProgramBuilder.mul(left: Expr, right: Expr): Expr = BinaryExpr(BinaryOperator.MUL, left, right)
46-
fun ProgramBuilder.div(left: Expr, right: Expr): Expr = BinaryExpr(BinaryOperator.DIV, left, right)
47-
48-
fun ProgramBuilder.not(expr: Expr): Expr = UnaryExpr(UnaryOperator.NOT, expr)
49-
fun ProgramBuilder.neg(expr: Expr): Expr = UnaryExpr(UnaryOperator.NEG, expr)
65+
class CustomUnaryExpr(
66+
val arg: Expr,
67+
val toEts: (arg: EtsEntity) -> EtsEntity,
68+
) : Expr
69+
70+
class CustomBinaryExpr(
71+
val left: Expr,
72+
val right: Expr,
73+
val toEts: (left: EtsEntity, right: EtsEntity) -> EtsEntity,
74+
) : Expr
5075

5176
class ProgramBuilderImpl : ProgramBuilder {
5277
private val _nodes: MutableList<Node> = mutableListOf()
@@ -60,46 +85,55 @@ class ProgramBuilderImpl : ProgramBuilder {
6085
_nodes += Nop
6186
}
6287

63-
override fun label(name: String) {
64-
_nodes += Label(name)
65-
}
66-
67-
override fun goto(label: String) {
68-
_nodes += Goto(label)
88+
override fun assign(target: Local, expr: Expr) {
89+
_nodes += Assign(target, expr)
6990
}
7091

7192
override fun ret(expr: Expr) {
7293
_nodes += Return(expr)
7394
}
7495

75-
override fun assign(target: Local, expr: Expr) {
76-
_nodes += Assign(target, expr)
96+
override fun label(name: String) {
97+
_nodes += Label(name)
98+
}
99+
100+
override fun goto(label: String) {
101+
_nodes += Goto(label)
77102
}
78103

79-
override fun ifStmt(condition: Expr, block: IfBuilder.() -> Unit) {
104+
override fun ifStmt(condition: Expr, block: ProgramBuilder.() -> Unit): IfBuilder {
80105
val builder = IfBuilder().apply(block)
81106
_nodes += If(condition, builder.thenNodes, builder.elseNodes)
107+
return builder
82108
}
83109
}
84110

85111
class IfBuilder : ProgramBuilder {
86112
private val thenBuilder = ProgramBuilderImpl()
87113
private val elseBuilder = ProgramBuilderImpl()
88-
private var elseEntered = false
89114

90115
val thenNodes: List<Node> get() = thenBuilder.nodes
91116
val elseNodes: List<Node> get() = elseBuilder.nodes
92117

118+
private var elseEntered = false
119+
93120
fun `else`(block: ProgramBuilder.() -> Unit) {
94121
check(!elseEntered) { "Multiple else branches" }
95122
elseEntered = true
96123
elseBuilder.apply(block)
97124
}
98125

126+
fun elseIf(condition: Expr, block: ProgramBuilder.() -> Unit): IfBuilder {
127+
elseBuilder.ifStmt(condition, block)
128+
return this
129+
}
130+
131+
override fun ifStmt(condition: Expr, block: ProgramBuilder.() -> Unit): IfBuilder =
132+
thenBuilder.ifStmt(condition, block)
133+
134+
override fun nop() = thenBuilder.nop()
99135
override fun assign(target: Local, expr: Expr) = thenBuilder.assign(target, expr)
100-
override fun ifStmt(condition: Expr, block: IfBuilder.() -> Unit) = thenBuilder.ifStmt(condition, block)
101136
override fun ret(expr: Expr) = thenBuilder.ret(expr)
102-
override fun nop() = thenBuilder.nop()
103-
override fun goto(label: String) = thenBuilder.goto(label)
104137
override fun label(name: String) = thenBuilder.label(name)
138+
override fun goto(label: String) = thenBuilder.goto(label)
105139
}

0 commit comments

Comments
 (0)