mirror of
https://github.com/IHaskell/IHaskell.git
synced 2025-04-16 03:16:20 +00:00
155 lines
4.1 KiB
Haskell
155 lines
4.1 KiB
Haskell
module Main where
|
|
|
|
import qualified Data.Text as T
|
|
|
|
import System.Environment (getArgs)
|
|
|
|
import Text.Parsec
|
|
import Text.Parsec.String
|
|
|
|
import IHaskell.IPython.EasyKernel (easyKernel, installKernelspec, KernelConfig(..))
|
|
import IHaskell.IPython.Types
|
|
|
|
-- Define the actual language!
|
|
data Expr = Plus Expr Expr
|
|
| Minus Expr Expr
|
|
| Times Expr Expr
|
|
| Div Expr Expr
|
|
| Exp Expr Expr
|
|
| Val Int
|
|
deriving (Show, Eq)
|
|
|
|
eval :: Expr -> Int
|
|
eval (Val i) = i
|
|
eval (Plus x y) = eval x + eval y
|
|
eval (Minus x y) = eval x - eval y
|
|
eval (Times x y) = eval x * eval y
|
|
eval (Div x y) = eval x `div` eval y
|
|
eval (Exp x y) = eval x ^ eval y
|
|
|
|
parseExpr :: String -> Either String Expr
|
|
parseExpr str =
|
|
case parse expr "interactive" (filter (/= ' ') str) of
|
|
Left err -> Left (show err)
|
|
Right e -> Right e
|
|
where
|
|
expr :: Parser Expr
|
|
expr = val <|> op
|
|
|
|
val :: Parser Expr
|
|
val = Val <$> read <$> many1 (oneOf "0123456789")
|
|
|
|
op :: Parser Expr
|
|
op = do
|
|
func <- choice $ map string $ ["plus", "minus", "times", "div", "exp"]
|
|
char '('
|
|
x <- expr
|
|
char ','
|
|
y <- expr
|
|
char ')'
|
|
return $
|
|
case func of
|
|
"plus" -> Plus x y
|
|
"minus" -> Minus x y
|
|
"times" -> Times x y
|
|
"div" -> Div x y
|
|
"exp" -> Exp x y
|
|
|
|
languageConfig :: LanguageInfo
|
|
languageConfig = LanguageInfo
|
|
{ languageName = "funcalc"
|
|
, languageVersion = "1.0.0"
|
|
, languageFileExtension = ".txt"
|
|
, languageCodeMirrorMode = "null"
|
|
, languagePygmentsLexer = "Text"
|
|
, languageMimeType = "x/funcalc"
|
|
}
|
|
|
|
languageKernelspec :: KernelSpec
|
|
languageKernelspec = KernelSpec
|
|
{ kernelDisplayName = "Calculator"
|
|
, kernelLanguage = "calc"
|
|
, kernelCommand = ["fun-calc-example", "kernel", "{connection_file}"]
|
|
}
|
|
|
|
displayString :: String -> [DisplayData]
|
|
displayString str = [DisplayData PlainText (T.pack str)]
|
|
|
|
languageCompletion :: Monad m => T.Text -> Int -> m (T.Text, [T.Text])
|
|
languageCompletion code pos = return $
|
|
let (before, _) = T.splitAt pos code
|
|
word = last $ T.words $ T.map replace before
|
|
in (word, map T.pack $ matches $ T.unpack word)
|
|
where
|
|
matches :: String -> [String]
|
|
matches word =
|
|
case head word of
|
|
'p' -> ["plus"]
|
|
'm' -> ["minus"]
|
|
'e' -> ["exp"]
|
|
'd' -> ["div"]
|
|
't' -> ["times"]
|
|
|
|
replace :: Char -> Char
|
|
replace '(' = ' '
|
|
replace ')' = ' '
|
|
replace ',' = ' '
|
|
replace x = x
|
|
|
|
languageInspect :: Monad m => T.Text -> Int -> m (Maybe [DisplayData])
|
|
languageInspect _ _ = return $
|
|
Just
|
|
[ DisplayData PlainText $ T.pack $
|
|
unlines
|
|
[ "We support five arithmetic functions:"
|
|
, " - plus +"
|
|
, " - minus -"
|
|
, " - div /"
|
|
, " - times *"
|
|
, " - exp ^"
|
|
, "Expressions are written as f(exp, exp)"
|
|
]
|
|
]
|
|
|
|
languageRun :: T.Text -> IO () -> (String -> IO ()) -> IO (String, ExecuteReplyStatus, String)
|
|
languageRun code init intermediate = do
|
|
init
|
|
let expr = parseExpr $ T.unpack code
|
|
intermediate (show expr)
|
|
|
|
return
|
|
(case expr of
|
|
Left err -> err
|
|
Right expr -> show (eval expr), IHaskell.IPython.Types.Ok, "")
|
|
|
|
simpleConfig :: KernelConfig IO String String
|
|
simpleConfig = KernelConfig
|
|
{ kernelLanguageInfo = languageConfig
|
|
, writeKernelspec = const $ return languageKernelspec
|
|
, displayOutput = displayString
|
|
, displayResult = displayString
|
|
, completion = languageCompletion
|
|
, inspectInfo = languageInspect
|
|
, run = languageRun
|
|
, debug = False
|
|
, kernelBanner = "Simple Arithmetic Expressions"
|
|
, kernelProtocolVersion = "5.0"
|
|
, kernelImplName = "funcalc"
|
|
, kernelImplVersion = "0.0"
|
|
}
|
|
|
|
main :: IO ()
|
|
main = do
|
|
args <- getArgs
|
|
case args of
|
|
["kernel", profileFile] ->
|
|
easyKernel profileFile simpleConfig
|
|
["install"] -> do
|
|
putStrLn "Installing kernelspec..."
|
|
installKernelspec simpleConfig False Nothing
|
|
_ -> do
|
|
putStrLn "Usage:"
|
|
putStrLn "fun-calc-example install -- set up the kernelspec"
|
|
putStrLn
|
|
"fun-calc-example kernel FILE -- run a kernel with FILE for communication with the frontend"
|