summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2019-03-24 22:39:43 -0400
committerJoe Crayne <joe@jerkface.net>2019-03-24 22:40:01 -0400
commitec1c7a5c0e2673388c5601353f2e54b1b364fdb4 (patch)
treeaaab2228d90e191845bedf07d29f36f897379f11
parent0d0feb172bebd181a9b1f993e5ce3e168abde966 (diff)
Handle branching control flow by creating a let-binding of the continuation.
Also, grok continue statement.
-rw-r--r--monkeypatch.hs29
1 files changed, 28 insertions, 1 deletions
diff --git a/monkeypatch.hs b/monkeypatch.hs
index 14359fe..b3bbe2d 100644
--- a/monkeypatch.hs
+++ b/monkeypatch.hs
@@ -211,12 +211,36 @@ modifyOperand1 f (InfixApp l x op y) = InfixApp l (f x) op y
211informalize :: FormalLambda -> HS.Exp () 211informalize :: FormalLambda -> HS.Exp ()
212informalize (FormalLambda k x) = Lambda () [hspvar k] x 212informalize (FormalLambda k x) = Lambda () [hspvar k] x
213 213
214
215
216-- Like applyComputation, but creates a let-binding rather than inlining the continuation.
217multiwayContinuation :: Computation FormalLambda -> Computation (HS.Exp ()) -> Computation (HS.Exp ())
218multiwayContinuation a@Computation{ comp = FormalLambda govar exp } b =
219 let k = uniqIdentifier "go" (foldr Map.union Map.empty [compFree a,compIntro a,compFree b,compIntro b])
220 vs = Map.keys $ compIntro a `Map.intersection` compFree b
221 matchgo (Var () (UnQual () (HS.Ident () v))) = v==govar
222 matchgo _ = False
223 subst x | matchgo x = callsite
224 | otherwise = x
225 callsite = foldl (App ()) (hsvar k) $ map hsvar vs
226 pats = map hspvar vs
227 letexpr = Let () (BDecls () [FunBind () [HS.Match () (HS.Ident () k) pats
228 (UnGuardedRhs () (comp b)) Nothing]])
229 (everywhere (mkT subst) exp)
230 in Computation
231 { compFree = Map.union (compFree a) (compFree b) Map.\\ compIntro a
232 , compIntro = compIntro a `Map.union` compIntro b
233 , compContinue = Nothing
234 , comp = letexpr
235 }
236
237
214applyComputation :: Computation FormalLambda -> Computation (HS.Exp ()) -> Computation (HS.Exp ()) 238applyComputation :: Computation FormalLambda -> Computation (HS.Exp ()) -> Computation (HS.Exp ())
215applyComputation a@Computation{ comp = FormalLambda govar exp } b = 239applyComputation a@Computation{ comp = FormalLambda govar exp } b =
216 let matchgo (Var () (UnQual () (HS.Ident () v))) = v==govar 240 let matchgo (Var () (UnQual () (HS.Ident () v))) = v==govar
217 matchgo _ = False 241 matchgo _ = False
218 in case listify matchgo exp of 242 in case listify matchgo exp of
219 (_:_:_) -> error "TODO: Multiple go-refs; make let binding." 243 (_:_:_) -> multiwayContinuation a b
220 _ -> Computation 244 _ -> Computation
221 { compFree = Map.union (compFree a) (compFree b) Map.\\ compIntro a 245 { compFree = Map.union (compFree a) (compFree b) Map.\\ compIntro a
222 , compIntro = compIntro a `Map.union` compIntro b 246 , compIntro = compIntro a `Map.union` compIntro b
@@ -564,6 +588,9 @@ grokStatement fe (CBlockStmt (CReturn (Just exp) _)) = do
564 return $ fmap (\y -> FormalLambda k y) $ foldr applyComputation x' xs 588 return $ fmap (\y -> FormalLambda k y) $ foldr applyComputation x' xs
565grokStatement fe (CBlockStmt (CReturn Nothing _)) = 589grokStatement fe (CBlockStmt (CReturn Nothing _)) =
566 Just $ mkcomp $ FormalLambda "go" retUnit 590 Just $ mkcomp $ FormalLambda "go" retUnit
591grokStatement fe (CBlockStmt (CCont _)) =
592 Just (mkcomp $ FormalLambda "go" $ hsvar " continue")
593 { compContinue = Just " continue" }
567grokStatement fe (CBlockStmt (CIf exp thn els _)) = do 594grokStatement fe (CBlockStmt (CIf exp thn els _)) = do
568 (xs,x) <- grokExpression fe exp 595 (xs,x) <- grokExpression fe exp
569 let mkif0 = If () (comp x) 596 let mkif0 = If () (comp x)