{-# LANGUAGE PackageImports #-}
module Graphics.Implicit.ExtOpenScad.Definitions (ArgParser(AP, APTest, APBranch, APTerminator, APFailIf, APExample),
Symbol(Symbol),
Pattern(Wild, Name, ListP),
Expr(LitE, Var, ListE, LamE, (:$)),
StatementI(StatementI),
Statement(DoNothing, NewModule, Include, If, ModuleCall, (:=)),
OVal(ONum, OBool, OString, OList, OFunc, OUndefined, OUModule, ONModule, OVargsModule, OError, OObj2, OObj3),
TestInvariant(EulerCharacteristic),
SourcePosition(SourcePosition),
StateC,
CompState(CompState, scadVars, oVals, sourceDir, messages, scadOpts),
VarLookup(VarLookup),
Message(Message),
MessageType(TextOut, Warning, Error, SyntaxError, Compatibility, Unimplemented),
ScadOpts(ScadOpts, openScadCompatibility, importsAllowed),
lookupVarIn,
varUnion
) where
import Prelude(Eq, Show, Ord, String, Maybe(Just), Bool(True, False), IO, FilePath, (==), show, ($), (<>), undefined, and, zipWith, foldl1, Int)
import Graphics.Implicit.Definitions (ℝ, ℕ, Fastℕ, SymbolicObj2, SymbolicObj3, fromFastℕ)
import Control.Applicative (Applicative, Alternative((<|>), empty), pure, (<*>))
import Control.Monad (Functor, Monad, fmap, (>>=), mzero, mplus, MonadPlus, liftM, ap, return, (>=>))
import Data.Map (Map, lookup, union)
import Data.Maybe (fromMaybe)
import Data.List (intercalate)
import "monads-tf" Control.Monad.State (StateT)
data CompState = CompState
{ scadVars :: VarLookup
, oVals :: [OVal]
, sourceDir :: FilePath
, messages :: [Message]
, scadOpts :: ScadOpts
}
type StateC = StateT CompState IO
data ArgParser a
= AP Symbol (Maybe OVal) String (OVal -> ArgParser a)
| APTerminator a
| APFailIf Bool String (ArgParser a)
| APExample String (ArgParser a)
| APTest String [TestInvariant] (ArgParser a)
| APBranch [ArgParser a]
instance Functor ArgParser where
fmap = liftM
instance Applicative ArgParser where
pure = APTerminator
(<*>) = ap
instance Monad ArgParser where
(AP str fallback d f) >>= g = AP str fallback d (f >=> g)
(APFailIf b errmsg child) >>= g = APFailIf b errmsg (child >>= g)
(APExample str child) >>= g = APExample str (child >>= g)
(APTest str tests child) >>= g = APTest str tests (child >>= g)
(APTerminator a) >>= g = g a
(APBranch bs) >>= g = APBranch $ fmap (>>= g) bs
return = pure
instance MonadPlus ArgParser where
mzero = APFailIf True "" undefined
mplus (APBranch as) (APBranch bs) = APBranch ( as <> bs )
mplus (APBranch as) b = APBranch ( as <> [b] )
mplus a (APBranch bs) = APBranch ( a : bs )
mplus a b = APBranch [ a , b ]
instance Alternative ArgParser where
(<|>) = mplus
empty = mzero
newtype Symbol = Symbol String
deriving (Show, Eq, Ord)
newtype VarLookup = VarLookup (Map Symbol OVal)
data Pattern = Name Symbol
| ListP [Pattern]
| Wild
deriving (Show, Eq)
data Expr = Var Symbol
| LitE OVal
| ListE [Expr]
| LamE [Pattern] Expr
| Expr :$ [Expr]
deriving (Show, Eq)
data StatementI = StatementI SourcePosition (Statement StatementI)
deriving (Show, Eq)
data Statement st = Include String Bool
| Pattern := Expr
| If Expr [st] [st]
| NewModule Symbol [(Symbol, Maybe Expr)] [st]
| ModuleCall Symbol [(Maybe Symbol, Expr)] [st]
| DoNothing
deriving (Show, Eq)
data OVal = OUndefined
| OError [String]
| OBool Bool
| ONum ℝ
| OList [OVal]
| OString String
| OFunc (OVal -> OVal)
| OUModule Symbol (Maybe [(Symbol, Bool)]) ([OVal] -> ArgParser (StateC [OVal]))
| ONModule Symbol (SourcePosition -> [OVal] -> ArgParser (StateC [OVal])) [([(Symbol, Bool)], Maybe Bool)]
| OVargsModule String (String -> SourcePosition -> [(Maybe Symbol, OVal)] -> [StatementI] -> ([StatementI] -> StateC ()) -> StateC ())
| OObj3 SymbolicObj3
| OObj2 SymbolicObj2
instance Eq OVal where
(OBool a) == (OBool b) = a == b
(ONum a) == (ONum b) = a == b
(OList a) == (OList b) = and $ zipWith (==) a b
(OString a) == (OString b) = a == b
_ == _ = False
instance Show OVal where
show OUndefined = "Undefined"
show (OBool b) = show b
show (ONum n) = show n
show (OList l) = show l
show (OString s) = show s
show (OFunc _) = "<function>"
show (OUModule (Symbol name) arguments _) = "module " <> name <> " (" <> intercalate ", " (fmap showArg (fromMaybe [] arguments)) <> ") {}"
where
showArg (Symbol a, hasDefault) = if hasDefault
then a
else a <> "=..."
show (ONModule (Symbol name) _ instances) = showInstances instances
where
showArg (Symbol a, hasDefault) = if hasDefault
then a
else a <> "=..."
showInstances :: [([(Symbol, Bool)], Maybe Bool)] -> String
showInstances [] = ""
showInstances [oneInstance] = "module " <> name <> showInstance oneInstance
showInstances multipleInstances = "Module " <> name <> "[ " <> intercalate ", " (fmap showInstance multipleInstances) <> " ]"
showInstance :: ([(Symbol, Bool)], Maybe Bool) -> String
showInstance (arguments, suiteInfo) = " (" <> intercalate ", " (fmap showArg arguments) <> ") {}" <> showSuiteInfo suiteInfo
showSuiteInfo suiteInfo = case suiteInfo of
Just requiresSuite -> if requiresSuite
then " requiring suite {}"
else " accepting suite {}"
_ -> ""
show (OVargsModule name _) = "varargs module " <> name
show (OError msgs) = "Execution Error:\n" <> foldl1 (\a b -> a <> "\n" <> b) msgs
show (OObj2 obj) = "<obj2: " <> show obj <> ">"
show (OObj3 obj) = "<obj3: " <> show obj <> ">"
data SourcePosition = SourcePosition
Fastℕ
Fastℕ
FilePath
deriving (Eq)
instance Show SourcePosition where
show (SourcePosition line col []) = "line " <> show (fromFastℕ line :: Int) <> ", column " <> show (fromFastℕ col :: Int)
show (SourcePosition line col filePath) = "line " <> show (fromFastℕ line :: Int) <> ", column " <> show (fromFastℕ col :: Int) <> ", file " <> filePath
data MessageType = TextOut
| Warning
| Error
| SyntaxError
| Compatibility
| Unimplemented
deriving (Show, Eq)
data Message = Message MessageType SourcePosition String
deriving (Eq)
instance Show Message where
show (Message mtype pos text) = show mtype <> " at " <> show pos <> ": " <> text
data ScadOpts = ScadOpts
{ openScadCompatibility :: Bool
, importsAllowed :: Bool
}
varUnion :: VarLookup -> VarLookup -> VarLookup
varUnion (VarLookup a) (VarLookup b) = VarLookup $ union a b
lookupVarIn :: String -> VarLookup -> Maybe OVal
lookupVarIn target (VarLookup vars) = lookup (Symbol target) vars
newtype TestInvariant = EulerCharacteristic ℕ
deriving (Show)