{-# LANGUAGE ImplicitParams #-} {-# LANGUAGE LambdaCase #-} module Cryptol.Eval.Prims where import Cryptol.Backend import Cryptol.Eval.Type import Cryptol.Eval.Value import Cryptol.ModuleSystem.Name import Cryptol.TypeCheck.Solver.InfNat(Nat'(..)) import Cryptol.Utils.Panic -- | This type provides a lightweight syntactic framework for defining -- Cryptol primitives. The main purpose of this type is to provide -- an abstraction barrier that insulates the definitions of primitives -- from possible changes in the representation of values. data Prim sym = PFun (SEval sym (GenValue sym) -> Prim sym) | PStrict (GenValue sym -> Prim sym) | PWordFun (SWord sym -> Prim sym) | PFloatFun (SFloat sym -> Prim sym) | PTyPoly (TValue -> Prim sym) | PNumPoly (Nat' -> Prim sym) | PFinPoly (Integer -> Prim sym) | PPrim (SEval sym (GenValue sym)) | PVal (GenValue sym) -- | Evaluate a primitive into a value computation evalPrim :: Backend sym => sym -> Name -> Prim sym -> SEval sym (GenValue sym) evalPrim sym nm p = case p of PFun f -> lam sym (evalPrim sym nm . f) PStrict f -> lam sym (\x -> evalPrim sym nm . f =<< x) PWordFun f -> lam sym (\x -> evalPrim sym nm . f =<< (fromVWord sym (show nm) =<< x)) PFloatFun f -> flam sym (evalPrim sym nm . f) PTyPoly f -> tlam sym (evalPrim sym nm . f) PNumPoly f -> nlam sym (evalPrim sym nm . f) PFinPoly f -> nlam sym (\case Inf -> panic "PFin" ["Unexpected `inf`", show nm]; Nat n -> evalPrim sym nm (f n)) PPrim m -> m PVal v -> pure v