Merge remote-tracking branch 'origin' into signed-arith

This commit is contained in:
Robert Dockins 2017-08-16 11:30:27 -07:00
commit 86d28bc01e
23 changed files with 636 additions and 21 deletions

View File

@ -114,6 +114,7 @@ library
Cryptol.TypeCheck.TypePat, Cryptol.TypeCheck.TypePat,
Cryptol.TypeCheck.SimpType, Cryptol.TypeCheck.SimpType,
Cryptol.TypeCheck.AST, Cryptol.TypeCheck.AST,
Cryptol.TypeCheck.Parseable,
Cryptol.TypeCheck.Monad, Cryptol.TypeCheck.Monad,
Cryptol.TypeCheck.Infer, Cryptol.TypeCheck.Infer,
Cryptol.TypeCheck.InferTypes, Cryptol.TypeCheck.InferTypes,

72
examples/HMAC.cry Normal file
View File

@ -0,0 +1,72 @@
////////////////////////////////////////////////////////////////
// Copyright 2016 Galois, Inc. All Rights Reserved
//
// Authors:
// Aaron Tomb : atomb@galois.com
// Nathan Collins : conathan@galois.com
// Joey Dodds : jdodds@galois.com
//
// Licensed under the Apache License, Version 2.0 (the "License").
// You may not use this file except in compliance with the License.
// A copy of the License is located at
//
// http://aws.amazon.com/apache2.0
//
// or in the "license" file accompanying this file. This file is distributed
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
//
////////////////////////////////////////////////////////////////
module HMAC where
import SHA256
//////// Functional version ////////
hmacSHA256 : {pwBytes, msgBytes}
(fin pwBytes, fin msgBytes
, 32 >= width msgBytes
, 64 >= width (8*pwBytes)
, 64 >= width (8 * (64 + msgBytes))
) => [pwBytes][8] -> [msgBytes][8] -> [256]
hmacSHA256 = hmac `{blockLength=64} SHA256 SHA256 SHA256
kinit : { pwBytes, blockLength, digest }
( fin pwBytes, fin blockLength, fin digest )
=> ([pwBytes][8] -> [8*digest])
-> [pwBytes][8]
-> [blockLength][8]
kinit hash key =
if `pwBytes > (`blockLength : [max (width pwBytes) (width blockLength)])
then take `{blockLength} (split (hash key) # (zero : [blockLength][8]))
else take `{blockLength} (key # (zero : [blockLength][8]))
// Due to limitations of the type system we must accept two
// separate arguments (both aledgedly the same) for two
// separate length inputs.
hmac : { msgBytes, pwBytes, digest, blockLength }
( fin pwBytes, fin digest, fin blockLength )
=> ([blockLength + msgBytes][8] -> [8*digest])
-> ([blockLength + digest][8] -> [8*digest])
-> ([pwBytes][8] -> [8*digest])
-> [pwBytes][8]
-> [msgBytes][8]
-> [digest*8]
hmac hash hash2 hash3 key message = hash2 (okey # internal)
where
ks : [blockLength][8]
ks = kinit hash3 key
okey = [k ^ 0x5C | k <- ks]
ikey = [k ^ 0x36 | k <- ks]
internal = split (hash (ikey # message))

194
examples/SHA256.cry Normal file
View File

@ -0,0 +1,194 @@
/*
* Copyright (c) 2013-2016 Galois, Inc.
* Distributed under the terms of the BSD3 license (see LICENSE file)
*
* @tmd - 24 April 2015 - took Ian's SHA512, converted to SHA256
* @ian - 15 August 2015 - he lies, probably ment 2014.
*
* This is a very simple implementation of SHA256, designed to be as clearly
* mathced to the specification in NIST's FIPS-PUB-180-4 as possible
*
* * The output correctly matches on all test vectors from
* http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA256.pdf
*/
module SHA256 where
/*
* SHA256 Functions : Section 4.1.2
*/
Ch : [32] -> [32] -> [32] -> [32]
Ch x y z = (x && y) ^ (~x && z)
Maj : [32] -> [32] -> [32] -> [32]
Maj x y z = (x && y) ^ (x && z) ^ (y && z)
S0 : [32] -> [32]
S0 x = (x >>> 2) ^ (x >>> 13) ^ (x >>> 22)
S1 : [32] -> [32]
S1 x = (x >>> 6) ^ (x >>> 11) ^ (x >>> 25)
s0 : [32] -> [32]
s0 x = (x >>> 7) ^ (x >>> 18) ^ (x >> 3)
s1 : [32] -> [32]
s1 x = (x >>> 17) ^ (x >>> 19) ^ (x >> 10)
/*
* SHA256 Constants : Section 4.2.2
*/
K : [64][32]
K = [ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
]
/*
* Preprocessing (padding and parsing) for SHA256 : Section 5.1.1 and 5.2.1
*/
preprocess : {msgLen,contentLen,chunks,padding}
( fin msgLen
, 64 >= width msgLen // message width fits in a word
, contentLen == msgLen + 65 // message + header
, chunks == (contentLen+511) / 512
, padding == (512 - contentLen % 512) % 512 // prettier if type #'s could be < 0
)
=> [msgLen] -> [chunks][512]
preprocess msg = split (msg # [True] # (zero:[padding]) # (`msgLen:[64]))
/*
* SHA256 Initial Hash Value : Section 5.3.3
*/
H0 : [8][32]
H0 = [ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19]
/*
* The SHA256 Hash computation : Section 6.2.2
*
* We have split the computation into a message scheduling function, corresponding
* to step 1 in the documents loop, and a compression function, corresponding to steps 2-4.
*/
SHA256MessageSchedule : [16][32] -> [64][32]
SHA256MessageSchedule M = W where
W = M # [ s1 (W@(j-2)) + (W@(j-7)) + s0 (W@(j-15)) + (W@(j-16)) | j <- [16 .. 63]:[_][8] ]
SHA256Compress : [8][32] -> [64][32] -> [8][32]
SHA256Compress H W = [as!0 + H@0, bs!0 + H@1, cs!0 + H@2, ds!0 + H@3, es!0 + H@4, fs!0 + H@5, gs!0 + H@6, hs!0 + H@7] where
T1 = [h + S1 e + Ch e f g + k + w | h <- hs | e <- es | f <- fs | g <- gs | k <- K | w <- W]
T2 = [S0 a + Maj a b c | a <- as | b <- bs | c <- cs]
hs = take `{65} ([H@7] # gs)
gs = take `{65} ([H@6] # fs)
fs = take `{65} ([H@5] # es)
es = take `{65} ([H@4] # [d + t1 | d <- ds | t1 <- T1])
ds = take `{65} ([H@3] # cs)
cs = take `{65} ([H@2] # bs)
bs = take `{65} ([H@1] # as)
as = take `{65} ([H@0] # [t1 + t2 | t1 <- T1 | t2 <- T2])
SHA256Block : [8][32] -> [16][32] -> [8][32]
SHA256Block H M = SHA256Compress H (SHA256MessageSchedule M)
//////// Functional/idiomatic top level ////////
/*
* The SHA256' function hashes a preprocessed sequence of blocks with the
* compression function. The SHA256 function hashes a sequence of bytes, and
* is more likely the function that will be similar to those seein in an
* implementation to be verified.
*/
SHA256' : {a} (fin a) => [a][16][32] -> [8][32]
SHA256' blocks = hash!0 where
hash = [H0] # [SHA256Block h b | h <- hash | b <- blocks]
SHA256 : {a} (fin a, 64 >= width (8*a)) => [a][8] -> [256]
SHA256 msg = join (SHA256' [ split x | x <- preprocess(join msg)])
property katsPass = ~zero == [test == kat | (test,kat) <- kats ]
kats = [ (SHA256 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
, 0x248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1)
, (SHA256 ""
,0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855)
, (SHA256 "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
, 0xcf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1)
// , ([0x61 | i <- [1..1000000] : [_][32]]
// , 0xcdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0)
]
//////// Imperative top level ////////
type SHA256State = { h : [8][32]
, block : [64][8]
, n : [16]
, sz : [64]
}
SHA256Init : SHA256State
SHA256Init = { h = H0
, block = zero
, n = 0
, sz = 0
}
SHA256Update1 : SHA256State -> [8] -> SHA256State
SHA256Update1 s b =
if s.n == 64
then { h = SHA256Block s.h (split (join s.block))
, block = [b] # zero
, n = 1
, sz = s.sz + 8
}
else { h = s.h
, block = update s.block s.n b
, n = s.n + 1
, sz = s.sz + 8
}
SHA256Update : {n} (fin n) => SHA256State -> [n][8] -> SHA256State
SHA256Update sinit bs = ss!0
where ss = [sinit] # [ SHA256Update1 s b | s <- ss | b <- bs ]
update : {a, b, c} (fin c, c >= width (2 ^^ c - 1)) => [b]a -> [c] -> a -> [min b (2 ^^ c)]a
update a i x = [ if j == i then x else e | e <- a | j <- [0 ..] ]
// Add padding and size and process the final block.
SHA256Final : SHA256State -> [256]
SHA256Final s = join (SHA256Block h b')
// Because the message is always made up of bytes, and the size is a
// fixed number of bytes, the 1 pad will always be at least a byte.
where s' = SHA256Update1 s 0x80
// Don't need to add zeros. They're already there. Just update
// the count of bytes in this block. After adding the 1 pad, there
// are two possible cases: the size will fit in the current block,
// or it won't.
(h, b) = if s'.n <= 56 then (s'.h, s'.block)
else (SHA256Block s'.h (split (join s'.block)), zero)
b' = split (join b || (zero # s.sz))
SHA256Imp : {a} (64 >= width (8*a)) => [a][8] -> [256]
SHA256Imp msg = SHA256Final (SHA256Update SHA256Init msg)
property katsPassImp = ~zero == [test == kat | (test,kat) <- katsImp ]
katsImp = [ (SHA256Imp "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 0x248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1), (SHA256Imp ""
, 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855)
, (SHA256Imp "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
, 0xcf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1)
// , ([0x61 | i <- [1..1000000] : [_][32]]
// , 0xcdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0)
]
property imp_correct msg = SHA256 msg == SHA256Imp msg

13
examples/append.cry Normal file
View File

@ -0,0 +1,13 @@
x : [_][8]
x = [1,2,3,4,5,19,12,38,5,3]
y : [_][8]
y = [19,3,27,5,12]
z = x # y
m = z @ (0 : [1]) //1
w = z @ 2 //3
t = z @ 10 //19 (0x13)
v = z @ 11 //3

View File

@ -0,0 +1,48 @@
//builtins lift over tuples, seqs, and records
//this file uses addition to model a builtin
//but this should work for any builtin operators
x = [True,False]
y = [False,True]
//make sure bitvectors are numbers
property p1 = x == (2 : [2])
//same thing written 2 different ways
property p2 = x + y == 3
property p3 = x + y == [True,True]
xx = [[True,False]]
yy = [[False,True]]
//addition lifts pointwise over sequences
property p4 = xx + yy == [3]
//negation is a unary operator that also lifts over sequences
property p5 = ~ xx == yy
xinf = [2 ... ]
yinf = [3 ... ]
//addition lifts pointwise over infinite lists
property p6 = (xinf + yinf) @ (0 : [0]) == (1 : [2])
//negation lifts pointwise over an infinite list
property p7 = (~ xinf) @ (0 : [0]) == (1 : [2])
xrec = { x = 2 : [2], y = 2 : [2] } : {x : [2], y : [2]}
property p8 = xrec + xrec + xrec == xrec
//lift over tuples and records at the same time
property p9 = (2,2,xrec) + (2,2,xrec) + (2,2,xrec) == (2:[2],2:[2],xrec)
//lift unary over tuples and lists
property p10 = (~ { x = (1,2), y = [3,4,5] }) == {x = (0:[1],1:[2]), y = [4, 3, 2] : [3][3] }

38
examples/builtins.cry Normal file
View File

@ -0,0 +1,38 @@
//Here's a test of some builtin operators
//nothing too deep, just making sure they all work out
t : [8]
t = if True then 5 else 4 //5
f : [8]
f = if False then 3 else 5 //5
times : [8]
times = 5 * 1 * 2 * 3 //30
div : [8]
div = (((30/1)/2)/3) //5
mod : [8]
mod = 205%10 //5
exp : [8]
exp = 2^^7 //128
lgtest : [8]
lgtest = lg2 128 //7
p : [8]
p = 3+2 //5
m : [8]
m = 8-3 //5
neg : [8]
neg = -(-5) //5
comp : [8]
comp = ~250 //5

10
examples/comp.cry Normal file
View File

@ -0,0 +1,10 @@
x : [_]([2],[3],[3],[4])
x = [(a,b,c,d) | a <- [1,2], b <- [3,4] | c <- [5,6], d <- [7,8,9] ]
property t1 = x @ 0 == (1,3,5,7)
property t2 = x @ 2 == (2,3,5,9)
property t3 = x @ 3 == (2,4,6,7)
y = [(a,b,c) | a <- [1,2,3], b <- [1,2] | c <- [1 ... ] ]
property t4 = y @ 3 == (2,2,0)

5
examples/demote.cry Normal file
View File

@ -0,0 +1,5 @@
x : {a}(fin a) => [a] -> [(a*2)+3]
x v = 0 + 1
y = x (2 : [3])

10
examples/inflist.cry Normal file
View File

@ -0,0 +1,10 @@
a = [1 ... ]
b = [1,2 ... ]
c = [1 .. 5]
d = [1,3 .. 9]
property t1 = a @ 3 == 1
property t2 = b @ 3 == 1
property t3 = c @ 3 == 4
property t4 = d @ 3 == 4

28
examples/mini.cry Normal file
View File

@ -0,0 +1,28 @@
id : [32] -> [32]
id x = rec x
where rec k = if (k == 0) then 0 else 1 + rec (k + (-1))
inflist = [1 ... ] : [_][8]
rc = {x = 3 : [8], y = 5 : [8]}
my_true = rc.x
tup = (1 : [8], 2 : [8], 3 : [8], 4 : [8])
my_3 = tup.2
sup = y where y = 3 : [8]
gf28Add : {n} (fin n) => [n][8] -> [8]
gf28Add ps = sums ! 0
where sums = [zero] # [ p ^ s | p <- ps | s <- sums ]
gex = gf28Add [1,2]
sum : [_][8] -> [_][8]
sum x = rec
where rec = [ p + q | p <- x | q <- [1,2,3,4] ]

27
examples/props.cry Normal file
View File

@ -0,0 +1,27 @@
x = [True, False]
y = [False, True]
z = x + y
property p1 = z == 3
xx = [[True,False]]
yy = [[False, True]]
zz = xx + yy
t : {a} [a*3] -> [a*3][a*3]
t d = zero
/*
t1 : [8] -> [2][2][2]
t1 x = split (split x)
t2 : [8] -> ([4],[4])
t2 x = splitAt x
t3 : [8] ->[8] -> [16]
t3 x y = x # y
*/

10
examples/split.cry Normal file
View File

@ -0,0 +1,10 @@
x = [1,2,3,4] : [_][8]
y = (split x) : [2][2][8]
a = (y@0) @ 0
b = (y@0) @ 1
c = (y@1) @ 0
d = (y@1) @ 1

9
examples/splitAt.cry Normal file
View File

@ -0,0 +1,9 @@
x = [1,2,3,4] : [_][8]
y = (splitAt x) : ([2][8],[2][8])
a = y.0 @ 0
b = y.0 @ 1
c = y.1 @ 0
d = y.1 @ 1

2
examples/width.cry Normal file
View File

@ -0,0 +1,2 @@
x : [8]
x = width (252 : [8])

7
examples/xor_cipher.cry Normal file
View File

@ -0,0 +1,7 @@
encrypt : {a}(fin a) => [8] -> [a][8] -> [a][8]
encrypt key plaintext = [pt ^ key | pt <- plaintext ]
decrypt : {a}(fin a) => [8] -> [a][8] -> [a][8]
decrypt key ciphertext = [ct ^ key | ct <- ciphertext ]
property roundtrip k ip = decrypt k (encrypt k ip) == ip

12
examples/zero_weird.cry Normal file
View File

@ -0,0 +1,12 @@
x : {a}() => a -> [16]
x v = zero v
property xprop v = x v == 0
y : [12] -> [4] -> [17]
y a b = zero a b
property yprop v w = y v w == 0
t1 = x 13
t2 = y 2 3

View File

@ -88,7 +88,8 @@ data Name = Name { nUnique :: {-# UNPACK #-} !Int
, nLoc :: !Range , nLoc :: !Range
-- ^ Where this name was defined -- ^ Where this name was defined
} deriving (Show, Generic, NFData) } deriving (Generic, NFData, Show)
instance Eq Name where instance Eq Name where
a == b = compare a b == EQ a == b = compare a b == EQ

View File

@ -131,7 +131,7 @@ data Decl name = DSignature [Located name] (Schema name)
| DPatBind (Pattern name) (Expr name) | DPatBind (Pattern name) (Expr name)
| DType (TySyn name) | DType (TySyn name)
| DLocated (Decl name) Range | DLocated (Decl name) Range
deriving (Eq, Show, Generic, NFData) deriving (Eq, Show, Generic, NFData, Functor)
-- | An import declaration. -- | An import declaration.
data Import = Import { iModule :: !ModName data Import = Import { iModule :: !ModName
@ -149,7 +149,7 @@ data ImportSpec = Hiding [Ident]
deriving (Eq, Show, Generic, NFData) deriving (Eq, Show, Generic, NFData)
data TySyn n = TySyn (Located n) [TParam n] (Type n) data TySyn n = TySyn (Located n) [TParam n] (Type n)
deriving (Eq, Show, Generic, NFData) deriving (Eq, Show, Generic, NFData, Functor)
{- | Bindings. Notes: {- | Bindings. Notes:
@ -172,17 +172,17 @@ data Bind name = Bind { bName :: Located name -- ^ Defined thing
, bPragmas :: [Pragma] -- ^ Optional pragmas , bPragmas :: [Pragma] -- ^ Optional pragmas
, bMono :: Bool -- ^ Is this a monomorphic binding , bMono :: Bool -- ^ Is this a monomorphic binding
, bDoc :: Maybe String -- ^ Optional doc string , bDoc :: Maybe String -- ^ Optional doc string
} deriving (Eq, Show, Generic, NFData) } deriving (Eq, Generic, NFData, Functor, Show)
type LBindDef = Located (BindDef PName) type LBindDef = Located (BindDef PName)
data BindDef name = DPrim data BindDef name = DPrim
| DExpr (Expr name) | DExpr (Expr name)
deriving (Eq, Show, Generic, NFData) deriving (Eq, Show, Generic, NFData, Functor)
data Fixity = Fixity { fAssoc :: !Assoc data Fixity = Fixity { fAssoc :: !Assoc
, fLevel :: !Int , fLevel :: !Int
} deriving (Eq, Show, Generic, NFData) } deriving (Eq, Generic, NFData, Show)
data FixityCmp = FCError data FixityCmp = FCError
| FCLeft | FCLeft
@ -293,11 +293,11 @@ data Expr n = EVar n -- ^ @ x @
| EParens (Expr n) -- ^ @ (e) @ (Removed by Fixity) | EParens (Expr n) -- ^ @ (e) @ (Removed by Fixity)
| EInfix (Expr n) (Located n) Fixity (Expr n)-- ^ @ a + b @ (Removed by Fixity) | EInfix (Expr n) (Located n) Fixity (Expr n)-- ^ @ a + b @ (Removed by Fixity)
deriving (Eq, Show, Generic, NFData) deriving (Eq, Show, Generic, NFData, Functor)
data TypeInst name = NamedInst (Named (Type name)) data TypeInst name = NamedInst (Named (Type name))
| PosInst (Type name) | PosInst (Type name)
deriving (Eq, Show, Generic, NFData) deriving (Eq, Show, Generic, NFData, Functor)
{- | Selectors are used for projecting from various components. {- | Selectors are used for projecting from various components.
Each selector has an option spec to specify the shape of the thing Each selector has an option spec to specify the shape of the thing
@ -320,7 +320,7 @@ data Selector = TupleSel Int (Maybe Int)
data Match name = Match (Pattern name) (Expr name) -- ^ p <- e data Match name = Match (Pattern name) (Expr name) -- ^ p <- e
| MatchLet (Bind name) | MatchLet (Bind name)
deriving (Eq, Show, Generic, NFData) deriving (Eq, Show, Generic, NFData, Functor)
data Pattern n = PVar (Located n) -- ^ @ x @ data Pattern n = PVar (Located n) -- ^ @ x @
| PWild -- ^ @ _ @ | PWild -- ^ @ _ @
@ -330,13 +330,13 @@ data Pattern n = PVar (Located n) -- ^ @ x @
| PTyped (Pattern n) (Type n) -- ^ @ x : [8] @ | PTyped (Pattern n) (Type n) -- ^ @ x : [8] @
| PSplit (Pattern n) (Pattern n)-- ^ @ (x # y) @ | PSplit (Pattern n) (Pattern n)-- ^ @ (x # y) @
| PLocated (Pattern n) Range -- ^ Location information | PLocated (Pattern n) Range -- ^ Location information
deriving (Eq, Show, Generic, NFData) deriving (Eq, Show, Generic, NFData, Functor)
data Named a = Named { name :: Located Ident, value :: a } data Named a = Named { name :: Located Ident, value :: a }
deriving (Eq, Show, Foldable, Traversable, Generic, NFData, Functor) deriving (Eq, Show, Foldable, Traversable, Generic, NFData, Functor)
data Schema n = Forall [TParam n] [Prop n] (Type n) (Maybe Range) data Schema n = Forall [TParam n] [Prop n] (Type n) (Maybe Range)
deriving (Eq, Show, Generic, NFData) deriving (Eq, Show, Generic, NFData, Functor)
data Kind = KNum | KType data Kind = KNum | KType
deriving (Eq, Show, Generic, NFData) deriving (Eq, Show, Generic, NFData)
@ -345,7 +345,7 @@ data TParam n = TParam { tpName :: n
, tpKind :: Maybe Kind , tpKind :: Maybe Kind
, tpRange :: Maybe Range , tpRange :: Maybe Range
} }
deriving (Eq, Show, Generic, NFData) deriving (Eq, Show, Generic, NFData, Functor)
data Type n = TFun (Type n) (Type n) -- ^ @[8] -> [8]@ data Type n = TFun (Type n) (Type n) -- ^ @[8] -> [8]@
| TSeq (Type n) (Type n) -- ^ @[8] a@ | TSeq (Type n) (Type n) -- ^ @[8] a@
@ -361,7 +361,7 @@ data Type n = TFun (Type n) (Type n) -- ^ @[8] -> [8]@
| TLocated (Type n) Range -- ^ Location information | TLocated (Type n) Range -- ^ Location information
| TParens (Type n) -- ^ @ (ty) @ | TParens (Type n) -- ^ @ (ty) @
| TInfix (Type n) (Located n) Fixity (Type n) -- ^ @ ty + ty @ | TInfix (Type n) (Located n) Fixity (Type n) -- ^ @ ty + ty @
deriving (Eq, Show, Generic, NFData) deriving (Eq, Show, Generic, NFData, Functor)
tconNames :: Map.Map PName (Type PName) tconNames :: Map.Map PName (Type PName)
tconNames = Map.fromList tconNames = Map.fromList
@ -377,7 +377,7 @@ data Prop n = CFin (Type n) -- ^ @ fin x @
| CSignedCmp (Type n) -- ^ @ SignedCmp a @ | CSignedCmp (Type n) -- ^ @ SignedCmp a @
| CLocated (Prop n) Range -- ^ Location information | CLocated (Prop n) Range -- ^ Location information
| CType (Type n) -- ^ After parsing | CType (Type n) -- ^ After parsing
deriving (Eq, Show, Generic, NFData) deriving (Eq, Show, Generic, NFData, Functor)
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Note: When an explicit location is missing, we could use the sub-components -- Note: When an explicit location is missing, we could use the sub-components
@ -904,7 +904,6 @@ instance NoPos Pragma where
instance NoPos (TySyn name) where instance NoPos (TySyn name) where
noPos (TySyn x y z) = TySyn (noPos x) (noPos y) (noPos z) noPos (TySyn x y z) = TySyn (noPos x) (noPos y) (noPos z)

View File

@ -24,6 +24,7 @@ import Cryptol.Utils.PP
data Located a = Located { srcRange :: !Range, thing :: !a } data Located a = Located { srcRange :: !Range, thing :: !a }
deriving (Eq, Show, Generic, NFData) deriving (Eq, Show, Generic, NFData)
data Position = Position { line :: !Int, col :: !Int } data Position = Position { line :: !Int, col :: !Int }
deriving (Eq, Ord, Show, Generic, NFData) deriving (Eq, Ord, Show, Generic, NFData)

View File

@ -55,6 +55,7 @@ import qualified Cryptol.ModuleSystem.Name as M
import qualified Cryptol.ModuleSystem.NamingEnv as M import qualified Cryptol.ModuleSystem.NamingEnv as M
import qualified Cryptol.ModuleSystem.Renamer as M (RenamerWarning(SymbolShadowed)) import qualified Cryptol.ModuleSystem.Renamer as M (RenamerWarning(SymbolShadowed))
import qualified Cryptol.Utils.Ident as M import qualified Cryptol.Utils.Ident as M
import qualified Cryptol.ModuleSystem.Env as M
import qualified Cryptol.Eval.Monad as E import qualified Cryptol.Eval.Monad as E
import qualified Cryptol.Eval.Value as E import qualified Cryptol.Eval.Value as E
@ -65,6 +66,7 @@ import Cryptol.Parser
(parseExprWith,parseReplWith,ParseError(),Config(..),defaultConfig (parseExprWith,parseReplWith,ParseError(),Config(..),defaultConfig
,parseModName,parseHelpName) ,parseModName,parseHelpName)
import qualified Cryptol.TypeCheck.AST as T import qualified Cryptol.TypeCheck.AST as T
import qualified Cryptol.TypeCheck.Parseable as T
import qualified Cryptol.TypeCheck.Subst as T import qualified Cryptol.TypeCheck.Subst as T
import qualified Cryptol.TypeCheck.InferTypes as T import qualified Cryptol.TypeCheck.InferTypes as T
import Cryptol.TypeCheck.Solve(defaultReplExpr) import Cryptol.TypeCheck.Solve(defaultReplExpr)
@ -184,6 +186,10 @@ nbCommandList =
"do type specialization on a closed expression" "do type specialization on a closed expression"
, CommandDescr [ ":eval" ] (ExprArg refEvalCmd) , CommandDescr [ ":eval" ] (ExprArg refEvalCmd)
"evaluate an expression with the reference evaluator" "evaluate an expression with the reference evaluator"
, CommandDescr [ ":ast" ] (ExprArg astOfCmd)
"print out the pre-typechecked AST of a given term"
, CommandDescr [ ":extract-coq" ] (NoArg allTerms)
"print out the post-typechecked AST of all currently defined terms, in a Coq parseable format"
] ]
commandList :: [CommandDescr] commandList :: [CommandDescr]
@ -581,6 +587,17 @@ refEvalCmd str = do
val <- liftModuleCmd (rethrowEvalError . R.evaluate expr) val <- liftModuleCmd (rethrowEvalError . R.evaluate expr)
rPrint $ R.ppValue val rPrint $ R.ppValue val
astOfCmd :: String -> REPL ()
astOfCmd str = do
expr <- replParseExpr str
(re,_,_) <- replCheckExpr (P.noPos expr)
rPrint (fmap M.nameUnique re)
allTerms :: REPL ()
allTerms = do
me <- getModuleEnv
rPrint $ T.showParseable $ concatMap T.mDecls $ M.loadedModules me
typeOfCmd :: String -> REPL () typeOfCmd :: String -> REPL ()
typeOfCmd str = do typeOfCmd str = do

View File

@ -33,7 +33,7 @@ import Cryptol.Prims.Syntax
import Cryptol.Parser.AST ( Selector(..),Pragma(..) import Cryptol.Parser.AST ( Selector(..),Pragma(..)
, Import(..), ImportSpec(..), ExportType(..) , Import(..), ImportSpec(..), ExportType(..)
, ExportSpec(..), isExportedBind , ExportSpec(..), isExportedBind
, isExportedType, Fixity(..) ) , isExportedType, Fixity(..))
import Cryptol.Utils.Ident (Ident,isInfixIdent,ModName,packIdent) import Cryptol.Utils.Ident (Ident,isInfixIdent,ModName,packIdent)
import Cryptol.TypeCheck.PP import Cryptol.TypeCheck.PP
import Cryptol.TypeCheck.Type import Cryptol.TypeCheck.Type
@ -44,6 +44,9 @@ import Control.DeepSeq
import Data.Map (Map) import Data.Map (Map)
import qualified Data.IntMap as IntMap import qualified Data.IntMap as IntMap
-- | A Cryptol module. -- | A Cryptol module.
data Module = Module { mName :: !ModName data Module = Module { mName :: !ModName
, mExports :: ExportSpec Name , mExports :: ExportSpec Name
@ -54,7 +57,6 @@ data Module = Module { mName :: !ModName
} deriving (Show, Generic, NFData) } deriving (Show, Generic, NFData)
data Expr = EList [Expr] Type -- ^ List value (with type of elements) data Expr = EList [Expr] Type -- ^ List value (with type of elements)
| ETuple [Expr] -- ^ Tuple value | ETuple [Expr] -- ^ Tuple value
| ERec [(Ident,Expr)] -- ^ Record value | ERec [(Ident,Expr)] -- ^ Record value
@ -112,6 +114,7 @@ groupDecls dg = case dg of
Recursive ds -> ds Recursive ds -> ds
NonRecursive d -> [d] NonRecursive d -> [d]
data Decl = Decl { dName :: !Name data Decl = Decl { dName :: !Name
, dSignature :: Schema , dSignature :: Schema
, dDefinition :: DeclDef , dDefinition :: DeclDef
@ -119,16 +122,15 @@ data Decl = Decl { dName :: !Name
, dInfix :: !Bool , dInfix :: !Bool
, dFixity :: Maybe Fixity , dFixity :: Maybe Fixity
, dDoc :: Maybe String , dDoc :: Maybe String
} deriving (Show, Generic, NFData) } deriving (Generic, NFData, Show)
data DeclDef = DPrim data DeclDef = DPrim
| DExpr Expr | DExpr Expr
deriving (Show, Generic, NFData) deriving (Show, Generic, NFData)
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- | Construct a primitive, given a map to the unique names of the Cryptol -- | Construct a primitive, given a map to the unique names of the Cryptol
-- module. -- module.
ePrim :: PrimMap -> Ident -> Expr ePrim :: PrimMap -> Ident -> Expr

View File

@ -0,0 +1,109 @@
-- |
-- Module : $Header$
-- Copyright : (c) 2013-2017 Galois, Inc.
-- License : BSD3
-- Maintainer : cryptol@galois.com
-- Stability : provisional
-- Portability : portable
{-# LANGUAGE Safe #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE FlexibleInstances, FlexibleContexts #-}
{-# LANGUAGE DeriveAnyClass, DeriveGeneric #-}
module Cryptol.TypeCheck.Parseable
( module Cryptol.TypeCheck.Parseable
, ShowParseable(..)
) where
import Cryptol.TypeCheck.AST
import Cryptol.Utils.Ident (Ident,unpackIdent)
import Cryptol.Parser.AST ( Located(..))
import Cryptol.ModuleSystem.Name
import Text.PrettyPrint
-- ShowParseable prints out a cryptol program in a way that it's parseable by Coq (and likely other things)
-- Used mainly for reasoning about the semantics of cryptol programs in Coq (https://github.com/GaloisInc/cryptol-semantics)
class ShowParseable t where
showParseable :: t -> Doc
instance ShowParseable Expr where
showParseable (EList es _) = parens (text "EList" <+> showParseable es)
showParseable (ETuple es) = parens (text "ETuple" <+> showParseable es)
showParseable (ERec ides) = parens (text "ERec" <+> showParseable ides)
showParseable (ESel e s) = parens (text "ESel" <+> showParseable e <+> showParseable s)
showParseable (EIf c t f) = parens (text "EIf" <+> showParseable c $$ showParseable t $$ showParseable f)
showParseable (EComp _ _ e mss) = parens (text "EComp" $$ showParseable e $$ showParseable mss)
showParseable (EVar n) = parens (text "EVar" <+> showParseable n)
showParseable (EApp fe ae) = parens (text "EApp" $$ showParseable fe $$ showParseable ae)
showParseable (EAbs n _ e) = parens (text "EAbs" <+> showParseable n $$ showParseable e)
showParseable (EWhere e dclg) = parens (text "EWhere" $$ showParseable e $$ showParseable dclg)
showParseable (ETAbs tp e) = parens (text "ETAbs" <+> showParseable tp
$$ showParseable e)
showParseable (ETApp e t) = parens (text "ETApp" $$ showParseable e $$ parens (text "ETyp" <+> showParseable t))
--NOTE: erase all "proofs" for now (change the following two lines to change that)
showParseable (EProofAbs {-p-}_ e) = showParseable e --"(EProofAbs " ++ show p ++ showParseable e ++ ")"
showParseable (EProofApp e) = showParseable e --"(EProofApp " ++ showParseable e ++ ")"
instance (ShowParseable a, ShowParseable b) => ShowParseable (a,b) where
showParseable (x,y) = parens (showParseable x <> comma <> showParseable y)
instance ShowParseable Int where
showParseable i = int i
instance ShowParseable Ident where
showParseable i = text $ show $ unpackIdent i
instance ShowParseable Type where
showParseable (TUser n lt t) = parens (text "TUser" <+> showParseable n <+> showParseable lt <+> showParseable t)
showParseable (TRec lidt) = parens (text "TRec" <+> showParseable lidt)
showParseable t = parens $ text $ show t
instance ShowParseable Selector where
showParseable (TupleSel n _) = parens (text "TupleSel" <+> showParseable n)
showParseable (RecordSel n _) = parens (text "RecordSel" <+> showParseable n)
showParseable (ListSel n _) = parens (text "ListSel" <+> showParseable n)
instance ShowParseable Match where
showParseable (From n _ _ e) = parens (text "From" <+> showParseable n <+> showParseable e)
showParseable (Let d) = parens (text "MLet" <+> showParseable d)
instance ShowParseable Decl where
showParseable d = parens (text "Decl" <+> showParseable (dName d)
$$ showParseable (dDefinition d))
instance ShowParseable DeclDef where
showParseable DPrim = text (show DPrim)
showParseable (DExpr e) = parens (text "DExpr" $$ showParseable e)
instance ShowParseable DeclGroup where
showParseable (Recursive ds) =
parens (text "Recursive" $$ showParseable ds)
showParseable (NonRecursive d) =
parens (text "NonRecursive" $$ showParseable d)
instance (ShowParseable a) => ShowParseable [a] where
showParseable a = case a of
[] -> text "[]"
[x] -> brackets (showParseable x)
x : xs -> text "[" <+> showParseable x $$
vcat [ comma <+> showParseable y | y <- xs ] $$
text "]"
instance (ShowParseable a) => ShowParseable (Maybe a) where
showParseable Nothing = text "(0,\"\")" --empty ident, won't shadow demote
showParseable (Just x) = showParseable x
instance (ShowParseable a) => ShowParseable (Located a) where
showParseable l = showParseable (thing l)
instance ShowParseable TParam where
showParseable tp = parens (text (show (tpUnique tp)) <> comma <> maybeNameDoc (tpName tp))
maybeNameDoc :: Maybe Name -> Doc
maybeNameDoc Nothing = doubleQuotes empty
maybeNameDoc (Just n) = showParseable (nameIdent n)
instance ShowParseable Name where
showParseable n = parens (text (show (nameUnique n)) <> comma <> showParseable (nameIdent n))

View File

@ -45,7 +45,7 @@ data TParam = TParam { tpUnique :: !Int -- ^ Parameter identifier
, tpKind :: Kind -- ^ Kind of parameter , tpKind :: Kind -- ^ Kind of parameter
, tpName :: Maybe Name -- ^ Name from source, if any. , tpName :: Maybe Name -- ^ Name from source, if any.
} }
deriving (Show, Generic, NFData) deriving (Generic, NFData, Show)
-- | The internal representation of types. -- | The internal representation of types.