technique-0.2.5: lib/Technique/Language.hs
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
module Technique.Language where
import Core.Data.Structures (Key)
import Core.Text.Rope
import Data.Hashable (Hashable)
import GHC.Generics (Generic)
import Technique.Quantity
data Technique = Technique
{ techniqueVersion :: Int,
techniqueLicense :: Rope,
techniqueCopyright :: Maybe Rope,
techniqueBody :: [Procedure]
}
deriving (Show, Eq)
emptyTechnique :: Technique
emptyTechnique =
Technique
{ techniqueVersion = 0,
techniqueLicense = emptyRope,
techniqueCopyright = Nothing,
techniqueBody = []
}
-- TODO
data Identifier
= Identifier Rope
deriving (Show, Eq, Ord, Generic, Hashable)
unIdentifier :: Identifier -> Rope
unIdentifier (Identifier text) = text
{-# INLINE unIdentifier #-}
instance Key Identifier
-- TODO construction needs to validate internal rules for labels. No
-- newlines, perhaps.
newtype Label = Label Rope
deriving (Show, Eq, Ord)
data Attribute
= Role Identifier
| Place Identifier
| Inherit
deriving (Show, Eq, Ord)
{-
| Anyone
| Anywhere
-}
data Markdown
= Markdown Rope
deriving (Eq, Ord)
instance Show Markdown where
show (Markdown text) = "[quote|\n" ++ fromRope text ++ "|]"
data Type
= Type Rope
deriving (Show, Eq, Ord)
unitType :: Type
unitType = Type "()"
data Procedure = Procedure
{ procedureOffset :: Offset,
procedureName :: Identifier,
procedureParams :: [Identifier],
procedureInput :: [Type],
procedureOutput :: [Type],
procedureTitle :: Maybe Markdown,
procedureDescription :: Maybe Markdown,
procedureBlock :: Block
}
deriving (Show, Eq, Ord)
emptyProcedure :: Procedure
emptyProcedure =
Procedure
{ procedureOffset = -1,
procedureName = Identifier "none",
procedureParams = [],
procedureInput = [unitType],
procedureOutput = [unitType],
procedureTitle = Nothing,
procedureDescription = Nothing,
procedureBlock = Block []
}
data Block = Block [Statement]
deriving (Show, Eq, Ord)
type Offset = Int
class Located a where
locationOf :: a -> Offset
instance Located Procedure where
locationOf = procedureOffset
data Statement
= Assignment Offset [Identifier] Expression
| Execute Offset Expression
| Comment Offset Rope
| Declaration Offset Procedure
| Blank Offset
| Series Offset
deriving (Show, Ord, Eq)
instance Located Statement where
locationOf statement = case statement of
Assignment o _ _ -> o
Execute o _ -> o
Comment o _ -> o
Declaration o _ -> o
Blank o -> o
Series o -> o
data Expression
= Application Offset Identifier Expression -- this had better turn out to be a procedure
| None Offset
| Text Offset Rope
| Amount Offset Quantity
| Undefined Offset
| Object Offset Tablet
| Variable Offset [Identifier]
| Operation Offset Operator Expression Expression
| Grouping Offset Expression
| Restriction Offset Attribute Block
deriving (Show, Ord, Eq)
instance Located Expression where
locationOf expr = case expr of
Application o _ _ -> o
None o -> o
Text o _ -> o
Amount o _ -> o
Undefined o -> o
Object o _ -> o
Variable o _ -> o
Operation o _ _ _ -> o
Grouping o _ -> o
Restriction o _ _ -> o
data Tablet
= Tablet [Binding]
deriving (Show, Ord, Eq)
-- only valid Expressions are Literal and Variable. Should we enforce that
-- somewhere?
data Binding
= Binding Label Expression
deriving (Show, Eq, Ord)
data Operator
= WaitEither
| WaitBoth
| Combine
deriving (Show, Eq, Ord)