packages feed

octopus-0.0.2.0: Language/Octopus/Basis.hs

{-# LANGUAGE OverloadedStrings #-}
{-| This module contains values that help create and manipulate Octopus
    values that are used by the interpreter, but not strictly primitive,
    that is, they could just as easily be defined in user-space, as long
    as the machine could get at them.
-}
module Language.Octopus.Basis where

import Import
import qualified Data.Sequence as Seq
import qualified Data.Map as Map
import System.IO

import Language.Octopus.Data
import Language.Octopus.Data.Shortcut


fpStdin = Fp stdin
fpStdout = Fp stdout
fpStderr = Fp stderr

exnTypeError   = Tg 0 "TypeError"
exnMatchFail   = Tg 1 "MatchFailure"
exnScopeError  = Tg 2 "ScopeError"
exnAttrError   = Tg 3 "AttributeError"
exnIndexError  = Tg 4 "IndexError"
exnDivZero     = Tg 5 "DivideByZero"
exnIOError     = Tg 6 "IOError"
exnSyntaxError = Tg 7 "SyntaxError"
exnImportError = Tg 8 "ImportError"
startTag :: Word
startTag       =    9



mkTypeError :: Val -> Text -> Val -> (Word, Val)
mkTypeError f ty val = (getTag exnTypeError, mkSq [exnTypeError, f, Tx ty, val])
mkMatchFail :: Val -> Val -> (Word, Val)
mkMatchFail p v = (getTag exnMatchFail, mkSq [exnMatchFail, p, v])


mkVau :: String -> String -> Val -> Val
mkVau e arg body = mkCall (Pr Vau) (mkSq [mkSq [Sy $ intern e, Sy $ intern arg], body])

{-| Construct a combination: an object with a
    @__car__@ slot and a @__cdr__@ slot.
-}
mkCall :: Val -- ^ Combiner (@__car__@)
           -> Val -- ^ Argument (@__cdr__@)
           -> Val
mkCall f x = mkOb [(callOpr, f), (callArg, x)]

{-| Extract a (combiner, argument) pair from a
    combination-responsive object.
-}
ensureCombination :: Val -> Maybe (Val, Val)
ensureCombination (Ob ob) = (,) <$> Map.lookup callOpr ob
                                <*> Map.lookup callArg ob
ensureCombination _ = Nothing

{-| Combiner slot name in a combination (aka. application) -}
callOpr :: Symbol
callOpr = intern "__car__"
{-| Argument slot name in a combination (aka. application) -}
callArg :: Symbol
callArg = intern "__cdr__"


{-| Construct a closure: an object with @__var__@,
    @__ast__@ and @__env__@ slots.
-}
mkClosure :: Val -- ^ Body (@__ast__@)
          -> Val -- ^ Static environment (@__env__@)
          -> Val -- ^ Parameter (@__arg__@)
          -> Val
mkClosure var ast env = Cl var ast env

{-| Extract a (body, environment, parameter) triple from
    a closure-responsive object.
-}
ensureClosure :: Val -> Maybe (Val, Val, Val)
ensureClosure (Cl var ast env) = Just (var, ast, env)
ensureClosure _ = Nothing


{-| Construct a thunk: a (environment, body) pair. -}
mkThunk :: Val -- ^ Environment (second element)
        -> Val -- ^ Body (first element)
        -> Val
mkThunk env ast = Sq $ Seq.fromList [env, ast]

{-| Extract a (environment, body) pair from a thunk-responsive pair. -}
ensureThunk :: Val -> Maybe (Val, Val)
ensureThunk (Sq xs) = case toList xs of
    [env, ast] -> Just (env, ast)
    _ -> Nothing
ensureThunk _ = Nothing