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

Merge eval and evalAST in purescript implementation #631

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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion impls/purs/packages.dhall
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ in upstream
-------------------------------
-}
let upstream =
https://github.com/purescript/package-sets/releases/download/psc-0.14.2-20210713/packages.dhall sha256:654c3148cb995f642c73b4508d987d9896e2ad3ea1d325a1e826c034c0d3cd7b
https://github.com/purescript/package-sets/releases/download/psc-0.15.8-20230420/packages.dhall
sha256:01f6ef030637be27a334e8f0977d563f9699543f596d60e8fb067e4f60d2e571

in upstream
1 change: 0 additions & 1 deletion impls/purs/spago.dhall
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ to generate this file without the comments in this block.
, "ordered-collections"
, "parsing"
, "prelude"
, "psci-support"
, "refs"
, "strings"
, "tailrec"
Expand Down
9 changes: 5 additions & 4 deletions impls/purs/src/Reader.purs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import Data.List (List(..), many, (:))
import Data.Maybe (Maybe(..), fromMaybe)
import Effect (Effect)
import Effect.Exception (throw)
import Parsing (Parser, fail, runParser)
import Parsing.Combinators (endBy, skipMany, skipMany1, try)
import Parsing.String (char, string)
import Parsing.String.Basic (noneOf, oneOf)
import Parsing.Token (digit, letter)
import Printer (keyValuePairs)
import Text.Parsing.Parser (Parser, fail, runParser)
import Text.Parsing.Parser.Combinators (endBy, skipMany, skipMany1, try)
import Text.Parsing.Parser.String (char, noneOf, oneOf, string)
import Text.Parsing.Parser.Token (digit, letter)
import Types (MalExpr(..), charListToString, listToMap, toHashMap, toList, toVector)


Expand Down
6 changes: 3 additions & 3 deletions impls/purs/src/Readline.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"use strict";

var readlineSync = require('readline-sync')
import readlineSync from 'readline-sync'

