Skip to content

todesking/PReTy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PReTy: Pluggable Refinement Types for Scala

Current status: Very experimental

Roadmap

  • Local variable refinement via annotation
  • Control structure with path dependency
  • Constructor
  • Inner class
  • Exception notation for refinement
  • Refine via type alias
  • Higher order type refinements
  • Abstract refinements
  • Refinement inference for local/private methods
  • Specification via proxy types
  • Unsafe cast
  • Compile time refinement assertions
  • Dynamic checking

References/Related works

Refinement Types and Liquid Types

Design of Scala Internals

Type checking scheme

# Value
v := r     # root value
   | v(id) # property

# Pred
p := (e, { id: p }) # Pred for the value and its properties

# Expr
e := _             # "the value"
   | e^+
e^+ := expr_value(v) # value reference
     | other expressions ...

# Logic
l := forall {v}. l
   | e^+

# Environment
E := ({ r: p }, {v1}, {v2})
  # Root value bindings: Value `r` has pred `p`.
  # Boolean values {v1} is true.
  # Boolean values {v2} is false.
# Given environment E, p1 <: p2
satisfy(E = (bindings, cond, uncond), p1, p2): Boolean =
  solve_SMT(embed(E, p1 <: p2)) == SAT


# Substitute
e[e1/e2] = Substitute sub-expr e1 in e to e2

all_values(p1=(e1, ps1), p2=(e2, ps2)) =
  values(e1) ++ values(e2) ++
    { all_values(ps1(id), ps2(id)) | id in keys(ps2) union keys(ps2) if modified(ps1, id) || modified(ps2, id) }

embed(E=(bindings, conds, unconds)), p1 <: p2) =
    forall {r | (r: p) in E}.
      { embed(v: pred1(bindings, v)) | v in all_values(p1, p2) }
      && { expr_value(v) == true | v in conds \hat all_values(p1, p2) }
      && { expr_value(v) == false | v in unconds \hat all_values(p1, p2) }
      && embed(p1 <: p2)

embed(p1=(e1, ps1) <: p2=(e2, ps2)): Logic =
  let diffs = { id | (id, _) in ps2 where ps1(id) != ps2(id) } in
    forall v=fresh().
      embed(v: e1) --> embed(v: e2)
      && { embed(ps1(id) <: ps2(id)) | id in diffs }

embed(v: e): Logic =
  e[_/v]

pred1(bindings, v): Expr =
  let (e, _) = pred(bindings, v) in e

pred(bindings, v): Pred = v match {
  v(id) => let (_, ps) = pred(bindings, v) in ps(id)
  r => bindings(r)
}

Releases

No releases published

Packages

No packages published

Languages