-
Notifications
You must be signed in to change notification settings - Fork 69
/
Copy pathPrelude.hs
146 lines (125 loc) · 4.52 KB
/
Prelude.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
{- |
Module : Verifier.SAW.Prelude
Copyright : Galois, Inc. 2012-2015
License : BSD3
Maintainer : jhendrix@galois.com
Stability : experimental
Portability : non-portable (language extensions)
-}
module Verifier.SAW.Prelude
( Module
, module Verifier.SAW.Prelude
, module Verifier.SAW.Prelude.Constants
) where
import qualified Data.Map as Map
import Verifier.SAW.ParserUtils
import Verifier.SAW.Prelude.Constants
import Verifier.SAW.SharedTerm
import Verifier.SAW.FiniteValue
import Verifier.SAW.Simulator.Concrete (evalSharedTerm)
import Verifier.SAW.Simulator.Value (asFirstOrderTypeValue)
$(defineModuleFromFileWithFns
"preludeModule" "scLoadPreludeModule" "prelude/Prelude.sawcore")
-- | Given two terms, compute a term representing a decidable
-- equality test between them. The terms are assumed to
-- be of the same type, which must be a first-order type.
-- The returned term will be of type @Bool@.
scEq :: SharedContext -> Term -> Term -> IO Term
scEq sc x y = do
xty <- scTypeOf sc x
mmap <- scGetModuleMap sc
case asFirstOrderTypeValue (evalSharedTerm mmap mempty mempty xty) of
Just fot -> scDecEq sc fot (Just (x,y))
Nothing -> fail ("scEq: expected first order type, but got: " ++ showTerm xty)
-- | Given a first-order type, return the decidable equality
-- operation on that type. If arguments are provided, they
-- will be applied, returning a value of type @Bool@. If no
-- arguments are provided a function of type @tp -> tp -> Bool@
-- will be returned.
scDecEq ::
SharedContext ->
FirstOrderType {- ^ Type of elements to test for equality -} ->
Maybe (Term,Term) {- ^ optional arguments to apply -} ->
IO Term
scDecEq sc fot args = case fot of
FOTBit ->
do fn <- scGlobalDef sc "Prelude.boolEq"
case args of
Nothing -> return fn
Just (x,y) -> scApplyAll sc fn [x,y]
FOTInt ->
do fn <- scGlobalDef sc "Prelude.intEq"
case args of
Nothing -> return fn
Just (x,y) -> scApplyAll sc fn [x,y]
FOTIntMod m ->
do fn <- scGlobalDef sc "Prelude.intModEq"
m' <- scNat sc m
case args of
Nothing -> scApply sc fn m'
Just (x,y) -> scApplyAll sc fn [m',x,y]
FOTVec w FOTBit ->
do fn <- scGlobalDef sc "Prelude.bvEq"
w' <- scNat sc w
case args of
Nothing -> scApply sc fn w'
Just (x,y) -> scApplyAll sc fn [w',x,y]
FOTVec w t ->
do fn <- scGlobalDef sc "Prelude.vecEq"
w' <- scNat sc w
t' <- scFirstOrderType sc t
subFn <- scDecEq sc t Nothing
case args of
Nothing -> scApplyAll sc fn [w',t',subFn]
Just (x,y) -> scApplyAll sc fn [w',t',subFn,x,y]
FOTArray a b ->
do a' <- scFirstOrderType sc a
b' <- scFirstOrderType sc b
fn <- scGlobalDef sc "Prelude.arrayEq"
case args of
Nothing -> scApplyAll sc fn [a',b']
Just (x,y) -> scApplyAll sc fn [a',b',x,y]
FOTTuple [] ->
case args of
Nothing -> scGlobalDef sc "Prelude.unitEq"
Just _ -> scBool sc True
FOTTuple [t] -> scDecEq sc t args
FOTTuple (t:ts) ->
do fnLeft <- scDecEq sc t Nothing
fnRight <- scDecEq sc (FOTTuple ts) Nothing
fn <- scGlobalDef sc "Prelude.pairEq"
t' <- scFirstOrderType sc t
ts' <- scFirstOrderType sc (FOTTuple ts)
case args of
Nothing -> scApplyAll sc fn [t',ts',fnLeft,fnRight]
Just (x,y) -> scApplyAll sc fn [t',ts',fnLeft,fnRight,x,y]
FOTRec fs ->
case args of
Just (x,y) ->
mkRecordEqBody (Map.toList fs) x y
Nothing ->
do x <- scLocalVar sc 1
y <- scLocalVar sc 0
tp <- scFirstOrderType sc fot
body <- mkRecordEqBody (Map.toList fs) x y
scLambdaList sc [("x",tp),("y",tp)] body
where
mkRecordEqBody [] _x _y = scBool sc True
mkRecordEqBody [(f,tp)] x y =
do xf <- scRecordSelect sc x f
yf <- scRecordSelect sc y f
scDecEq sc tp (Just (xf,yf))
mkRecordEqBody ((f,tp):fs) x y =
do xf <- scRecordSelect sc x f
yf <- scRecordSelect sc y f
fp <- scDecEq sc tp (Just (xf,yf))
fsp <- mkRecordEqBody fs x y
scAnd sc fp fsp
-- | For backwards compatibility: @Bool@ used to be a datatype, and so its
-- creation function was called @scPrelude_Bool@ instead of
-- @scApplyPrelude_Bool@
scPrelude_Bool :: SharedContext -> IO Term
scPrelude_Bool = scApplyPrelude_Bool