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
22 changes: 11 additions & 11 deletions jacodb-ets/src/main/kotlin/org/jacodb/ets/dsl/DSL.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,26 @@ private fun main() {
val prog = program {
assign(local("i"), param(0))

ifStmt(gt(local("i"), const(10.0))) {
ifStmt(eq(local("i"), const(42.0))) {
ifStmt(gt(local("i"), const(10))) {
ifStmt(eq(local("i"), const(42))) {
ret(local("i"))
`else` {
assign(local("i"), const(10.0))
}
}.elseIf(eq(local("i"), const(20))) {
ret(local("i"))
}.`else` {
assign(local("i"), const(10))
}
nop()
}

label("loop")
ifStmt(gt(local("i"), const(0.0))) {
assign(local("i"), sub(local("i"), const(1.0)))
ifStmt(gt(local("i"), const(0))) {
assign(local("i"), sub(local("i"), const(1)))
goto("loop")
`else` {
ret(local("i"))
}
}.`else` {
ret(local("i"))
}

ret(const(42.0)) // unreachable
ret(const(100)) // unreachable
}

val doView = false
Expand Down
29 changes: 25 additions & 4 deletions jacodb-ets/src/main/kotlin/org/jacodb/ets/dsl/Expr.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,35 @@ object ThisRef : Expr {
override fun toString() = "this"
}

data class Constant(val value: Double) : Expr {
data class ConstantNumber(val value: Double) : Expr {
override fun toString() = "const($value)"
}

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

data class ConstantString(val value: String) : Expr {
override fun toString() = "const(\"$value\")"
}

enum class BinaryOperator {
AND, OR,
EQ, NEQ, LT, LTE, GT, GTE,
ADD, SUB, MUL, DIV
AND, // &&
OR, // ||
EQ, // ==
NEQ, // !=
EQQ, // ===
NEQQ, // !==
LT, // <
LTE, // <=
GT, // >
GTE, // >=
ADD, // +
SUB, // -
MUL, // *
DIV, // /
REM, // %
// TODO: shift
}

data class BinaryExpr(
Expand Down
104 changes: 69 additions & 35 deletions jacodb-ets/src/main/kotlin/org/jacodb/ets/dsl/ProgramBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,35 +18,60 @@

package org.jacodb.ets.dsl

import org.jacodb.ets.model.EtsEntity

interface ProgramBuilder {
fun nop()
fun assign(target: Local, expr: Expr)
fun ret(expr: Expr)
fun ifStmt(condition: Expr, block: IfBuilder.() -> Unit)
fun nop()
fun label(name: String)
fun goto(label: String)
fun ifStmt(condition: Expr, block: ProgramBuilder.() -> Unit): IfBuilder
}

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: Double) = ConstantNumber(value)
fun ProgramBuilder.const(value: Boolean) = ConstantBoolean(value)
fun ProgramBuilder.const(value: String) = ConstantString(value)

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)
fun ProgramBuilder.neq(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.NEQ, left, right)
fun ProgramBuilder.eqq(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.EQQ, left, right)
Comment thread
Lipen marked this conversation as resolved.
fun ProgramBuilder.neqq(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.NEQQ, left, right)
fun ProgramBuilder.lt(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.LT, left, right)
fun ProgramBuilder.leq(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.LTE, left, right)
fun ProgramBuilder.gt(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.GT, left, right)
fun ProgramBuilder.geq(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.GTE, left, right)
fun ProgramBuilder.add(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.ADD, left, right)
fun ProgramBuilder.sub(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.SUB, left, right)
fun ProgramBuilder.mul(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.MUL, left, right)
fun ProgramBuilder.div(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.DIV, left, right)
fun ProgramBuilder.rem(left: Expr, right: Expr) = BinaryExpr(BinaryOperator.REM, left, right)

fun ProgramBuilder.not(expr: Expr) = UnaryExpr(UnaryOperator.NOT, expr)
fun ProgramBuilder.neg(expr: Expr) = UnaryExpr(UnaryOperator.NEG, expr)

class CustomValue(
val toEts: () -> EtsEntity,
) : Expr {
constructor(value: EtsEntity) : this({ value })
}

fun ProgramBuilder.local(name: String): Local = Local(name)
fun ProgramBuilder.param(index: Int): Parameter = Parameter(index)
fun ProgramBuilder.thisRef(): Expr = ThisRef
fun ProgramBuilder.const(value: Double): Constant = Constant(value)

fun ProgramBuilder.and(left: Expr, right: Expr): Expr = BinaryExpr(BinaryOperator.AND, left, right)
fun ProgramBuilder.or(left: Expr, right: Expr): Expr = BinaryExpr(BinaryOperator.OR, left, right)
fun ProgramBuilder.eq(left: Expr, right: Expr): Expr = BinaryExpr(BinaryOperator.EQ, left, right)
fun ProgramBuilder.neq(left: Expr, right: Expr): Expr = BinaryExpr(BinaryOperator.NEQ, left, right)
fun ProgramBuilder.lt(left: Expr, right: Expr): Expr = BinaryExpr(BinaryOperator.LT, left, right)
fun ProgramBuilder.leq(left: Expr, right: Expr): Expr = BinaryExpr(BinaryOperator.LTE, left, right)
fun ProgramBuilder.gt(left: Expr, right: Expr): Expr = BinaryExpr(BinaryOperator.GT, left, right)
fun ProgramBuilder.geq(left: Expr, right: Expr): Expr = BinaryExpr(BinaryOperator.GTE, left, right)
fun ProgramBuilder.add(left: Expr, right: Expr): Expr = BinaryExpr(BinaryOperator.ADD, left, right)
fun ProgramBuilder.sub(left: Expr, right: Expr): Expr = BinaryExpr(BinaryOperator.SUB, left, right)
fun ProgramBuilder.mul(left: Expr, right: Expr): Expr = BinaryExpr(BinaryOperator.MUL, left, right)
fun ProgramBuilder.div(left: Expr, right: Expr): Expr = BinaryExpr(BinaryOperator.DIV, left, right)

fun ProgramBuilder.not(expr: Expr): Expr = UnaryExpr(UnaryOperator.NOT, expr)
fun ProgramBuilder.neg(expr: Expr): Expr = UnaryExpr(UnaryOperator.NEG, expr)
class CustomUnaryExpr(
val arg: Expr,
val toEts: (arg: EtsEntity) -> EtsEntity,
) : Expr

class CustomBinaryExpr(
val left: Expr,
val right: Expr,
val toEts: (left: EtsEntity, right: EtsEntity) -> EtsEntity,
) : Expr

class ProgramBuilderImpl : ProgramBuilder {
private val _nodes: MutableList<Node> = mutableListOf()
Expand All @@ -60,46 +85,55 @@ class ProgramBuilderImpl : ProgramBuilder {
_nodes += Nop
}

override fun label(name: String) {
_nodes += Label(name)
}

override fun goto(label: String) {
_nodes += Goto(label)
override fun assign(target: Local, expr: Expr) {
_nodes += Assign(target, expr)
}

override fun ret(expr: Expr) {
_nodes += Return(expr)
}

override fun assign(target: Local, expr: Expr) {
_nodes += Assign(target, expr)
override fun label(name: String) {
_nodes += Label(name)
}

override fun goto(label: String) {
_nodes += Goto(label)
}

override fun ifStmt(condition: Expr, block: IfBuilder.() -> Unit) {
override fun ifStmt(condition: Expr, block: ProgramBuilder.() -> Unit): IfBuilder {
val builder = IfBuilder().apply(block)
_nodes += If(condition, builder.thenNodes, builder.elseNodes)
return builder
}
}

class IfBuilder : ProgramBuilder {
private val thenBuilder = ProgramBuilderImpl()
private val elseBuilder = ProgramBuilderImpl()
private var elseEntered = false

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

private var elseEntered = false

fun `else`(block: ProgramBuilder.() -> Unit) {
check(!elseEntered) { "Multiple else branches" }
elseEntered = true
elseBuilder.apply(block)
}

fun elseIf(condition: Expr, block: ProgramBuilder.() -> Unit): IfBuilder {
elseBuilder.ifStmt(condition, block)
return this
}

override fun ifStmt(condition: Expr, block: ProgramBuilder.() -> Unit): IfBuilder =
thenBuilder.ifStmt(condition, block)

override fun nop() = thenBuilder.nop()
override fun assign(target: Local, expr: Expr) = thenBuilder.assign(target, expr)
override fun ifStmt(condition: Expr, block: IfBuilder.() -> Unit) = thenBuilder.ifStmt(condition, block)
override fun ret(expr: Expr) = thenBuilder.ret(expr)
override fun nop() = thenBuilder.nop()
override fun goto(label: String) = thenBuilder.goto(label)
override fun label(name: String) = thenBuilder.label(name)
override fun goto(label: String) = thenBuilder.goto(label)
}
Loading
Loading