diff options
author | Joe Crayne <joe@jerkface.net> | 2019-03-24 22:39:43 -0400 |
---|---|---|
committer | Joe Crayne <joe@jerkface.net> | 2019-03-24 22:40:01 -0400 |
commit | ec1c7a5c0e2673388c5601353f2e54b1b364fdb4 (patch) | |
tree | aaab2228d90e191845bedf07d29f36f897379f11 | |
parent | 0d0feb172bebd181a9b1f993e5ce3e168abde966 (diff) |
Handle branching control flow by creating a let-binding of the continuation.
Also, grok continue statement.
-rw-r--r-- | monkeypatch.hs | 29 |
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 | |||
211 | informalize :: FormalLambda -> HS.Exp () | 211 | informalize :: FormalLambda -> HS.Exp () |
212 | informalize (FormalLambda k x) = Lambda () [hspvar k] x | 212 | informalize (FormalLambda k x) = Lambda () [hspvar k] x |
213 | 213 | ||
214 | |||
215 | |||
216 | -- Like applyComputation, but creates a let-binding rather than inlining the continuation. | ||
217 | multiwayContinuation :: Computation FormalLambda -> Computation (HS.Exp ()) -> Computation (HS.Exp ()) | ||
218 | multiwayContinuation 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 | |||
214 | applyComputation :: Computation FormalLambda -> Computation (HS.Exp ()) -> Computation (HS.Exp ()) | 238 | applyComputation :: Computation FormalLambda -> Computation (HS.Exp ()) -> Computation (HS.Exp ()) |
215 | applyComputation a@Computation{ comp = FormalLambda govar exp } b = | 239 | applyComputation 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 |
565 | grokStatement fe (CBlockStmt (CReturn Nothing _)) = | 589 | grokStatement fe (CBlockStmt (CReturn Nothing _)) = |
566 | Just $ mkcomp $ FormalLambda "go" retUnit | 590 | Just $ mkcomp $ FormalLambda "go" retUnit |
591 | grokStatement fe (CBlockStmt (CCont _)) = | ||
592 | Just (mkcomp $ FormalLambda "go" $ hsvar " continue") | ||
593 | { compContinue = Just " continue" } | ||
567 | grokStatement fe (CBlockStmt (CIf exp thn els _)) = do | 594 | grokStatement 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) |