@@ -130,14 +130,14 @@ optimize cycle (A.At region expression) =
130130 obranch <- optimize cycle branch
131131 pure (pattern, foldr Opt.Let obranch defs)
132132 in
133− do oexpr <- optimize cycle expr
133+ do temp <- Names.generate
134+ oexpr <- optimize cycle expr
134135 case oexpr of
135136 Opt.VarLocal root ->
136− Case.optimize root <$> traverse (optimizeBranch root) branches
137+ Case.optimize temp root <$> traverse (optimizeBranch root) branches
137138
138139 _ ->
139− do root <- Names.generate
140− Case.optimize root <$> traverse (optimizeBranch root) branches
140+ Case.optimize temp temp <$> traverse (optimizeBranch temp) branches
141141
142142 Can.Accessor field ->
143143 Names.registerField field (Opt.Accessor field)
@@ -246,13 +246,13 @@ destructHelp root (A.At region pattern) revDefs =
246246 let newRevDefs = Opt.Def name root : revDefs
247247 case maybeC of
248248 Nothing ->
249− destructHelp (Opt.CtorAccess tuple Index.second) b =<<
250− destructHelp (Opt.CtorAccess tuple Index.first) a newRevDefs
249+ destructHelp (Opt.Index tuple 1) b =<<
250+ destructHelp (Opt.Index tuple 0) a newRevDefs
251251
252252 Just c ->
253− destructHelp (Opt.CtorAccess tuple Index.third) c =<<
254− destructHelp (Opt.CtorAccess tuple Index.second) b =<<
255− destructHelp (Opt.CtorAccess tuple Index.first) a newRevDefs
253+ destructHelp (Opt.Index tuple 2) c =<<
254+ destructHelp (Opt.Index tuple 1) b =<<
255+ destructHelp (Opt.Index tuple 0) a newRevDefs
256256
257257 Can.PList [] ->
258258 pure revDefs
@@ -272,7 +272,7 @@ destructHelp root (A.At region pattern) revDefs =
272272 Can.PInt _ ->
273273 pure revDefs
274274
275− Can.PCtor _ _ _ _ _ args ->
275+ Can.PCtor _ _ _ _ _ _ args ->
276276 do name <- Names.generate
277277 foldM
278278 (destructCtorArg (Opt.VarLocal name))
@@ -284,13 +284,13 @@ destructCons :: Opt.Expr -> Can.Pattern -> Can.Pattern -> [Opt.Def] -> Names.Tra
284284destructCons root hd tl revDefs =
285285 do name <- Names.generate
286286 let list = Opt.VarLocal name
287− destructHelp (Opt.CtorAccess list Index.first) hd =<<
288− destructHelp (Opt.CtorAccess list Index.second) tl (Opt.Def name root : revDefs)
287+ destructHelp (Opt.Index list 0) hd =<<
288+ destructHelp (Opt.Index list 1) tl (Opt.Def name root : revDefs)
289289
290290
291291destructCtorArg :: Opt.Expr -> [Opt.Def] -> Can.PatternCtorArg -> Names.Tracker [Opt.Def]
292292destructCtorArg root revDefs (Can.PatternCtorArg index _ arg) =
293− destructHelp (Opt.CtorAccess root index) arg revDefs
293+ destructHelp (Opt.Index root (Index.toZeroBased index)) arg revDefs
294294
295295
296296
@@ -312,37 +312,46 @@ optimizePotentialTailCall cycle def =
312312
313313
314314optimizeTail :: Cycle -> N.Name -> [N.Name] -> Can.Expr -> Names.Tracker Opt.Expr
315−optimizeTail cycle name argNames locExpr@(A.At _ expression) =
315+optimizeTail cycle rootName argNames locExpr@(A.At _ expression) =
316316 case expression of
317− Can.Call (A.At _ (Can.VarTopLevel _ funcName)) args ->
318− if funcName == name && length args == length argNames then
319− Opt.TailCall name argNames <$> traverse (optimize cycle) args
320− else
321− optimize cycle locExpr
317+ Can.Call func@(A.At _ (Can.VarTopLevel _ name)) args ->
318+ do oargs <- traverse (optimize cycle) args
319+ if name == rootName
320+ then
321+ case Index.indexedZipWith (\_ a b -> (a,b)) argNames oargs of
322+ Index.LengthMatch pairs ->
323+ pure $ Opt.TailCall name pairs
324+
325+ Index.LengthMismatch _ _ ->
326+ do ofunc <- optimize cycle func
327+ pure $ Opt.Call ofunc oargs
328+ else
329+ do ofunc <- optimize cycle func
330+ pure $ Opt.Call ofunc oargs
322331
323332 Can.If branches finally ->
324333 let
325334 optimizeBranch (condition, branch) =
326335 (,)
327336 <$> optimize cycle condition
328− <*> optimizeTail cycle name argNames branch
337+ <*> optimizeTail cycle rootName argNames branch
329338 in
330339 Opt.If
331340 <$> traverse optimizeBranch branches
332− <*> optimizeTail cycle name argNames finally
341+ <*> optimizeTail cycle rootName argNames finally
333342
334343 Can.Let def body ->
335− optimizeDef cycle def =<< optimizeTail cycle name argNames body
344+ optimizeDef cycle def =<< optimizeTail cycle rootName argNames body
336345
337346 Can.LetRec defs body ->
338347 case defs of
339348 [def] ->
340349 Opt.Let
341350 <$> optimizePotentialTailCall cycle def
342− <*> optimizeTail cycle name argNames body
351+ <*> optimizeTail cycle rootName argNames body
343352
344353 _ ->
345− do obody <- optimizeTail cycle name argNames body
354+ do obody <- optimizeTail cycle rootName argNames body
346355 foldM (\bod def -> optimizeDef cycle def bod) obody defs
347356
348357 Can.LetDestruct pattern expr body ->
@@ -356,17 +365,17 @@ optimizeTail cycle name argNames locExpr@(A.At _ expression) =
356365 let
357366 optimizeBranch root (Can.CaseBranch pattern branch) =
358367 do defs <- destructHelp (Opt.VarLocal root) pattern []
359− obranch <- optimizeTail cycle name argNames branch
368+ obranch <- optimizeTail cycle rootName argNames branch
360369 pure (pattern, foldr Opt.Let obranch defs)
361370 in
362− do oexpr <- optimize cycle expr
371+ do temp <- Names.generate
372+ oexpr <- optimize cycle expr
363373 case oexpr of
364374 Opt.VarLocal root ->
365− Case.optimize root <$> traverse (optimizeBranch root) branches
375+ Case.optimize temp root <$> traverse (optimizeBranch root) branches
366376
367377 _ ->
368− do root <- Names.generate
369− Case.optimize root <$> traverse (optimizeBranch root) branches
378+ Case.optimize temp temp <$> traverse (optimizeBranch temp) branches
370379
371380 _ ->
372381 optimize cycle locExpr
@@ -387,7 +396,7 @@ toTailDef name argNames defss body =
387396hasTailCall :: Opt.Expr -> Bool
388397hasTailCall expression =
389398 case expression of
390− Opt.TailCall _ _ _ ->
399+ Opt.TailCall _ _ ->
391400 True
392401
393402 Opt.If branches finally ->
@@ -396,7 +405,7 @@ hasTailCall expression =
396405 Opt.Let _ body ->
397406 hasTailCall body
398407
399− Opt.Case _ _ branches ->
408+ Opt.Case _ _ _ branches ->
400409 any (hasTailCall . snd) branches
401410
402411 _ ->