koneko-0.0.2: src/Koneko/Bltn.hs
-- -- ; {{{1
--
-- File : Koneko/Bltn.hs
-- Maintainer : Felix C. Stegerman <flx@obfusk.net>
-- Date : 2022-02-12
--
-- Copyright : Copyright (C) 2022 Felix C. Stegerman
-- Version : v0.0.1
-- License : GPLv3+
--
-- -- ; }}}1
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
module Koneko.Bltn (initCtx) where
import Data.Foldable (traverse_)
import Data.Maybe (fromJust) -- careful!
#if !MIN_VERSION_GLASGOW_HASKELL(8, 8, 1, 0)
import Data.Monoid ((<>))
#endif
import qualified Data.HashMap.Strict as H
import Koneko.Data
import Koneko.Misc (pInt, pFloat, parseMaybe)
import Koneko.Prim (swap)
initCtx :: Context -> Evaluator -> IO ()
initCtx ctxMain call = do
ctx <- forkContext bltnModule ctxMain
traverse_ (defPrim ctx) $ typePreds ++ [
strToInt, strToFloat,
dup, drop_, mkBltn "swap" (biRun swap), dip call,
dollar, at, percent,
br_pred call, br_nil call
]
typePreds :: [Builtin]
typePreds = [ mkBltn (x <> "?") $ pop1push1
$ (== x) . typeToStr . typeOf | x <- typeNames ]
strToInt, strToFloat :: Builtin
strToInt = mkBltn "str->int" $ pop1push1 $ parseMaybe pInt
strToFloat = mkBltn "str->float" $ pop1push1 $ parseMaybe pFloat
dup, drop_ :: Builtin
dup = mkBltn "dup" $ \_ s -> push' s . fst <$> pop_' s
drop_ = mkBltn "drop" $ \_ s -> snd <$> pop_' s
dip :: Evaluator -> Builtin
dip call = mkBltn "dip" $ \c s -> do
((x, f), s') <- pop2' s
flip rpush1 (x :: KValue) =<< call c (push' s' f)
dollar, at, percent :: Builtin
dollar = mkBltn "$" $ pop2push1 partial
at = mkBltn "@" $ pop2push1 compose
percent = mkBltn "%" $ pop2push1 $ flip compose
compose, partial :: KValue -> KValue -> KValue
compose f g = block [] [KIdent $ _ID "f", KIdent $ _ID "g"]
$ _sc [("f", f), ("g", g), ("name", KIdent $ _ID "@")]
partial x f = block [] [KQuot $ _ID "_x", KIdent $ _ID "f"]
$ _sc [("_x", x), ("f", f), ("name", KIdent $ _ID "$")]
-- UNSAFE!
_ID :: Identifier -> Ident
_ID = fromJust . ident
_sc :: [(Identifier, KValue)] -> Maybe Scope
_sc = Just . Scope bltnModule . H.fromList
br_pred, br_nil :: Evaluator -> Builtin
br_pred call = mkBltn "~?" $ \c s0 -> do
((x, f, g, p), s1) <- pop4' s0
s2 <- call c $ foldl push' s1 [x, x, p]
(b, s3) <- pop' s2
call c $ push' s3 $ if truthy b then f else g
br_nil call = mkBltn "~nil" $ \c s -> do
((x, f, g), s') <- pop3' s
call c $ foldl push' s' $ if isNil x then [f] else [x, g]
-- vim: set tw=70 sw=2 sts=2 et fdm=marker :