12 Commits
Author SHA1 Message Date
msyds d1588bd917 fix runtime parsing lol
build / build (push) Failing after 1m35s
2026-09-05 20:22:07 -06:00
msyds c495fc064a arith prims 2026-09-05 20:22:07 -06:00
msyds ac39175767 eval agian 2026-09-05 20:22:07 -06:00
msyds 31c610db34 superfuck 2026-09-05 20:22:07 -06:00
msyds 1ec3d35282 arith 2026-09-05 20:22:07 -06:00
msyds 9f37d10e4f ughhh evaluate cps 2026-09-05 20:22:07 -06:00
msyds ba5dc401d9 okay it's time for a hard reset and some thinking </3 2026-09-05 20:22:07 -06:00
msyds bc599df65f shared closures maybe 2026-09-05 20:22:07 -06:00
msyds f26ac50d4e hoist 2026-09-05 20:22:07 -06:00
msyds 3196d8db84 kexp 2026-09-05 20:22:07 -06:00
msyds 75e6c963c7 stupid 2026-09-05 20:22:07 -06:00
msyds 25f1f008bd wip: call/cc = capture/cc × invoke/cc 2026-09-05 20:22:06 -06:00
3 changed files with 149 additions and 62 deletions
+145 -60
View File
@@ -9,37 +9,57 @@ module Gyehoek.CPS.Eval
, eGrammar , eGrammar
) where ) where
import Gyehoek.CPS.Syntax hiding (Hob(..), Obj(..)) import Gyehoek.CPS.Syntax hiding (Hob(..), Obj(..), cont)
import Gyehoek.Sexp qualified as S import Gyehoek.Sexp qualified as S
import Control.Lens import Control.Lens hiding (assign)
import Data.Maybe (fromMaybe) import Data.Maybe (fromMaybe)
import Text.Show.Functions () import Text.Show.Functions ()
import qualified Data.HashMap.Strict as H import qualified Data.HashMap.Strict as H
import Gyehoek.Prelude import Gyehoek.Prelude hiding (assign)
import Debug.Pretty.Simple import Debug.Pretty.Simple
import Gyehoek.Jalmot import Gyehoek.Jalmot
import Control.Monad.Cont qualified as Cont import Control.Monad.Cont
import Gyehoek.Sexp qualified as S import Gyehoek.Sexp qualified as S
import GHC.Generics (Generically(..)) import GHC.Generics (Generically(..))
import Gyehoek.Sexp ((:-)(..)) import Gyehoek.Sexp ((:-)(..))
import Data.List (nub) import Data.List (nub, mapAccumR, compareLength)
import Data.HashSet.Lens (setOf) import Data.HashSet.Lens (setOf)
import Data.IntMap.Strict (IntMap) import Data.IntMap.Strict (IntMap)
import Data.IntMap.Strict qualified as IM import Data.IntMap.Strict qualified as IM
import Data.Monoid
import Control.Monad.State
import Data.Traversable (for)
import Data.Foldable (traverse_)
newtype Loc = MkLoc { getLoc :: Int } newtype Loc = MkLoc { getLoc :: Int }
deriving stock (Generic, Data) deriving stock (Generic, Data)
deriving newtype (Show, Eq, Ord) deriving newtype (Show, Eq, Ord, Enum)
data Store = MkStore data Store = MkStore
{ nextLoc :: Loc { nextLoc :: Loc
, heap :: IntMap E , heap :: IntMap E
} }
deriving stock (Show, Generic, Data) deriving stock (Show, Generic)
type instance Index Store = Loc
type instance IxValue Store = E
instance Ixed Store where ix (MkLoc j) = #heap . ix j
instance At Store where at (MkLoc j) = #heap . at j
emptyStore :: Store
emptyStore = MkStore
{ nextLoc = MkLoc 0
, heap = mempty
}
newtype Env = MkEnv { getEnv :: HashMap Name Loc } newtype Env = MkEnv { getEnv :: HashMap Name Loc }
deriving stock (Show, Generic, Data) deriving stock (Show, Generic, Data)
deriving newtype (Semigroup, Monoid)
emptyEnv :: Env
emptyEnv = mempty
type instance Index Env = Name type instance Index Env = Name
type instance IxValue Env = Loc type instance IxValue Env = Loc
@@ -53,42 +73,60 @@ update (MkLoc loc) v = #heap %~ IM.alter f loc
f (Just _) = Just v f (Just _) = Just v
f Nothing = error "segfault lol" f Nothing = error "segfault lol"
fetch :: Loc -> Store -> E updates :: Foldable f => f (Loc, E) -> Store -> Store
fetch (MkLoc loc) st = st ^?! #heap . ix loc updates = alaf Endo foldMap (uncurry update)
new :: Store -> Loc fetch :: Loc -> M r E
new = _ fetch (MkLoc loc) = gets (^?! #heap . ix loc)
var :: HasCallStack => Env -> Name -> Loc new :: M r Loc
var g x = g ^?! ix x new = state \st -> (st.nextLoc, st & #nextLoc %~ succ)
new' :: E -> M r Loc
new' e = state \st ->
( st.nextLoc
, st & #nextLoc %~ succ & at st.nextLoc ?~ e
)
defines :: Traversable t => t (Name, E) -> M Answer Env
defines = alaf Ap foldMap \(name,e) -> do
l <- new' e
pure $ bind name l
var :: HasCallStack => Env -> Name -> M Answer Loc
var g x = case g ^. at x of
Just l -> pure l
Nothing -> wrong [i|unbound variable #{x}|]
type CmdCont = Store -> Answer type CmdCont = Store -> Answer
type ExpCont = List E -> CmdCont type ExpCont = List E -> CmdCont
type M r = ContT r (State Store)
data Answer data Answer
= AnswerValues (List E) = AnswerValues (List E)
| AnswerError Text | AnswerError AJalmot
deriving (Show, Generic, Data) deriving (Show, Generic)
data Mutability data Mutability
= Mut = Mut
| NoMut | NoMut
deriving (Show, Generic, Data, Eq) deriving (Show, Generic, Data, Eq)
wrong :: Text -> CmdCont wrong :: Text -> M Answer a
wrong = const . AnswerError wrong s = ContT \_ -> pure . AnswerError . EvalError $ s
single :: (E -> CmdCont) -> ExpCont bind :: Name -> Loc -> Env
single k = \case bind k = MkEnv . H.singleton k
[x] -> k x
_ -> wrong "wrong number of return values"
send :: E -> ExpCont -> CmdCont extends :: Foldable f => f (Name, Loc) -> Env -> Env
send e k = k [e] extends xs g = g <> foldMap (uncurry bind) xs
-- | Continue with the value located at a given 'Loc'. assign :: Loc -> E -> M Answer ()
hold :: Loc -> ExpCont -> CmdCont assign l e = do
hold loc k st = send (fetch loc st) k st use (at l) >>= \case
Just _ -> at l ?= e
Nothing -> wrong [i|#{e}에서 #{l}이라는 주소는 없다|]
@@ -96,7 +134,7 @@ hold loc k st = send (fetch loc st) k st
data E data E
= ESymbol Text = ESymbol Text
| ECharacter Char | ECharacter Char
| EInteger Int | EInt Int
| EBool Bool | EBool Bool
| EUndefined | EUndefined
| EUnspecified | EUnspecified
@@ -104,17 +142,19 @@ data E
| EPair Loc Loc Mutability | EPair Loc Loc Mutability
| EVec (List Loc) Mutability | EVec (List Loc) Mutability
| EString (List Loc) Mutability | EString (List Loc) Mutability
| EProcedure Loc (List E -> DynPoints -> ExpCont -> CmdCont) | EProcedure Procedure
deriving stock (Show, Generic, Data) deriving stock (Show, Generic)
type Procedure = List E -> DynPoints -> M Answer (List E)
eGrammar :: Store -> S.DatumGrammar E eGrammar :: Store -> S.DatumGrammar E
eGrammar st = S.partialOsi (const . Left $ mempty) go eGrammar st = S.partialOsi (const . Left $ mempty) go
where where
gofetch x = go $ fetch x st gofetch x = go $ st ^?! ix x
go = \case go = \case
ESymbol s -> S.Symbol s ESymbol s -> S.Symbol s
ECharacter c -> S.Character c ECharacter c -> S.Character c
EInteger n -> S.Number (fromIntegral n) EInt n -> S.Number (fromIntegral n)
EBool b -> S.Boolean b EBool b -> S.Boolean b
EUndefined -> S.Unreadable "#<undefined>" EUndefined -> S.Unreadable "#<undefined>"
EUnspecified -> S.Unreadable "#<unspecified>" EUnspecified -> S.Unreadable "#<unspecified>"
@@ -128,47 +168,92 @@ data DynPoints = MkDynPoints
-- 뻘짓이어라 evalVal :: Env -> Val -> M Answer E
telescope
:: Traversable t
=> (a -> (b -> r) -> r)
-> t a -> (t b -> r) -> r
telescope f = Cont.runCont . traverse (Cont.cont . f)
evalVal g (ValVar x) = var g x >>= fetch
evalVal :: Env -> Val -> ExpCont -> CmdCont evalVal g (ValImm imm) = pure case imm of
evalVal g (ValVar x) k = hold (var g x) $ single \case ImmLabel l -> error [i|#{l}|]
EUndefined -> wrong "undefined variable" ImmInt n -> EInt n
e -> send e k ImmBool b -> EBool b
ImmUndefined -> EUndefined
evalVal1 :: Env -> Val -> (E -> CmdCont) -> CmdCont evalKexp :: Env -> Kexp -> M Answer E
evalVal1 g v k = evalVal g v (single k) evalKexp g (KexpVar x) = var g x >>= fetch
evalKexp g (KexpKappa kap) = evalAbs g (AbsKappa kap)
evalKexp :: Env -> Kexp -> ExpCont -> CmdCont evalAbs :: Env -> Abs -> M Answer E
evalAbs g (MkAbs formals ktail e) = pure . EProcedure $ \xs dps ->
let
formals' = formals ++ foldMap (:[]) ktail
lformals = length formals'
lxs = length xs
in if lformals /= lxs
then wrong [i|함수는 #{lformals}개의 인자를 필요로 하는데 #{lxs}개 받았다.|]
else do
ls <- xs & traverse new'
let g' = g & extends (zip formals' ls)
eval g' dps e
evalKexp g (KexpVar x) k = evalVal g (ValVar x) k eval :: Env -> DynPoints -> Exp -> M Answer (List E)
evalKexp g (KexpKappa kap) k = _ eval g dps (ExpJump f xs ktail) = do
f' <- evalVal g f
xs' <- traverse (evalVal g) xs
ktail' <- traverse (evalKexp g) (ktail ^.. _Just)
case f' of
EProcedure p -> p (xs' ++ ktail') dps
_ -> wrong "bad procedure"
eval :: Env -> DynPoints -> Exp -> ExpCont -> CmdCont eval g dps (ExpLetRec bs e) = do
ls <- for bs . const $ new' EUndefined
let g' = g & extends (zip (bs ^.. each . _1) ls)
bs' <- forOf (each . _2) bs (evalAbs g')
traverse_ (uncurry assign) $ zip ls (bs' ^.. each . _2)
eval g' dps e
eval g dps (ExpContinue f xs) k = eval g dps (ExpPrim p k) = do
telescope (evalVal1 g) (f:|xs) \(f':|xs') -> p' <- evalPrim g =<< traverse (evalVal g) p
case f' of evalKexp g k >>= \case
EProcedure _loc fp -> fp xs' dps k EProcedure fp -> fp p' dps
_ -> wrong "bad procedure" _ -> wrong [i|prim(#{p})의 계속을 나쁘다|]
eval g dps (ExpApply f xs ktail) k = eval g dps e = error [i|unimplemented #{e}|]
telescope (evalVal1 g) (f:|xs) \(f':|xs') ->
case f' of evalPrim :: Env -> Prim E -> M Answer (List E)
EProcedure _loc fp -> fp xs' dps k evalPrim g = \case
_ -> wrong "bad procedure" PrimAdd x y -> arith2 (+) x y
PrimMul x y -> arith2 (*) x y
PrimSub x y -> arith2 (-) x y
PrimDiv x y -> arith2 div x y
PrimValues xs -> pure xs
p -> wrong [i|prim(#{p})은 벌써 나지 않다|]
where
arith2 f (EInt x) (EInt y) = pure [EInt $ f x y]
arith2 f x y = wrong [i|나쁜 인자: #{x}, #{y}|]
evalExp :: Jalmot :> es => Exp -> Eff es _ evalExp :: Jalmot :> es => Exp -> Eff es _
evalExp e = _ evalExp e = _
evalProgram :: Jalmot :> es => Program -> Eff es _ evalProgram :: Jalmot :> es => Program -> Eff es (List S.Datum)
evalProgram (MkProgram lam) = _ evalProgram (MkProgram lam) = case run (pure . AnswerValues) of
(AnswerError jm, _) -> throwError jm
(AnswerValues vs, st) -> traverse (S.toDatum $ eGrammar st) vs
where
run f = (`runState` emptyStore) . (`runContT` f) $ do
g <- setup
eval g MkDynPoints (ExpLetRec
[("_start",AbsLambda lam)]
(ExpApply (ValVar "_start") [] (KexpVar "halt")))
setup :: M Answer Env
setup = defines @List
[ ("halt", EProcedure prim_halt)
]
prim_halt :: Procedure
prim_halt xs _dps = ContT \_ -> pure $ AnswerValues xs
+2
View File
@@ -31,6 +31,7 @@ data AJalmot
= ReaderError (ParseErrorBundle Text Void) = ReaderError (ParseErrorBundle Text Void)
| GrammarError (Grammar.ErrorMessage Ann) | GrammarError (Grammar.ErrorMessage Ann)
| VMError Text | VMError Text
| EvalError Text
deriving (Show, Generic, Data) deriving (Show, Generic, Data)
data AJalmotCS = MkAJalmotCS !CallStack !AJalmot data AJalmotCS = MkAJalmotCS !CallStack !AJalmot
@@ -66,6 +67,7 @@ instance Exception AJalmot where
& layoutPretty defaultLayoutOptions & layoutPretty defaultLayoutOptions
& renderString & renderString
VMError err -> [i|#{err}|] VMError err -> [i|#{err}|]
EvalError err -> [i|#{err}|]
instance Exception AJalmotCS where instance Exception AJalmotCS where
backtraceDesired = const False backtraceDesired = const False
+2 -2
View File
@@ -54,8 +54,8 @@ runtimeValues = ["stackify","wasm","cps","none"]
runtimeReader = maybeReader \case runtimeReader = maybeReader \case
"stackify" -> Just (Just Stackify) "stackify" -> Just (Just Stackify)
"wasm" -> Just (Just Wasm) "wasm" -> Just (Just Wasm)
"cps" -> Just (Just CPS) "cps1" -> Just (Just CPS)
("cps2";"higher-order-cps") -> Just (Just CPS) ("cps";"higher-order-cps") -> Just (Just HigherOrderCPS)
"none" -> Just Nothing "none" -> Just Nothing
_ -> Nothing _ -> Nothing