module Language.Ast (
Definition(..)
, Expression(..)
, PrimitiveMap(..)
, SugaredDefinition(..)
, SugaredExpression(..)
, mappyChar
, mappyNat
, mappyList
, mappyZero
, mappyOne
) where
import Data.Bits
import Data.Char (ord)
import qualified Data.Map.Strict as M
import Language.Primitives.IoAble
import Language.Primitives.Map
data SugaredDefinition =
SugaredFnDefinition Expression [Expression] Expression
deriving (Eq, Show, Ord)
data SugaredExpression =
SugaredLet [Definition] Expression
| SugaredList [Expression]
| SugaredChar Char
| SugaredString String
deriving (Eq, Show, Ord)
data Definition =
MappyDef Expression Expression
| DefSugar SugaredDefinition
deriving (Eq, Show, Ord)
data Expression =
MappyMap (PrimitiveMap Expression)
| MappyApp Expression [Expression]
| MappyLambda [Expression] Expression
| MappyClosure [Expression] Expression [(Expression, Expression)]
| MappyKeyword String
| MappyNamedValue String
| MappyLazyArgument String
| ExprSugar SugaredExpression
deriving (Eq, Show, Ord)
instance IoAble Expression where
classifyOutput (MappyKeyword "print") = Just IoPrint
classifyOutput (MappyKeyword "write-file") = Just IoWriteFile
classifyOutput _ = Nothing
classifyInput (MappyMap (StandardMap map')) =
case M.lookup (MappyKeyword "read-file") map' of
Nothing -> Nothing
_ -> Just IoReadFile
classifyInput _ = Nothing
pluckInner (MappyMap (StandardMap map')) IoFilename =
M.findWithDefault (error " - No file given in IO action") (MappyKeyword "file") map'
pluckInner (MappyMap (StandardMap map')) IoContents =
M.findWithDefault (error " - No file text given in IO action") (MappyKeyword "text") map'
pluckInner (MappyMap (StandardMap map')) IoReadFileSel =
M.findWithDefault (error " - No file given in IO action") (MappyKeyword "read-file") map'
pluckInner _ _ = error " - Non-map given in IO action"
fromString = mappyList id . map mappyChar
mappyList :: (Expression -> Expression) -> [Expression] -> Expression
mappyList f = MappyMap . StandardMap . go
where
go [] = M.empty
go (v:vs) = M.fromList [(MappyKeyword "head", f v), (MappyKeyword "tail", MappyMap $ StandardMap $ go vs)]
withTypeHint :: Expression -> String -> Expression
withTypeHint (MappyMap (StandardMap map')) typeHint =
MappyMap $ StandardMap $ M.union (M.singleton (MappyKeyword "__type") $ MappyKeyword typeHint) map'
withTypeHint v _ = v
mappyChar :: Char -> Expression
mappyChar c = toBinary (ord c) `withTypeHint` "char"
mappyNat :: Int -> Expression
mappyNat 0 = MappyMap $ StandardMap M.empty
mappyNat n = MappyMap $ StandardMap $ M.singleton (MappyKeyword "pred") $ mappyNat $ n 1
toBinary :: Int -> Expression
toBinary = mappyList id . go
where
single 0 = mappyZero
single 1 = mappyOne
go 0 = []
go 1 = [mappyOne]
go n = (single $ 1 .&. n):go (shiftR n 1)
mappyZero :: Expression
mappyZero = MappyMap $ StandardMap M.empty
mappyOne :: Expression
mappyOne = MappyMap $ StandardMap $ M.singleton (MappyKeyword "pred") mappyZero