Skip to content
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

Reconcile full-imperative using a ShareCell abstraction #1458

Open
vkuncak opened this issue Oct 28, 2023 · 3 comments
Open

Reconcile full-imperative using a ShareCell abstraction #1458

vkuncak opened this issue Oct 28, 2023 · 3 comments
Labels
aliasing Alias and effect analysis for imperative feature imperative

Comments

@vkuncak
Copy link
Collaborator

vkuncak commented Oct 28, 2023

import stainless.annotation.*
object Shared:

  type REF = Int
  type Heap = Array[AnyRef]

  @extern
  given programHeap: Heap = new Array[AnyRef](1)

  class SharedCell[@mutable T](val ref: REF):

    @extern
    def apply()(using heap: Heap): T = heap(ref).asInstanceOf[T]

    @extern
    def update(newValue: T)(using heap: Heap): Unit =
      heap(ref) = newValue.asInstanceOf[AnyRef]

  end SharedCell

end Shared
@vkuncak vkuncak added imperative feature aliasing Alias and effect analysis for imperative labels Oct 28, 2023
@vkuncak
Copy link
Collaborator Author

vkuncak commented Oct 28, 2023

The idea would be to use similar injection of assumptions on well-typedness of heap as used in full-imperative.
Instead of using Array, we could use a list of pairs for the heap.

The idea is that SharedCell is not special in stainless. The shared cell as data is indeed only a wrapper for some integer data type (unbounded if want to postpone reasoning about heap overflow).

The key is that it's the update and apply of the ref cell that refer to a global mutable object.

The beauty is that this can be made to work with the existing non-shared memory model. The cells themselves are not shared, it's just that some of them may store identical integers.

@vkuncak
Copy link
Collaborator Author

vkuncak commented Oct 28, 2023

The actual implementation for the execution purposes in normal scala should be @inline method that updates a normal var inner field of the class.

@vkuncak
Copy link
Collaborator Author

vkuncak commented Oct 28, 2023

Maybe something like this would be a sketch of the model we want, if we additionally relax @extern var T to be ignored for the purpose of alias analysis in case class parameters.

import stainless.annotation.*
import stainless.collection.*
import stainless.lang.*
object SharedListHeap:

  type REF = BigInt

  case class Heap[@mutable T](var content: Array[T], nextRef: REF):
    @extern
    def NEW(v: T): SharedCell[T] = ???

    @pure
    def apply(ref: REF): T = ???

    def update(ref: REF, v: T): Unit = {
      (??? : Unit)
    }.ensuring(_ => apply(ref) == v)
  end Heap

  given HEAP[@mutable T]: Heap[T] = ???

  @extern
  class SharedCell[@mutable T](val ref: REF, @extern var content: T):

    def apply()(using heap: Heap[T]): T = 
      heap(ref)

    @extern
    def update(newValue: T)(using heap: Heap[T]): Unit = 
      heap.update(ref, newValue)

  end SharedCell

  case class M(var x:Int)
  case class Two(c1: SharedCell[M], c2: SharedCell[M])

  def test =
    val c = HEAP.NEW(M(32))
    val sc1 = c
    val sc2 = c
    val t = Two(c, c)
    ()

end SharedListHeap

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
aliasing Alias and effect analysis for imperative feature imperative
Projects
None yet
Development

No branches or pull requests

1 participant