@@ -15,10 +15,7 @@ import Parser (Environment, Expr (..))
1515
1616compileNumExpr :: Environment -> Expr -> CatExpr () Integer
1717compileNumExpr env expr =
18- either (\ e -> error (" Compilation failed: " ++ e)) id (compileIntExpr env expr)
19- where
20- compileIntExpr :: Environment -> Expr -> Either String (CatExpr () Integer )
21- compileIntExpr env expr = compile env [] expr >>= expectInt
18+ either (\ e -> error (" Compilation failed: " ++ e)) id (compile env [] expr >>= expectInt)
2219
2320-- Core compilation ------------------------------------------------------------
2421
@@ -64,22 +61,19 @@ compileFix :: forall c. Environment -> Expr -> Either String (RVal c)
6461compileFix env = \ case
6562 Lam fName body ->
6663 let (params, bodyExpr) = collectLams body
67- in case mkIntArgs (length params) of
68- Just (SomeIntArgs args) -> Right $ compileFixBody env args fName params bodyExpr
69- Nothing -> Left " fix expects at least one integer argument"
64+ in maybe (Left " fix expects at least one integer argument" ) Right $
65+ withIntArgs (length params) $ \ args ->
66+ curryIntArgs args $ \ actualArgs -> do
67+ paramTuple <- tupleFromExprs args actualArgs
68+ let recCall = curryIntArgs args $ \ recArgs -> do
69+ t <- tupleFromExprs args recArgs
70+ Right (RInt (Comp Apply (fanC Fst t)))
71+ let fixLocal = (fName, recCall) :
72+ zipWith (\ n p -> (n, RInt p)) params (projections args Snd )
73+ stepBody <- compile env fixLocal bodyExpr >>= expectInt
74+ Right (RInt (Comp (Fix stepBody) paramTuple))
7075 _ -> Left " fix expects a lambda step function"
7176
72- compileFixBody ::
73- forall c input . Environment -> IntArgs input ->
74- String -> [String ] -> Expr -> RVal c
75- compileFixBody env args fName params body =
76- curryIntArgs args $ \ actualArgs -> do
77- paramTuple <- tupleFromExprs args actualArgs
78- let fixLocal = (fName, recFun args) :
79- zipWith (\ n p -> (n, RInt p)) params (projections args Snd )
80- stepBody <- compile env fixLocal body >>= expectInt
81- Right (RInt (Comp (Fix stepBody) paramTuple))
82-
8377-- | Build a curried RVal that collects n integer arguments, then applies a continuation.
8478curryIntArgs :: forall c input . IntArgs input -> ([CatExpr c Integer ] -> Either String (RVal c )) -> RVal c
8579curryIntArgs args k = go args []
@@ -92,27 +86,16 @@ curryIntArgs args k = go args []
9286 RInt a -> Right (go rest (a : acc))
9387 _ -> Left " Expected Integer argument"
9488
95- -- | Build the recursive-call RVal inside a Fix body.
96- -- Context is (CatExpr input Integer, input), so Fst projects the step function
97- -- and a recursive call f a1...an becomes: Apply . fanC Fst (a1 ... an)
98- recFun :: forall input . IntArgs input -> RVal (CatExpr input Integer , input )
99- recFun args = curryIntArgs args $ \ actualArgs -> do
100- t <- tupleFromExprs args actualArgs
101- Right (RInt (Comp Apply (fanC Fst t)))
102-
10389-- IntArgs helpers -------------------------------------------------------------
10490
10591data IntArgs input where
10692 OneArg :: IntArgs Integer
10793 MoreArgs :: IntArgs rest -> IntArgs (Integer , rest )
10894
109- data SomeIntArgs where
110- SomeIntArgs :: IntArgs input -> SomeIntArgs
111-
112- mkIntArgs :: Int -> Maybe SomeIntArgs
113- mkIntArgs n | n <= 0 = Nothing
114- mkIntArgs 1 = Just (SomeIntArgs OneArg )
115- mkIntArgs n = (\ (SomeIntArgs r) -> SomeIntArgs (MoreArgs r)) <$> mkIntArgs (n - 1 )
95+ withIntArgs :: Int -> (forall input . IntArgs input -> r ) -> Maybe r
96+ withIntArgs n _ | n <= 0 = Nothing
97+ withIntArgs 1 k = Just (k OneArg )
98+ withIntArgs n k = withIntArgs (n - 1 ) (k . MoreArgs )
11699
117100tupleFromExprs :: IntArgs input -> [CatExpr c Integer ] -> Either String (CatExpr c input )
118101tupleFromExprs OneArg [a] = Right a
0 commit comments