@@ -13,18 +13,22 @@ import org.jacodb.ets.base.EtsUnionType
1313import org.jacodb.ets.base.EtsUnknownType
1414import org.jacodb.ets.model.EtsScene
1515import org.usvm.UAddressSort
16+ import org.usvm.UBoolExpr
1617import org.usvm.UBoolSort
1718import org.usvm.UBv32Sort
1819import org.usvm.UConcreteHeapRef
1920import org.usvm.UContext
2021import org.usvm.UExpr
22+ import org.usvm.UHeapRef
2123import org.usvm.USort
24+ import org.usvm.api.typeStreamOf
2225import org.usvm.collection.field.UFieldLValue
2326import org.usvm.isTrue
2427import org.usvm.machine.expr.TsUndefinedSort
2528import org.usvm.machine.expr.TsUnresolvedSort
2629import org.usvm.machine.interpreter.TsStepScope
2730import org.usvm.machine.types.FakeType
31+ import org.usvm.types.UTypeStream
2832import org.usvm.types.single
2933import org.usvm.util.mkFieldLValue
3034import kotlin.contracts.ExperimentalContracts
@@ -44,8 +48,11 @@ class TsContext(
4448 * In TS we treat undefined value as a null reference in other objects.
4549 * For real null represented in the language we create another reference.
4650 */
47- private val undefinedValue: UExpr <UAddressSort >
48- get() = mkNullRef()
51+ private val undefinedValue: UExpr <UAddressSort > = mkNullRef()
52+ fun mkUndefinedValue (): UExpr <UAddressSort > = undefinedValue
53+
54+ private val nullValue: UConcreteHeapRef = mkConcreteHeapRef(addressCounter.freshStaticAddress())
55+ fun mkTsNullValue (): UConcreteHeapRef = nullValue
4956
5057 fun typeToSort (type : EtsType ): USort = when (type) {
5158 is EtsBooleanType -> boolSort
@@ -59,6 +66,14 @@ class TsContext(
5966 else -> TODO (" Support all JacoDB types, encountered $type " )
6067 }
6168
69+ fun UHeapRef.getTypeStream (scope : TsStepScope ): UTypeStream <EtsType > =
70+ scope.calcOnState {
71+ memory.typeStreamOf(this @getTypeStream)
72+ }
73+
74+ fun UConcreteHeapRef.getFakeType (scope : TsStepScope ): FakeType =
75+ getTypeStream(scope).single() as FakeType
76+
6277 @OptIn(ExperimentalContracts ::class )
6378 fun UExpr <out USort >.isFakeObject (): Boolean {
6479 contract {
@@ -136,22 +151,35 @@ class TsContext(
136151 return mkConcreteHeapRef(address)
137152 }
138153
139- fun mkUndefinedValue (): UExpr <UAddressSort > = undefinedValue
140-
141- fun mkTsNullValue (): UConcreteHeapRef = nullValue
142- private val nullValue: UConcreteHeapRef = mkConcreteHeapRef(addressCounter.freshStaticAddress())
143-
144154 fun getIntermediateBoolLValue (addr : Int ): UFieldLValue <IntermediateLValueField , UBoolSort > {
155+ require(addr > MAGIC_OFFSET )
145156 return mkFieldLValue(boolSort, mkConcreteHeapRef(addr), IntermediateLValueField .BOOL )
146157 }
147158
148159 fun getIntermediateFpLValue (addr : Int ): UFieldLValue <IntermediateLValueField , KFp64Sort > {
160+ require(addr > MAGIC_OFFSET )
149161 return mkFieldLValue(fp64Sort, mkConcreteHeapRef(addr), IntermediateLValueField .FP )
150162 }
151163
152164 fun getIntermediateRefLValue (addr : Int ): UFieldLValue <IntermediateLValueField , UAddressSort > {
165+ require(addr > MAGIC_OFFSET )
153166 return mkFieldLValue(addressSort, mkConcreteHeapRef(addr), IntermediateLValueField .REF )
154167 }
168+
169+ fun UConcreteHeapRef.extractBool (scope : TsStepScope ): UBoolExpr {
170+ val lValue = getIntermediateBoolLValue(address)
171+ return scope.calcOnState { memory.read(lValue) }
172+ }
173+
174+ fun UConcreteHeapRef.extractFp (scope : TsStepScope ): UExpr <KFp64Sort > {
175+ val lValue = getIntermediateFpLValue(address)
176+ return scope.calcOnState { memory.read(lValue) }
177+ }
178+
179+ fun UConcreteHeapRef.extractRef (scope : TsStepScope ): UHeapRef {
180+ val lValue = getIntermediateRefLValue(address)
181+ return scope.calcOnState { memory.read(lValue) }
182+ }
155183}
156184
157185const val MAGIC_OFFSET = 1000000
0 commit comments