2024-12-18 18:55:51 -06:00
|
|
|
module Eval where
|
|
|
|
|
|
|
|
import Parser
|
|
|
|
import Research
|
2024-12-27 12:27:00 -06:00
|
|
|
|
2024-12-27 08:17:06 -06:00
|
|
|
import Data.Map (Map)
|
2024-12-27 12:27:00 -06:00
|
|
|
import qualified Data.Map as Map
|
|
|
|
import Data.List (foldl')
|
|
|
|
import qualified Data.Set as Set
|
2024-12-27 08:17:06 -06:00
|
|
|
|
2024-12-27 12:27:00 -06:00
|
|
|
evalSingle :: Map String T -> SaplingAST -> Map String T
|
2024-12-27 08:17:06 -06:00
|
|
|
evalSingle env term = case term of
|
2024-12-27 12:27:00 -06:00
|
|
|
SFunc name [] body ->
|
2024-12-27 15:40:50 -06:00
|
|
|
let lineNoLambda = eliminateLambda body
|
2024-12-27 12:27:00 -06:00
|
|
|
result = evalAST env lineNoLambda
|
|
|
|
in Map.insert name result env
|
|
|
|
SLambda _ body ->
|
|
|
|
let result = evalAST env body
|
|
|
|
in Map.insert "__result" result env
|
|
|
|
SApp func arg ->
|
2024-12-27 20:46:30 -06:00
|
|
|
let result = apply (evalAST env $ eliminateLambda func) (evalAST env $ eliminateLambda arg)
|
2024-12-27 12:27:00 -06:00
|
|
|
in Map.insert "__result" result env
|
|
|
|
SVar name ->
|
|
|
|
case Map.lookup name env of
|
|
|
|
Just value -> Map.insert "__result" value env
|
|
|
|
Nothing -> error $ "Variable " ++ name ++ " not defined"
|
|
|
|
_ ->
|
|
|
|
let result = evalAST env term
|
|
|
|
in Map.insert "__result" result env
|
2024-12-19 18:57:57 -06:00
|
|
|
|
2024-12-20 11:38:09 -06:00
|
|
|
evalSapling :: Map String T -> [SaplingAST] -> Map String T
|
|
|
|
evalSapling env [] = env
|
|
|
|
evalSapling env [lastLine] =
|
2024-12-27 12:27:00 -06:00
|
|
|
let lastLineNoLambda = eliminateLambda lastLine
|
2024-12-27 08:17:06 -06:00
|
|
|
updatedEnv = evalSingle env lastLineNoLambda
|
2024-12-19 18:57:57 -06:00
|
|
|
in Map.insert "__result" (result updatedEnv) updatedEnv
|
2024-12-20 11:38:09 -06:00
|
|
|
evalSapling env (line:rest) =
|
2024-12-27 12:27:00 -06:00
|
|
|
let lineNoLambda = eliminateLambda line
|
2024-12-27 08:17:06 -06:00
|
|
|
updatedEnv = evalSingle env lineNoLambda
|
2024-12-20 11:38:09 -06:00
|
|
|
in evalSapling updatedEnv rest
|
2024-12-19 18:57:57 -06:00
|
|
|
|
2024-12-27 08:17:06 -06:00
|
|
|
evalAST :: Map String T -> SaplingAST -> T
|
|
|
|
evalAST env term = case term of
|
2024-12-27 12:27:00 -06:00
|
|
|
SVar name -> case Map.lookup name env of
|
|
|
|
Just value -> value
|
|
|
|
Nothing -> error $ "Variable " ++ name ++ " not defined"
|
2024-12-27 08:17:06 -06:00
|
|
|
TLeaf -> Leaf
|
2024-12-27 12:27:00 -06:00
|
|
|
TStem t -> Stem (evalAST env t)
|
|
|
|
TFork t1 t2 -> Fork (evalAST env t1) (evalAST env t2)
|
|
|
|
SApp t1 t2 -> apply (evalAST env t1) (evalAST env t2)
|
2024-12-27 08:17:06 -06:00
|
|
|
SStr str -> toString str
|
|
|
|
SInt num -> toNumber num
|
|
|
|
SList elems -> toList (map (evalAST Map.empty) elems)
|
|
|
|
SFunc name args body ->
|
|
|
|
error $ "Unexpected function definition " ++ name
|
|
|
|
++ " in evalAST; define via evalSingle."
|
2024-12-27 12:27:00 -06:00
|
|
|
SLambda {} -> error "Internal error: SLambda found in evalAST after elimination."
|
2024-12-27 08:17:06 -06:00
|
|
|
|
|
|
|
eliminateLambda :: SaplingAST -> SaplingAST
|
|
|
|
eliminateLambda (SLambda (v:vs) body)
|
2024-12-27 12:27:00 -06:00
|
|
|
| null vs = lambdaToT v (eliminateLambda body)
|
|
|
|
| otherwise = eliminateLambda (SLambda [v] (SLambda vs body))
|
|
|
|
eliminateLambda (SApp f arg) = SApp (eliminateLambda f) (eliminateLambda arg)
|
|
|
|
eliminateLambda (TStem t) = TStem (eliminateLambda t)
|
|
|
|
eliminateLambda (TFork l r) = TFork (eliminateLambda l) (eliminateLambda r)
|
|
|
|
eliminateLambda (SList xs) = SList (map eliminateLambda xs)
|
2024-12-27 08:17:06 -06:00
|
|
|
eliminateLambda other = other
|
|
|
|
|
2024-12-27 15:40:50 -06:00
|
|
|
-- This is my attempt to implement the lambda calculus elimination rules defined
|
|
|
|
-- in "Typed Program Analysis without Encodings" by Barry Jay.
|
|
|
|
-- https://github.com/barry-jay-personal/typed_tree_calculus/blob/main/typed_program_analysis.pdf
|
2024-12-27 08:17:06 -06:00
|
|
|
lambdaToT :: String -> SaplingAST -> SaplingAST
|
|
|
|
lambdaToT x (SVar y)
|
2024-12-27 12:27:00 -06:00
|
|
|
| x == y = tI
|
2024-12-27 08:17:06 -06:00
|
|
|
lambdaToT x (SVar y)
|
2024-12-27 12:27:00 -06:00
|
|
|
| x /= y = SApp tK (SVar y)
|
2024-12-27 08:17:06 -06:00
|
|
|
lambdaToT x t
|
2024-12-27 12:27:00 -06:00
|
|
|
| not (isFree x t) = SApp tK t
|
2024-12-27 08:17:06 -06:00
|
|
|
lambdaToT x (SApp n u)
|
2024-12-27 12:27:00 -06:00
|
|
|
| not (isFree x (SApp n u)) = SApp tK (SApp (eliminateLambda n) (eliminateLambda u))
|
|
|
|
lambdaToT x (SApp n u) = SApp (SApp tS (lambdaToT x (eliminateLambda n))) (lambdaToT x (eliminateLambda u))
|
2024-12-27 08:17:06 -06:00
|
|
|
lambdaToT x body
|
2024-12-27 12:27:00 -06:00
|
|
|
| not (isFree x body) = SApp tK body
|
|
|
|
| otherwise = SApp (SApp tS (lambdaToT x body)) TLeaf
|
2024-12-27 08:17:06 -06:00
|
|
|
|
2024-12-27 12:27:00 -06:00
|
|
|
freeVars :: SaplingAST -> Set.Set String
|
2024-12-27 08:17:06 -06:00
|
|
|
freeVars (SVar v) = Set.singleton v
|
|
|
|
freeVars (SInt _) = Set.empty
|
|
|
|
freeVars (SStr _) = Set.empty
|
|
|
|
freeVars (SList xs) = foldMap freeVars xs
|
|
|
|
freeVars (SApp f arg) = freeVars f <> freeVars arg
|
|
|
|
freeVars TLeaf = Set.empty
|
2024-12-27 12:27:00 -06:00
|
|
|
freeVars (SFunc _ _ b) = freeVars b
|
2024-12-27 08:17:06 -06:00
|
|
|
freeVars (TStem t) = freeVars t
|
|
|
|
freeVars (TFork l r) = freeVars l <> freeVars r
|
|
|
|
freeVars (SLambda vs b) = foldr Set.delete (freeVars b) vs
|
|
|
|
|
|
|
|
isFree :: String -> SaplingAST -> Bool
|
|
|
|
isFree x = Set.member x . freeVars
|
2024-12-19 18:57:57 -06:00
|
|
|
|
|
|
|
toAST :: T -> SaplingAST
|
2024-12-27 08:17:06 -06:00
|
|
|
toAST Leaf = TLeaf
|
|
|
|
toAST (Stem a) = TStem (toAST a)
|
2024-12-19 18:57:57 -06:00
|
|
|
toAST (Fork a b) = TFork (toAST a) (toAST b)
|
2024-12-27 08:17:06 -06:00
|
|
|
|
2024-12-27 15:40:50 -06:00
|
|
|
-- We need the SKI operators in an unevaluated SaplingAST tree form so that we
|
|
|
|
-- can keep the evaluation functions straightforward
|
2024-12-27 08:17:06 -06:00
|
|
|
tI :: SaplingAST
|
2024-12-27 12:27:00 -06:00
|
|
|
tI = SApp (SApp TLeaf (SApp TLeaf (SApp TLeaf TLeaf))) TLeaf
|
2024-12-27 08:17:06 -06:00
|
|
|
|
|
|
|
tK :: SaplingAST
|
2024-12-27 12:27:00 -06:00
|
|
|
tK = SApp TLeaf TLeaf
|
2024-12-27 08:17:06 -06:00
|
|
|
|
|
|
|
tS :: SaplingAST
|
2024-12-27 12:27:00 -06:00
|
|
|
tS = SApp (SApp TLeaf (SApp TLeaf (SApp (SApp TLeaf TLeaf) TLeaf))) TLeaf
|
2024-12-27 08:17:06 -06:00
|
|
|
|
2024-12-27 12:27:00 -06:00
|
|
|
result :: Map String T -> T
|
|
|
|
result r = case Map.lookup "__result" r of
|
|
|
|
Just a -> a
|
|
|
|
Nothing -> error "No __result field found in provided environment"
|