module Graphics.Implicit.ExtOpenScad.Util where import Prelude hiding (lookup) import Graphics.Implicit.Definitions import Graphics.Implicit.ExtOpenScad.Definitions import Graphics.Implicit.ExtOpenScad.Expressions import Data.Map (Map, lookup, insert) import qualified Data.List import Text.ParserCombinators.Parsec import Text.ParserCombinators.Parsec.Expr import Control.Monad (liftM) instance Monad ArgParser where (ArgParser str fallback f) >>= g = ArgParser str fallback (\a -> (f a) >>= g) (ArgParserTerminator a) >>= g = g a (ArgParserFail) >>= g = ArgParserFail return a = ArgParserTerminator a argMap :: [OpenscadObj] -> [(String, OpenscadObj)] -> ArgParser a -> Maybe a argMap _ _ (ArgParserTerminator a) = Just a argMap _ _ ArgParserFail = Nothing argMap (x:unnamedArgs) namedArgs (ArgParser _ _ f) = argMap unnamedArgs namedArgs (f x) argMap [] namedArgs (ArgParser str fallback f) = case Data.List.lookup str namedArgs of Just a -> argMap [] namedArgs (f a) Nothing -> case fallback of Just b -> argMap [] namedArgs (f b) Nothing -> Nothing argument :: String -> ArgParser OpenscadObj argument str = ArgParser str Nothing (\a -> return a) realArgument :: String -> ArgParser ℝ realArgument str = ArgParser str Nothing (\a -> case a of {(ONum a) -> return a; _ -> ArgParserFail;}) intArgument :: String -> ArgParser Int intArgument str = ArgParser str Nothing (\a -> case a of {(ONum a) -> return (floor a); _ -> ArgParserFail;}) boolArgument :: String -> ArgParser Bool boolArgument str = ArgParser str Nothing (\a -> case a of {(OBool a) -> return a; _ -> ArgParserFail;}) argumentWithDefault :: String -> OpenscadObj -> ArgParser OpenscadObj argumentWithDefault str fallback = ArgParser str (Just fallback) (\a -> return a) realArgumentWithDefault :: String -> ℝ -> ArgParser ℝ realArgumentWithDefault str fallback = ArgParser str (Just (ONum fallback)) (\a -> case a of {(ONum a) -> return a; _ -> ArgParserFail;}) intArgumentWithDefault :: String -> Int -> ArgParser Int intArgumentWithDefault str fallback = ArgParser str (Just (ONum (fromIntegral fallback))) (\a -> case a of {(ONum a) -> return (floor a); _ -> ArgParserFail;}) boolArgumentWithDefault :: String -> Bool -> ArgParser Bool boolArgumentWithDefault str fallback = ArgParser str (Just (OBool fallback)) (\a -> case a of {(OBool a) -> return a; _ -> ArgParserFail;}) addObj2 :: (Monad m) => Obj2Type -> m ComputationStateModifier addObj2 obj = return $ \ ioWrappedState -> do (varlookup, obj2s, obj3s) <- ioWrappedState return (varlookup, obj2s ++ [obj], obj3s) addObj3 :: (Monad m) => Obj3Type -> m ComputationStateModifier addObj3 obj = return $ \ ioWrappedState -> do (varlookup, obj2s, obj3s) <- ioWrappedState return (varlookup, obj2s, obj3s ++ [obj]) changeObjs :: (Monad m) => ([Obj2Type] -> [Obj2Type]) -> ([Obj3Type] -> [Obj3Type]) -> m ComputationStateModifier changeObjs mod2s mod3s = return $ \ ioWrappedState -> do (varlookup, obj2s, obj3s) <- ioWrappedState return (varlookup, mod2s obj2s, mod3s obj3s) runIO :: (Monad m) => IO() -> m ComputationStateModifier runIO newio = return $ \ ioWrappedState -> do state <- ioWrappedState newio return state noChange :: (Monad m) => m ComputationStateModifier noChange = return id moduleArgsUnit :: GenParser Char st ([VariableLookup -> OpenscadObj], [(String, VariableLookup -> OpenscadObj)]) moduleArgsUnit = do char '('; many space; args <- sepBy ( (try $ do symb <- variableSymb; many space; char '='; many space; expr <- expression 0; return $ Right (symb, expr); ) <|> (try $ do symb <- variableSymb; many space; char '(' many space argVars <- sepBy variableSymb (many space >> char ',' >> many space) char ')' many space char '='; many space; expr <- expression 0; let makeFunc baseExpr (argVar:xs) varlookup' = OFunc $ \argObj -> makeFunc baseExpr xs (insert argVar argObj varlookup') makeFunc baseExpr [] varlookup' = baseExpr varlookup' funcExpr = makeFunc expr argVars return $ Right (symb, funcExpr); ) <|> (do { expr <- expression 0; return $ Left expr; }) ) (many space >> char ',' >> many space); many space; char ')'; let isRight (Right a) = True isRight _ = False named = map (\(Right a) -> a) $ filter isRight $ args unnamed = map (\(Left a) -> a) $ filter (not . isRight) $ args in return (unnamed, named) moduleWithoutSuite :: String -> ArgParser ComputationStateModifier -> GenParser Char st ComputationStateModifier moduleWithoutSuite name argHandeler = (do string name; many space; (unnamed, named) <- moduleArgsUnit return $ \ ioWrappedState -> do state@(varlookup, obj2s, obj3s) <- ioWrappedState case argMap (map ($varlookup) unnamed) (map (\(a,b) -> (a, b varlookup)) named) argHandeler of Just computationModifier -> computationModifier (return state) Nothing -> (return state); ) name pad parser = do many space a <- parser many space return a