{-# LANGUAGE OverloadedStrings #-} module Funcons.Operations.ADTs where import Funcons.Operations.Internal import Data.Maybe (fromJust, isJust) import Data.Text (pack, unpack) import Data.String(fromString) library :: HasValues t => Ord t => Library t library = libFromList [ ("adts", NullaryExpr adts) , ("adt-construct", NaryExpr adt_construct_) , ("adt-type", NaryExpr adt_type_construct_) , ("adt-type-construct", NaryExpr adt_type_construct_) , ("adt-constructor", UnaryExpr adt_constructor) , ("adt-fields", UnaryExpr adt_fields) ] adts_ :: HasValues t => [OpExpr t] -> OpExpr t adts_ = nullaryOp adts adts :: HasValues t => OpExpr t adts = NullaryOp "adts" (Normal $ injectT ADTs) adt_construct_ :: HasValues t => [OpExpr t] -> OpExpr t adt_construct_ = NaryOp "adt-construct" op where op :: HasValues t => [t] -> Result t op (x : vs) = case project x of Just v -> if isString_ v then Normal $ inject $ ADTVal (pack (unString v)) vs else SortErr "adt-construct: first argument not a string" _ -> ProjErr "adt-construct" op _ = SortErr "adt-construct: insufficient arguments" adt_type_construct_ :: HasValues t => [OpExpr t] -> OpExpr t adt_type_construct_ = vNaryOp "adt-type-construct" op where op (s : vs) | isString_ s = Normal $ injectT $ ADT (pack (unString s)) (map inject vs) op _ = SortErr "adt-construct: first argument not a string" adt_constructor_ :: HasValues t => [OpExpr t] -> OpExpr t adt_constructor_ = unaryOp adt_constructor adt_constructor :: HasValues t => OpExpr t -> OpExpr t adt_constructor = vUnaryOp "adt-constructor" op where op (ADTVal cons _) = Normal $ inject $ fromString (unpack cons) op _ = SortErr "adt-constructor: argument not an adt value" adt_fields_ :: HasValues t => [OpExpr t] -> OpExpr t adt_fields_ = unaryOp adt_fields adt_fields :: HasValues t => OpExpr t -> OpExpr t adt_fields = vUnaryOp "adt-fields" op where op (ADTVal _ fs) = Normal $ inject $ ADTVal "list" fs op _ = SortErr "adt-fields: argument not an adt value"