exports.readLine = function (x) {
export const readLine = function (x) {
return function () {
const result = readlineSync.question(x);

Expand All @@ -14,4 +14,4 @@ exports.readLine = function (x) {
}


exports.argv = process.argv;
export const argv = process.argv;
24 changes: 11 additions & 13 deletions impls/purs/src/step2_eval.purs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import Effect.Exception (throw, try)
import Reader (readStr)
import Printer (printStr)
import Readline (readLine)
import Types (MalExpr(..), MalFn, toHashMap, toList, toVector)
import Types (MalExpr(..), MalFn, toHashMap, toVector)


-- MAIN
Expand All @@ -27,24 +27,22 @@ main = loop

-- EVAL

eval :: MalExpr -> Effect MalExpr
eval ast@(MalList _ Nil) = pure ast
eval (MalList _ ast) = do
es <- traverse evalAst ast
evalCallFn :: List MalExpr -> Effect MalExpr
evalCallFn ast = do
es <- traverse eval ast
case es of
MalFunction {fn:f}: args -> f args
_ -> pure $ toList es
eval ast = evalAst ast
_ -> throw $ "invalid function"


evalAst :: MalExpr -> Effect MalExpr
evalAst (MalSymbol s) = case lookup s replEnv of
eval :: MalExpr -> Effect MalExpr
eval (MalSymbol s) = case lookup s replEnv of
Just f -> pure f
Nothing -> throw "invalid function"
evalAst ast@(MalList _ _ ) = eval ast
evalAst (MalVector _ es) = toVector <$> (traverse eval es)
evalAst (MalHashMap _ es) = toHashMap <$> (traverse eval es)
evalAst ast = pure ast
eval (MalList _ es@(_ : _)) = evalCallFn es
eval (MalVector _ es) = toVector <$> (traverse eval es)
eval (MalHashMap _ es) = toHashMap <$> (traverse eval es)
eval ast = pure ast



Expand Down
53 changes: 30 additions & 23 deletions impls/purs/src/step3_env.purs
Original file line number Diff line number Diff line change
Expand Up @@ -29,34 +29,41 @@ main = do

-- EVAL

eval :: RefEnv -> MalExpr -> Effect MalExpr
eval _ ast@(MalList _ Nil) = pure ast
eval env (MalList _ ast) = case ast of
MalSymbol "def!" : es -> evalDef env es
MalSymbol "let*" : es -> evalLet env es
_ -> do
es <- traverse (evalAst env) ast
evalCallFn :: RefEnv -> List MalExpr -> Effect MalExpr
evalCallFn env ast = do
es <- traverse (eval env) ast
case es of
MalFunction {fn:f} : args -> f args
_ -> throw "invalid function"
eval env ast = evalAst env ast


evalAst :: RefEnv -> MalExpr -> Effect MalExpr
evalAst env (MalSymbol s) = do
result <- Env.get env s
case result of
Just k -> pure k
Nothing -> throw $ "'" <> s <> "'" <> " not found"
evalAst env ast@(MalList _ _) = eval env ast
evalAst env (MalVector _ envs) = toVector <$> traverse (eval env) envs
evalAst env (MalHashMap _ envs) = toHashMap <$> traverse (eval env) envs
evalAst _ ast = pure ast
eval :: RefEnv -> MalExpr -> Effect MalExpr
eval env ast = do
dbgeval <- Env.get env "DEBUG-EVAL"
case dbgeval of
Nothing -> pure unit
Just MalNil -> pure unit
Just (MalBoolean false) -> pure unit
_ -> do
image <- print ast
log ("EVAL: " <> image)
case ast of
MalSymbol s -> do
result <- Env.get env s
case result of
Just k -> pure k
Nothing -> throw $ "'" <> s <> "'" <> " not found"
MalList _ (MalSymbol "def!" : es) -> evalDef env es
MalList _ (MalSymbol "let*" : es) -> evalLet env es
MalList _ es@(_ : _) -> evalCallFn env es
MalVector _ es -> toVector <$> traverse (eval env) es
MalHashMap _ es -> toHashMap <$> traverse (eval env) es
_ -> pure ast


evalDef :: RefEnv -> List MalExpr -> Effect MalExpr
evalDef env (MalSymbol v : e : Nil) = do
evd <- evalAst env e
evd <- eval env e
Env.set env v evd
pure evd
evalDef _ _ = throw "invalid def!"
Expand All @@ -66,18 +73,18 @@ evalLet :: RefEnv -> List MalExpr -> Effect MalExpr
evalLet env (MalList _ ps : e : Nil) = do
letEnv <- Env.newEnv env
letBind letEnv ps
evalAst letEnv e
eval letEnv e
evalLet env (MalVector _ ps : e : Nil) = do
letEnv <- Env.newEnv env
letBind letEnv ps
evalAst letEnv e
eval letEnv e
evalLet _ _ = throw "invalid let*"


letBind :: RefEnv -> List MalExpr -> Effect Unit
letBind _ Nil = pure unit
letBind env (MalSymbol ky : e : es) = do
Env.set env ky =<< evalAst env e
Env.set env ky =<< eval env e
letBind env es
letBind _ _ = throw "invalid let*"

Expand All @@ -86,7 +93,7 @@ letBind _ _ = throw "invalid let*"
-- REPL

rep :: RefEnv -> String -> Effect String
rep env str = print =<< evalAst env =<< read str
rep env str = print =<< eval env =<< read str


loop :: RefEnv -> Effect Unit
Expand Down
71 changes: 39 additions & 32 deletions impls/purs/src/step4_if_fn_do.purs
Original file line number Diff line number Diff line change
Expand Up @@ -33,37 +33,44 @@ main = do

-- EVAL

eval :: RefEnv -> MalExpr -> Effect MalExpr
eval _ ast@(MalList _ Nil) = pure ast
eval env (MalList _ ast) = case ast of
MalSymbol "def!" : es -> evalDef env es
MalSymbol "let*" : es -> evalLet env es
MalSymbol "if" : es -> evalIf env es
MalSymbol "do" : es -> evalDo env es
MalSymbol "fn*" : es -> evalFnMatch env es
_ -> do
es <- traverse (evalAst env) ast
evalCallFn :: RefEnv -> List MalExpr -> Effect MalExpr
evalCallFn env ast = do
es <- traverse (eval env) ast
case es of
MalFunction {fn:f} : args -> f args
_ -> throw "invalid function"
eval env ast = evalAst env ast


evalAst :: RefEnv -> MalExpr -> Effect MalExpr
evalAst env (MalSymbol s) = do
result <- Env.get env s
case result of
Just k -> pure k
Nothing -> throw $ "'" <> s <> "'" <> " not found"
evalAst env ast@(MalList _ _) = eval env ast
evalAst env (MalVector _ envs) = toVector <$> traverse (eval env) envs
evalAst env (MalHashMap _ envs) = toHashMap <$> traverse (eval env) envs
evalAst _ ast = pure ast
eval :: RefEnv -> MalExpr -> Effect MalExpr
eval env ast = do
dbgeval <- Env.get env "DEBUG-EVAL"
case dbgeval of
Nothing -> pure unit
Just MalNil -> pure unit
Just (MalBoolean false) -> pure unit
_ -> do
image <- print ast
log ("EVAL: " <> image)
case ast of
MalSymbol s -> do
result <- Env.get env s
case result of
Just k -> pure k
Nothing -> throw $ "'" <> s <> "'" <> " not found"
MalList _ (MalSymbol "def!" : es) -> evalDef env es
MalList _ (MalSymbol "let*" : es) -> evalLet env es
MalList _ (MalSymbol "if" : es) -> evalIf env es
MalList _ (MalSymbol "do" : es) -> evalDo env es
MalList _ (MalSymbol "fn*" : es) -> evalFnMatch env es
MalList _ es@(_ : _) -> evalCallFn env es
MalVector _ es -> toVector <$> traverse (eval env) es
MalHashMap _ es -> toHashMap <$> traverse (eval env) es
_ -> pure ast


evalDef :: RefEnv -> List MalExpr -> Effect MalExpr
evalDef env (MalSymbol v : e : Nil) = do
evd <- evalAst env e
evd <- eval env e
Env.set env v evd
pure evd
evalDef _ _ = throw "invalid def!"
Expand All @@ -73,41 +80,41 @@ evalLet :: RefEnv -> List MalExpr -> Effect MalExpr
evalLet env (MalList _ ps : e : Nil) = do
letEnv <- Env.newEnv env
letBind letEnv ps
evalAst letEnv e
eval letEnv e
evalLet env (MalVector _ ps : e : Nil) = do
letEnv <- Env.newEnv env
letBind letEnv ps
evalAst letEnv e
eval letEnv e
evalLet _ _ = throw "invalid let*"



letBind :: RefEnv -> List MalExpr -> Effect Unit
letBind _ Nil = pure unit
letBind env (MalSymbol ky : e : es) = do
Env.set env ky =<< evalAst env e
Env.set env ky =<< eval env e
letBind env es
letBind _ _ = throw "invalid let*"


evalIf :: RefEnv -> List MalExpr -> Effect MalExpr
evalIf env (b:t:e:Nil) = do
cond <- evalAst env b
evalAst env case cond of
cond <- eval env b
eval env case cond of
MalNil -> e
MalBoolean false -> e
_ -> t
evalIf env (b:t:Nil) = do
cond <- evalAst env b
evalAst env case cond of
cond <- eval env b
eval env case cond of
MalNil -> MalNil
MalBoolean false -> MalNil
_ -> t
evalIf _ _ = throw "invalid if"


evalDo :: RefEnv -> List MalExpr -> Effect MalExpr
evalDo env es = foldM (const $ evalAst env) MalNil es
evalDo env es = foldM (const $ eval env) MalNil es


evalFnMatch :: RefEnv -> List MalExpr -> Effect MalExpr
Expand All @@ -133,7 +140,7 @@ evalFn env params body = do
fnEnv <- Env.newEnv env
ok <- Env.sets fnEnv params' args
if ok
then evalAst fnEnv body'
then eval fnEnv body'
else throw "actual parameters do not match signature "

unwrapSymbol :: MalExpr -> Effect String
Expand All @@ -145,7 +152,7 @@ evalFn env params body = do
-- REPL

rep :: RefEnv -> String -> Effect String
rep env str = print =<< evalAst env =<< read str
rep env str = print =<< eval env =<< read str


loop :: RefEnv -> Effect Unit
Expand Down