MetaObject-0.0.1: src/MO/Compile.hs
{-# OPTIONS_GHC -fglasgow-exts -fallow-undecidable-instances -funbox-strict-fields #-}
module MO.Compile where
import MO.Base
import MO.Util
-- A Method must have name and an implementation encapsulated in a
-- MethodCompile type. This abstraction allows having different
-- types of methods, but for now we have only SimpleMethod, which is
-- the minimal sane instance of Method.
type MethodName = Atom
class Monad m => Method m a | a -> m where
methodName :: a -> MethodName
methodCompile :: a -> MethodCompiled m
instance Monad m => Method m (AnyMethod m) where
methodName (MkMethod x) = methodName x
methodCompile (MkMethod x) = methodCompile x
data SimpleMethod m
= MkSimpleMethod
{ sm_name :: MethodName
, sm_definition :: MethodCompiled m
}
instance Monad m => Method m (SimpleMethod m) where
methodName = sm_name
methodCompile = sm_definition
-- AnyMethod may contain any type of the Method class. This makes
-- other functions life easier. And is a common pattern in MO code.
data AnyMethod m = forall a. Method m a => MkMethod !a
-- FIXME: Its not ok to use this since we can define method with
-- same name which are different.
instance Eq (AnyMethod m) where
MkMethod a == MkMethod b = methodName a == methodName b
instance Ord (AnyMethod m) where
MkMethod a `compare` MkMethod b = methodName a `compare` (methodName b)
instance Show (AnyMethod m) where
show (MkMethod m) = show (methodName m)
-- MethodCompiled represent a method that maybe called (via runMC) with
-- an Arguments and return an Invocant. It may in the future use the
-- Codeable abstraction (see Base.hs) but for now is "just" a Haskell method.
newtype MethodCompiled m = MkMethodCompiled { runMC :: Arguments m -> m (Invocant m) }