{-# LANGUAGE FlexibleContexts #-} module LText.Eval where import LText.Expr (Expr (..)) import Data.HashSet (HashSet) import qualified Data.HashSet as HS evaluate :: Expr -> Expr evaluate :: Expr -> Expr evaluate Expr e = case Expr e of Var String n -> String -> Expr Var String n Abs String n Expr e' -> String -> Expr -> Expr Abs String n (Expr -> Expr evaluate Expr e') Lit [Text] t -> [Text] -> Expr Lit [Text] t Concat Expr e1 Expr e2 -> case (Expr -> Expr evaluate Expr e1, Expr -> Expr evaluate Expr e2) of (Lit [Text] t1, Lit [Text] t2) -> [Text] -> Expr Lit forall a b. (a -> b) -> a -> b $! [Text] t1 forall a. [a] -> [a] -> [a] ++ [Text] t2 (Expr e1' , Expr e2' ) -> Expr -> Expr -> Expr Concat Expr e1' Expr e2' App Expr e1 Expr e2 -> case Expr -> Expr evaluate Expr e1 of Abs String n Expr e1' -> String -> Expr -> Expr -> Expr substitute String n (Expr -> Expr evaluate Expr e2) (Expr -> Expr evaluate Expr e1') Expr e1' -> Expr -> Expr -> Expr App Expr e1' (Expr -> Expr evaluate Expr e2) substitute :: String -> Expr -> Expr -> Expr substitute :: String -> Expr -> Expr -> Expr substitute String n Expr x Expr e = case Expr e of Lit [Text] t -> [Text] -> Expr Lit [Text] t Concat Expr e1 Expr e2 -> Expr -> Expr -> Expr Concat (String -> Expr -> Expr -> Expr substitute String n Expr x Expr e1) (String -> Expr -> Expr -> Expr substitute String n Expr x Expr e2) Var String n' | String n forall a. Eq a => a -> a -> Bool == String n' -> Expr x | Bool otherwise -> String -> Expr Var String n' App Expr e1 Expr e2 -> Expr -> Expr -> Expr App (String -> Expr -> Expr -> Expr substitute String n Expr x Expr e1) (String -> Expr -> Expr -> Expr substitute String n Expr x Expr e2) Abs String n' Expr e' | String n forall a. Eq a => a -> a -> Bool == String n' -> String -> Expr -> Expr Abs String n' Expr e' | Bool otherwise -> String -> Expr -> Expr Abs String n' forall a b. (a -> b) -> a -> b $ String -> Expr -> Expr -> Expr substitute String n Expr x Expr e' freeVars :: Expr -> HashSet String freeVars :: Expr -> HashSet String freeVars Expr e = case Expr e of Abs String n Expr e' -> forall a. (Eq a, Hashable a) => a -> HashSet a -> HashSet a HS.delete String n forall a b. (a -> b) -> a -> b $ Expr -> HashSet String freeVars Expr e' App Expr e1 Expr e2 -> Expr -> HashSet String freeVars Expr e1 forall a. Semigroup a => a -> a -> a <> Expr -> HashSet String freeVars Expr e2 Var String n -> forall a. Hashable a => a -> HashSet a HS.singleton String n Lit [Text] _ -> forall a. HashSet a HS.empty Concat Expr e1 Expr e2 -> Expr -> HashSet String freeVars Expr e1 forall a. Semigroup a => a -> a -> a <> Expr -> HashSet String freeVars Expr e2