packages feed

sifflet-1.1: sifflet.hs

module Main (main) where

import Control.Monad (when)
import Data.IORef
import System.Exit

import Sifflet.Data.Functoid
import Sifflet.Data.TreeLayout
import Sifflet.Examples
import Sifflet.Language.Expr
import Sifflet.Language.Parser
import Sifflet.UI
import Sifflet.Util

import Options


-- | Main function

main :: IO ()
main = do
  {
    -- scim-bridge causes many errors, so don't use it
    suppressScimBridge

  -- Initialize GTK, returning args unused by Gtk itself
  ; args <- initGUI
  -- Process remaining command-line arguments
  ; let commands = processArgs args

    -- create the user interface
  ; vpui <- vpuiNew wstyle initialEnv
  ; let vpui' = vpui {vpuiToolkits = defaultVPUIToolkitsWithExamples}
  ; uiref <- newIORef vpui'
    -- Create wome windows
  ; let cbmgr = mkCBMgr uiref
  ; vpui'' <- showWorkWin vpui' workspaceId cbmgr
  ; writeIORef uiref vpui''

  -- Obey command-line arguments, then let Gtk take over
  ; mExitCode <- performCommands commands cbmgr uiref
  ; case mExitCode of
      Nothing -> mainGUI >> return ()
      Just code -> exitWith code
  }

-- | Environment

initialEnv :: Env
initialEnv = exampleEnv

-- | Default toolkit

defaultVPUIToolkitsWithExamples :: [(String, VPToolkit)]
defaultVPUIToolkitsWithExamples =
    let toolkits =
            -- each item has name, width, list of rows tools
            [VPToolkit "Base" 500 (functionToolsFromLists baseFunctionsRows),
             VPToolkit "Examples" 500 
                           (functionToolsFromLists [exampleFunctionNames]),
             VPToolkit "My Functions" 500 (functionToolsFromLists [[]])]
    in zip (map toolkitName toolkits) toolkits

-- | Perform the things requested in command-line arguments.
-- Return an exit code if processing should continue.

performCommands :: Options -> CBMgr -> IORef VPUI -> IO (Maybe ExitCode)
performCommands options cbmgr uiref =
    -- Error?
    case optionsErrorMsg options of
      Just msg ->
          putStrLn ("sifflet: " ++ msg) >> return (Just (ExitFailure 1))
      Nothing ->
          -- Help requested?
          if optionsHelp options
          then showHelp >> return (Just ExitSuccess)
          else do
            {
              -- show function pad?
              when (optionsShowFunPad options)
                   (modifyIORefIO uiref (showFunctionPadWindow cbmgr))

              -- source a file?
              -- What if no such file???
            ; case optionsSourceFile options of
                Nothing -> return ()
                Just file ->
                    modifyIORefIO uiref (openFilePath cbmgr file)

              -- show or call a function?
            ; case (optionsShowFunction options, 
                    optionsCallFunction options) of
                -- neither
                (Nothing, Nothing) -> return Nothing
                -- just show
                (Just fname, Nothing) -> 
                    showFunctionFrame fname Nothing uiref >>
                    return Nothing
                -- call, overrides show if both are given
                (_, Just fname) ->
                    showFunctionFrame fname 
                                      (Just (optionsAdditionalArgs options))
                                      uiref
            }

showFunctionFrame :: String -- ^ function name
                  -> Maybe [String] -- ^ Just args, to call with args
                  -> IORef VPUI
                  -> IO (Maybe ExitCode)
showFunctionFrame fname mArgStrs uiref = do
  {
    vpui <- readIORef uiref
  ; let x = styleFramePad (vpuiStyle vpui)
        y = 150
        env = vpuiGlobalEnv vpui

        showFun :: Function -> Maybe [Value] -> IO ()
        showFun f mArgValues = 
            vpuiAddFrame vpui workspaceId (FunctoidFunc f)
                         mArgValues CallFrame env x y 0 Nothing >>=
            writeIORef uiref

  ; case envLookup env fname of
      Just (VFun f@(Function _fname argTypes _retType (Compound _ _))) ->
          case mArgStrs of
            Nothing -> showFun f Nothing >> return Nothing
            Just argStrs ->
                case parseTypedInputs2 argStrs argTypes of
                  Fail msg ->
                      putStrLn ("sifflet: " ++ msg) >>
                      return (Just (ExitFailure 1))
                  Succ argValues ->
                      showFun f (Just argValues) >> return Nothing

      _ -> putStrLn ("sifflet: function not found or not compound") >>
           return (Just (ExitFailure 2))
  }