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
24 changes: 22 additions & 2 deletions jacodb-ets/src/main/kotlin/org/jacodb/ets/dto/Convert.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
package org.jacodb.ets.dto

import mu.KotlinLogging
import org.jacodb.ets.model.EtsDefineDataPropertyStmt
import org.jacodb.ets.model.EtsPropertyRef
import org.jacodb.ets.model.EtsToPropertyKeyExpr
import org.jacodb.ets.toArrayType
import org.jacodb.ets.model.BasicBlock
import org.jacodb.ets.model.EtsAddExpr
Expand Down Expand Up @@ -222,7 +225,7 @@ class EtsMethodBuilder(
}

private fun ensureOneAddress(entity: EtsEntity): EtsValue {
if (entity is EtsExpr || entity is EtsFieldRef || entity is EtsArrayAccess) {
if (entity is EtsExpr || entity is EtsFieldRef || entity is EtsArrayAccess || entity is EtsPropertyRef) {
return ensureLocal(entity)
} else {
if (entity !is EtsValue) {
Expand Down Expand Up @@ -275,6 +278,13 @@ class EtsMethodBuilder(
)
}

is DefineDataPropertyStmtDto -> EtsDefineDataPropertyStmt(
location = loc(),
target = (target as LocalDto).toEtsLocal(),
key = ensureOneAddress(key.toEtsEntity()),
value = ensureOneAddress(value.toEtsEntity()),
)

is CallStmtDto -> {
val expr = expr.toEtsEntity()
if (expr !is EtsCallExpr) {
Expand Down Expand Up @@ -351,6 +361,16 @@ class EtsMethodBuilder(
expectedCount = expectedCount,
)

is ToPropertyKeyExprDto -> EtsToPropertyKeyExpr(
arg = ensureOneAddress(arg.toEtsEntity()),
)

is PropertyRefDto -> EtsPropertyRef(
instance = (instance as LocalDto).toEtsLocal(),
key = ensureOneAddress(key.toEtsEntity()),
type = type.toEtsType(),
)

is NewArrayExprDto -> EtsNewArrayExpr(
elementType = elementType.toEtsType(),
size = size.toEtsEntity(),
Expand Down Expand Up @@ -565,7 +585,7 @@ class EtsMethodBuilder(

private fun EtsStmt.mayThrow(): Boolean = when (this) {
is EtsAssignStmt -> lhv !is EtsLocal || rhv.mayThrow()
is EtsCallStmt, is EtsThrowStmt -> true
is EtsDefineDataPropertyStmt, is EtsCallStmt, is EtsThrowStmt -> true
is EtsRawStmt -> true
is EtsIfStmt, is EtsNopStmt, is EtsReturnStmt -> false
else -> error("Unknown statement: ${this::class.java}")
Expand Down
8 changes: 8 additions & 0 deletions jacodb-ets/src/main/kotlin/org/jacodb/ets/dto/Stmts.kt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ data class AssignStmtDto(
val right: ValueDto,
) : StmtDto

@Serializable
@SerialName("DefineDataPropertyStmt")
data class DefineDataPropertyStmtDto(
val target: ValueDto,
val key: ValueDto,
val value: ValueDto,
) : StmtDto

@Serializable
@SerialName("CallStmt")
data class CallStmtDto(
Expand Down
16 changes: 16 additions & 0 deletions jacodb-ets/src/main/kotlin/org/jacodb/ets/dto/Values.kt
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,22 @@ data class SpreadExpansionExprDto(
override val type: TypeDto get() = UnknownTypeDto.toArrayType(dimensions = 1)
}

@Serializable
@SerialName("ToPropertyKeyExpr")
data class ToPropertyKeyExprDto(
val arg: ValueDto,
) : ExprDto {
override val type: TypeDto get() = UnknownTypeDto
}

@Serializable
@SerialName("PropertyRef")
data class PropertyRefDto(
val instance: ValueDto, // Local; polymorphic discriminator is required.
val key: ValueDto,
override val type: TypeDto,
) : RefDto

@Serializable
@SerialName("NewArrayExpr")
data class NewArrayExprDto(
Expand Down
15 changes: 15 additions & 0 deletions jacodb-ets/src/main/kotlin/org/jacodb/ets/model/Expr.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ interface EtsExpr : EtsEntity {
if (this is Default) return defaultVisit(expr)
error("Cannot handle ${expr::class.java.simpleName}: $expr")
}
fun visit(expr: EtsToPropertyKeyExpr): R {
if (this is Default) return defaultVisit(expr)
error("Cannot handle ${expr::class.java.simpleName}: $expr")
}
fun visit(expr: EtsNewArrayExpr): R
fun visit(expr: EtsCastExpr): R
fun visit(expr: EtsInstanceOfExpr): R
Expand Down Expand Up @@ -86,6 +90,7 @@ interface EtsExpr : EtsEntity {
interface Default<out R> : Visitor<R> {
override fun visit(expr: EtsNewExpr): R = defaultVisit(expr)
override fun visit(expr: EtsSpreadExpansionExpr): R = defaultVisit(expr)
override fun visit(expr: EtsToPropertyKeyExpr): R = defaultVisit(expr)
override fun visit(expr: EtsNewArrayExpr): R = defaultVisit(expr)
override fun visit(expr: EtsCastExpr): R = defaultVisit(expr)
override fun visit(expr: EtsInstanceOfExpr): R = defaultVisit(expr)
Expand Down Expand Up @@ -180,6 +185,16 @@ data class EtsSpreadExpansionExpr(

override fun toString(): String = "expandSpread($iterable, $expectedCount)"


override fun <R> accept(visitor: EtsExpr.Visitor<R>): R = visitor.visit(this)
}

/** ECMAScript ToPropertyKey (ToPrimitive with string hint, then string or symbol). */
data class EtsToPropertyKeyExpr(val arg: EtsValue) : EtsExpr {
override val type: EtsType get() = EtsUnknownType

override fun toString(): String = "toPropertyKey($arg)"

override fun <R> accept(visitor: EtsExpr.Visitor<R>): R = visitor.visit(this)
}

Expand Down
13 changes: 13 additions & 0 deletions jacodb-ets/src/main/kotlin/org/jacodb/ets/model/Ref.kt
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,19 @@ data class EtsArrayAccess(
}
}

/** ECMAScript property Get/Set, including prototypes and getter/setter invocation.
* [key] is the result of ToPropertyKey and must not be converted a second time.
*/
data class EtsPropertyRef(
val instance: EtsLocal,
val key: EtsValue,
override val type: EtsType,
) : EtsRef, EtsLValue {
override fun toString(): String = "$instance[$key]"

override fun <R> accept(visitor: EtsValue.Visitor<R>): R = visitor.visit(this)
}

interface EtsFieldRef : EtsRef, EtsLValue, CommonFieldRef {
override val instance: EtsLocal?
val field: EtsFieldSignature
Expand Down
21 changes: 21 additions & 0 deletions jacodb-ets/src/main/kotlin/org/jacodb/ets/model/Stmt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ interface EtsStmt : CommonInst {
interface Visitor<out R> {
fun visit(stmt: EtsNopStmt): R
fun visit(stmt: EtsAssignStmt): R
fun visit(stmt: EtsDefineDataPropertyStmt): R {
if (this is Default) return defaultVisit(stmt)
error("Cannot handle ${stmt::class.java.simpleName}: $stmt")
}
fun visit(stmt: EtsReturnStmt): R
fun visit(stmt: EtsThrowStmt): R
fun visit(stmt: EtsIfStmt): R
Expand All @@ -43,6 +47,7 @@ interface EtsStmt : CommonInst {
interface Default<out R> : Visitor<R> {
override fun visit(stmt: EtsNopStmt): R = defaultVisit(stmt)
override fun visit(stmt: EtsAssignStmt): R = defaultVisit(stmt)
override fun visit(stmt: EtsDefineDataPropertyStmt): R = defaultVisit(stmt)
override fun visit(stmt: EtsReturnStmt): R = defaultVisit(stmt)
override fun visit(stmt: EtsThrowStmt): R = defaultVisit(stmt)
override fun visit(stmt: EtsIfStmt): R = defaultVisit(stmt)
Expand Down Expand Up @@ -94,6 +99,22 @@ data class EtsAssignStmt(
}
}

/**
* CreateDataPropertyOrThrow: an own writable, enumerable, configurable data property.
* Replaces an existing accessor descriptor without invoking its setter.
* [key] has already been converted by ToPropertyKey.
*/
data class EtsDefineDataPropertyStmt(
override val location: EtsStmtLocation,
val target: EtsLocal,
val key: EtsValue,
val value: EtsValue,
) : EtsStmt {
override fun toString(): String = "defineDataProperty($target, $key, $value)"

override fun <R> accept(visitor: EtsStmt.Visitor<R>): R = visitor.visit(this)
}

interface EtsTerminatingStmt : EtsStmt

data class EtsReturnStmt(
Expand Down
5 changes: 5 additions & 0 deletions jacodb-ets/src/main/kotlin/org/jacodb/ets/model/Value.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ interface EtsValue : EtsEntity, CommonValue {
fun visit(value: EtsThis): R
fun visit(value: EtsParameterRef): R
fun visit(value: EtsArrayAccess): R
fun visit(value: EtsPropertyRef): R {
if (this is Default) return defaultVisit(value)
error("Cannot handle ${value::class.java.simpleName}: $value")
}
fun visit(value: EtsInstanceFieldRef): R
fun visit(value: EtsStaticFieldRef): R

Expand All @@ -59,6 +63,7 @@ interface EtsValue : EtsEntity, CommonValue {
override fun visit(value: EtsThis): R = defaultVisit(value)
override fun visit(value: EtsParameterRef): R = defaultVisit(value)
override fun visit(value: EtsArrayAccess): R = defaultVisit(value)
override fun visit(value: EtsPropertyRef): R = defaultVisit(value)
override fun visit(value: EtsInstanceFieldRef): R = defaultVisit(value)
override fun visit(value: EtsStaticFieldRef): R = defaultVisit(value)

Expand Down
12 changes: 12 additions & 0 deletions jacodb-ets/src/main/kotlin/org/jacodb/ets/utils/GetOperands.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import org.jacodb.ets.model.EtsCastExpr
import org.jacodb.ets.model.EtsCaughtExceptionRef
import org.jacodb.ets.model.EtsClosureFieldRef
import org.jacodb.ets.model.EtsConstant
import org.jacodb.ets.model.EtsDefineDataPropertyStmt
import org.jacodb.ets.model.EtsDeleteExpr
import org.jacodb.ets.model.EtsDivExpr
import org.jacodb.ets.model.EtsEntity
Expand Down Expand Up @@ -66,6 +67,7 @@ import org.jacodb.ets.model.EtsPostDecExpr
import org.jacodb.ets.model.EtsPostIncExpr
import org.jacodb.ets.model.EtsPreDecExpr
import org.jacodb.ets.model.EtsPreIncExpr
import org.jacodb.ets.model.EtsPropertyRef
import org.jacodb.ets.model.EtsPtrCallExpr
import org.jacodb.ets.model.EtsRawEntity
import org.jacodb.ets.model.EtsRawStmt
Expand All @@ -81,6 +83,7 @@ import org.jacodb.ets.model.EtsStringConstant
import org.jacodb.ets.model.EtsSubExpr
import org.jacodb.ets.model.EtsThis
import org.jacodb.ets.model.EtsThrowStmt
import org.jacodb.ets.model.EtsToPropertyKeyExpr
import org.jacodb.ets.model.EtsTypeOfExpr
import org.jacodb.ets.model.EtsUnaryPlusExpr
import org.jacodb.ets.model.EtsUndefinedConstant
Expand All @@ -104,6 +107,9 @@ private object StmtGetOperands : EtsStmt.Visitor<Sequence<EtsEntity>> {
override fun visit(stmt: EtsAssignStmt): Sequence<EtsEntity> =
sequenceOf(stmt.rhv)

override fun visit(stmt: EtsDefineDataPropertyStmt): Sequence<EtsEntity> =
sequenceOf(stmt.target, stmt.key, stmt.value)

override fun visit(stmt: EtsCallStmt): Sequence<EtsEntity> =
sequenceOf(stmt.expr)

Expand Down Expand Up @@ -173,6 +179,12 @@ private object EntityGetOperands : EtsEntity.Visitor<Sequence<EtsEntity>> {
override fun visit(expr: EtsNewExpr): Sequence<EtsEntity> =
listOfNotNull(expr.constructorValue).asSequence()

override fun visit(expr: EtsToPropertyKeyExpr): Sequence<EtsEntity> =
sequenceOf(expr.arg)

override fun visit(value: EtsPropertyRef): Sequence<EtsEntity> =
sequenceOf(value.instance, value.key)

override fun visit(expr: EtsNewArrayExpr): Sequence<EtsEntity> =
sequenceOf(expr.size)

Expand Down
21 changes: 21 additions & 0 deletions jacodb-ets/src/main/kotlin/org/jacodb/ets/utils/Handler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import org.jacodb.ets.model.EtsCastExpr
import org.jacodb.ets.model.EtsCaughtExceptionRef
import org.jacodb.ets.model.EtsClosureFieldRef
import org.jacodb.ets.model.EtsConstant
import org.jacodb.ets.model.EtsDefineDataPropertyStmt
import org.jacodb.ets.model.EtsDeleteExpr
import org.jacodb.ets.model.EtsDivExpr
import org.jacodb.ets.model.EtsEntity
Expand Down Expand Up @@ -66,6 +67,7 @@ import org.jacodb.ets.model.EtsPostDecExpr
import org.jacodb.ets.model.EtsPostIncExpr
import org.jacodb.ets.model.EtsPreDecExpr
import org.jacodb.ets.model.EtsPreIncExpr
import org.jacodb.ets.model.EtsPropertyRef
import org.jacodb.ets.model.EtsPtrCallExpr
import org.jacodb.ets.model.EtsRawEntity
import org.jacodb.ets.model.EtsRawStmt
Expand All @@ -81,6 +83,7 @@ import org.jacodb.ets.model.EtsStringConstant
import org.jacodb.ets.model.EtsSubExpr
import org.jacodb.ets.model.EtsThis
import org.jacodb.ets.model.EtsThrowStmt
import org.jacodb.ets.model.EtsToPropertyKeyExpr
import org.jacodb.ets.model.EtsTypeOfExpr
import org.jacodb.ets.model.EtsUnaryPlusExpr
import org.jacodb.ets.model.EtsUndefinedConstant
Expand Down Expand Up @@ -128,6 +131,13 @@ abstract class AbstractHandler : EtsEntity.Visitor<Unit>, EtsStmt.Visitor<Unit>
stmt.rhv.accept(this)
}

final override fun visit(stmt: EtsDefineDataPropertyStmt) {
handle(stmt)
stmt.target.accept(this)
stmt.key.accept(this)
stmt.value.accept(this)
}

final override fun visit(stmt: EtsCallStmt) {
handle(stmt)
stmt.expr.accept(this)
Expand Down Expand Up @@ -226,6 +236,17 @@ abstract class AbstractHandler : EtsEntity.Visitor<Unit>, EtsStmt.Visitor<Unit>
expr.constructorValue?.accept(this)
}

final override fun visit(expr: EtsToPropertyKeyExpr) {
handle(expr)
expr.arg.accept(this)
}

final override fun visit(value: EtsPropertyRef) {
handle(value)
value.instance.accept(this)
value.key.accept(this)
}

final override fun visit(expr: EtsNewArrayExpr) {
handle(expr)
expr.size.accept(this)
Expand Down
Loading