{-# LANGUAGE MultiParamTypeClasses #-} -- import Prelude hiding (foldr) -- import Data.Foldable -- I'm trying to figure out what kind of structure I'm working with in -- Staapl. A metaprogram or macro (m) is interpreted (I) as a target -- program (t) transformer (t -> t). -- -- I :: m -> (t -> t) -- -- To `compile' an m is to apply its interpretation (I m) to the empty -- target program t0. -- -- Multiple layers of metaprogramming can be chained in this way. -- -- This seems to work well for concatenative languages as it gives the -- relation between concatenation (syntax) and function composition -- (semantics), i.e. we can define a variant of I to work on lists: -- -- I' :: [m] -> (t -> t) -- I' = compose . (map I) -- We try to capture this in type classes. A concatenative language L -- is a type that supports the operation I. class Concat m t where iPrim :: m -> (t -> t) -- interpret primitive iComp :: [m] -> (t -> t) -- interpret concatenation nop :: t -- empty program iComp [] = \x -> x iComp (x:xs) = (iComp xs) . (iPrim x) data Macro a = Add | Sub | Lit a deriving Show data Target a = Plus | Min | Const a deriving Show data TCode a = TCode [Target a] deriving Show instance Concat (Macro a) (TCode a) where iPrim Add = \(TCode xs) -> TCode (Plus : xs) iPrim Sub = \(TCode xs) -> TCode (Min : xs) iPrim (Lit x) = \(TCode xs) -> TCode (Const x : xs) nop = TCode []