{-# OPTIONS_GHC -fglasgow-exts #-} module PIL.Native.Prims where import PIL.Native.Types import PIL.Native.Coerce import qualified Data.Map as NMap {-| PIL.Native.Prims This module defines the methods available for our Native types. NOTE: All types respond to the methods of Any Any as_bit () -> Bit as_int () -> Int as_num () -> Num as_str () -> Str is_nil () -> Bit not_nil () -> Bit eq () -> Bit lt () -> Bit le () -> Bit gt () -> Bit ge () -> Bit Bit not () -> Bit and (Block) -> Bit or (Block) -> Bit Int increment () -> Int decrement () -> Int add (Int) -> Int subtract (Int) -> Int multiply (Int) -> Int divide (Int) -> Int Num increment () -> Num decrement () -> Num add (Num) -> Num subtract (Num) -> Num multiply (Num) -> Num divide (Num) -> Num Str length () -> Num concat (Str) -> Str fetch () -> Str store (Str) -> Nil List length () -> Num concat (Any) -> Nil fetch (Num) -> Any store (Num, Any) -> Nil push (List) -> Nil Hash length () -> Num keys () -> List values () -> List concat (Any) -> Nil fetch (Any) -> Any exists (Any) -> Any store (Any, Any) -> Nil push (Hash) -> Nil See Also: PIL.Native.Types PIL.Native.Coerce -} type Prims = MapOf (Native -> Native) anyPrims :: MapOf (Native -> SeqOf Native -> Native) anyPrims = mkMap [ prim0 "as_bit" (fromNative :: Native -> NativeBit) , prim0 "as_int" (fromNative :: Native -> NativeInt) , prim0 "as_num" (fromNative :: Native -> NativeNum) , prim0 "as_str" (fromNative :: Native -> NativeStr) , prim0 "is_nil" is_nil , prim0 "not_nil" (not . is_nil) , prim1 "eq" (==) , prim1 "lt" (<) , prim1 "le" (<=) , prim1 "gt" (>) , prim1 "ge" (>=) ] bitPrims :: MapOf (NativeBit -> SeqOf Native -> Native) bitPrims = mkMap [ prim0 "not" not , prim1 "and" (&&) , prim1 "or" (||) ] intPrims :: MapOf (NativeInt -> SeqOf Native -> Native) intPrims = mkMap [ prim0 "increment" succ , prim0 "decrement" pred , prim1 "add" (+) , prim1 "subtract" (-) , prim1 "multiply" (*) , prim1 "divide" div ] numPrims :: MapOf (NativeNum -> SeqOf Native -> Native) numPrims = mkMap [ prim0 "increment" succ , prim0 "decrement" pred , prim1 "add" (+) , prim1 "subtract" (-) , prim1 "multiply" (*) , prim1 "divide" (/) ] strPrims :: MapOf (NativeStr -> SeqOf Native -> Native) strPrims = mkMap [ prim0 "length" (size) , prim0 "reverse" (reversed) , prim0 "is_empty" (isEmpty) , prim1 "concat" (append) , prim1 "fetch" (fetch) , prim1 "splice" (splice) , prim2 "store" (insert) ] seqPrims :: MapOf (NativeSeq -> SeqOf Native -> Native) seqPrims = mkMap [ prim0 "length" (size) , prim0 "reverse" (reversed) , prim0 "is_empty" (isEmpty) , prim1 "concat" (append) , prim1 "fetch" (fetch) , prim1 "splice" (splice) , prim2 "store" (insert) , primX "push" (push) ] mapPrims :: MapOf (NativeMap -> SeqOf Native -> Native) mapPrims = mkMap [ prim0 "length" (size) , prim0 "keys" (indices) , prim0 "is_empty" (isEmpty) , prim0 "values" (elems) , prim1 "concat" (append) , prim1 "fetch" (fetch) , prim1 "exists" (exists) , prim1 "delete" (delete) , prim2 "store" (insert) , primX "push" (pushHash) ] where pushHash :: NativeMap -> SeqOf Native -> NativeMap pushHash obj args = obj `NMap.union` (NMap.fromList $ listHash $ elems args) listHash [] = [] listHash (k:v:xs) = (fromNative k, v):(listHash xs) listHash _ = error "odd number of elements for hash" prim0 :: (IsNative inv, IsNative ret) => String -> (inv -> ret) -> (String, inv -> SeqOf Native -> Native) prim0 str f = (str, f') where f' obj args | isEmpty args = toNative (f obj) f' _ _ = errArgs prim1 :: (IsNative inv, IsNative a, IsNative ret) => String -> (inv -> a -> ret) -> (String, inv -> SeqOf Native -> Native) prim1 str f = (str, f') where f' obj args | size args == 1 = toNative $ f obj (fromNative $ args ! 0) f' _ _ = errArgs prim2 :: (IsNative inv, IsNative a, IsNative b, IsNative ret) => String -> (inv -> a -> b -> ret) -> (String, inv -> SeqOf Native -> Native) prim2 str f = (str, f') where f' obj args | size args == 2 = toNative $ f obj (fromNative $ args ! 0) (fromNative $ args ! 1) f' _ _ = errArgs primX :: (IsNative inv, IsNative ret) => String -> (inv -> SeqOf Native -> ret) -> (String, inv -> SeqOf Native -> Native) primX str f = (str, f') where f' obj args = toNative $ f obj args errArgs :: forall a. a errArgs = error "Invalid number of arguments"