-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Basic USVM TS type system with type coercion #215
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
detekt found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.
This PR indirectly introduces a bug |
|
||
class TSTestResolver { | ||
class TSTestResolver( | ||
private val state: TSState |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why? Resolver should be able to resolve many states independently
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TSTestResolver
was instantiated for each returned state, and I needed access to state.typeStorage
.
So I decided to add state as private constructor param.
private fun approximateParam(expr: UConcreteHeapRef, idx: Int, model: UModelBase<EtsType>): TSObject = | ||
with(expr.ctx as TSContext) { | ||
val suggestedType = state.getSuggestedType(idx) | ||
return suggestedType?.let { newType -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something odd is happening here. You can always access all required information using symbolic values and symbolic values only, otherwise you will encounter path divergence. This map cannot be built from concrete values to type info, only from symbolic ones
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe different types of ref entities (reg readings, etc.) have unique ways to generate a key. For example, reg readings can use its' idx
field as a key, and this key leads to correct list of types from any model.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But you might store it with another key -- if I resolve something from registerReading(1), it doesn't mean that I always accessed this value using this key. Probably, I could do it with registerReading(2).getByIndex(3), i could have accessed it with RR(3) (because of aliasing) and many many other ways
// TODO: draft | ||
override fun internEquals(other: Any): Boolean = structurallyEqual(other) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is it a draft? Seems like we can implement it
private fun generateAdditionalExprs(rawExprs: List<UExpr<out USort>>): List<UExpr<out USort>> = with(ctx) { | ||
if (!rawExprs.all { it.sort == boolSort }) return emptyList() | ||
val newExpr = when (baseExpr.sort) { | ||
addressSort -> addedExprCache.putOrNull(mkEq(fpToBoolSort(asFp64()), asBool())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why don't we need to add a connection between baseSort expr and them? If it already exists for baseSort <-> fp and bool, it exists for bool and fp by transitivity as well
private fun approximateParam(expr: UConcreteHeapRef, idx: Int, model: UModelBase<EtsType>): TSObject = | ||
with(expr.ctx as TSContext) { | ||
val suggestedType = state.getSuggestedType(idx) | ||
return suggestedType?.let { newType -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But you might store it with another key -- if I resolve something from registerReading(1), it doesn't mean that I always accessed this value using this key. Probably, I could do it with registerReading(2).getByIndex(3), i could have accessed it with RR(3) (because of aliasing) and many many other ways
|
||
private fun approximateParam(expr: UConcreteHeapRef, idx: Int, model: UModelBase<EtsType>): TSObject = | ||
when (val tr = model.typeStreamOf(expr).take(1)) { | ||
is TypesResult.SuccessfulTypesResult -> with (expr.tctx) { |
Check warning
Code scanning / detekt
Reports spaces around parentheses
} | ||
|
||
val types = primitiveTypes.toMutableList() | ||
return when (val remainingTypes = anyTypeStream.take(n - primitiveTypes.size)) { |
Check warning
Code scanning / detekt
Braces do not comply with the specified policy Warning
// (primitives can't be cast to ref in TypeScript type coercion) | ||
addressSort -> { | ||
val fpToBoolLink = mkEq(fpToBoolSort(asFp64()), asBool()) | ||
val boolToRefLink = mkEq(asBool(), (baseExpr as UExpr<UAddressSort>).neq(mkNullRef())) |
Check warning
Code scanning / detekt
Reports multiple space usages
@@ -0,0 +1,111 @@ | |||
package org.usvm.machine.expr | |||
|
|||
import io.ksmt.KAst |
Check warning
Code scanning / detekt
Detects imports in non default order
private fun coerce( | ||
other: UExpr<out USort>, | ||
action: CoerceAction, | ||
): UExpr<out USort> = when (other) { |
Check warning
Code scanning / detekt
Braces do not comply with the specified policy
@@ -0,0 +1,151 @@ | |||
package org.usvm.machine.operator | |||
|
|||
import io.ksmt.utils.cast |
Check warning
Code scanning / detekt
Detects imports in non default order
discoverProperties( | ||
methodIdentifier: MethodDescriptor, | ||
vararg analysisResultMatchers: (T1, T2, T3, T4, R?) -> Boolean, | ||
protected inline fun <reified T1 : TSObject, reified T2 : TSObject, reified T3 : TSObject, reified T4 : TSObject, reified R : TSObject> discoverProperties( |
Check warning
Code scanning / detekt
Reports lines with exceeded length Warning test
discoverProperties( | ||
methodIdentifier: MethodDescriptor, | ||
vararg analysisResultMatchers: (T1, T2, T3, T4, R?) -> Boolean, | ||
protected inline fun <reified T1 : TSObject, reified T2 : TSObject, reified T3 : TSObject, reified T4 : TSObject, reified R : TSObject> discoverProperties( |
Check warning
Code scanning / detekt
Line detected, which is longer than the defined maximum line length in the code style. Warning test
only KClass<TSObject> is available to match different objects. | ||
However, this method is also used in parent TestRunner class | ||
and passes here TSObject instances. So this check on current level is required. | ||
*/ |
Check warning
Code scanning / detekt
Detect the alignment of the initial star in a block comment.
@@ -1,5 +1,6 @@ | |||
package org.usvm.util | |||
|
|||
import io.ksmt.utils.cast |
Check warning
Code scanning / detekt
Detects imports in non default order
ctx: TSContext, | ||
model: UModelBase<EtsType>, | ||
): List<TSObject> = with(ctx) { | ||
params.map { param -> |
Check warning
Code scanning / detekt
Reports multiple space usages
1eed307
to
b58e886
Compare
556fa95
to
703b36c
Compare
bbe7107
to
aa18660
Compare
No description provided.