on master help sign in
javascript: tailcalls
e1898cbraichoo
src/IRTS/CodegenJavaScript.hs+53−16
@@ -26,15 +26,28 @@ codegenJavaScript
26 -> FilePath
26 -> FilePath
27 -> OutputType
27 -> OutputType
28 -> IO ()
28 -> IO ()
29−codegenJavaScript definitions filename outputType = do
29+codegenJavaScript definitions filename outputType =
30− let def = map (first translateNamespace) definitions
31− let output = idrRuntime ++ concatMap (translateModule Nothing) def ++ "\nMain.main()"
32 writeFile filename output
30 writeFile filename output
31+ where
32+ def = map (first translateNamespace) definitions
33+
34+ mainLoop :: String
35+ mainLoop = intercalate "\n" [ "\nfunction main() {"
36+ , createTrampoline "Main.main()" ++ ";"
37+ , "}\n\nmain();\n"
38+ ]
39+
40+ output :: String
41+ output = concat [ idrRuntime
42+ , concatMap (translateModule Nothing) def
43+ , mainLoop
44+ ]
33
45
34idrRuntime :: String
46idrRuntime :: String
35idrRuntime =
47idrRuntime =
36 createModule Nothing idrNamespace $ concat
48 createModule Nothing idrNamespace $ concat
37 [ "__IDR__.IntType = { type: 'IntType' };"
49 [ "__IDR__.IntType = { type: 'IntType' };"
50+ , "__IDR__.Tailcall = function(f) { this.f = f };"
38 , "__IDR__.Con = function(i,name,vars)"
51 , "__IDR__.Con = function(i,name,vars)"
39 , "{this.i = i;this.name = name;this.vars = vars;};"
52 , "{this.i = i;this.name = name;this.vars = vars;};"
40 ]
53 ]
@@ -165,13 +178,16 @@ translateExpression _ (SConst cst) =
165translateExpression _ (SV var) =
178translateExpression _ (SV var) =
166 translateVariableName var
179 translateVariableName var
167
180
168−translateExpression modname (SApp tc name vars) =
181+translateExpression modname (SApp False name vars) =
169− concat (intersperse "." $ translateNamespace name)
182+ createTrampoline $ translateFunctionCall name vars
170− ++ "."
183+
171− ++ translateName name
184+translateExpression modname (SApp True name vars) =
185+ "(function(){\n"
186+ ++ "throw new __IDR__.Tailcall("
172− ++ "("
187+ ++ "function(){\n"
173− ++ intercalate "," (map translateVariableName vars)
188+ ++ "return " ++ translateFunctionCall name vars
189+ ++ ";\n});"
174− ++ ")"
190+ ++ "\n})()"
175
191
176translateExpression _ (SOp op vars)
192translateExpression _ (SOp op vars)
177 | LPlus <- op
193 | LPlus <- op
@@ -284,14 +300,10 @@ translateExpression _ (SCon i name vars) =
284 ]
300 ]
285
301
286translateExpression modname (SUpdate var e) =
302translateExpression modname (SUpdate var e) =
287− "(function(){\nreturn ("
288− ++ translateVariableName var
289− ++ " = " ++ translateExpression modname e
303+ translateVariableName var ++ " = " ++ translateExpression modname e
290− ++ ");\n})()"
291
304
292translateExpression modname (SProj var i) =
305translateExpression modname (SProj var i) =
293− "(function(){\nreturn "
294− ++ translateVariableName var ++ ".vars[" ++ show i ++"];\n})()"
306+ translateVariableName var ++ ".vars[" ++ show i ++"]"
295
307
296translateExpression _ SNothing = "null"
308translateExpression _ SNothing = "null"
297
309
@@ -324,3 +336,28 @@ createIfBlock cond e =
324 "if (" ++ cond ++") {\n"
336 "if (" ++ cond ++") {\n"
325 ++ "return " ++ e
337 ++ "return " ++ e
326 ++ ";\n}"
338 ++ ";\n}"
339+
340+createTrampoline call =
341+ "(function(){\n"
342+ ++ "var __f = function(){return " ++ call ++ "};\n"
343+ ++ "while (__f) {\ntry {\n"
344+ ++ "var f = __f;\n"
345+ ++ "__f = null;\n"
346+ ++ "return f();"
347+ ++ "\n} catch(ex) {\n"
348+ ++ "if (ex instanceof __IDR__.Tailcall) {\n"
349+ ++ "__f = ex.f;"
350+ ++ "\n} else {\n"
351+ ++ "throw ex;"
352+ ++ "\n}"
353+ ++ "\n}"
354+ ++ "\n}"
355+ ++ "\n})()"
356+
357+translateFunctionCall name vars =
358+ concat (intersperse "." $ translateNamespace name)
359+ ++ "."
360+ ++ translateName name
361+ ++ "("
362+ ++ intercalate "," (map translateVariableName vars)
363+ ++ ")"