Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature repl #288

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions mulang.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ library
Language.Mulang.Edl.Parser
Language.Mulang.Interpreter
Language.Mulang.Interpreter.Internals
Language.Mulang.Interpreter.Repl
Language.Mulang.Interpreter.Runner
Language.Mulang.Transform.Normalizer
Language.Mulang.Transform.Renamer
Expand Down
33 changes: 33 additions & 0 deletions spec/ReplSpec.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module ReplSpec (spec) where

import Test.Hspec
import Language.Mulang.Parsers.JavaScript
import Language.Mulang.Interpreter.Repl
import Language.Mulang.Interpreter.Internals (Value (..))

spec :: Spec
spec = do
describe "repl" $ do
let s0 = newSession js
it "evals and returns" $ do
(r1, _) <- repl "1" s0
r1 `shouldBe` (MuNumber 1)

it "can eval multiple statements and return" $ do
(r1, s1) <- repl "var x = 1" s0
r1 `shouldBe` (MuNumber 1)

(r2, s2) <- repl "x + 3" s1
r2 `shouldBe` (MuNumber 4)

(_, s3) <- repl "function double(x) { return x * 2 }" s2
(r4, _) <- repl "double(x)" s3
r4 `shouldBe` (MuNumber 2)

it "can save state" $ do
(_, s1) <- repl "function succ(x) { return x + 1 }" s0
(_, s2) <- repl "function pred(x) { return x - 1 }" s1

(r, _) <- repl "succ(succ(pred(10)))" (reload s2)
r `shouldBe` (MuNumber 11)

48 changes: 48 additions & 0 deletions src/Language/Mulang/Interpreter/Repl.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
module Language.Mulang.Interpreter.Repl (
Session (..),
newSession,
repl,
dump,
load,
reload) where

import Language.Mulang.Ast (Expression)
import Language.Mulang.Interpreter (eval)
import Language.Mulang.Interpreter.Internals (Value, Reference (..), ExecutionContext (..), defaultContext)

import qualified Data.Map as Map
import Data.Map ((!))

type SessionState = ([(Int, Value)], [Int])
type Language = (String -> Expression)

data Session = Session { language :: Language, context :: ExecutionContext }

newSession :: Language -> Session
newSession language = Session language defaultContext

repl :: String -> Session -> IO (Value, Session)
repl line session = do
(ref, newContext) <- eval (context session) (language session line)
return (globalObjects newContext ! ref, session { context = newContext } )

dump :: Session -> SessionState
dump (Session _ (ExecutionContext globals scopes _ _ _ )) = (dumpGlobals globals, dumpScopes scopes)
where
dumpGlobals = Map.toList . Map.mapKeys asInt
dumpScopes = map asInt

load :: Language -> SessionState -> Session
load language (globalsState, scopesState) = Session language (defaultContext { globalObjects = loadGlobals globalsState, scopes = loadScopes scopesState } )
where
loadGlobals = Map.mapKeys fromInt . Map.fromList
loadScopes = map fromInt

reload :: Session -> Session
reload s@(Session l _) = load l (dump s)

fromInt :: Int -> Reference
fromInt = Reference

asInt :: Reference -> Int
asInt (Reference i) = i