@@ -85,8 +85,6 @@ type EffectBindingAssoc a =
8585data BackendRewrite
8686 = RewriteInline (Maybe Ident) Level BackendExpr BackendExpr
8787 | RewriteUncurry (Maybe Ident) Level (NonEmptyArray (Tuple (Maybe Ident) Level)) BackendExpr BackendExpr
88− | RewriteLetAssoc (Array (LetBindingAssoc BackendExpr)) BackendExpr
89− | RewriteEffectBindAssoc (Array (EffectBindingAssoc BackendExpr)) BackendExpr
9088 | RewriteStop (Qualified Ident)
9189 | RewriteUnpackOp (Maybe Ident) Level UnpackOp BackendExpr
9290 | RewriteDistBranchesLet (Maybe Ident) Level (NonEmptyArray (Pair BackendExpr)) BackendExpr BackendExpr
@@ -253,14 +251,12 @@ instance Eval f => Eval (BackendSyntax f) where
253251 idents
254252 env
255253 Let ident _ binding body ->
256− guardFail (eval env binding) \binding' ->
257− makeLet ident binding' (flip eval body <<< bindLocal env <<< One)
254+ makeLet ident (eval env binding) (flip eval body <<< bindLocal env <<< One)
258255 LetRec _ bindings body -> do
259256 let bindGroup sem = flip eval sem <<< bindLocal env <<< Group
260257 SemLetRec (map bindGroup <$> bindings) (bindGroup body)
261258 EffectBind ident _ binding body ->
262− guardFail (eval env binding) \binding' ->
263− SemEffectBind ident binding' (flip eval body <<< bindLocal env <<< One)
259+ makeEffectBind ident (eval env binding) (flip eval body <<< bindLocal env <<< One)
264260 EffectPure val ->
265261 guardFail (eval env val) SemEffectPure
266262 EffectDefer val ->
@@ -297,28 +293,6 @@ instance Eval BackendExpr where
297293 RewriteUncurry ident _ args binding body ->
298294 SemLet ident (mkFnFromArgs env (NonEmptyArray.toArray args) binding) \newFn -> do
299295 eval (bindLocal env (One (mkUncurriedAppRewrite env newFn (NonEmptyArray.length args)))) body
300− RewriteLetAssoc bindings body -> do
301− let
302− goBinding env' = case _ of
303− List.Nil ->
304− eval env' body
305− List.Cons b bs ->
306− makeLet b.ident (eval env' b.binding) \nextBinding ->
307− goBinding (bindLocal env (One nextBinding)) bs
308− goBinding env (List.fromFoldable bindings)
309− RewriteEffectBindAssoc bindings body -> do
310− let
311− goBinding env' = case _ of
312− List.Nil ->
313− eval env' body
314− List.Cons b bs
315− | b.pure ->
316− makeLet b.ident (eval env' b.binding) \nextBinding ->
317− goBinding (bindLocal env (One nextBinding)) bs
318− | otherwise ->
319− SemEffectBind b.ident (eval env' b.binding) \nextBinding ->
320− goBinding (bindLocal env (One nextBinding)) bs
321− goBinding env (List.fromFoldable bindings)
322296 RewriteStop qual ->
323297 NeutStop qual
324298 RewriteUnpackOp _ _ op body ->
@@ -500,7 +474,7 @@ neutralApp hd spine
500474 NeutApp hd spine
501475
502476evalAccessor :: Env -> BackendSemantics -> BackendAccessor -> BackendSemantics
503−evalAccessor env lhs accessor = evalAssocLet lhs case _ of
477+evalAccessor env lhs accessor = floatLet lhs case _ of
504478 SemRef ref spine sem ->
505479 evalRef env ref spine (ExternAccessor accessor) sem
506480 NeutLit (LitRecord props)
@@ -528,7 +502,7 @@ evalAccessor env lhs accessor = evalAssocLet lhs case _ of
528502 NeutAccessor lhs' accessor
529503
530504evalUpdate :: BackendSemantics -> Array (Prop BackendSemantics) -> BackendSemantics
531−evalUpdate lhs props = evalAssocLet lhs case _ of
505+evalUpdate lhs props = floatLet lhs case _ of
532506 NeutLit (LitRecord props') ->
533507 NeutLit (LitRecord (NonEmptyArray.head <$> Array.groupAllBy (comparing propKey) (props <> props')))
534508 NeutUpdate r props' ->
@@ -573,31 +547,60 @@ rewriteBranches k = go
573547evalPair :: forall f. Eval f => Env -> Pair f -> SemConditional BackendSemantics
574548evalPair env (Pair a b) = SemConditional (defer \_ -> eval env a) (defer \_ -> eval env b)
575549
576−evalAssocLet :: BackendSemantics -> (BackendSemantics -> BackendSemantics) -> BackendSemantics
577−evalAssocLet sem go = case sem of
578− SemLet ident val k ->
579− SemLet ident val \nextVal1 ->
580− makeLet Nothing (k nextVal1) go
581− SemLetRec vals k ->
582− SemLetRec vals \nextVals1 ->
583− makeLet Nothing (k nextVals1) go
584− NeutFail err ->
585− NeutFail err
586− _ ->
587− go sem
550+makeEffectBind :: Maybe Ident -> BackendSemantics -> (BackendSemantics -> BackendSemantics) -> BackendSemantics
551+makeEffectBind = go
552+ where
553+ go ident1 binding1 k1 = case binding1 of
554+ SemLet ident2 binding2 k2 ->
555+ makeLet ident2 binding2 \nextBinding2 ->
556+ makeEffectBind ident1 (k2 nextBinding2) k1
557+ SemEffectBind ident2 binding2 k2 ->
558+ go ident2 binding2 \nextBinding2 ->
559+ makeEffectBind ident1 (k2 nextBinding2) k1
560+ SemEffectDefer binding2 ->
561+ SemEffectDefer $ floatLet binding2 \nextBinding2 ->
562+ makeEffectBind ident1 nextBinding2 k1
563+ _ ->
564+ floatLet binding1 \nextBinding2 ->
565+ SemEffectBind ident1 nextBinding2 k1
588566
589567makeLet :: Maybe Ident -> BackendSemantics -> (BackendSemantics -> BackendSemantics) -> BackendSemantics
590−makeLet ident binding go = case binding of
591− SemRef _ [] _ ->
592− go binding
593− NeutLocal _ _ ->
594− go binding
595− NeutStop _ ->
596− go binding
597− NeutVar _ ->
598− go binding
599− _ ->
600− SemLet ident binding go
568+makeLet = floatLetWith go
569+ where
570+ go ident binding k = case binding of
571+ SemRef _ [] _ ->
572+ k binding
573+ NeutLocal _ _ ->
574+ k binding
575+ NeutStop _ ->
576+ k binding
577+ NeutVar _ ->
578+ k binding
579+ _ ->
580+ SemLet ident binding k
581+
582+floatLet :: BackendSemantics -> (BackendSemantics -> BackendSemantics) -> BackendSemantics
583+floatLet = floatLetWith (const (#)) Nothing
584+
585+floatLetWith
586+ :: (Maybe Ident -> BackendSemantics -> (BackendSemantics -> BackendSemantics) -> BackendSemantics)
587+ -> Maybe Ident
588+ -> BackendSemantics
589+ -> (BackendSemantics -> BackendSemantics)
590+ -> BackendSemantics
591+floatLetWith = go
592+ where
593+ go f ident1 binding1 k1 = case binding1 of
594+ SemLet ident2 binding2 k2 ->
595+ go f ident2 binding2 \nextBinding2 ->
596+ makeLet ident1 (k2 nextBinding2) k1
597+ SemLetRec bindings k2 ->
598+ SemLetRec bindings \nextBindings ->
599+ makeLet ident1 (k2 nextBindings) k1
600+ NeutFail _ ->
601+ binding1
602+ _ ->
603+ f ident1 binding1 k1
601604
602605deref :: BackendSemantics -> BackendSemantics
603606deref = case _ of
@@ -636,7 +639,7 @@ evalPrimOp env = case _ of
636639 _, NeutFail err ->
637640 NeutFail err
638641 _, _ ->
639− evalAssocLet x (NeutPrimOp <<< Op1 op1)
642+ floatLet x (NeutPrimOp <<< Op1 op1)
640643 Op2 op2 x y ->
641644 case op2 of
642645 OpBooleanAnd
@@ -742,8 +745,8 @@ evalPrimOp env = case _ of
742745 NeutFail err, _ -> NeutFail err
743746 _, NeutFail err -> NeutFail err
744747 _, _ ->
745− evalAssocLet x \x' ->
746− evalAssocLet y \y' ->
748+ floatLet x \x' ->
749+ floatLet y \y' ->
747750 if isAssocPrimOp op2 then
748751 evalAssocOp env (Right op2) x' y'
749752 else
@@ -1260,16 +1263,6 @@ build ctx = case _ of
12601263 build ctx $ App hd (tl1 <> tl2)
12611264 Abs ids1 (ExprSyntax _ (Abs ids2 body)) ->
12621265 build ctx $ Abs (ids1 <> ids2) body
1263− expr@(Let ident1 level1 (ExprSyntax _ (Let ident2 level2 binding2 body2)) body1) ->
1264− ExprRewrite (withRewrite (analyzeDefault ctx expr)) $ RewriteLetAssoc
1265− [ { ident: ident2, level: level2, binding: binding2 }
1266− , { ident: ident1, level: level1, binding: body2 }
1267− ]
1268− body1
1269− expr@(Let ident1 level1 (ExprRewrite _ (RewriteLetAssoc bindings body2)) body1) ->
1270− ExprRewrite (withRewrite (analyzeDefault ctx expr)) $ RewriteLetAssoc
1271− (Array.snoc bindings { ident: ident1, level: level1, binding: body2 })
1272− body1
12731266 Let ident level binding body
12741267 | shouldInlineLet level binding body ->
12751268 rewriteInline ident level binding body
@@ -1312,29 +1305,6 @@ build ctx = case _ of
13121305 PrimOp (Op2 op2 lhs (ExprSyntax analysis (Branch bs def)))
13131306 | Just expr' <- shouldDistributeBranchPrimOp2R analysis bs def lhs op2 ->
13141307 expr'
1315− expr@(EffectBind ident1 level1 (ExprSyntax _ (EffectBind ident2 level2 binding2 body2)) body1) ->
1316− ExprRewrite (withRewrite (analyzeDefault ctx expr)) $ RewriteEffectBindAssoc
1317− [ { ident: ident2, level: level2, binding: binding2, pure: false }
1318− , { ident: ident1, level: level1, binding: body2, pure: false }
1319− ]
1320− body1
1321− expr@(EffectBind ident1 level1 (ExprSyntax _ (Let ident2 level2 binding2 body2)) body1) ->
1322− ExprRewrite (withRewrite (analyzeDefault ctx expr)) $ RewriteEffectBindAssoc
1323− [ { ident: ident2, level: level2, binding: binding2, pure: true }
1324− , { ident: ident1, level: level1, binding: body2, pure: false }
1325− ]
1326− body1
1327− expr@(EffectBind ident1 level1 (ExprRewrite _ (RewriteEffectBindAssoc bindings body2)) body1) ->
1328− ExprRewrite (withRewrite (analyzeDefault ctx expr)) $ RewriteEffectBindAssoc
1329− (Array.snoc bindings { ident: ident1, level: level1, binding: body2, pure: false })
1330− body1
1331− expr@(EffectBind ident1 level1 (ExprRewrite _ (RewriteLetAssoc bindings body2)) body1) ->
1332− ExprRewrite (withRewrite (analyzeDefault ctx expr)) $ RewriteEffectBindAssoc
1333− (Array.snoc (withPure <$> bindings) { ident: ident1, level: level1, binding: body2, pure: false })
1334− body1
1335− where
1336− withPure { ident, level, binding } =
1337− { ident, level, binding, pure: true }
13381308 EffectBind ident level (ExprSyntax _ (EffectPure binding)) body ->
13391309 build ctx $ EffectDefer $ build ctx $ Let ident level binding body
13401310 EffectBind ident level (ExprSyntax _ (EffectDefer binding)) body ->
@@ -1657,7 +1627,7 @@ optimize traceSteps ctx env (Qualified mn (Ident id)) initN originalExpr =
16571627 if rewrite then
16581628 go newSteps (n - 1) expr2
16591629 else
1660− Tuple (Array.reverse (List.toUnfoldable steps)) expr2
1630+ Tuple (Array.reverse (List.toUnfoldable newSteps)) expr2
16611631
16621632 goStep :: Int -> BackendExpr -> Tuple Boolean BackendExpr
16631633 goStep n expr1
@@ -1686,39 +1656,6 @@ foldBackendExpr foldSyntax foldRewrite = go
16861656 foldSyntax $ Let ident level (foldSyntax (Abs args (go binding))) (go body)
16871657 RewriteStop qual ->
16881658 foldSyntax $ Var qual
1689− RewriteLetAssoc bindings body ->
1690− case NonEmptyArray.fromArray bindings of
1691− Just bindings' -> do
1692− let
1693− { ident, level, binding } = foldl1Array
1694− ( \inner outer -> outer
1695− { binding =
1696− foldSyntax $ Let inner.ident inner.level inner.binding (go outer.binding)
1697− }
1698− )
1699− (\outer -> outer { binding = go outer.binding })
1700− bindings'
1701− foldSyntax $ Let ident level binding (go body)
1702− Nothing ->
1703− go body
1704− RewriteEffectBindAssoc bindings body ->
1705− case NonEmptyArray.fromArray bindings of
1706− Just bindings' -> do
1707− let
1708− { ident, level, binding } = foldl1Array
1709− ( \inner outer -> outer
1710− { binding =
1711− if inner.pure then
1712− foldSyntax $ Let inner.ident inner.level inner.binding (go outer.binding)
1713− else
1714− foldSyntax $ EffectBind inner.ident inner.level inner.binding (go outer.binding)
1715− }
1716− )
1717− (\outer -> outer { binding = go outer.binding })
1718− bindings'
1719− foldSyntax $ Let ident level binding (go body)
1720− Nothing ->
1721− go body
17221659 RewriteUnpackOp ident level op body ->
17231660 case op of
17241661 UnpackRecord props ->