Skip to content

Commit

Permalink
give string literals a refined type with their length
Browse files Browse the repository at this point in the history
  • Loading branch information
gridaphobe committed Jul 10, 2015
1 parent ecd0c42 commit 82dcf7d
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 5 deletions.
1 change: 1 addition & 0 deletions include/GHC/Base.spec
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module spec GHC.Base where

import GHC.CString
import GHC.Prim
import GHC.Classes
import GHC.Types
Expand Down
4 changes: 3 additions & 1 deletion include/GHC/CString.spec
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ module spec GHC.CString where

import GHC.Prim

GHC.CString.unpackCString# :: x:GHC.Prim.Addr# -> {v:String | v ~~ x}
GHC.CString.unpackCString#
:: x:GHC.Prim.Addr#
-> {v:String | len v == strLen x}
2 changes: 1 addition & 1 deletion src/Language/Haskell/Liquid/Bare/GhcSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ makeGhcSpecCHOP2 cbs specs dcSelectors datacons cls embs
name <- gets modName
mapM_ (makeHaskellInlines cbs name) specs
hmeans <- mapM (makeHaskellMeasures cbs name) specs
let measures = mconcat (measures':Ms.mkMSpec' dcSelectors:hmeans)
let measures = mconcat (Ms.wiredInMeasures:measures':Ms.mkMSpec' dcSelectors:hmeans)
let (cs, ms) = makeMeasureSpec' measures
let cms = makeClassMeasureSpec measures
let cms' = [ (x, Loc l l' $ cSort t) | (Loc l l' x, t) <- cms ]
Expand Down
18 changes: 15 additions & 3 deletions src/Language/Haskell/Liquid/Literals.hs
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
{-# LANGUAGE OverloadedStrings #-}
module Language.Haskell.Liquid.Literals (
literalFRefType, literalFReft, literalConst
) where

import TypeRep
import Literal

import Language.Haskell.Liquid.Measure
import Language.Haskell.Liquid.Types
import Language.Haskell.Liquid.RefType
import Language.Haskell.Liquid.CoreToLogic (mkLit)

import Language.Fixpoint.Types (exprReft)
import qualified Language.Fixpoint.Types as F

import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import Data.Monoid
import Control.Applicative

Expand All @@ -26,10 +30,18 @@ makeRTypeBase _ _
= error "RefType : makeRTypeBase"

literalFRefType tce l
= makeRTypeBase (literalType l) (literalFReft tce l)
= makeRTypeBase (literalType l) (addStrLen l $ literalFReft tce l)

literalFReft tce = maybe mempty exprReft . snd . literalConst tce
literalFReft tce = maybe mempty F.exprReft . snd . literalConst tce

addStrLen l = F.meet r
where
r = case l of
MachStr str ->
F.reft "v" (F.PAtom F.Eq
(F.EApp (name strLen) [F.EVar "v"])
(F.ECon (F.I (fromIntegral (T.length $ T.decodeUtf8 str)))))
_ -> mempty

-- | `literalConst` returns `Nothing` for unhandled lits because
-- otherwise string-literals show up as global int-constants
Expand Down
17 changes: 17 additions & 0 deletions src/Language/Haskell/Liquid/Measure.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,15 @@ module Language.Haskell.Liquid.Measure (
, mapTy
, dataConTypes
, defRefType
, strLen
, wiredInMeasures
) where

import GHC hiding (Located)
import Var
import Type
import TysPrim
import TysWiredIn
import Text.PrettyPrint.HughesPJ hiding (first)
import Text.Printf (printf)
import DataCon
Expand Down Expand Up @@ -347,3 +352,15 @@ bodyPred :: Expr -> Body -> Pred
bodyPred fv (E e) = PAtom Eq fv e
bodyPred fv (P p) = PIff (PBexp fv) p
bodyPred fv (R v' p) = subst1 p (v', fv)


-- | A wired-in measure @strLen@ that describes the length of a string
-- literal, with type @Addr#@.
strLen :: Measure SpecType ctor
strLen = M { name = dummyLoc "strLen"
, sort = ofType (mkFunTy addrPrimTy intTy)
, eqns = []
}

wiredInMeasures :: MSpec SpecType DataCon
wiredInMeasures = mkMSpec' [strLen]
4 changes: 4 additions & 0 deletions tests/pos/StringLit.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module StringLit where

{-@ foo :: {v:String | len v = 3} @-}
foo = "foo"

0 comments on commit 82dcf7d

Please sign in to comment.