packages feed

pec-0.1: test_cases/Prelude.pec

module Prelude

exports all

where

type W8 = W #256 //singleton "Count" type.  In this case, used to specify a word that holds 256 values.
type W16 = W #65536
type I32 = I #4294967296 // 32 bit int

type Bool = | False | True
// enum type
// the "|" is used to specify "or"

type Maybe a = | Nothing | Just a // polymorphic variant
// order doesn't matter
// type Maybe a = | Just a | Nothing would be compiled exactly the same way

type Either a b = | Left a | Right b // polymorphic variant

type Ordering = | LT | EQ | GT // another enum

extern putchar :: Char -> ()
// external C call
// name on the left, type on the right

extern puts :: Ptr Char -> ()
extern exit :: I32 -> ()

to_ordering :: I32 -> Ordering
to_ordering x = branch of
  | x < 0 -> LT
  | x > 0 -> GT
  | -> EQ

putCh :: Char -> ()
putCh c = putchar c

assert :: Bool -> ()
assert x = when (not x)
  (do
    putLn "assertion failed"
    exit -1
  )
// "when" is not a primitive, it is a library function, see "when_" below

not :: Bool -> Bool
not x = if x False True

putLn :: IString -> ()
putLn x = puts (from_istring x)

is_upper :: Char -> Bool
is_upper c = (c >= 'A') && (c <= 'Z') // operators don't have precedence, parens are required

is_lower :: Char -> Bool
is_lower c = (c >= 'a') && (c <= 'z')

is_digit :: Char -> Bool
is_digit c = (c >= '0') && (c <= '9')

to_lower :: Char -> Char
to_lower c = branch of
  | is_upper c -> chr (ord c + 32)
  | -> c

to_upper :: Char -> Char
to_upper c = branch of
  | is_lower c -> chr (ord c - 32)
  | -> c

// inline Haskell "library" DSL code

