@@ -31,7 +31,8 @@ defmodule ElixirScript.Translate.Function do
3131 :let
3232 )
3333
34- function_dec = J . arrow_function_expression (
34+ function_recur_dec = J . function_declaration (
35+ J . identifier ( "recur" ) ,
3536 [ J . rest_element ( J . identifier ( "__function_args__" ) ) ] ,
3637 [ ] ,
3738 J . block_statement ( [
@@ -49,6 +50,17 @@ defmodule ElixirScript.Translate.Function do
4950 ] )
5051 )
5152
53+ function_dec = J . arrow_function_expression (
54+ [ J . rest_element ( J . identifier ( "__function_args__" ) ) ] ,
55+ [ ] ,
56+ J . block_statement ( [
57+ function_recur_dec ,
58+ J . return_statement (
59+ trampoline ( )
60+ )
61+ ] )
62+ )
63+
5264 { function_dec , state }
5365 end
5466
@@ -66,8 +78,8 @@ defmodule ElixirScript.Translate.Function do
6678 :let
6779 )
6880
69- function_dec = J . function_declaration (
70- ElixirScript.Translate.Identifier . make_function_name ( name ) ,
81+ function_recur_dec = J . function_declaration (
82+ J . identifier ( "recur" ) ,
7183 [ J . rest_element ( J . identifier ( "__function_args__" ) ) ] ,
7284 [ ] ,
7385 J . block_statement ( [
@@ -85,6 +97,18 @@ defmodule ElixirScript.Translate.Function do
8597 ] )
8698 )
8799
100+ function_dec = J . function_declaration (
101+ ElixirScript.Translate.Identifier . make_function_name ( name ) ,
102+ [ J . rest_element ( J . identifier ( "__function_args__" ) ) ] ,
103+ [ ] ,
104+ J . block_statement ( [
105+ function_recur_dec ,
106+ J . return_statement (
107+ trampoline ( )
108+ )
109+ ] )
110+ )
111+
88112 { function_dec , state }
89113 end
90114
@@ -132,6 +156,7 @@ defmodule ElixirScript.Translate.Function do
132156
133157 body = body
134158 |> Clause . return_last_statement
159+ |> update_last_call ( state )
135160
136161 declarator = J . variable_declarator (
137162 J . array_expression ( params ) ,
@@ -168,4 +193,70 @@ defmodule ElixirScript.Translate.Function do
168193
169194 { ast , state }
170195 end
196+
197+ defp update_last_call ( clause_body , % { function: { name , _ } } ) do
198+ last_item = List . last ( clause_body )
199+ function_name = ElixirScript.Translate.Identifier . make_function_name ( name )
200+
201+ case last_item do
202+ % ESTree.ReturnStatement { argument: % ESTree.CallExpression { callee: ^ function_name , arguments: arguments } } ->
203+ new_last_item = J . return_statement (
204+ recurse (
205+ recur_bind ( arguments )
206+ )
207+ )
208+
209+ List . replace_at ( clause_body , length ( clause_body ) - 1 , new_last_item )
210+ _ ->
211+ clause_body
212+ end
213+ end
214+
215+ defp recur_bind ( args ) do
216+ J . call_expression (
217+ J . member_expression (
218+ J . identifier ( "recur" ) ,
219+ J . identifier ( "bind" )
220+ ) ,
221+ [ J . identifier ( "null" ) ] ++ args
222+ )
223+ end
224+
225+ defp recurse ( func ) do
226+ J . new_expression (
227+ J . member_expression (
228+ J . member_expression (
229+ J . identifier ( "ElixirScript" ) ,
230+ J . member_expression (
231+ J . identifier ( "Core" ) ,
232+ J . identifier ( "Functions" )
233+ )
234+ ) ,
235+ J . identifier ( "Recurse" )
236+ ) ,
237+ [
238+ func
239+ ]
240+ )
241+ end
242+
243+ defp trampoline ( ) do
244+ J . call_expression (
245+ J . member_expression (
246+ J . member_expression (
247+ J . identifier ( "ElixirScript" ) ,
248+ J . member_expression (
249+ J . identifier ( "Core" ) ,
250+ J . identifier ( "Functions" )
251+ )
252+ ) ,
253+ J . identifier ( "trampoline" )
254+ ) ,
255+ [
256+ recurse (
257+ recur_bind ( [ J . rest_element ( J . identifier ( "__function_args__" ) ) ] )
258+ )
259+ ]
260+ )
261+ end
171262end
0 commit comments