{-# LANGUAGE OverloadedStrings #-}
module StdLib where
import Analyzer.AnalyzedAst (Identifier)
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Text (Text, pack)
import qualified Data.Text as T
import Interpreter.Result (Err (Panic, UnexpectedError), ResultValue, RuntimeValue' (..))
import MaybeVoid (MaybeVoid (NonVoid, Void))
data StdLibFunction = StdLibFunction
{ StdLibFunction -> Identifier
name :: Identifier,
StdLibFunction -> StdLibFuncImpl
impl :: StdLibFuncImpl
}
type StdLibFuncImpl = [RuntimeValue'] -> StdLibFuncResult
type StdLibFuncResult = ResultValue (MaybeVoid RuntimeValue', Text)
stdLibFunctions :: [StdLibFunction]
stdLibFunctions :: [StdLibFunction]
stdLibFunctions = [StdLibFunction
lenFunction, StdLibFunction
printFunction, StdLibFunction
printlnFunction, StdLibFunction
panicFunction]
stdLibFunctionsMap :: Map Identifier StdLibFuncImpl
stdLibFunctionsMap :: Map Identifier StdLibFuncImpl
stdLibFunctionsMap = forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList forall a b. (a -> b) -> a -> b
$ (\StdLibFunction
f -> (StdLibFunction -> Identifier
name StdLibFunction
f, StdLibFunction -> StdLibFuncImpl
impl StdLibFunction
f)) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [StdLibFunction]
stdLibFunctions
lenFunction :: StdLibFunction
lenFunction :: StdLibFunction
lenFunction = StdLibFunction {name :: Identifier
name = Identifier
"len", impl :: StdLibFuncImpl
impl = StdLibFuncImpl
lenImpl}
lenImpl :: StdLibFuncImpl
lenImpl :: StdLibFuncImpl
lenImpl [RuntimeValue']
args = case [RuntimeValue']
args of
[ValString' Identifier
x] -> forall {b} {a}.
IsString b =>
Int -> Either a (MaybeVoid RuntimeValue', b)
ok forall a b. (a -> b) -> a -> b
$ Identifier -> Int
T.length Identifier
x
[ValArray' [RuntimeValue']
xs] -> forall {b} {a}.
IsString b =>
Int -> Either a (MaybeVoid RuntimeValue', b)
ok forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t a -> Int
length [RuntimeValue']
xs
[RuntimeValue']
_ -> forall a b. a -> Either a b
Left Err
UnexpectedError
where
ok :: Int -> Either a (MaybeVoid RuntimeValue', b)
ok Int
int = forall a b. b -> Either a b
Right (forall a. a -> MaybeVoid a
NonVoid forall a b. (a -> b) -> a -> b
$ Int -> RuntimeValue'
ValInt' Int
int, b
"")
printFunction :: StdLibFunction
printFunction :: StdLibFunction
printFunction = StdLibFunction {name :: Identifier
name = Identifier
"print", impl :: StdLibFuncImpl
impl = StdLibFuncImpl
printImpl}
printImpl :: StdLibFuncImpl
printImpl :: StdLibFuncImpl
printImpl [RuntimeValue']
args = forall a b. b -> Either a b
Right (forall a. MaybeVoid a
Void, [Identifier] -> Identifier
T.concat (String -> Identifier
pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> String
show forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [RuntimeValue']
args))
printlnFunction :: StdLibFunction
printlnFunction :: StdLibFunction
printlnFunction = StdLibFunction {name :: Identifier
name = Identifier
"println", impl :: StdLibFuncImpl
impl = StdLibFuncImpl
printlnImpl}
printlnImpl :: StdLibFuncImpl
printlnImpl :: StdLibFuncImpl
printlnImpl [RuntimeValue']
args = forall a b. b -> Either a b
Right (forall a. MaybeVoid a
Void, [Identifier] -> Identifier
T.unwords (String -> Identifier
pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> String
show forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [RuntimeValue']
args) forall a. Semigroup a => a -> a -> a
<> Identifier
"\n")
panicFunction :: StdLibFunction
panicFunction :: StdLibFunction
panicFunction = StdLibFunction {name :: Identifier
name = Identifier
"panic", impl :: StdLibFuncImpl
impl = StdLibFuncImpl
panicImpl}
panicImpl :: StdLibFuncImpl
panicImpl :: StdLibFuncImpl
panicImpl [RuntimeValue']
args = case [RuntimeValue']
args of
[ValString' Identifier
msg] -> forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ Identifier -> Err
Panic Identifier
msg
[RuntimeValue']
_ -> forall a b. a -> Either a b
Left Err
UnexpectedError