git @ Cat's Eye Technologies Argyle / 39fa325
Track declared free variables in VABT. Chris Pressey 3 months ago
6 changed file(s) with 48 addition(s) and 46 deletion(s). Raw diff Collapse all Expand all
5555 in Binder freshVar (substitute newBody v replacement)
5656
5757 performSubstitution :: BaseABT v -> String -> BaseABT v -> BaseABT v
58 performSubstitution m n k
59 | occursFree n m = performSubstitution' m n k
60 | otherwise = m -- TODO: should be an error?
61
62 performSubstitution' :: BaseABT v -> String -> BaseABT v -> BaseABT v
63 performSubstitution' m n k = case m of
58 performSubstitution m n k = case m of
6459 -- Base cases
6560 Var x | x == n -> k
6661 | otherwise -> Var x
6868 freeVars = Set.union (freeVars scope)
6969 (Set.difference (freeVars bodyScope) declaredFreeVarsSet)
7070 }
71 undeclaredFreeVars = Set.difference (collectUnboundVars bodyABT) declaredFreeVarsSet
71 undeclaredFreeVars =
72 Set.difference (collectUnboundVars bodyABT)
73 (Set.union (boundVars scope) declaredFreeVarsSet)
7274 in
7375 if Set.null undeclaredFreeVars
74 then return $ Right (Literal $ VABT bodyABT, finalScope)
76 then return $ Right (Literal $ VABT declaredFreeVars bodyABT, finalScope)
7577 else return $ Left $ "Unbound variables in quoted ABT: " ++ (show undeclaredFreeVars)
7678
7779 Op name args -> do
3131 env <- ask
3232 return $ VClosure param body env
3333
34 Literal (VABT abt) -> do
34 Literal (VABT fvs abt) -> do
3535 -- We need to extract the ABT so that the bindings from the
3636 -- current environment are captured in the ABT.
3737 env <- ask
3838 -- Build bindings for all unbound vars in the quoted ABT
39 let unboundVars = Set.elems $ collectUnboundVars abt
39 let unboundVars = Set.elems $ Set.difference
40 (collectUnboundVars abt)
41 (Set.fromList $ fvs)
4042 bindings <- mapM (\name -> do
4143 case Map.lookup name env of
4244 Just value -> return (name, Literal value)
4345 Nothing -> throwError $ "Required binding not found in environment: " ++ name)
4446 -- (traceShow ("literal-unbound-vars", unboundVars) unboundVars)
4547 unboundVars
46 return $ VABT $
48 return $ VABT fvs $
4749 if null bindings
4850 then abt
4951 else Operator "let"
110112
111113 -- Core homoiconic functions
112114 , ("eval", VBuiltin "eval" $ \case
113 [VABT abt] -> runEval abt
114 _ -> Left "'eval' expects an ABT")
115 [VABT [] abt] ->
116 runEval abt
117 [VABT fvs abt] ->
118 Left $ "eval: Cannot evaluate ABT with declared free variables (" ++ (show fvs) ++ ")"
119 _ ->
120 Left "'eval' expects an ABT")
115121
116122 , ("subst", VBuiltin "subst" $ \case
117 [VABT m] -> Right $ VBuiltin "subst" $ \case
123 [VABT mfvs m] -> Right $ VBuiltin "subst" $ \case
118124 [VString n] -> Right $ VBuiltin "subst" $ \case
119 [VABT k] -> Right $ VABT $ performSubstitution m n k
125 [VABT kfvs k] -> Right $ performVABTSubstitution mfvs m n kfvs k
120126 _ -> Left "subst: third argument must be an ABT"
121127 _ -> Left "subst: second argument must be a string"
122128 _ -> Left "subst: first argument must be an ABT")
123129 ]
124130
131 performVABTSubstitution mfvs m n kfvs k =
132 -- FIXME: is this wrong? The tests pass but I'm suspicious.
133 let
134 abt = performSubstitution m n k
135 fvs = Set.elems $ Set.union
136 (Set.difference (Set.fromList mfvs) (Set.singleton n))
137 (Set.fromList kfvs)
138 in
139 VABT fvs abt
140
125141 -- | Run evaluation in the initial environment
126142 runEval :: ABT -> Either String Value
127143 runEval expr = runReaderT (eval expr) initialEnv
1818 return $ Just val
1919
2020 showParses source = do
21 --
22 -- FIXME: if there is an error, show the error
23 -- FIXME: unify this with the version in Main
24 --
2125 conslist <- parseUsing (sexprToConsList) source
22 putStrLn $ show conslist
26 putStrLn $ "ConsList: " ++ show conslist
2327 ast <- parseUsing (sexprToAST) source
24 putStrLn $ show ast
28 putStrLn $ "AST: " ++ show ast
2529 abt <- parseUsing (sexprToABT) source
26 putStrLn $ show abt
30 putStrLn $ "ABT: " ++ show abt
2731 case abt of
2832 Just theAbt -> do
29 putStrLn $ unparseABT theAbt
33 putStrLn $ unparseABT [] theAbt
3034 return abt
3135 Nothing -> do
3236 return abt
33
34 -- putStrLn "Parse output:"
35 -- case sexprToConsList input of
36 -- Left err -> putStrLn $ "ConsList parse error: " ++ err
37 -- Right conslist -> do
38 -- putStrLn $ "ConsList: " ++ show conslist
39 -- case sexprToAST input of
40 -- Left err -> putStrLn $ "AST parse error: " ++ err
41 -- Right ast -> do
42 -- putStrLn $ "AST: " ++ show ast
43 -- case sexprToABT input of
44 -- Left err -> putStrLn $ "ABT conversion error: " ++ err
45 -- Right abt -> putStrLn $ "ABT: " ++ show abt
4637
4738
4839 data ReplState = ReplState
1212 data Value
1313 = VNum Integer
1414 | VString String
15 | VABT ABT
15 | VABT [String] ABT
1616 | VClosure String ABT Environment
1717 | VBuiltin String ([Value] -> Either String Value)
1818
1919 instance Eq Value where
20 VNum n1 == VNum n2 = n1 == n2
21 VString s1 == VString s2 = s1 == s2
22 VABT a1 == VABT a2 = a1 == a2
20 VNum n1 == VNum n2 = n1 == n2
21 VString s1 == VString s2 = s1 == s2
22 VABT fvs1 a1 == VABT fvs2 a2 = a1 == a2 && fvs1 == fvs2 -- FIXME this is laughable
2323 VClosure s1 a1 e1 == VClosure s2 a2 e2 = s1 == s2 && a1 == a2 && e1 == e2
24 VBuiltin s1 _ == VBuiltin s2 _ = s1 == s2
24 VBuiltin s1 _ == VBuiltin s2 _ = s1 == s2
2525
2626 instance Show Value where
2727 show (VNum n) = show n
2828 show (VString s) = show s
29 show (VABT abt) = unparseABT abt
29 show (VABT fvs abt) = unparseABT fvs abt
3030 show (VClosure {}) = "<closure>"
3131 show (VBuiltin name _) = "<builtin:" ++ name ++ ">"
3232
3333 type Environment = Map.Map String Value
3434
3535 -- | Convert an ABT back to Argyle syntax
36 unparseABT :: ABT -> String
37 unparseABT abt =
38 let freeVars = collectUnboundVars abt
39 in if Set.null freeVars
40 then "(quote " ++ unparseABTExpr abt ++ ")"
41 else "(abt (" ++ unwords (Set.toList freeVars) ++ ") " ++
42 unparseABTExpr abt ++ ")"
36 unparseABT :: [String] -> ABT -> String
37 unparseABT [] abt =
38 "(quote " ++ unparseABTExpr abt ++ ")"
39 unparseABT freeVars abt =
40 "(abt (" ++ unwords freeVars ++ ") " ++ unparseABTExpr abt ++ ")"
4341
4442 -- | Convert an ABT expression to Argyle syntax
4543 unparseABTExpr :: ABT -> String
4646 ast <- parseUsing (sexprToAST) source
4747 putStrLn $ show ast
4848 abt <- parseUsing (sexprToABT) source
49 putStrLn $ unparseABT abt
49 putStrLn $ unparseABT [] abt
5050 putStrLn $ show abt
5151
5252 parseUsing :: (String -> Either String x) -> String -> IO x