>import Pec.Base
>import Data.List
>
>type CntW8 = Cnt256
>type W8 = W CntW8
>type Char_ = Char
>type Ptr_ a = Ptr a
>type IString_ = IString
>type W32_ = W32
>type Float_ = Float
>type Double_ = Double
>
>class Typed a => ARITH a where
>  add :: Term a -> Term a -> Term a
>  sub :: Term a -> Term a -> Term a
>  mul :: Term a -> Term a -> Term a
>  adiv :: Term a -> Term a -> Term a
>  arem :: Term a -> Term a -> Term a
>
>class Typed a => BITS a where
>  shl :: Term a -> Term a -> Term a
>  shr :: Typed a => Term a -> Term a -> Term a
>  band :: Term a -> Term a -> Term a
>  bor :: Term a -> Term a -> Term a
>  xor :: Term a -> Term a -> Term a
>  -- support ashr?
>
>class Typed a => ORD a where
>  gt :: Term a -> Term a -> Term Bool_
>  ge :: Term a -> Term a -> Term Bool_
>  lt :: Term a -> Term a -> Term Bool_
>  le :: Term a -> Term a -> Term Bool_
>
>class Typed a => EQ a where
>  eq :: Term a -> Term a -> Term Bool_
>  eq = prim2 "icmp eq"
>  ne :: Term a -> Term a -> Term Bool_
>  ne = prim2 "icmp ne"
>
>class (Typed a, Show a) => FRAC a where
>  frac :: a -> Term a
>  frac = val . show
>
// operators must be defined using the DSL
// The '$' is tacked on by the compiler in order to avoid name clashes.
>(@$) :: Typed a => Term (Ptr a) -> Term a
>(@$) = load
>
>(>$) :: ORD a => Term a -> Term a -> Term Bool_
>(>$) = gt
>
>(>=$) :: ORD a => Term a -> Term a -> Term Bool_
>(>=$) = ge
>
>(<$) :: ORD a => Term a -> Term a -> Term Bool_
>(<$) = lt
>
>(<=$) :: ORD a => Term a -> Term a -> Term Bool_
>(<=$) = le
>
>(+$) :: ARITH a => Term a -> Term a -> Term a
>(+$) = add
>
>(-$) :: ARITH a => Term a -> Term a -> Term a
>(-$) = sub
>
>(*$) :: ARITH a => Term a -> Term a -> Term a
>(*$) = mul
>
>(/$) :: ARITH a => Term a -> Term a -> Term a
>(/$) = adiv
>
>(%$) :: ARITH a => Term a -> Term a -> Term a
>(%$) = arem
>
>(==$) :: EQ a => Term a -> Term a -> Term Bool_
>(==$) = eq
>
>(!=$) :: EQ a => Term a -> Term a -> Term Bool_
>(!=$) = ne
>
>(<<$) :: BITS a => Term a -> Term a -> Term a
>(<<$) = shl
>
>(>>$) :: BITS a => Term a -> Term a -> Term a
>(>>$) = shr
>
>(&$) :: BITS a => Term a -> Term a -> Term a
>(&$) = band
>
>(|$) :: BITS a => Term a -> Term a -> Term a
>(|$) = bor
>
>(^$) :: BITS a => Term a -> Term a -> Term a
>(^$) = xor
>
>(&&$) :: Term Bool_ -> Term Bool_ -> Term Bool_
>(&&$) x y = Lift $ do
>  a <- eval x
>  b <- eval y
>  return $ switch a
>    [(false_tag, false_alt (\ _ -> false_))
>    ,(defaulttag, \ _ -> b)]
>
>(||$) :: Term Bool_ -> Term Bool_ -> Term Bool_
>(||$) x y = Lift $ do
>  a <- eval x
>  b <- eval y
>  return $ switch a
>    [(true_tag, true_alt (\ _ -> true_))
>    ,(defaulttag, \ _ -> b)]
>
// ad-hoc polymorphism, using Haskell classes
>instance Count cnt => EQ (I cnt)
>instance Count cnt => EQ (W cnt)
>instance EQ Char
>instance EQ IString
>instance (EQ a, EQ b) => EQ (a,b)
>instance INT Double where int = frac . fromInteger
>instance INT Float where int = frac . fromInteger
>instance FRAC Double
>instance FRAC Float
>
>instance Count cnt => BITS (W cnt) where
>  shl = prim2 "shl"
>  shr = prim2 "lshr"
>  band = prim2 "and"
>  bor = prim2 "or"
>  xor = prim2 "xor"
>
>instance Count cnt => ORD (W cnt) where
>  gt = prim2 "icmp ugt"
>  ge = prim2 "icmp uge"
>  lt = prim2 "icmp ult"
>  le = prim2 "icmp ule"
>
>instance ORD Char where
>  gt = prim2 "icmp ugt"
>  ge = prim2 "icmp uge"
>  lt = prim2 "icmp ult"
>  le = prim2 "icmp ule"
>
>instance Count cnt => ORD (I cnt) where
>  gt = prim2 "icmp sgt"
>  ge = prim2 "icmp sge"
>  lt = prim2 "icmp slt"
>  le = prim2 "icmp sle"
>
>instance ORD Double where
>  gt = prim2 "fcmp ogt"
>  ge = prim2 "fcmp oge"
>  lt = prim2 "fcmp olt"
>  le = prim2 "fcmp ole"
>
>instance ORD Float where
>  gt = prim2 "fcmp ogt"
>  ge = prim2 "fcmp oge"
>  lt = prim2 "fcmp olt"
>  le = prim2 "fcmp ole"
>
>instance Count cnt => ARITH (I cnt) where
>  add = prim2 "add"
>  sub = prim2 "sub"
>  mul = prim2 "mul"
>  adiv = prim2 "sdiv"
>  arem = prim2 "srem"
>
>instance Count cnt => ARITH (W cnt) where
>  add = prim2 "add"
>  sub = prim2 "sub"
>  mul = prim2 "mul"
>  adiv = prim2 "udiv"
>  arem = prim2 "urem"
>
>instance ARITH Double where
>  add = prim2 "fadd"
>  sub = prim2 "fsub"
>  mul = prim2 "fmul"
>  adiv = prim2 "fdiv"
>  arem = prim2 "frem"
>
>instance ARITH Float where
>  add = prim2 "fadd"
>  sub = prim2 "fsub"
>  mul = prim2 "fmul"
>  adiv = prim2 "fdiv"
>  arem = prim2 "frem"
>
>eq_unit = \_ _ -> true_
>ne_unit = \_ _ -> false_
>
>instance EQ () where
>  eq = eq_unit
>  ne = ne_unit
>
// polymorphic function
// note that the '_' is added to the end of pec names to avoid name clashes
>array_ :: (Count cnt, Typed cnt, Typed a) => Term (cnt -> a -> Array cnt a)
>array_ = lam2_ $ \(cnt :: Term cnt) x -> Lift $ do
>  a <- eval x
>  return $ array cnt $ genericReplicate (countof (unused :: cnt)) a
>
>ord_ :: Term (Char -> W8)
>ord_ = lam_ cast
>
>chr_ :: Term (W8 -> Char)
>chr_ = lam_ cast
>
>if_ :: Typed a => Term (Bool_ -> a -> a -> a)
>if_ = lam3_ $ \f g h ->
>  switch f [(true_tag, \_ -> g), (false_tag, \_ -> h)]
>
>when_ :: Term (Bool_ -> () -> ())
>when_ = lam2_ $ \a b -> app3 if_ a b unit