@@ -18,7 +18,7 @@ import PureScript.Backend.Chez.Syntax (ChezDefinition(..), ChezExport(..), ChezE
1818import PureScript.Backend.Chez.Syntax as S
1919import PureScript.Backend.Optimizer.Convert (BackendModule, BackendBindingGroup)
2020import PureScript.Backend.Optimizer.CoreFn (Ident(..), Literal(..), ModuleName(..))
21−import PureScript.Backend.Optimizer.Semantics (NeutralExpr(..))
21+import PureScript.Backend.Optimizer.Semantics (NeutralExpr)
2222import PureScript.Backend.Optimizer.Syntax (BackendAccessor(..), BackendOperator(..), BackendOperator1(..), BackendOperator2(..), BackendOperatorNum(..), BackendOperatorOrd(..), BackendSyntax(..), Pair(..))
2323import Safe.Coerce (coerce)
2424
@@ -130,7 +130,7 @@ codegenTopLevelBinding codegenEnv (Tuple (Ident i) n) =
130130 [ DefineValue i $ codegenExpr codegenEnv n ]
131131
132132codegenExpr :: CodegenEnv -> NeutralExpr -> ChezExpr
133−codegenExpr codegenEnv@{ currentModule } (NeutralExpr s) = case s of
133+codegenExpr codegenEnv@{ currentModule } s = case unwrap s of
134134 Var qi ->
135135 S.Identifier $ S.resolve currentModule qi
136136 Local i l ->
@@ -177,8 +177,8 @@ codegenExpr codegenEnv@{ currentModule } (NeutralExpr s) = case s of
177177
178178 LetRec _ _ _ ->
179179 S.Identifier "let-rec"
180− Let i l v e ->
181− S.chezLet (S.toChezIdent i l) (codegenExpr codegenEnv v) (codegenExpr codegenEnv e)
180+ Let _ _ _ _ ->
181+ codegenChain pureBlockMode codegenEnv s
182182 Branch b o -> do
183183 let
184184 goPair :: Pair NeutralExpr -> { c :: _, e :: _ }
@@ -186,11 +186,11 @@ codegenExpr codegenEnv@{ currentModule } (NeutralExpr s) = case s of
186186 S.chezCond (goPair <$> b) (codegenExpr codegenEnv <$> o)
187187
188188 EffectBind _ _ _ _ ->
189− S.Identifier "effect-bind"
189+ codegenEffectChain codegenEnv s
190190 EffectPure _ ->
191− S.Identifier "effect-pure"
191+ codegenEffectChain codegenEnv s
192192 EffectDefer _ ->
193− S.Identifier "effect-defer"
193+ codegenEffectChain codegenEnv s
194194
195195 PrimOp o ->
196196 codegenPrimOp codegenEnv o
@@ -225,6 +225,43 @@ codegenLiteral codegenEnv = case _ of
225225 LitArray a -> S.vector $ codegenExpr codegenEnv <$> a
226226 LitRecord r -> S.record $ (map $ codegenExpr codegenEnv) <$> r
227227
228+type BlockMode = { effect :: Boolean }
229+
230+pureBlockMode :: BlockMode
231+pureBlockMode = { effect: false }
232+
233+effectBlockMode :: BlockMode
234+effectBlockMode = { effect: true }
235+
236+codegenPureChain :: CodegenEnv -> NeutralExpr -> ChezExpr
237+codegenPureChain = codegenChain pureBlockMode
238+
239+codegenEffectChain :: CodegenEnv -> NeutralExpr -> ChezExpr
240+codegenEffectChain codegenEnv = S.chezThunk <<< codegenChain effectBlockMode codegenEnv
241+
242+codegenChain :: BlockMode -> CodegenEnv -> NeutralExpr -> ChezExpr
243+codegenChain blockMode codegenEnv = go []
244+ where
245+ go :: Array _ -> NeutralExpr -> ChezExpr
246+ go bindings expression = case unwrap expression of
247+ Let i l v e' ->
248+ go (Array.cons { i, l, v: codegenExpr codegenEnv v } bindings) e'
249+ EffectBind i l v e' | blockMode.effect ->
250+ go (Array.cons { i, l, v: S.chezUnthunk $ codegenExpr codegenEnv v } bindings) e'
251+ EffectPure e' | blockMode.effect ->
252+ go bindings e'
253+ EffectDefer e' | blockMode.effect ->
254+ go bindings e'
255+ _ | Array.null bindings ->
256+ codegenExpr codegenEnv expression
257+ _ ->
258+ S.List $
259+ [ S.Identifier "scm:let*"
260+ , S.List $ Array.reverse bindings <#> \binding ->
261+ S.List [ S.Identifier $ S.toChezIdent binding.i binding.l, binding.v ]
262+ , codegenExpr codegenEnv expression
263+ ]
264+
228265codegenPrimOp :: CodegenEnv -> BackendOperator NeutralExpr -> ChezExpr
229266codegenPrimOp codegenEnv@{ currentModule } = case _ of
230267 Op1 o x -> do