on master help sign in
Merge pull request #1328 from raichoo/javascript

New JavaScript Backend

commit2fafe80f6fd0ff554b41ebd3e6c8930f01998543 authorraichoo <raichoo@googlemail.com> dateWed 25 Jun 2014, 09:53 (12 years ago) parent18c33c5464a4b9
4 files changed+1271−2367
jsrts/Runtime-browser.js+9−9 jsrts/Runtime-common.js+78−37 jsrts/Runtime-node.js+8−8 src/IRTS/CodegenJavaScript.hs+1176−2313
jsrts/Runtime-browser.js+9−9
@@ -1,14 +1,14 @@
1−var __IDRRT__print = function(s) {
1+var i$putStr = function(s) {
22 console.log(s);
33};
44
55
6−var __IDRRT__systemInfo = function(index) {
7− switch(index) {
8− case 0:
9− return "javascript";
10− case 1:
11− return navigator.platform;
12− }
13− return "";
6+var i$systemInfo = function(index) {
7+ switch(index) {
8+ case 0:
9+ return "javascript";
10+ case 1:
11+ return navigator.platform;
12+ }
13+ return "";
1414}
jsrts/Runtime-common.js+78−37
@@ -1,51 +1,92 @@
11/** @constructor */
2−var __IDRRT__Type = function(type) {
3− this.type = type;
4−};
5−
6−var __IDRRT__Int = new __IDRRT__Type('Int');
7−var __IDRRT__Char = new __IDRRT__Type('Char');
8−var __IDRRT__String = new __IDRRT__Type('String');
9−var __IDRRT__Integer = new __IDRRT__Type('Integer');
10−var __IDRRT__Float = new __IDRRT__Type('Float');
11−var __IDRRT__Ptr = new __IDRRT__Type('Pointer');
12−var __IDRRT__Forgot = new __IDRRT__Type('Forgot');
13−
14−var __IDRRT__ffiWrap = function(fid) {
15− return function(){
2+var i$VM = function() {
3+ this.valstack = [];
4+ this.valstack_top = 0;
5+ this.valstack_base = 0;
6+
7+ this.ret = null;
8+ this.reg1 = null;
9+
10+ this.callstack = [];
11+}
12+
13+var i$vm;
14+var i$valstack;
15+var i$valstack_top;
16+var i$valstack_base;
17+var i$ret;
18+var i$callstack;
19+
20+/** @constructor */
21+var i$CON = function(tag,args,app,ev) {
22+ this.tag = tag;
23+ this.args = args;
24+ this.app = app;
25+ this.ev = ev;
26+}
27+
28+var i$SCHED = function(vm) {
29+ i$vm = vm;
30+ i$valstack = vm.valstack;
31+ i$valstack_top = vm.valstack_top;
32+ i$valstack_base = vm.valstack_base;
33+ i$ret = vm.ret;
34+ i$callstack = vm.callstack;
35+}
36+
37+var i$SLIDE = function(args) {
38+ for (var i = 0; i < args; ++i)
39+ i$valstack[i$valstack_base + i] = i$valstack[i$valstack_top + i];
40+}
41+
42+var i$PROJECT = function(val,loc,arity) {
43+ for (var i = 0; i < arity; ++i)
44+ i$valstack[i$valstack_base + i + loc] = val.args[i];
45+}
46+
47+var i$CALL = function(fun,args) {
48+ i$callstack.push(args);
49+ i$callstack.push(fun);
50+}
51+
52+var i$ffiWrap = function(fid,oldbase,myoldbase) {
53+ return function() {
54+ i$callstack = [];
55+
1656 var res = fid;
17− var i = 0;
18− var arg;
19− while (res instanceof __IDRRT__Con){
20− arg = arguments[i];
21− res = __IDRRT__tailcall(function(){
22− return __IDR__mAPPLY0(res, arg);
23− });
24− ++i;
57+
58+ for(var i = 0; i < arguments.length; ++i) {
59+ while (res instanceof i$CON) {
60+ i$valstack_top += 1;
61+ i$valstack[i$valstack_top] = res;
62+ i$valstack[i$valstack_top + 1] = arguments[i];
63+ i$SLIDE(2);
64+ i$valstack_top = i$valstack_base + 2;
65+ i$CALL(_idris__123_APPLY0_125_,[oldbase])
66+ while (i$callstack.length) {
67+ var func = i$callstack.pop();
68+ var args = i$callstack.pop();
69+ func.apply(this,args);
70+ }
71+ res = i$ret;
72+ }
2573 }
26− return res;
27− }
28−};
2974
30−var __IDRRT__tailcall = function(k) {
31− var ret = k();
32− while (ret instanceof __IDRRT__Cont)
33− ret = ret.k();
75+ i$callstack = i$vm.callstack;
3476
35− return ret;
36−};
77+ return i$ret;
78+ }
79+}
3780
38−var __IDRRT__charCode = function(str) {
39− var type = typeof str;
40− if (type == "string")
81+var i$charCode = function(str) {
82+ if (typeof str == "string")
4183 return str.charCodeAt(0);
4284 else
4385 return str;
4486}
4587
46−var __IDRRT__fromCharCode = function(chr) {
47− var type = typeof chr;
48− if (type == "string")
88+var i$fromCharCode = function(chr) {
89+ if (typeof chr == "string")
4990 return chr;
5091 else
5192 return String.fromCharCode(chr);
jsrts/Runtime-node.js+8−8
@@ -1,17 +1,17 @@
1−var __IDRRT__print = (function() {
1+var i$putStr = (function() {
22 var util = require('util');
33 return function(s) {
44 util.print(s);
55 };
66})();
77
8−var __IDRRT__systemInfo = function(index) {
9− var os = require('os')
8+var i$systemInfo = function(index) {
9+ var os = require('os')
1010 switch(index) {
11− case 0:
12− return "node";
13− case 1:
14− return os.platform();
11+ case 0:
12+ return "node";
13+ case 1:
14+ return os.platform();
1515 }
16− return "";
16+ return "";
1717}
src/IRTS/CodegenJavaScript.hs+1176−2313
@@ -1,5 +1,4 @@
11{-# LANGUAGE PatternGuards #-}
2−
32module IRTS.CodegenJavaScript (codegenJavaScript, codegenNode, JSTarget(..)) where
43
54import Idris.AbsSyntax hiding (TypeCase)
@@ -12,12 +11,15 @@ import Paths_idris
1211import Util.System
1312
1413import Control.Arrow
14+import Control.Monad (mapM)
1515import Control.Applicative ((<$>), (<*>), pure)
16+import Control.Monad.RWS hiding (mapM)
1617import Data.Char
1718import Numeric
1819import Data.List
1920import Data.Maybe
2021import Data.Word
22+import Data.Traversable hiding (mapM)
2123import System.IO
2224import System.Directory
2325
@@ -28,6 +30,30 @@ idrRTNamespace = "__IDRRT__"
2830idrLTNamespace = "__IDRLT__"
2931idrCTRNamespace = "__IDRCTR__"
3032
33+data CompileInfo = CompileInfo { compileInfoApplyCases :: [Int]
34+ , compileInfoEvalCases :: [Int]
35+ }
36+
37+
38+initCompileInfo :: [(Name, [BC])] -> CompileInfo
39+initCompileInfo bc =
40+ CompileInfo (collectCases "APPLY" bc) (collectCases "EVAL" bc)
41+ where
42+ collectCases :: String -> [(Name, [BC])] -> [Int]
43+ collectCases fun bc = getCases $ findFunction fun bc
44+
45+ findFunction :: String -> [(Name, [BC])] -> [BC]
46+ findFunction f ((MN 0 fun, bc):_)
47+ | fun == txt f = bc
48+ findFunction f (_:bc) = findFunction f bc
49+
50+ getCases :: [BC] -> [Int]
51+ getCases = concatMap analyze
52+ where
53+ analyze :: BC -> [Int]
54+ analyze (CASE _ _ b _) = map fst b
55+ analyze _ = []
56+
3157
3258data JSTarget = Node | JavaScript deriving Eq
3359
@@ -45,6 +71,7 @@ data JSType = JSIntTy
4571data JSInteger = JSBigZero
4672 | JSBigOne
4773 | JSBigInt Integer
74+ | JSBigIntExpr JS
4875 deriving Eq
4976
5077
@@ -81,8 +108,8 @@ data JS = JSRaw String
81108 | JSPreOp String JS
82109 | JSPostOp String JS
83110 | JSProj JS String
84− | JSVar LVar
85111 | JSNull
112+ | JSUndefined
86113 | JSThis
87114 | JSTrue
88115 | JSFalse
@@ -93,6 +120,7 @@ data JS = JSRaw String
93120 | JSAssign JS JS
94121 | JSAlloc String (Maybe JS)
95122 | JSIndex JS JS
123+ | JSSwitch JS [(JS, JS)] (Maybe JS)
96124 | JSCond [(JS, JS)]
97125 | JSTernary JS JS JS
98126 | JSParens JS
@@ -105,7 +133,6 @@ data JS = JSRaw String
105133
106134data FFI = FFICode Char | FFIArg Int | FFIError String
107135
108−
109136ffi :: String -> [String] -> String
110137ffi code args = let parsed = ffiParse code in
111138 case ffiError parsed of
@@ -137,30 +164,32 @@ ffi code args = let parsed = ffiParse code in
137164 | i < length args && i >= 0 = args !! i ++ renderFFI fs args
138165 | otherwise = error "FFI - Argument index out of bounds"
139166
140−
141167compileJS :: JS -> String
142−compileJS JSNoop = ""
168+compileJS = compileJS' 0
143169
144−compileJS (JSAnnotation annotation js) =
145− "/** @" ++ show annotation ++ " */\n" ++ compileJS js
170+compileJS' :: Int -> JS -> String
171+compileJS' indent JSNoop = ""
146172
147−compileJS (JSFFI raw args) =
148− ffi raw (map compileJS args)
173+compileJS' indent (JSAnnotation annotation js) =
174+ "/** @" ++ show annotation ++ " */\n" ++ compileJS' indent js
149175
150−compileJS (JSRaw code) =
176+compileJS' indent (JSFFI raw args) =
177+ ffi raw (map (compileJS' indent) args)
178+
179+compileJS' indent (JSRaw code) =
151180 code
152181
153−compileJS (JSIdent ident) =
182+compileJS' indent (JSIdent ident) =
154183 ident
155184
156−compileJS (JSFunction args body) =
157− "function("
185+compileJS' indent (JSFunction args body) =
186+ replicate indent ' ' ++ "function("
158187 ++ intercalate "," args
159188 ++ "){\n"
160− ++ compileJS body
161− ++ "\n}"
189+ ++ compileJS' (indent + 2) body
190+ ++ "\n}\n"
162191
163−compileJS (JSType ty)
192+compileJS' indent (JSType ty)
164193 | JSIntTy <- ty = idrRTNamespace ++ "Int"
165194 | JSStringTy <- ty = idrRTNamespace ++ "String"
166195 | JSIntegerTy <- ty = idrRTNamespace ++ "Integer"
@@ -169,2473 +198,1307 @@ compileJS (JSType ty)
169198 | JSPtrTy <- ty = idrRTNamespace ++ "Ptr"
170199 | JSForgotTy <- ty = idrRTNamespace ++ "Forgot"
171200
172−compileJS (JSSeq seq) =
173− intercalate ";\n" (map compileJS seq)
201+compileJS' indent (JSSeq seq) =
202+ intercalate ";\n" (
203+ map (
204+ ((replicate indent ' ') ++) . (compileJS' indent)
205+ ) $ filter (/= JSNoop) seq
206+ ) ++ ";"
174207
175−compileJS (JSReturn val) =
176− "return " ++ compileJS val
208+compileJS' indent (JSReturn val) =
209+ "return " ++ compileJS' indent val
177210
178−compileJS (JSApp lhs rhs)
211+compileJS' indent (JSApp lhs rhs)
179212 | JSFunction {} <- lhs =
180− concat ["(", compileJS lhs, ")(", args, ")"]
213+ concat ["(", compileJS' indent lhs, ")(", args, ")"]
181214 | otherwise =
182− concat [compileJS lhs, "(", args, ")"]
215+ concat [compileJS' indent lhs, "(", args, ")"]
183216 where args :: String
184− args = intercalate "," $ map compileJS rhs
217+ args = intercalate "," $ map (compileJS' 0) rhs
185218
186−compileJS (JSNew name args) =
187− "new " ++ name ++ "(" ++ intercalate "," (map compileJS args) ++ ")"
219+compileJS' indent (JSNew name args) =
220+ "new " ++ name ++ "(" ++ intercalate "," (map (compileJS' 0) args) ++ ")"
188221
189−compileJS (JSError exc) =
222+compileJS' indent (JSError exc) =
190223 "throw new Error(\"" ++ exc ++ "\")"
191224
192−compileJS (JSBinOp op lhs rhs) =
193− compileJS lhs ++ " " ++ op ++ " " ++ compileJS rhs
225+compileJS' indent (JSBinOp op lhs rhs) =
226+ compileJS' indent lhs ++ " " ++ op ++ " " ++ compileJS' indent rhs
194227
195−compileJS (JSPreOp op val) =
196− op ++ compileJS val
228+compileJS' indent (JSPreOp op val) =
229+ op ++ compileJS' indent val
197230
198−compileJS (JSProj obj field)
231+compileJS' indent (JSProj obj field)
199232 | JSFunction {} <- obj =
200− concat ["(", compileJS obj, ").", field]
233+ concat ["(", compileJS' indent obj, ").", field]
201234 | JSAssign {} <- obj =
202− concat ["(", compileJS obj, ").", field]
235+ concat ["(", compileJS' indent obj, ").", field]
203236 | otherwise =
204− compileJS obj ++ '.' : field
205−
206−compileJS (JSVar var) =
207− translateVariableName var
237+ compileJS' indent obj ++ '.' : field
208238
209−compileJS JSNull =
239+compileJS' indent JSNull =
210240 "null"
211241
212−compileJS JSThis =
242+compileJS' indent JSUndefined =
243+ "undefined"
244+
245+compileJS' indent JSThis =
213246 "this"
214247
215−compileJS JSTrue =
248+compileJS' indent JSTrue =
216249 "true"
217250
218−compileJS JSFalse =
251+compileJS' indent JSFalse =
219252 "false"
220253
221−compileJS (JSArray elems) =
222− "[" ++ intercalate "," (map compileJS elems) ++ "]"
254+compileJS' indent (JSArray elems) =
255+ "[" ++ intercalate "," (map (compileJS' 0) elems) ++ "]"
223256
224−compileJS (JSString str) =
257+compileJS' indent (JSString str) =
225258 "\"" ++ str ++ "\""
226259
227−compileJS (JSNum num)
228− | JSInt i <- num = show i
229− | JSFloat f <- num = show f
230− | JSInteger JSBigZero <- num = "__IDRRT__ZERO"
231− | JSInteger JSBigOne <- num = "__IDRRT__ONE"
232− | JSInteger (JSBigInt i) <- num = show i
260+compileJS' indent (JSNum num)
261+ | JSInt i <- num = show i
262+ | JSFloat f <- num = show f
263+ | JSInteger JSBigZero <- num = "__IDRRT__ZERO"
264+ | JSInteger JSBigOne <- num = "__IDRRT__ONE"
265+ | JSInteger (JSBigInt i) <- num = show i
266+ | JSInteger (JSBigIntExpr e) <- num = "__IDRRT__bigInt(" ++ compileJS' indent e ++ ")"
233267
234−compileJS (JSAssign lhs rhs) =
235− compileJS lhs ++ "=" ++ compileJS rhs
268+compileJS' indent (JSAssign lhs rhs) =
269+ compileJS' indent lhs ++ " = " ++ compileJS' indent rhs
236270
237−compileJS (JSAlloc name val) =
238− "var " ++ name ++ maybe "" ((" = " ++) . compileJS) val
271+compileJS' indent (JSAlloc name val) =
272+ "var " ++ name ++ maybe "" ((" = " ++) . compileJS' indent) val
239273
240−compileJS (JSIndex lhs rhs) =
241− compileJS lhs ++ "[" ++ compileJS rhs ++ "]"
274+compileJS' indent (JSIndex lhs rhs) =
275+ compileJS' indent lhs ++ "[" ++ compileJS' indent rhs ++ "]"
242276
243−compileJS (JSCond branches) =
277+compileJS' indent (JSCond branches) =
244278 intercalate " else " $ map createIfBlock branches
245279 where
280+ createIfBlock (JSNoop, e@(JSSeq _)) =
281+ "{\n"
282+ ++ compileJS' (indent + 2) e
283+ ++ "\n" ++ replicate indent ' ' ++ "}"
246284 createIfBlock (JSNoop, e) =
247285 "{\n"
248− ++ compileJS e
249− ++ ";\n}"
286+ ++ compileJS' (indent + 2) e
287+ ++ ";\n" ++ replicate indent ' ' ++ "}"
288+ createIfBlock (cond, e@(JSSeq _)) =
289+ "if (" ++ compileJS' indent cond ++") {\n"
290+ ++ compileJS' (indent + 2) e
291+ ++ "\n" ++ replicate indent ' ' ++ "}"
250292 createIfBlock (cond, e) =
251− "if (" ++ compileJS cond ++") {\n"
252− ++ compileJS e
253− ++ ";\n}"
254−
255−compileJS (JSTernary cond true false) =
256− let c = compileJS cond
257− t = compileJS true
258− f = compileJS false in
293+ "if (" ++ compileJS' indent cond ++") {\n"
294+ ++ replicate (indent + 2) ' ' ++ compileJS' (indent + 2) e
295+ ++ ";\n" ++ replicate indent ' ' ++ "}"
296+
297+compileJS' indent (JSSwitch val [(_,seq)] Nothing) =
298+ compileJS' indent seq
299+
300+compileJS' indent (JSSwitch val branches def) =
301+ "switch(" ++ compileJS' indent val ++ "){\n"
302+ ++ concatMap mkBranch branches
303+ ++ mkDefault def
304+ ++ (replicate indent ' ') ++ "}"
305+ where
306+ mkBranch :: (JS, JS) -> String
307+ mkBranch (tag, code) =
308+ replicate (indent + 2) ' ' ++ "case " ++ compileJS' indent tag ++ ":\n"
309+ ++ compileJS' (indent + 4) code
310+ ++ "\n" ++ (replicate (indent + 4) ' ' ++ "break;\n")
311+
312+ mkDefault :: Maybe JS -> String
313+ mkDefault Nothing = ""
314+ mkDefault (Just def) =
315+ replicate (indent + 2) ' ' ++ "default:\n"
316+ ++ compileJS' (indent + 4)def
317+ ++ "\n"
318+
319+
320+compileJS' indent (JSTernary cond true false) =
321+ let c = compileJS' indent cond
322+ t = compileJS' indent true
323+ f = compileJS' indent false in
259324 "(" ++ c ++ ")?(" ++ t ++ "):(" ++ f ++ ")"
260325
261−compileJS (JSParens js) =
262− "(" ++ compileJS js ++ ")"
326+compileJS' indent (JSParens js) =
327+ "(" ++ compileJS' indent js ++ ")"
263328
264−compileJS (JSWhile cond body) =
265− "while (" ++ compileJS cond ++ ") {\n"
266− ++ compileJS body
267− ++ "\n}"
329+compileJS' indent (JSWhile cond body) =
330+ "while (" ++ compileJS' indent cond ++ ") {\n"
331+ ++ compileJS' (indent + 2) body
332+ ++ "\n" ++ replicate indent ' ' ++ "}"
268333
269−compileJS (JSWord word)
334+compileJS' indent (JSWord word)
270335 | JSWord8 b <- word = "new Uint8Array([" ++ show b ++ "])"
271336 | JSWord16 b <- word = "new Uint16Array([" ++ show b ++ "])"
272337 | JSWord32 b <- word = "new Uint32Array([" ++ show b ++ "])"
273338 | JSWord64 b <- word = idrRTNamespace ++ "bigInt(\"" ++ show b ++ "\")"
274339
340+codegenJavaScript :: CodeGenerator
341+codegenJavaScript ci = codegenJS_all JavaScript (simpleDecls ci)
342+ (includes ci) (outputFile ci) (outputType ci)
275343
276−jsTailcall :: JS -> JS
277−jsTailcall call =
278− jsCall (idrRTNamespace ++ "tailcall") [
279− JSFunction [] (JSReturn call)
280− ]
281−
282−
283−jsCall :: String -> [JS] -> JS
284−jsCall fun = JSApp (JSIdent fun)
285−
286−
287−jsMeth :: JS -> String -> [JS] -> JS
288−jsMeth obj meth =
289− JSApp (JSProj obj meth)
290−
291−
292−jsInstanceOf :: JS -> JS -> JS
293−jsInstanceOf = JSBinOp "instanceof"
294−
295−
296−jsEq :: JS -> JS -> JS
297−jsEq = JSBinOp "=="
298−
299−jsNotEq :: JS -> JS -> JS
300−jsNotEq = JSBinOp "!="
301−
302−jsAnd :: JS -> JS -> JS
303−jsAnd = JSBinOp "&&"
304−
305−
306−jsOr :: JS -> JS -> JS
307−jsOr = JSBinOp "||"
308−
309−
310−jsType :: JS
311−jsType = JSIdent $ idrRTNamespace ++ "Type"
312−
313−
314−jsCon :: JS
315−jsCon = JSIdent $ idrRTNamespace ++ "Con"
316−
317−
318−jsTag :: JS -> JS
319−jsTag obj = JSProj obj "tag"
320−
321−
322−jsTypeTag :: JS -> JS
323−jsTypeTag obj = JSProj obj "type"
324−
344+codegenNode :: CodeGenerator
345+codegenNode ci = codegenJS_all Node (simpleDecls ci)
346+ (includes ci) (outputFile ci) (outputType ci)
325347
326−jsBigInt :: JS -> JS
327−jsBigInt (JSString "0") = JSNum $ JSInteger JSBigZero
328−jsBigInt (JSString "1") = JSNum $ JSInteger JSBigOne
329−jsBigInt val = JSApp (JSIdent $ idrRTNamespace ++ "bigInt") [val]
348+codegenJS_all
349+ :: JSTarget
350+ -> [(Name, SDecl)]
351+ -> [FilePath]
352+ -> FilePath
353+ -> OutputType
354+ -> IO ()
355+codegenJS_all target definitions includes filename outputType = do
356+ let bytecode = map toBC definitions
357+ let info = initCompileInfo bytecode
358+ let js = concatMap (translateDecl info) bytecode
359+ let code = concatMap ((map compileJS) . collectSplitFunctions . (\x -> evalRWS (splitFunction x) () 0)) js
360+ let (header, rt) = case target of
361+ Node -> ("#!/usr/bin/env node\n", "-node")
362+ JavaScript -> ("", "-browser")
330363
364+ included <- concat <$> getIncludes includes
365+ path <- (++) <$> getDataDir <*> (pure "/jsrts/")
366+ idrRuntime <- readFile $ path ++ "Runtime-common.js"
367+ tgtRuntime <- readFile $ concat [path, "Runtime", rt, ".js"]
368+ jsbn <- readFile $ path ++ "jsbn/jsbn.js"
369+ let runtime = header ++ included ++ jsbn ++ idrRuntime ++ tgtRuntime
370+ writeFile filename $ runtime ++ concat code ++ main ++ invokeMain
371+ setPermissions filename (emptyPermissions { readable = True
372+ , executable = target == Node
373+ , writable = True
374+ })
375+ where
376+ getIncludes :: [FilePath] -> IO [String]
377+ getIncludes = mapM readFile
378+
379+ main :: String
380+ main =
381+ compileJS $ JSAlloc "main" (Just $
382+ JSFunction [] (
383+ case target of
384+ Node -> mainFun
385+ JavaScript -> jsMain
386+ )
387+ )
331388
332−jsVar :: Int -> String
333−jsVar = ("__var_" ++) . show
389+ jsMain :: JS
390+ jsMain =
391+ JSCond [ (exists document `jsAnd` isReady, mainFun)
392+ , (exists window, windowMainFun)
393+ , (JSTrue, mainFun)
394+ ]
395+ where
396+ exists :: JS -> JS
397+ exists js = jsTypeOf js `jsNotEq` JSString "undefined"
398+
399+ window :: JS
400+ window = JSIdent "window"
401+
402+ document :: JS
403+ document = JSIdent "document"
404+
405+ windowMainFun :: JS
406+ windowMainFun =
407+ jsMeth window "addEventListener" [ JSString "DOMContentLoaded"
408+ , JSFunction [] ( mainFun )
409+ , JSFalse
410+ ]
411+
412+ isReady :: JS
413+ isReady = JSParens $ readyState `jsEq` JSString "complete" `jsOr` readyState `jsEq` JSString "loaded"
414+
415+ readyState :: JS
416+ readyState = JSProj (JSIdent "document") "readyState"
417+
418+ mainFun :: JS
419+ mainFun =
420+ JSSeq [ JSAlloc "vm" (Just $ JSNew "i$VM" [])
421+ , JSApp (JSIdent "i$SCHED") [JSIdent "vm"]
422+ , JSApp (
423+ JSIdent (translateName (sMN 0 "runMain"))
424+ ) [JSNum (JSInt 0)]
425+ , JSWhile (JSProj jsCALLSTACK "length") (
426+ JSSeq [ JSAlloc "func" (Just jsPOP)
427+ , JSAlloc "args" (Just jsPOP)
428+ , JSApp (JSProj (JSIdent "func") "apply") [JSThis, JSIdent "args"]
429+ ]
430+ )
431+ ]
334432
433+ invokeMain :: String
434+ invokeMain = compileJS $ JSApp (JSIdent "main") []
335435
336−jsLet :: String -> JS -> JS -> JS
337−jsLet name value body =
338− JSApp (
339− JSFunction [name] (
340− JSReturn body
341− )
342− ) [value]
436+collectSplitFunctions :: (JS, [(Int,JS)]) -> [JS]
437+collectSplitFunctions (fun, splits) = map generateSplitFunction splits ++ [fun]
438+ where
439+ generateSplitFunction :: (Int,JS) -> JS
440+ generateSplitFunction (depth, JSAlloc name fun) =
441+ JSAlloc (name ++ "$" ++ show depth) fun
442+
443+splitFunction :: JS -> RWS () [(Int,JS)] Int JS
444+splitFunction (JSAlloc name (Just (JSFunction args body@(JSSeq _)))) = do
445+ body' <- splitSequence body
446+ return $ JSAlloc name (Just (JSFunction args body'))
447+ where
448+ splitCondition :: JS -> RWS () [(Int,JS)] Int JS
449+ splitCondition js
450+ | JSCond branches <- js =
451+ JSCond <$> processBranches branches
452+ | JSSwitch cond branches def <- js =
453+ JSSwitch cond <$> (processBranches branches) <*> (traverse splitSequence def)
454+ | otherwise = return js
455+ where
456+ processBranches :: [(JS,JS)] -> RWS () [(Int,JS)] Int [(JS,JS)]
457+ processBranches =
458+ traverse (runKleisli (arr id *** (Kleisli splitSequence)))
459+
460+ splitSequence :: JS -> RWS () [(Int, JS)] Int JS
461+ splitSequence js@(JSSeq seq) = do
462+ let (pre,post) = break isCall seq in
463+ case post of
464+ [] -> JSSeq <$> traverse splitCondition seq
465+ [js@(JSCond _)] -> splitCondition js
466+ [js@(JSSwitch _ _ _)] -> splitCondition js
467+ [_] -> return js
468+ (call:rest) -> do
469+ depth <- get
470+ put (depth + 1)
471+ new <- splitFunction (newFun rest)
472+ tell [(depth, new)]
473+ return $ JSSeq (pre ++ (newCall depth : [call]))
474+
475+ splitSequence js = return js
476+
477+ isCall :: JS -> Bool
478+ isCall (JSApp (JSIdent "i$CALL") _) = True
479+ isCall _ = False
480+
481+ newCall :: Int -> JS
482+ newCall depth =
483+ JSApp (JSIdent "i$CALL") [ JSIdent $ name ++ "$" ++ show depth
484+ , JSArray [jsOLDBASE, jsMYOLDBASE]
485+ ]
486+
487+ newFun :: [JS] -> JS
488+ newFun seq =
489+ JSAlloc name (Just $ JSFunction ["oldbase", "myoldbase"] (JSSeq seq))
490+
491+splitFunction js = return js
492+
493+translateDecl :: CompileInfo -> (Name, [BC]) -> [JS]
494+translateDecl info (name@(MN 0 fun), bc)
495+ | txt "APPLY" == fun =
496+ allocCaseFunctions (snd body)
497+ ++ [ JSAlloc (
498+ translateName name
499+ ) (Just $ JSFunction ["oldbase"] (
500+ JSSeq $ JSAlloc "myoldbase" Nothing : map (translateBC info) (fst body) ++ [
501+ JSCond [ ( (translateReg $ caseReg (snd body)) `jsInstanceOf` "i$CON" `jsAnd` (JSProj (translateReg $ caseReg (snd body)) "app")
502+ , JSApp (JSProj (translateReg $ caseReg (snd body)) "app") [jsOLDBASE, jsMYOLDBASE]
503+ )
504+ , ( JSNoop
505+ , JSSeq $ map (translateBC info) (defaultCase (snd body))
506+ )
507+ ]
508+ ]
509+ )
510+ )
511+ ]
512+
513+ | txt "EVAL" == fun =
514+ allocCaseFunctions (snd body)
515+ ++ [ JSAlloc (
516+ translateName name
517+ ) (Just $ JSFunction ["oldbase"] (
518+ JSSeq $ JSAlloc "myoldbase" Nothing : map (translateBC info) (fst body) ++ [
519+ JSCond [ ( (translateReg $ caseReg (snd body)) `jsInstanceOf` "i$CON" `jsAnd` (JSProj (translateReg $ caseReg (snd body)) "ev")
520+ , JSApp (JSProj (translateReg $ caseReg (snd body)) "ev") [jsOLDBASE, jsMYOLDBASE]
521+ )
522+ , ( JSNoop
523+ , JSSeq $ map (translateBC info) (defaultCase (snd body))
524+ )
525+ ]
526+ ]
527+ )
528+ )
529+ ]
530+ where
531+ body :: ([BC], [BC])
532+ body = break isCase bc
343533
534+ isCase :: BC -> Bool
535+ isCase bc
536+ | CASE _ _ _ _ <- bc = True
537+ | otherwise = False
344538
345−jsError :: String -> JS
346−jsError err = JSApp (JSFunction [] (JSError err)) []
539+ defaultCase :: [BC] -> [BC]
540+ defaultCase ((CASE _ _ _ (Just d)):_) = d
347541
348−jsUnPackBits :: JS -> JS
349−jsUnPackBits js = JSIndex js $ JSNum (JSInt 0)
542+ caseReg :: [BC] -> Reg
543+ caseReg ((CASE _ r _ _):_) = r
350544
545+ allocCaseFunctions :: [BC] -> [JS]
546+ allocCaseFunctions ((CASE _ _ c _):_) = splitBranches c
547+ allocCaseFunctions _ = []
351548
352−jsPackUBits8 :: JS -> JS
353−jsPackUBits8 js = JSNew "Uint8Array" [JSArray [js]]
549+ splitBranches :: [(Int, [BC])] -> [JS]
550+ splitBranches = map prepBranch
354551
355−jsPackUBits16 :: JS -> JS
356−jsPackUBits16 js = JSNew "Uint16Array" [JSArray [js]]
552+ prepBranch :: (Int, [BC]) -> JS
553+ prepBranch (tag, code) =
554+ JSAlloc (
555+ translateName name ++ "$" ++ show tag
556+ ) (Just $ JSFunction ["oldbase", "myoldbase"] (
557+ JSSeq $ map (translateBC info) code
558+ )
559+ )
357560
358−jsPackUBits32 :: JS -> JS
359−jsPackUBits32 js = JSNew "Uint32Array" [JSArray [js]]
561+translateDecl info (name, bc) =
562+ [ JSAlloc (
563+ translateName name
564+ ) (Just $ JSFunction ["oldbase"] (
565+ JSSeq $ JSAlloc "myoldbase" Nothing : map (translateBC info)bc
566+ )
567+ )
568+ ]
360569
361−jsPackSBits8 :: JS -> JS
362−jsPackSBits8 js = JSNew "Int8Array" [JSArray [js]]
363570
364−jsPackSBits16 :: JS -> JS
365−jsPackSBits16 js = JSNew "Int16Array" [JSArray [js]]
571+translateReg :: Reg -> JS
572+translateReg reg
573+ | RVal <- reg = jsRET
574+ | Tmp <- reg = JSProj (JSIdent "vm") "reg1"
575+ | L n <- reg = jsLOC n
576+ | T n <- reg = jsTOP n
366577
367−jsPackSBits32 :: JS -> JS
368−jsPackSBits32 js = JSNew "Int32Array" [JSArray [js]]
578+translateConstant :: Const -> JS
579+translateConstant (I i) = JSNum (JSInt i)
580+translateConstant (Fl f) = JSNum (JSFloat f)
581+translateConstant (Ch c) = JSString $ translateChar c
582+translateConstant (Str s) = JSString $ concatMap translateChar s
583+translateConstant (AType (ATInt ITNative)) = JSType JSIntTy
584+translateConstant StrType = JSType JSStringTy
585+translateConstant (AType (ATInt ITBig)) = JSType JSIntegerTy
586+translateConstant (AType ATFloat) = JSType JSFloatTy
587+translateConstant (AType (ATInt ITChar)) = JSType JSCharTy
588+translateConstant PtrType = JSType JSPtrTy
589+translateConstant Forgot = JSType JSForgotTy
590+translateConstant (BI 0) = JSNum (JSInteger JSBigZero)
591+translateConstant (BI 1) = JSNum (JSInteger JSBigOne)
592+translateConstant (BI i) = jsBigInt (JSString $ show i)
593+translateConstant (B8 b) = JSWord (JSWord8 b)
594+translateConstant (B16 b) = JSWord (JSWord16 b)
595+translateConstant (B32 b) = JSWord (JSWord32 b)
596+translateConstant (B64 b) = JSWord (JSWord64 b)
597+translateConstant c =
598+ JSError $ "Unimplemented Constant: " ++ show c
369599
370600
371−foldJS :: (JS -> a) -> (a -> a -> a) -> a -> JS -> a
372−foldJS tr add acc js =
373− fold js
374− where
375− fold js
376− | JSFunction args body <- js =
377− add (tr js) (fold body)
378− | JSSeq seq <- js =
379− add (tr js) $ foldl' add acc (map fold seq)
380− | JSReturn ret <- js =
381− add (tr js) (fold ret)
382− | JSApp lhs rhs <- js =
383− add (tr js) $ add (fold lhs) (foldl' add acc $ map fold rhs)
384− | JSNew _ args <- js =
385− add (tr js) $ foldl' add acc $ map fold args
386− | JSBinOp _ lhs rhs <- js =
387− add (tr js) $ add (fold lhs) (fold rhs)
388− | JSPreOp _ val <- js =
389− add (tr js) $ fold val
390− | JSPostOp _ val <- js =
391− add (tr js) $ fold val
392− | JSProj obj _ <- js =
393− add (tr js) (fold obj)
394− | JSArray vals <- js =
395− add (tr js) $ foldl' add acc $ map fold vals
396− | JSAssign lhs rhs <- js =
397− add (tr js) $ add (fold lhs) (fold rhs)
398− | JSIndex lhs rhs <- js =
399− add (tr js) $ add (fold lhs) (fold rhs)
400− | JSAlloc _ val <- js =
401− add (tr js) $ fromMaybe acc $ fmap fold val
402− | JSTernary c t f <- js =
403− add (tr js) $ add (fold c) (add (fold t) (fold f))
404− | JSParens val <- js =
405− add (tr js) $ fold val
406− | JSCond conds <- js =
407− add (tr js) $ foldl' add acc $ map (uncurry add . (fold *** fold)) conds
408− | JSWhile cond body <- js =
409− add (tr js) $ add (fold cond) (fold body)
410− | JSFFI raw args <- js =
411− add (tr js) $ foldl' add acc $ map fold args
412− | JSAnnotation a js <- js =
413− add (tr js) $ fold js
414− | otherwise =
415− tr js
416−
417−
418−transformJS :: (JS -> JS) -> JS -> JS
419−transformJS tr js =
420− transformHelper js
421− where
422− transformHelper :: JS -> JS
423− transformHelper js
424− | JSFunction args body <- js = JSFunction args $ tr body
425− | JSSeq seq <- js = JSSeq $ map tr seq
426− | JSReturn ret <- js = JSReturn $ tr ret
427− | JSApp lhs rhs <- js = JSApp (tr lhs) $ map tr rhs
428− | JSNew con args <- js = JSNew con $ map tr args
429− | JSBinOp op lhs rhs <- js = JSBinOp op (tr lhs) (tr rhs)
430− | JSPreOp op val <- js = JSPreOp op (tr val)
431− | JSPostOp op val <- js = JSPostOp op (tr val)
432− | JSProj obj field <- js = JSProj (tr obj) field
433− | JSArray vals <- js = JSArray $ map tr vals
434− | JSAssign lhs rhs <- js = JSAssign (tr lhs) (tr rhs)
435− | JSAlloc var val <- js = JSAlloc var $ fmap tr val
436− | JSIndex lhs rhs <- js = JSIndex (tr lhs) (tr rhs)
437− | JSCond conds <- js = JSCond $ map (tr *** tr) conds
438− | JSTernary c t f <- js = JSTernary (tr c) (tr t) (tr f)
439− | JSParens val <- js = JSParens $ tr val
440− | JSWhile cond body <- js = JSWhile (tr cond) (tr body)
441− | JSFFI raw args <- js = JSFFI raw (map tr args)
442− | JSAnnotation a js <- js = JSAnnotation a (tr js)
443− | otherwise = js
444−
445−
446−moveJSDeclToTop :: String -> [JS] -> [JS]
447−moveJSDeclToTop decl js = move ([], js)
601+translateChar :: Char -> String
602+translateChar ch
603+ | '\a' <- ch = "\\u0007"
604+ | '\b' <- ch = "\\b"
605+ | '\f' <- ch = "\\f"
606+ | '\n' <- ch = "\\n"
607+ | '\r' <- ch = "\\r"
608+ | '\t' <- ch = "\\t"
609+ | '\v' <- ch = "\\v"
610+ | '\SO' <- ch = "\\u000E"
611+ | '\DEL' <- ch = "\\u007F"
612+ | '\\' <- ch = "\\\\"
613+ | '\"' <- ch = "\\\""
614+ | '\'' <- ch = "\\\'"
615+ | ch `elem` asciiTab = "\\u00" ++ fill (showIntAtBase 16 intToDigit (ord ch) "")
616+ | otherwise = [ch]
448617 where
449− move :: ([JS], [JS]) -> [JS]
450− move (front, js@(JSAnnotation _ (JSAlloc name _)):back)
451− | name == decl = js : front ++ back
452−
453− move (front, js@(JSAlloc name _):back)
454− | name == decl = js : front ++ back
618+ fill :: String -> String
619+ fill s = if length s == 1
620+ then '0' : s
621+ else s
455622
456− move (front, js:back) =
457− move (front ++ [js], back)
623+ asciiTab =
624+ ['\NUL', '\SOH', '\STX', '\ETX', '\EOT', '\ENQ', '\ACK', '\BEL',
625+ '\BS', '\HT', '\LF', '\VT', '\FF', '\CR', '\SO', '\SI',
626+ '\DLE', '\DC1', '\DC2', '\DC3', '\DC4', '\NAK', '\SYN', '\ETB',
627+ '\CAN', '\EM', '\SUB', '\ESC', '\FS', '\GS', '\RS', '\US']
458628
629+translateName :: Name -> String
630+translateName n = "_idris_" ++ concatMap cchar (showCG n)
631+ where cchar x | isAlpha x || isDigit x = [x]
632+ | otherwise = "_" ++ show (fromEnum x) ++ "_"
459633
460−jsSubst :: JS -> JS -> JS -> JS
461−jsSubst var new old
462− | var == old = new
634+jsASSIGN :: CompileInfo -> Reg -> Reg -> JS
635+jsASSIGN _ r1 r2 = JSAssign (translateReg r1) (translateReg r2)
463636
464−jsSubst (JSIdent var) new (JSVar old)
465− | var == translateVariableName old = new
466− | otherwise = JSVar old
637+jsASSIGNCONST :: CompileInfo -> Reg -> Const -> JS
638+jsASSIGNCONST _ r c = JSAssign (translateReg r) (translateConstant c)
467639
468−jsSubst var new old@(JSIdent _)
469− | var == old = new
470− | otherwise = old
640+jsCALL :: CompileInfo -> Name -> JS
641+jsCALL _ n =
642+ JSApp (
643+ JSIdent "i$CALL"
644+ ) [JSIdent (translateName n), JSArray [jsMYOLDBASE]]
471645
472−jsSubst var new (JSArray fields) =
473− JSArray (map (jsSubst var new) fields)
646+jsTAILCALL :: CompileInfo -> Name -> JS
647+jsTAILCALL _ n =
648+ JSApp (
649+ JSIdent "i$CALL"
650+ ) [JSIdent (translateName n), JSArray [jsOLDBASE]]
651+
652+jsFOREIGN :: CompileInfo -> Reg -> String -> [(FType, Reg)] -> JS
653+jsFOREIGN _ reg n args
654+ | n == "putStr"
655+ , [(FString, arg)] <- args =
656+ JSAssign (
657+ translateReg reg
658+ ) (
659+ JSApp (JSIdent "i$putStr") [translateReg arg]
660+ )
474661
475−jsSubst var new (JSNew con vals) =
476− JSNew con $ map (jsSubst var new) vals
662+ | n == "isNull"
663+ , [(FPtr, arg)] <- args =
664+ JSAssign (
665+ translateReg reg
666+ ) (
667+ JSBinOp "==" (translateReg arg) JSNull
668+ )
477669
478−jsSubst (JSIdent var) new (JSApp (JSProj (JSFunction args body) "apply") vals)
479− | var `notElem` args =
480− JSApp (JSProj (JSFunction args (jsSubst (JSIdent var) new body)) "apply") (
481− map (jsSubst (JSIdent var) new) vals
670+ | n == "idris_eqPtr"
671+ , [(_, lhs),(_, rhs)] <- args =
672+ JSAssign (
673+ translateReg reg
674+ ) (
675+ JSBinOp "==" (translateReg lhs) (translateReg rhs)
482676 )
483677 | otherwise =
484− JSApp (JSProj (JSFunction args body) "apply") (
485− map (jsSubst (JSIdent var) new) vals
486− )
487−
488−jsSubst (JSIdent var) new (JSApp (JSFunction [arg] body) vals)
489− | var /= arg =
490− JSApp (JSFunction [arg] (
491− jsSubst (JSIdent var) new body
492− )) $ map (jsSubst (JSIdent var) new) vals
678+ JSAssign (
679+ translateReg reg
680+ ) (
681+ JSFFI n (map generateWrapper args)
682+ )
683+ where
684+ generateWrapper :: (FType, Reg) -> JS
685+ generateWrapper (ty, reg)
686+ | FFunction <- ty =
687+ JSApp (JSIdent "i$ffiWrap") [ translateReg reg
688+ , JSIdent "oldbase"
689+ , JSIdent "myoldbase"
690+ ]
691+ | FFunctionIO <- ty =
692+ JSApp (JSIdent "i$ffiWrap") [ translateReg reg
693+ , JSIdent "oldbase"
694+ , JSIdent "myoldbase"
695+ ]
696+
697+ generateWrapper (_, reg) =
698+ translateReg reg
699+
700+jsREBASE :: CompileInfo -> JS
701+jsREBASE _ = JSAssign jsSTACKBASE jsOLDBASE
702+
703+jsSTOREOLD :: CompileInfo ->JS
704+jsSTOREOLD _ = JSAssign jsMYOLDBASE jsSTACKBASE
705+
706+jsADDTOP :: CompileInfo -> Int -> JS
707+jsADDTOP info n
708+ | 0 <- n = JSNoop
493709 | otherwise =
494− JSApp (JSFunction [arg] (
495− body
496− )) $ map (jsSubst (JSIdent var) new) vals
710+ JSBinOp "+=" jsSTACKTOP (JSNum (JSInt n))
497711
498−jsSubst var new js = transformJS (jsSubst var new) js
712+jsTOPBASE :: CompileInfo -> Int -> JS
713+jsTOPBASE _ 0 = JSAssign jsSTACKTOP jsSTACKBASE
714+jsTOPBASE _ n = JSAssign jsSTACKTOP (JSBinOp "+" jsSTACKBASE (JSNum (JSInt n)))
499715
500716
501−removeAllocations :: JS -> JS
502−removeAllocations (JSSeq body) =
503− let opt = removeHelper (map removeAllocations body) in
504− case opt of
505− [ret] -> ret
506− _ -> JSSeq opt
507− where
508− removeHelper :: [JS] -> [JS]
509− removeHelper [js] = [js]
510− removeHelper ((JSAlloc name (Just val@(JSIdent _))):js) =
511− map (jsSubst (JSIdent name) val) (removeHelper js)
512− removeHelper (j:js) = j : removeHelper js
513−
514−removeAllocations js = transformJS removeAllocations js
515−
516−
517−isJSConstant :: JS -> Bool
518−isJSConstant js
519− | JSString _ <- js = True
520− | JSNum _ <- js = True
521− | JSType _ <- js = True
522− | JSNull <- js = True
523− | JSArray vals <- js = all isJSConstant vals
524−
525− | JSApp (JSIdent "__IDRRT__bigInt") _ <- js = True
526−
527− | otherwise = False
528−
529−isJSConstantConstructor :: [String] -> JS -> Bool
530−isJSConstantConstructor constants js
531− | isJSConstant js =
532− True
533− | JSArray vals <- js =
534− all (isJSConstantConstructor constants) vals
535− | JSNew "__IDRRT__Con" args <- js =
536− all (isJSConstantConstructor constants) args
537− | JSIndex (JSProj (JSIdent name) "vars") (JSNum _) <- js
538− , name `elem` constants =
539− True
540− | JSIdent name <- js
541− , name `elem` constants =
542− True
543− | otherwise = False
544−
545−
546−inlineJS :: JS -> JS
547−inlineJS = inlineAssign . inlineError . inlineApply . inlineCaseMatch . inlineJSLet
548− where
549− inlineJSLet :: JS -> JS
550− inlineJSLet (JSApp (JSFunction [arg] (JSReturn ret)) [val])
551− | opt <- inlineJSLet val =
552− inlineJS $ jsSubst (JSIdent arg) opt ret
717+jsBASETOP :: CompileInfo -> Int -> JS
718+jsBASETOP _ 0 = JSAssign jsSTACKBASE jsSTACKTOP
719+jsBASETOP _ n = JSAssign jsSTACKBASE (JSBinOp "+" jsSTACKTOP (JSNum (JSInt n)))
553720
554− inlineJSLet js = transformJS inlineJSLet js
721+jsNULL :: CompileInfo -> Reg -> JS
722+jsNULL _ r = JSAssign (translateReg r) JSNull
555723
724+jsERROR :: CompileInfo -> String -> JS
725+jsERROR _ = JSError
556726
557− inlineCaseMatch (JSReturn (JSApp (JSFunction ["cse"] body) [val]))
558− | opt <- inlineCaseMatch val =
559− inlineCaseMatch $ jsSubst (JSIdent "cse") opt body
727+jsSLIDE :: CompileInfo -> Int -> JS
728+jsSLIDE _ n = JSApp (JSIdent "i$SLIDE") [JSNum (JSInt n)]
560729
561− inlineCaseMatch js = transformJS inlineCaseMatch js
730+jsMKCON :: CompileInfo -> Reg -> Int -> [Reg] -> JS
731+jsMKCON info r t rs =
732+ JSAssign (translateReg r) (
733+ JSNew "i$CON" [ JSNum (JSInt t)
734+ , JSArray (map translateReg rs)
735+ , if t `elem` compileInfoApplyCases info
736+ then JSIdent $ translateName (sMN 0 "APPLY") ++ "$" ++ show t
737+ else JSNull
738+ , if t `elem` compileInfoEvalCases info
739+ then JSIdent $ translateName (sMN 0 "EVAL") ++ "$" ++ show t
740+ else JSNull
741+ ]
742+ )
562743
744+jsInstanceOf :: JS -> String -> JS
745+jsInstanceOf obj cls = JSBinOp "instanceof" obj (JSIdent cls)
563746
564− inlineApply js
565− | JSApp (
566− JSProj (JSFunction args (JSReturn body)) "apply"
567− ) [JSThis, JSProj var "vars"] <- js =
568− inlineApply $ inlineApply' var args body 0
569− | JSReturn (JSApp (
570− JSProj (JSFunction args body@(JSCond _)) "apply"
571− ) [JSThis, JSProj var "vars"]) <- js =
572− inlineApply $ inlineApply' var args body 0
573− where
574− inlineApply' _ [] body _ = body
575− inlineApply' var (a:as) body n =
576− inlineApply' var as (
577− jsSubst (JSIdent a) (
578− JSIndex (JSProj var "vars") (JSNum (JSInt n))
579− ) body
580− ) (n + 1)
747+jsOr :: JS -> JS -> JS
748+jsOr lhs rhs = JSBinOp "||" lhs rhs
581749
582− inlineApply js = transformJS inlineApply js
750+jsAnd :: JS -> JS -> JS
751+jsAnd lhs rhs = JSBinOp "&&" lhs rhs
583752
753+jsMeth :: JS -> String -> [JS] -> JS
754+jsMeth obj meth args = JSApp (JSProj obj meth) args
584755
585− inlineError (JSReturn (JSApp (JSFunction [] error@(JSError _)) [])) =
586− inlineError error
756+jsCall :: String -> [JS] -> JS
757+jsCall fun args = JSApp (JSIdent fun) args
587758
588− inlineError js = transformJS inlineError js
759+jsTypeOf :: JS -> JS
760+jsTypeOf js = JSPreOp "typeof " js
589761
762+jsEq :: JS -> JS -> JS
763+jsEq lhs@(JSNum (JSInteger _)) rhs = JSApp (JSProj lhs "equals") [rhs]
764+jsEq lhs rhs@(JSNum (JSInteger _)) = JSApp (JSProj lhs "equals") [rhs]
765+jsEq lhs rhs = JSBinOp "==" lhs rhs
590766
591− inlineAssign (JSAssign lhs rhs)
592− | JSVar _ <- lhs
593− , JSVar _ <- rhs
594− , lhs == rhs =
595− lhs
767+jsNotEq :: JS -> JS -> JS
768+jsNotEq lhs rhs = JSBinOp "!=" lhs rhs
596769
597− inlineAssign (JSAssign lhs rhs)
598− | JSIdent _ <- lhs
599− , JSIdent _ <- rhs
600− , lhs == rhs =
601− lhs
770+jsIsNumber :: JS -> JS
771+jsIsNumber js = (jsTypeOf js) `jsEq` (JSString "number")
602772
603− inlineAssign js = transformJS inlineAssign js
773+jsIsNull :: JS -> JS
774+jsIsNull js = JSBinOp "==" js JSNull
604775
776+jsBigInt :: JS -> JS
777+jsBigInt (JSString "0") = JSNum (JSInteger JSBigZero)
778+jsBigInt (JSString "1") = JSNum (JSInteger JSBigOne)
779+jsBigInt js = JSNum $ JSInteger $ JSBigIntExpr js
605780
606−removeEval :: [JS] -> [JS]
607−removeEval js =
608− let (ret, isReduced) = checkEval js in
609− if isReduced
610− then removeEvalApp ret
611− else ret
612− where
613− removeEvalApp js = catMaybes (map removeEvalApp' js)
614− where
615− removeEvalApp' :: JS -> Maybe JS
616− removeEvalApp' (JSAlloc "__IDR__mEVAL0" _) = Nothing
617− removeEvalApp' js = Just $ transformJS match js
618− where
619− match (JSApp (JSIdent "__IDR__mEVAL0") [val]) = val
620− match js = transformJS match js
621−
622− checkEval :: [JS] -> ([JS], Bool)
623− checkEval js = foldr f ([], False) $ map checkEval' js
624− where
625− f :: (Maybe JS, Bool) -> ([JS], Bool) -> ([JS], Bool)
626− f (Just js, isReduced) (ret, b) = (js : ret, isReduced || b)
627− f (Nothing, isReduced) (ret, b) = (ret, isReduced || b)
781+jsUnPackBits :: JS -> JS
782+jsUnPackBits js = JSIndex js $ JSNum (JSInt 0)
628783
784+jsPackUBits8 :: JS -> JS
785+jsPackUBits8 js = JSNew "Uint8Array" [JSArray [js]]
629786
630− checkEval' :: JS -> (Maybe JS, Bool)
631− checkEval' (JSAlloc "__IDRLT__EVAL" (Just (JSApp (JSFunction [] (
632− JSSeq [ _
633− , JSReturn (JSIdent "t")
634− ]
635− )) []))) = (Nothing, True)
787+jsPackUBits16 :: JS -> JS
788+jsPackUBits16 js = JSNew "Uint16Array" [JSArray [js]]
636789
637− checkEval' js = (Just js, False)
790+jsPackUBits32 :: JS -> JS
791+jsPackUBits32 js = JSNew "Uint32Array" [JSArray [js]]
638792
793+jsPackSBits8 :: JS -> JS
794+jsPackSBits8 js = JSNew "Int8Array" [JSArray [js]]
639795
640−reduceJS :: [JS] -> [JS]
641−reduceJS js = moveJSDeclToTop "__IDRRT__Con" $ reduceLoop [] ([], js)
796+jsPackSBits16 :: JS -> JS
797+jsPackSBits16 js = JSNew "Int16Array" [JSArray [js]]
642798
799+jsPackSBits32 :: JS -> JS
800+jsPackSBits32 js = JSNew "Int32Array" [JSArray [js]]
643801
644−funName :: JS -> String
645−funName (JSAlloc fun _) = fun
802+jsCASE :: CompileInfo -> Bool -> Reg -> [(Int, [BC])] -> Maybe [BC] -> JS
803+jsCASE info safe reg cases def =
804+ JSSwitch (tag safe $ translateReg reg) (
805+ map ((JSNum . JSInt) *** prepBranch) cases
806+ ) (fmap prepBranch def)
807+ where
808+ tag :: Bool -> JS -> JS
809+ tag True = jsCTAG
810+ tag False = jsTAG
811+
812+ prepBranch :: [BC] -> JS
813+ prepBranch bc = JSSeq $ map (translateBC info) bc
814+
815+ jsTAG :: JS -> JS
816+ jsTAG js =
817+ (JSTernary (js `jsInstanceOf` "i$CON") (
818+ JSProj js "tag"
819+ ) (JSNum (JSInt $ negate 1)))
820+
821+ jsCTAG :: JS -> JS
822+ jsCTAG js = JSProj js "tag"
823+
824+
825+jsCONSTCASE :: CompileInfo -> Reg -> [(Const, [BC])] -> Maybe [BC] -> JS
826+jsCONSTCASE info reg cases def =
827+ JSCond $ (
828+ map (jsEq (translateReg reg) . translateConstant *** prepBranch) cases
829+ ) ++ (maybe [] ((:[]) . ((,) JSNoop) . prepBranch) def)
830+ where
831+ prepBranch :: [BC] -> JS
832+ prepBranch bc = JSSeq $ map (translateBC info) bc
833+
834+jsPROJECT :: CompileInfo -> Reg -> Int -> Int -> JS
835+jsPROJECT _ reg loc ar =
836+ JSApp (JSIdent "i$PROJECT") [ translateReg reg
837+ , JSNum (JSInt loc)
838+ , JSNum (JSInt ar)
839+ ]
646840
841+jsOP :: CompileInfo -> Reg -> PrimFn -> [Reg] -> JS
842+jsOP _ reg op args = JSAssign (translateReg reg) jsOP'
843+ where
844+ jsOP' :: JS
845+ jsOP'
846+ | LNoOp <- op = translateReg (last args)
847+
848+ | (LZExt (ITFixed IT8) ITNative) <- op = jsUnPackBits $ translateReg (last args)
849+ | (LZExt (ITFixed IT16) ITNative) <- op = jsUnPackBits $ translateReg (last args)
850+ | (LZExt (ITFixed IT32) ITNative) <- op = jsUnPackBits $ translateReg (last args)
851+
852+ | (LZExt _ ITBig) <- op = jsBigInt $ JSApp (JSIdent "String") [translateReg (last args)]
853+ | (LPlus (ATInt ITBig)) <- op
854+ , (lhs:rhs:_) <- args = invokeMeth lhs "add" [rhs]
855+ | (LMinus (ATInt ITBig)) <- op
856+ , (lhs:rhs:_) <- args = invokeMeth lhs "subtract" [rhs]
857+ | (LTimes (ATInt ITBig)) <- op
858+ , (lhs:rhs:_) <- args = invokeMeth lhs "multiply" [rhs]
859+ | (LSDiv (ATInt ITBig)) <- op
860+ , (lhs:rhs:_) <- args = invokeMeth lhs "divide" [rhs]
861+ | (LSRem (ATInt ITBig)) <- op
862+ , (lhs:rhs:_) <- args = invokeMeth lhs "mod" [rhs]
863+ | (LEq (ATInt ITBig)) <- op
864+ , (lhs:rhs:_) <- args = invokeMeth lhs "equals" [rhs]
865+ | (LSLt (ATInt ITBig)) <- op
866+ , (lhs:rhs:_) <- args = invokeMeth lhs "lesser" [rhs]
867+ | (LSLe (ATInt ITBig)) <- op
868+ , (lhs:rhs:_) <- args = invokeMeth lhs "lesserOrEquals" [rhs]
869+ | (LSGt (ATInt ITBig)) <- op
870+ , (lhs:rhs:_) <- args = invokeMeth lhs "greater" [rhs]
871+ | (LSGe (ATInt ITBig)) <- op
872+ , (lhs:rhs:_) <- args = invokeMeth lhs "greaterOrEquals" [rhs]
873+
874+ | (LPlus ATFloat) <- op
875+ , (lhs:rhs:_) <- args = translateBinaryOp "+" lhs rhs
876+ | (LMinus ATFloat) <- op
877+ , (lhs:rhs:_) <- args = translateBinaryOp "-" lhs rhs
878+ | (LTimes ATFloat) <- op
879+ , (lhs:rhs:_) <- args = translateBinaryOp "*" lhs rhs
880+ | (LSDiv ATFloat) <- op
881+ , (lhs:rhs:_) <- args = translateBinaryOp "/" lhs rhs
882+ | (LEq ATFloat) <- op
883+ , (lhs:rhs:_) <- args = translateBinaryOp "==" lhs rhs
884+ | (LSLt ATFloat) <- op
885+ , (lhs:rhs:_) <- args = translateBinaryOp "<" lhs rhs
886+ | (LSLe ATFloat) <- op
887+ , (lhs:rhs:_) <- args = translateBinaryOp "<=" lhs rhs
888+ | (LSGt ATFloat) <- op
889+ , (lhs:rhs:_) <- args = translateBinaryOp ">" lhs rhs
890+ | (LSGe ATFloat) <- op
891+ , (lhs:rhs:_) <- args = translateBinaryOp ">=" lhs rhs
892+
893+ | (LPlus (ATInt ITChar)) <- op
894+ , (lhs:rhs:_) <- args =
895+ jsCall "i$fromCharCode" [
896+ JSBinOp "+" (
897+ jsCall "i$charCode" [translateReg lhs]
898+ ) (
899+ jsCall "i$charCode" [translateReg rhs]
900+ )
901+ ]
647902
648−elimDeadLoop :: [JS] -> [JS]
649−elimDeadLoop js
650− | ret <- deadEvalApplyCases js
651− , ret /= js = elimDeadLoop ret
652− | otherwise = js
903+ | (LTrunc (ITFixed IT16) (ITFixed IT8)) <- op
904+ , (arg:_) <- args =
905+ jsPackUBits8 (
906+ JSBinOp "&" (jsUnPackBits $ translateReg arg) (JSNum (JSInt 0xFF))
907+ )
653908
909+ | (LTrunc (ITFixed IT32) (ITFixed IT16)) <- op
910+ , (arg:_) <- args =
911+ jsPackUBits16 (
912+ JSBinOp "&" (jsUnPackBits $ translateReg arg) (JSNum (JSInt 0xFFFF))
913+ )
654914
655−deadEvalApplyCases :: [JS] -> [JS]
656−deadEvalApplyCases js =
657− let tags = sort $ nub $ concatMap (getTags) js in
658− map (removeHelper tags) js
659− where
660− getTags :: JS -> [Int]
661− getTags = foldJS match (++) []
662− where
663− match js
664− | JSNew "__IDRRT__Con" [JSNum (JSInt tag), _] <- js = [tag]
665− | otherwise = []
666−
667−
668− removeHelper :: [Int] -> JS -> JS
669− removeHelper tags (JSAlloc fun (Just (
670− JSApp (JSFunction [] (JSSeq seq)) []))
671− ) =
672− (JSAlloc fun (Just (
673− JSApp (JSFunction [] (JSSeq $ remover tags seq)) []))
674− )
915+ | (LTrunc (ITFixed IT64) (ITFixed IT32)) <- op
916+ , (arg:_) <- args =
917+ jsPackUBits32 (
918+ jsMeth (jsMeth (translateReg arg) "and" [
919+ jsBigInt (JSString $ show 0xFFFFFFFF)
920+ ]) "intValue" []
921+ )
675922
676− removeHelper _ js = js
923+ | (LTrunc ITBig (ITFixed IT64)) <- op
924+ , (arg:_) <- args =
925+ jsMeth (translateReg arg) "and" [
926+ jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
927+ ]
677928
929+ | (LLSHR (ITFixed IT8)) <- op
930+ , (lhs:rhs:_) <- args =
931+ jsPackUBits8 (
932+ JSBinOp ">>" (jsUnPackBits $ translateReg lhs) (jsUnPackBits $ translateReg rhs)
933+ )
678934
679− remover :: [Int] -> [JS] -> [JS]
680− remover tags (
681− j@(JSAssign ((JSIndex (JSIdent "t") (JSNum (JSInt tag)))) _):js
935+ | (LLSHR (ITFixed IT16)) <- op
936+ , (lhs:rhs:_) <- args =
937+ jsPackUBits16 (
938+ JSBinOp ">>" (jsUnPackBits $ translateReg lhs) (jsUnPackBits $ translateReg rhs)
682939 )
683− | tag `notElem` tags = remover tags js
684940
685− remover tags (j:js) = j : remover tags js
686− remover _ [] = []
941+ | (LLSHR (ITFixed IT32)) <- op
942+ , (lhs:rhs:_) <- args =
943+ jsPackUBits32 (
944+ JSBinOp ">>" (jsUnPackBits $ translateReg lhs) (jsUnPackBits $ translateReg rhs)
945+ )
687946
947+ | (LLSHR (ITFixed IT64)) <- op
948+ , (lhs:rhs:_) <- args =
949+ jsMeth (translateReg lhs) "shiftRight" [translateReg rhs]
688950
689−initConstructors :: [JS] -> [JS]
690−initConstructors js =
691− let tags = nub $ sort $ concat (map getTags js) in
692− rearrangePrelude $ map createConstant tags ++ replaceConstructors tags js
693− where
694− rearrangePrelude :: [JS] -> [JS]
695− rearrangePrelude = moveJSDeclToTop $ idrRTNamespace ++ "Con"
951+ | (LSHL (ITFixed IT8)) <- op
952+ , (lhs:rhs:_) <- args =
953+ jsPackUBits8 (
954+ JSBinOp "<<" (jsUnPackBits $ translateReg lhs) (jsUnPackBits $ translateReg rhs)
955+ )
696956
957+ | (LSHL (ITFixed IT16)) <- op
958+ , (lhs:rhs:_) <- args =
959+ jsPackUBits16 (
960+ JSBinOp "<<" (jsUnPackBits $ translateReg lhs) (jsUnPackBits $ translateReg rhs)
961+ )
697962
698− getTags :: JS -> [Int]
699− getTags = foldJS match (++) []
700− where
701− match js
702− | JSNew "__IDRRT__Con" [JSNum (JSInt tag), JSArray []] <- js = [tag]
703− | otherwise = []
963+ | (LSHL (ITFixed IT32)) <- op
964+ , (lhs:rhs:_) <- args =
965+ jsPackUBits32 (
966+ JSBinOp "<<" (jsUnPackBits $ translateReg lhs) (jsUnPackBits $ translateReg rhs)
967+ )
704968
969+ | (LSHL (ITFixed IT64)) <- op
970+ , (lhs:rhs:_) <- args =
971+ jsMeth (jsMeth (translateReg lhs) "shiftLeft" [translateReg rhs]) "and" [
972+ jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
973+ ]
705974
706− replaceConstructors :: [Int] -> [JS] -> [JS]
707− replaceConstructors tags js = map (replaceHelper tags) js
708− where
709− replaceHelper :: [Int] -> JS -> JS
710− replaceHelper tags (JSNew "__IDRRT__Con" [JSNum (JSInt tag), JSArray []])
711− | tag `elem` tags = JSIdent (idrCTRNamespace ++ show tag)
975+ | (LAnd (ITFixed IT8)) <- op
976+ , (lhs:rhs:_) <- args =
977+ jsPackUBits8 (
978+ JSBinOp "&" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
979+ )
712980
713− replaceHelper tags js = transformJS (replaceHelper tags) js
981+ | (LAnd (ITFixed IT16)) <- op
982+ , (lhs:rhs:_) <- args =
983+ jsPackUBits16 (
984+ JSBinOp "&" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
985+ )
714986
987+ | (LAnd (ITFixed IT32)) <- op
988+ , (lhs:rhs:_) <- args =
989+ jsPackUBits32 (
990+ JSBinOp "&" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
991+ )
715992
716− createConstant :: Int -> JS
717− createConstant tag =
718− JSAlloc (idrCTRNamespace ++ show tag) (Just (
719− JSNew (idrRTNamespace ++ "Con") [JSNum (JSInt tag), JSArray []]
720− ))
993+ | (LAnd (ITFixed IT64)) <- op
994+ , (lhs:rhs:_) <- args =
995+ jsMeth (translateReg lhs) "and" [translateReg rhs]
721996
997+ | (LOr (ITFixed IT8)) <- op
998+ , (lhs:rhs:_) <- args =
999+ jsPackUBits8 (
1000+ JSBinOp "|" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1001+ )
7221002
723−removeIDs :: [JS] -> [JS]
724−removeIDs js =
725− case partition isID js of
726− ([], rest) -> rest
727− (ids, rest) -> removeIDs $ map (removeIDCall (map idFor ids)) rest
728− where isID :: JS -> Bool
729− isID (JSAlloc _ (Just (JSFunction _ (JSSeq body))))
730− | JSReturn (JSVar _) <- last body = True
1003+ | (LOr (ITFixed IT16)) <- op
1004+ , (lhs:rhs:_) <- args =
1005+ jsPackUBits16 (
1006+ JSBinOp "|" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1007+ )
7311008
732− isID _ = False
1009+ | (LOr (ITFixed IT32)) <- op
1010+ , (lhs:rhs:_) <- args =
1011+ jsPackUBits32 (
1012+ JSBinOp "|" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1013+ )
7331014
1015+ | (LOr (ITFixed IT64)) <- op
1016+ , (lhs:rhs:_) <- args =
1017+ jsMeth (translateReg lhs) "or" [translateReg rhs]
7341018
735− idFor :: JS -> (String, Int)
736− idFor (JSAlloc fun (Just (JSFunction _ (JSSeq body))))
737− | JSReturn (JSVar (Loc pos)) <- last body = (fun, pos)
1019+ | (LXOr (ITFixed IT8)) <- op
1020+ , (lhs:rhs:_) <- args =
1021+ jsPackUBits8 (
1022+ JSBinOp "^" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1023+ )
7381024
1025+ | (LXOr (ITFixed IT16)) <- op
1026+ , (lhs:rhs:_) <- args =
1027+ jsPackUBits16 (
1028+ JSBinOp "^" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1029+ )
7391030
740− removeIDCall :: [(String, Int)] -> JS -> JS
741− removeIDCall ids (JSApp (JSIdent "__IDRRT__tailcall") [JSFunction [] (
742− JSReturn (JSApp (JSIdent fun) args)
743− )])
744− | Just pos <- lookup fun ids
745− , pos < length args = removeIDCall ids (args !! pos)
1031+ | (LXOr (ITFixed IT32)) <- op
1032+ , (lhs:rhs:_) <- args =
1033+ jsPackUBits32 (
1034+ JSBinOp "^" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1035+ )
7461036
747− removeIDCall ids (JSNew _ [JSFunction [] (
748− JSReturn (JSApp (JSIdent fun) args)
749− )])
750− | Just pos <- lookup fun ids
751− , pos < length args = removeIDCall ids (args !! pos)
1037+ | (LXOr (ITFixed IT64)) <- op
1038+ , (lhs:rhs:_) <- args =
1039+ jsMeth (translateReg lhs) "xor" [translateReg rhs]
7521040
753− removeIDCall ids js@(JSApp id@(JSIdent fun) args)
754− | Just pos <- lookup fun ids
755− , pos < length args = removeIDCall ids (args !! pos)
1041+ | (LPlus (ATInt (ITFixed IT8))) <- op
1042+ , (lhs:rhs:_) <- args =
1043+ jsPackUBits8 (
1044+ JSBinOp "+" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1045+ )
7561046
757− removeIDCall ids js = transformJS (removeIDCall ids) js
1047+ | (LPlus (ATInt (ITFixed IT16))) <- op
1048+ , (lhs:rhs:_) <- args =
1049+ jsPackUBits16 (
1050+ JSBinOp "+" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1051+ )
7581052
1053+ | (LPlus (ATInt (ITFixed IT32))) <- op
1054+ , (lhs:rhs:_) <- args =
1055+ jsPackUBits32 (
1056+ JSBinOp "+" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1057+ )
7591058
760−inlineFunction :: String -> [String] -> JS -> JS -> JS
761−inlineFunction fun args body js = inline' js
762− where
763− inline' :: JS -> JS
764− inline' (JSApp (JSIdent name) vals)
765− | name == fun =
766− let (js, phs) = insertPlaceHolders args body in
767− inline' $ foldr (uncurry jsSubst) js (zip phs vals)
1059+ | (LPlus (ATInt (ITFixed IT64))) <- op
1060+ , (lhs:rhs:_) <- args =
1061+ jsMeth (jsMeth (translateReg lhs) "add" [translateReg rhs]) "and" [
1062+ jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
1063+ ]
7681064
769− inline' js = transformJS inline' js
1065+ | (LMinus (ATInt (ITFixed IT8))) <- op
1066+ , (lhs:rhs:_) <- args =
1067+ jsPackUBits8 (
1068+ JSBinOp "-" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1069+ )
7701070
771− insertPlaceHolders :: [String] -> JS -> (JS, [JS])
772− insertPlaceHolders args body = insertPlaceHolders' args body []
773− where
774− insertPlaceHolders' :: [String] -> JS -> [JS] -> (JS, [JS])
775− insertPlaceHolders' (a:as) body ph
776− | (body', ph') <- insertPlaceHolders' as body ph =
777− let phvar = JSIdent $ "__PH_" ++ show (length ph') in
778− (jsSubst (JSIdent a) phvar body', phvar : ph')
1071+ | (LMinus (ATInt (ITFixed IT16))) <- op
1072+ , (lhs:rhs:_) <- args =
1073+ jsPackUBits16 (
1074+ JSBinOp "-" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1075+ )
7791076
780− insertPlaceHolders' [] body ph = (body, ph)
1077+ | (LMinus (ATInt (ITFixed IT32))) <- op
1078+ , (lhs:rhs:_) <- args =
1079+ jsPackUBits32 (
1080+ JSBinOp "-" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1081+ )
7811082
1083+ | (LMinus (ATInt (ITFixed IT64))) <- op
1084+ , (lhs:rhs:_) <- args =
1085+ jsMeth (jsMeth (translateReg lhs) "subtract" [translateReg rhs]) "and" [
1086+ jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
1087+ ]
7821088
783−inlineFunctions :: [JS] -> [JS]
784−inlineFunctions js =
785− inlineHelper ([], js)
786− where
787− inlineHelper :: ([JS], [JS]) -> [JS]
788− inlineHelper (front , (JSAlloc fun (Just (JSFunction args body))):back)
789− | countAll fun front + countAll fun back == 0 =
790− inlineHelper (front, back)
791− | Just new <- inlineAble (
792− countAll fun front + countAll fun back
793− ) fun args body =
794− let f = map (inlineFunction fun args new) in
795− inlineHelper (f front, f back)
1089+ | (LTimes (ATInt (ITFixed IT8))) <- op
1090+ , (lhs:rhs:_) <- args =
1091+ jsPackUBits8 (
1092+ JSBinOp "*" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1093+ )
7961094
797− inlineHelper (front, next:back) = inlineHelper (front ++ [next], back)
798− inlineHelper (front, []) = front
1095+ | (LTimes (ATInt (ITFixed IT16))) <- op
1096+ , (lhs:rhs:_) <- args =
1097+ jsPackUBits16 (
1098+ JSBinOp "*" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1099+ )
7991100
1101+ | (LTimes (ATInt (ITFixed IT32))) <- op
1102+ , (lhs:rhs:_) <- args =
1103+ jsPackUBits32 (
1104+ JSBinOp "*" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1105+ )
8001106
801− inlineAble :: Int -> String -> [String] -> JS -> Maybe JS
802− inlineAble 1 fun args (JSReturn body)
803− | nonRecur fun body =
804− if all (<= 1) (map ($ body) (map countIDOccurences args))
805− then Just body
806− else Nothing
1107+ | (LTimes (ATInt (ITFixed IT64))) <- op
1108+ , (lhs:rhs:_) <- args =
1109+ jsMeth (jsMeth (translateReg lhs) "multiply" [translateReg rhs]) "and" [
1110+ jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
1111+ ]
8071112
808− inlineAble _ _ _ _ = Nothing
1113+ | (LEq (ATInt (ITFixed IT8))) <- op
1114+ , (lhs:rhs:_) <- args =
1115+ jsPackUBits8 (
1116+ JSBinOp "==" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1117+ )
8091118
1119+ | (LEq (ATInt (ITFixed IT16))) <- op
1120+ , (lhs:rhs:_) <- args =
1121+ jsPackUBits16 (
1122+ JSBinOp "==" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1123+ )
8101124
811− nonRecur :: String -> JS -> Bool
812− nonRecur name body = countInvokations name body == 0
1125+ | (LEq (ATInt (ITFixed IT32))) <- op
1126+ , (lhs:rhs:_) <- args =
1127+ jsPackUBits32 (
1128+ JSBinOp "==" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1129+ )
8131130
1131+ | (LEq (ATInt (ITFixed IT64))) <- op
1132+ , (lhs:rhs:_) <- args =
1133+ jsMeth (jsMeth (translateReg lhs) "equals" [translateReg rhs]) "and" [
1134+ jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
1135+ ]
8141136
815− countAll :: String -> [JS] -> Int
816− countAll name js = sum $ map (countInvokations name) js
1137+ | (LLt (ITFixed IT8)) <- op
1138+ , (lhs:rhs:_) <- args =
1139+ jsPackUBits8 (
1140+ JSBinOp "<" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1141+ )
8171142
1143+ | (LLt (ITFixed IT16)) <- op
1144+ , (lhs:rhs:_) <- args =
1145+ jsPackUBits16 (
1146+ JSBinOp "<" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1147+ )
8181148
819− countIDOccurences :: String -> JS -> Int
820− countIDOccurences name = foldJS match (+) 0
821− where
822− match :: JS -> Int
823− match js
824− | JSIdent ident <- js
825− , name == ident = 1
826− | otherwise = 0
1149+ | (LLt (ITFixed IT32)) <- op
1150+ , (lhs:rhs:_) <- args =
1151+ jsPackUBits32 (
1152+ JSBinOp "<" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1153+ )
8271154
1155+ | (LLt (ITFixed IT64)) <- op
1156+ , (lhs:rhs:_) <- args = invokeMeth lhs "lesser" [rhs]
8281157
829− countInvokations :: String -> JS -> Int
830− countInvokations name = foldJS match (+) 0
831− where
832− match :: JS -> Int
833− match js
834− | JSApp (JSIdent ident) _ <- js
835− , name == ident = 1
836− | JSNew con _ <- js
837− , name == con = 1
838− | otherwise = 0
1158+ | (LLe (ITFixed IT8)) <- op
1159+ , (lhs:rhs:_) <- args =
1160+ jsPackUBits8 (
1161+ JSBinOp "<=" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1162+ )
8391163
1164+ | (LLe (ITFixed IT16)) <- op
1165+ , (lhs:rhs:_) <- args =
1166+ jsPackUBits16 (
1167+ JSBinOp "<=" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1168+ )
8401169
841−reduceContinuations :: JS -> JS
842−reduceContinuations = inlineTC . reduceJS
843− where
844− reduceJS :: JS -> JS
845− reduceJS (JSNew "__IDRRT__Cont" [JSFunction [] (
846− JSReturn js@(JSNew "__IDRRT__Cont" [JSFunction [] body])
847− )]) = reduceJS js
1170+ | (LLe (ITFixed IT32)) <- op
1171+ , (lhs:rhs:_) <- args =
1172+ jsPackUBits32 (
1173+ JSBinOp "<=" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1174+ )
8481175
849− reduceJS js = transformJS reduceJS js
1176+ | (LLe (ITFixed IT64)) <- op
1177+ , (lhs:rhs:_) <- args = invokeMeth lhs "lesserOrEquals" [rhs]
8501178
1179+ | (LGt (ITFixed IT8)) <- op
1180+ , (lhs:rhs:_) <- args =
1181+ jsPackUBits8 (
1182+ JSBinOp ">" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1183+ )
8511184
852− inlineTC :: JS -> JS
853− inlineTC js
854− | JSApp (JSIdent "__IDRRT__tailcall") [JSFunction [] (
855− JSReturn (JSNew "__IDRRT__Cont" [JSFunction [] (
856− JSReturn ret@(JSApp (JSIdent "__IDRRT__tailcall") [JSFunction [] (
857− JSReturn (JSNew "__IDRRT__Cont" _)
858− )])
859− )])
860− )] <- js = inlineTC ret
1185+ | (LGt (ITFixed IT16)) <- op
1186+ , (lhs:rhs:_) <- args =
1187+ jsPackUBits16 (
1188+ JSBinOp ">" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1189+ )
1190+ | (LGt (ITFixed IT32)) <- op
1191+ , (lhs:rhs:_) <- args =
1192+ jsPackUBits32 (
1193+ JSBinOp ">" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1194+ )
8611195
862− inlineTC js = transformJS inlineTC js
1196+ | (LGt (ITFixed IT64)) <- op
1197+ , (lhs:rhs:_) <- args = invokeMeth lhs "greater" [rhs]
8631198
1199+ | (LGe (ITFixed IT8)) <- op
1200+ , (lhs:rhs:_) <- args =
1201+ jsPackUBits8 (
1202+ JSBinOp ">=" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1203+ )
8641204
1205+ | (LGe (ITFixed IT16)) <- op
1206+ , (lhs:rhs:_) <- args =
1207+ jsPackUBits16 (
1208+ JSBinOp ">=" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1209+ )
1210+ | (LGe (ITFixed IT32)) <- op
1211+ , (lhs:rhs:_) <- args =
1212+ jsPackUBits32 (
1213+ JSBinOp ">=" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1214+ )
8651215
1216+ | (LGe (ITFixed IT64)) <- op
1217+ , (lhs:rhs:_) <- args = invokeMeth lhs "greaterOrEquals" [rhs]
8661218
867−reduceConstant :: JS -> JS
868−reduceConstant
869− (JSApp (JSIdent "__IDRRT__tailcall") [JSFunction [] (
870− JSReturn (JSApp (JSIdent "__IDR__mEVAL0") [val])
871− )])
872− | JSNum num <- val = val
873− | JSBinOp op lhs rhs <- val =
874− JSParens $ JSBinOp op (reduceConstant lhs) (reduceConstant rhs)
1219+ | (LUDiv (ITFixed IT8)) <- op
1220+ , (lhs:rhs:_) <- args =
1221+ jsPackUBits8 (
1222+ JSBinOp "/" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1223+ )
8751224
876− | JSApp (JSProj lhs op) [rhs] <- val
877− , op `elem` [ "subtract"
878− , "add"
879− , "multiply"
880− , "divide"
881− , "mod"
882− , "equals"
883− , "lesser"
884− , "lesserOrEquals"
885− , "greater"
886− , "greaterOrEquals"
887− ] = val
1225+ | (LUDiv (ITFixed IT16)) <- op
1226+ , (lhs:rhs:_) <- args =
1227+ jsPackUBits16 (
1228+ JSBinOp "/" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1229+ )
8881230
889−reduceConstant (JSApp ident [(JSParens js)]) =
890− JSApp ident [reduceConstant js]
1231+ | (LUDiv (ITFixed IT32)) <- op
1232+ , (lhs:rhs:_) <- args =
1233+ jsPackUBits32 (
1234+ JSBinOp "/" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1235+ )
8911236
892−reduceConstant js = transformJS reduceConstant js
1237+ | (LUDiv (ITFixed IT64)) <- op
1238+ , (lhs:rhs:_) <- args = invokeMeth lhs "divide" [rhs]
8931239
1240+ | (LSDiv (ATInt (ITFixed IT8))) <- op
1241+ , (lhs:rhs:_) <- args =
1242+ jsPackSBits8 (
1243+ JSBinOp "/" (
1244+ jsUnPackBits $ jsPackSBits8 $ jsUnPackBits (translateReg lhs)
1245+ ) (
1246+ jsUnPackBits $ jsPackSBits8 $ jsUnPackBits (translateReg rhs)
1247+ )
1248+ )
8941249
895−reduceConstants :: JS -> JS
896−reduceConstants js
897− | ret <- reduceConstant js
898− , ret /= js = reduceConstants ret
899− | otherwise = js
1250+ | (LSDiv (ATInt (ITFixed IT16))) <- op
1251+ , (lhs:rhs:_) <- args =
1252+ jsPackSBits16 (
1253+ JSBinOp "/" (
1254+ jsUnPackBits $ jsPackSBits16 $ jsUnPackBits (translateReg lhs)
1255+ ) (
1256+ jsUnPackBits $ jsPackSBits16 $ jsUnPackBits (translateReg rhs)
1257+ )
1258+ )
9001259
1260+ | (LSDiv (ATInt (ITFixed IT32))) <- op
1261+ , (lhs:rhs:_) <- args =
1262+ jsPackSBits32 (
1263+ JSBinOp "/" (
1264+ jsUnPackBits $ jsPackSBits32 $ jsUnPackBits (translateReg lhs)
1265+ ) (
1266+ jsUnPackBits $ jsPackSBits32 $ jsUnPackBits (translateReg rhs)
1267+ )
1268+ )
9011269
902−elimDuplicateEvals :: JS -> JS
903−elimDuplicateEvals (JSAlloc fun (Just (JSFunction args (JSSeq seq)))) =
904− JSAlloc fun $ Just (JSFunction args $ JSSeq (elimHelper seq))
905− where
906− elimHelper :: [JS] -> [JS]
907− elimHelper (j@(JSAlloc var (Just val)):js) =
908− j : map (jsSubst val (JSIdent var)) (elimHelper js)
909− elimHelper (j:js) =
910− j : elimHelper js
911− elimHelper [] = []
1270+ | (LSDiv (ATInt (ITFixed IT64))) <- op
1271+ , (lhs:rhs:_) <- args = invokeMeth lhs "divide" [rhs]
9121272
913−elimDuplicateEvals js = js
1273+ | (LSRem (ATInt (ITFixed IT8))) <- op
1274+ , (lhs:rhs:_) <- args =
1275+ jsPackSBits8 (
1276+ JSBinOp "%" (
1277+ jsUnPackBits $ jsPackSBits8 $ jsUnPackBits (translateReg lhs)
1278+ ) (
1279+ jsUnPackBits $ jsPackSBits8 $ jsUnPackBits (translateReg rhs)
1280+ )
1281+ )
9141282
1283+ | (LSRem (ATInt (ITFixed IT16))) <- op
1284+ , (lhs:rhs:_) <- args =
1285+ jsPackSBits16 (
1286+ JSBinOp "%" (
1287+ jsUnPackBits $ jsPackSBits16 $ jsUnPackBits (translateReg lhs)
1288+ ) (
1289+ jsUnPackBits $ jsPackSBits16 $ jsUnPackBits (translateReg rhs)
1290+ )
1291+ )
9151292
916−optimizeRuntimeCalls :: String -> String -> [JS] -> [JS]
917−optimizeRuntimeCalls fun tc js =
918− optTC tc : map optHelper js
919− where
920− optHelper :: JS -> JS
921− optHelper (JSApp (JSIdent "__IDRRT__tailcall") [
922− JSFunction [] (JSReturn (JSApp (JSIdent n) args))
923− ])
924− | n == fun = JSApp (JSIdent tc) $ map optHelper args
925−
926− optHelper js = transformJS optHelper js
927−
928−
929− optTC :: String -> JS
930− optTC tc@"__IDRRT__EVALTC" =
931− JSAlloc tc (Just $ JSFunction ["arg0"] (
932− JSSeq [ JSAlloc "ret" $ Just (
933− JSTernary (
934− (JSIdent "arg0" `jsInstanceOf` jsCon) `jsAnd`
935− (hasProp "__IDRLT__EVAL" "arg0")
936− ) (JSApp
937− (JSIndex
938− (JSIdent "__IDRLT__EVAL")
939− (JSProj (JSIdent "arg0") "tag")
940− )
941− [JSIdent "arg0"]
942− ) (JSIdent "arg0")
943− )
944− , JSWhile (JSIdent "ret" `jsInstanceOf` (JSIdent "__IDRRT__Cont")) (
945− JSAssign (JSIdent "ret") (
946− JSApp (JSProj (JSIdent "ret") "k") []
947− )
948− )
949− , JSReturn $ JSIdent "ret"
950− ]
951− ))
952−
953− optTC tc@"__IDRRT__APPLYTC" =
954− JSAlloc tc (Just $ JSFunction ["fn0", "arg0"] (
955− JSSeq [ JSAlloc "ret" $ Just (
956− JSTernary (
957− (JSIdent "fn0" `jsInstanceOf` jsCon) `jsAnd`
958− (hasProp "__IDRLT__APPLY" "fn0")
959− ) (JSApp
960− (JSIndex
961− (JSIdent "__IDRLT__APPLY")
962− (JSProj (JSIdent "fn0") "tag")
963− )
964− [JSIdent "fn0", JSIdent "arg0", JSIdent "fn0"]
965− ) JSNull
966− )
967− , JSWhile (JSIdent "ret" `jsInstanceOf` (JSIdent "__IDRRT__Cont")) (
968− JSAssign (JSIdent "ret") (
969− JSApp (JSProj (JSIdent "ret") "k") []
970− )
971− )
972− , JSReturn $ JSIdent "ret"
973− ]
974− ))
975−
976−
977− hasProp :: String -> String -> JS
978− hasProp table var =
979− JSIndex (JSIdent table) (JSProj (JSIdent var) "tag")
980−
981−
982−unfoldLookupTable :: [JS] -> [JS]
983−unfoldLookupTable input =
984− let (evals, evalunfold) = unfoldLT "__IDRLT__EVAL" input
985− (applys, applyunfold) = unfoldLT "__IDRLT__APPLY" evalunfold
986− js = applyunfold in
987− adaptRuntime $ expandCons evals applys js
988− where
989− adaptRuntime :: [JS] -> [JS]
990− adaptRuntime =
991− adaptEvalTC . adaptApplyTC . adaptEval . adaptApply . adaptCon
992−
993−
994− adaptApply :: [JS] -> [JS]
995− adaptApply js = adaptApply' [] js
996− where
997− adaptApply' :: [JS] -> [JS] -> [JS]
998− adaptApply' front ((JSAlloc "__IDR__mAPPLY0" (Just _)):back) =
999− front ++ (new:back)
1000−
1001− adaptApply' front (next:back) =
1002− adaptApply' (front ++ [next]) back
1003−
1004− adaptApply' front [] = front
1005−
1006− new =
1007− JSAlloc "__IDR__mAPPLY0" (Just $ JSFunction ["mfn0", "marg0"] (JSReturn $
1008− JSTernary (
1009− (JSIdent "mfn0" `jsInstanceOf` jsCon) `jsAnd`
1010− (JSProj (JSIdent "mfn0") "app")
1011− ) (JSApp
1012− (JSProj (JSIdent "mfn0") "app")
1013− [JSIdent "mfn0", JSIdent "marg0"]
1014− ) JSNull
1015− )
1016− )
1017−
1018−
1019− adaptApplyTC :: [JS] -> [JS]
1020− adaptApplyTC js = adaptApplyTC' [] js
1021− where
1022− adaptApplyTC' :: [JS] -> [JS] -> [JS]
1023− adaptApplyTC' front ((JSAlloc "__IDRRT__APPLYTC" (Just _)):back) =
1024− front ++ (new:back)
1025−
1026− adaptApplyTC' front (next:back) =
1027− adaptApplyTC' (front ++ [next]) back
1028−
1029− adaptApplyTC' front [] = front
1030−
1031− new =
1032− JSAlloc "__IDRRT__APPLYTC" (Just $ JSFunction ["mfn0", "marg0"] (
1033− JSSeq [ JSAlloc "ret" $ Just (
1034− JSTernary (
1035− (JSIdent "mfn0" `jsInstanceOf` jsCon) `jsAnd`
1036− (JSProj (JSIdent "mfn0") "app")
1037− ) (JSApp
1038− (JSProj (JSIdent "mfn0") "app")
1039− [JSIdent "mfn0", JSIdent "marg0"]
1040− ) JSNull
1041− )
1042− , JSWhile (JSIdent "ret" `jsInstanceOf` (JSIdent "__IDRRT__Cont")) (
1043− JSAssign (JSIdent "ret") (
1044− JSApp (JSProj (JSIdent "ret") "k") []
1045− )
1046− )
1047− , JSReturn $ JSIdent "ret"
1048− ]
1049− ))
1050−
1051−
1052− adaptEval :: [JS] -> [JS]
1053− adaptEval js = adaptEval' [] js
1054− where
1055− adaptEval' :: [JS] -> [JS] -> [JS]
1056− adaptEval' front ((JSAlloc "__IDR__mEVAL0" (Just _)):back) =
1057− front ++ (new:back)
1058−
1059− adaptEval' front (next:back) =
1060− adaptEval' (front ++ [next]) back
1061−
1062− adaptEval' front [] = front
1063−
1064− new =
1065− JSAlloc "__IDR__mEVAL0" (Just $ JSFunction ["marg0"] (JSReturn $
1066− JSTernary (
1067− (JSIdent "marg0" `jsInstanceOf` jsCon) `jsAnd`
1068− (JSProj (JSIdent "marg0") "eval")
1069− ) (JSApp
1070− (JSProj (JSIdent "marg0") "eval")
1071− [JSIdent "marg0"]
1072− ) (JSIdent "marg0")
1073− )
1074− )
1075−
1076−
1077− adaptEvalTC :: [JS] -> [JS]
1078− adaptEvalTC js = adaptEvalTC' [] js
1079− where
1080− adaptEvalTC' :: [JS] -> [JS] -> [JS]
1081− adaptEvalTC' front ((JSAlloc "__IDRRT__EVALTC" (Just _)):back) =
1082− front ++ (new:back)
1083−
1084− adaptEvalTC' front (next:back) =
1085− adaptEvalTC' (front ++ [next]) back
1086−
1087− adaptEvalTC' front [] = front
1088−
1089− new =
1090− JSAlloc "__IDRRT__EVALTC" (Just $ JSFunction ["marg0"] (
1091− JSSeq [ JSAlloc "ret" $ Just (
1092− JSTernary (
1093− (JSIdent "marg0" `jsInstanceOf` jsCon) `jsAnd`
1094− (JSProj (JSIdent "marg0") "eval")
1095− ) (JSApp
1096− (JSProj (JSIdent "marg0") "eval")
1097− [JSIdent "marg0"]
1098− ) (JSIdent "marg0")
1099− )
1100− , JSWhile (JSIdent "ret" `jsInstanceOf` (JSIdent "__IDRRT__Cont")) (
1101− JSAssign (JSIdent "ret") (
1102− JSApp (JSProj (JSIdent "ret") "k") []
1103− )
1104− )
1105− , JSReturn $ JSIdent "ret"
1106− ]
1107− ))
1108−
1109−
1110− adaptCon js =
1111− adaptCon' [] js
1112− where
1113− adaptCon' front ((JSAnnotation _ (JSAlloc "__IDRRT__Con" _)):back) =
1114− front ++ (new:back)
1115−
1116− adaptCon' front (next:back) =
1117− adaptCon' (front ++ [next]) back
1118−
1119− adaptCon' front [] = front
1120−
1121−
1122− new =
1123− JSAnnotation JSConstructor $
1124− JSAlloc "__IDRRT__Con" (Just $
1125− JSFunction newArgs (
1126− JSSeq (map newVar newArgs)
1127− )
1128− )
1129− where
1130− newVar var = JSAssign (JSProj JSThis var) (JSIdent var)
1131− newArgs = ["tag", "eval", "app", "vars"]
1132−
1133−
1134− unfoldLT :: String -> [JS] -> ([Int], [JS])
1135− unfoldLT lt js =
1136− let (table, code) = extractLT lt js
1137− expanded = expandLT lt table in
1138− (map fst expanded, map snd expanded ++ code)
1139−
1140−
1141− expandCons :: [Int] -> [Int] -> [JS] -> [JS]
1142− expandCons evals applys js =
1143− map expandCons' js
1144− where
1145− expandCons' :: JS -> JS
1146− expandCons' (JSNew "__IDRRT__Con" [JSNum (JSInt tag), JSArray args])
1147− | evalid <- getId "__IDRLT__EVAL" tag evals
1148− , applyid <- getId "__IDRLT__APPLY" tag applys =
1149− JSNew "__IDRRT__Con" [ JSNum (JSInt tag)
1150− , maybe JSNull JSIdent evalid
1151− , maybe JSNull JSIdent applyid
1152− , JSArray (map expandCons' args)
1153− ]
1154−
1155− expandCons' js = transformJS expandCons' js
1156−
1157−
1158− getId :: String -> Int -> [Int] -> Maybe String
1159− getId lt tag entries
1160− | tag `elem` entries = Just $ ltIdentifier lt tag
1161− | otherwise = Nothing
1162−
1163−
1164− ltIdentifier :: String -> Int -> String
1165− ltIdentifier "__IDRLT__EVAL" id = idrLTNamespace ++ "EVAL" ++ show id
1166− ltIdentifier "__IDRLT__APPLY" id = idrLTNamespace ++ "APPLY" ++ show id
1167−
1168−
1169− extractLT :: String -> [JS] -> (JS, [JS])
1170− extractLT lt js =
1171− extractLT' ([], js)
1172− where
1173− extractLT' :: ([JS], [JS]) -> (JS, [JS])
1174− extractLT' (front, js@(JSAlloc fun _):back)
1175− | fun == lt = (js, front ++ back)
1176−
1177− extractLT' (front, js:back) = extractLT' (front ++ [js], back)
1178− extractLT' (front, back) = (JSNoop, front ++ back)
1179−
1180−
1181− expandLT :: String -> JS -> [(Int, JS)]
1182− expandLT lt (
1183− JSAlloc _ (Just (JSApp (JSFunction [] (JSSeq seq)) []))
1184− ) = catMaybes (map expandEntry seq)
1185− where
1186− expandEntry :: JS -> Maybe (Int, JS)
1187− expandEntry (JSAssign (JSIndex _ (JSNum (JSInt id))) body) =
1188− Just $ (id, JSAlloc (ltIdentifier lt id) (Just body))
1189−
1190− expandEntry js = Nothing
1191−
1192− expandLT lt JSNoop = []
1193−
1194−
1195−removeInstanceChecks :: JS -> JS
1196−removeInstanceChecks (JSCond conds) =
1197− removeNoopConds $ JSCond $ eliminateDeadBranches $ map (
1198− removeHelper *** removeInstanceChecks
1199− ) conds
1200− where
1201− removeHelper (
1202− JSBinOp "&&" (JSBinOp "instanceof" _ (JSIdent "__IDRRT__Con")) check
1203− ) = removeHelper check
1204− removeHelper js = js
1205−
1206−
1207− eliminateDeadBranches ((JSTrue, cond):_) = [(JSNoop, cond)]
1208− eliminateDeadBranches [(_, js)] = [(JSNoop, js)]
1209− eliminateDeadBranches (x:xs) = x : eliminateDeadBranches xs
1210− eliminateDeadBranches [] = []
1211−
1212−
1213− removeNoopConds :: JS -> JS
1214− removeNoopConds (JSCond [(JSNoop, js)]) = js
1215− removeNoopConds js = js
1216−
1217−removeInstanceChecks js = transformJS removeInstanceChecks js
1218−
1219−
1220−reduceLoop :: [String] -> ([JS], [JS]) -> [JS]
1221−reduceLoop reduced (cons, program) =
1222− case partition findConstructors program of
1223− ([], js) -> cons ++ js
1224− (candidates, rest) ->
1225− let names = reduced ++ map funName candidates in
1226− reduceLoop names (
1227− cons ++ map reduce candidates, map (reduceCall names) rest
1228− )
1229− where findConstructors :: JS -> Bool
1230− findConstructors js
1231− | (JSAlloc fun (Just (JSFunction _ (JSSeq body)))) <- js =
1232− reducable $ last body
1233− | otherwise = False
1234− where reducable :: JS -> Bool
1235− reducable js
1236− | JSReturn ret <- js = reducable ret
1237− | JSNew _ args <- js = and $ map reducable args
1238− | JSArray fields <- js = and $ map reducable fields
1239− | JSNum _ <- js = True
1240− | JSNull <- js = True
1241− | JSIdent _ <- js = True
1242− | otherwise = False
1243−
1244−
1245− reduce :: JS -> JS
1246− reduce (JSAlloc fun (Just (JSFunction _ (JSSeq body))))
1247− | JSReturn js <- last body = (JSAlloc fun (Just js))
1248−
1249− reduce js = js
1250−
1251−
1252− reduceCall :: [String] -> JS -> JS
1253− reduceCall funs (JSApp (JSIdent "__IDRRT__tailcall") [JSFunction [] (
1254− JSReturn (JSApp id@(JSIdent ret) _)
1255− )])
1256− | ret `elem` funs = id
1257−
1258− reduceCall funs js@(JSApp id@(JSIdent fun) _)
1259− | fun `elem` funs = id
1260−
1261− reduceCall funs js = transformJS (reduceCall funs) js
1262−
1263−
1264−extractLocalConstructors :: [JS] -> [JS]
1265−extractLocalConstructors js =
1266− concatMap extractLocalConstructors' js
1267− where
1268− globalCons :: [String]
1269− globalCons = concatMap (getGlobalCons) js
1270−
1271−
1272− extractLocalConstructors' :: JS -> [JS]
1273− extractLocalConstructors' js@(JSAlloc fun (Just (JSFunction args body))) =
1274− addCons cons [foldr (uncurry jsSubst) js (reverse cons)]
1275− where
1276− cons :: [(JS, JS)]
1277− cons = zipWith genName (foldJS match (++) [] body) [1..]
1278− where
1279− genName :: JS -> Int -> (JS, JS)
1280− genName js id =
1281− (js, JSIdent $ idrCTRNamespace ++ fun ++ "_" ++ show id)
1282−
1283− match :: JS -> [JS]
1284− match js
1285− | JSNew "__IDRRT__Con" args <- js
1286− , all isConstant args = [js]
1287− | otherwise = []
1288−
1289−
1290− addCons :: [(JS, JS)] -> [JS] -> [JS]
1291− addCons [] js = js
1292− addCons (con@(_, name):cons) js
1293− | sum (map (countOccur name) js) > 0 =
1294− addCons cons ((allocCon con) : js)
1295− | otherwise =
1296− addCons cons js
1297−
1298−
1299− countOccur :: JS -> JS -> Int
1300− countOccur ident js = foldJS match (+) 0 js
1301− where
1302− match :: JS -> Int
1303− match js
1304− | js == ident = 1
1305− | otherwise = 0
1306−
1307−
1308− allocCon :: (JS, JS) -> JS
1309− allocCon (js, JSIdent name) =
1310− JSAlloc name (Just js)
1311−
1312−
1313− isConstant :: JS -> Bool
1314− isConstant js
1315− | JSNew "__IDRRT__Con" args <- js
1316− , all isConstant args =
1317− True
1318− | otherwise =
1319− isJSConstantConstructor globalCons js
1320−
1321− extractLocalConstructors' js = [js]
1322−
1323−
1324− getGlobalCons :: JS -> [String]
1325− getGlobalCons js = foldJS match (++) [] js
1326− where
1327− match :: JS -> [String]
1328− match js
1329− | (JSAlloc name (Just (JSNew "__IDRRT__Con" _))) <- js =
1330− [name]
1331− | otherwise =
1332− []
1333−
1334−
1335−evalCons :: [JS] -> [JS]
1336−evalCons js =
1337− map (collapseCont . collapseTC . expandProj . evalCons') js
1338− where
1339− cons :: [(String, JS)]
1340− cons = concatMap getGlobalCons js
1341−
1342− evalCons' :: JS -> JS
1343− evalCons' js = transformJS match js
1344− where
1345− match :: JS -> JS
1346− match (JSApp (JSIdent "__IDRRT__EVALTC") [arg])
1347− | JSIdent name <- arg
1348− , Just (JSNew _ [_, JSNull, _, _]) <- lookupConstructor name cons =
1349− arg
1350−
1351− match (JSApp (JSIdent "__IDR__mEVAL0") [arg])
1352− | JSIdent name <- arg
1353− , Just (JSNew _ [_, JSNull, _, _]) <- lookupConstructor name cons =
1354− arg
1355−
1356− match js = transformJS match js
1357−
1358−
1359− lookupConstructor :: String -> [(String, JS)] -> Maybe JS
1360− lookupConstructor ctr cons
1361− | Just (JSIdent name) <- lookup ctr cons = lookupConstructor name cons
1362− | Just con@(JSNew _ _) <- lookup ctr cons = Just con
1363− | otherwise = Nothing
1364−
1365−
1366− expandProj :: JS -> JS
1367− expandProj js = transformJS match js
1368− where
1369− match :: JS -> JS
1370− match (
1371− JSIndex (
1372− JSProj (JSIdent name) "vars"
1293+ | (LSRem (ATInt (ITFixed IT32))) <- op
1294+ , (lhs:rhs:_) <- args =
1295+ jsPackSBits32 (
1296+ JSBinOp "%" (
1297+ jsUnPackBits $ jsPackSBits32 $ jsUnPackBits (translateReg lhs)
13731298 ) (
1374− JSNum (JSInt idx)
1299+ jsUnPackBits $ jsPackSBits32 $ jsUnPackBits (translateReg rhs)
13751300 )
13761301 )
1377− | Just (JSNew _ [_, _, _, JSArray args]) <- lookup name cons =
1378− args !! idx
1379−
1380− match js = transformJS match js
1381−
1382−
1383− collapseTC :: JS -> JS
1384− collapseTC js = transformJS match js
1385− where
1386− match :: JS -> JS
1387− match (JSApp (JSIdent "__IDRRT__tailcall") [JSFunction [] (
1388− JSReturn (JSIdent name)
1389− )])
1390− | Just _ <- lookup name cons = (JSIdent name)
13911302
1392− match js = transformJS match js
1393−
1394−
1395− collapseCont :: JS -> JS
1396− collapseCont js = transformJS match js
1397− where
1398− match :: JS -> JS
1399− match (JSNew "__IDRRT__Cont" [JSFunction [] (
1400− JSReturn ret@(JSNew "__IDRRT__Cont" [JSFunction [] _])
1401− )]) = collapseCont ret
1402−
1403−
1404− match (JSNew "__IDRRT__Cont" [JSFunction [] (
1405− JSReturn (JSIdent name)
1406− )]) = JSIdent name
1407−
1408− match (JSNew "__IDRRT__Cont" [JSFunction [] (
1409− JSReturn ret@(JSNew "__IDRRT__Con" [_, _, _, JSArray args])
1410− )])
1411− | all collapsable args = ret
1412− where
1413− collapsable :: JS -> Bool
1414− collapsable (JSIdent _) = True
1415− collapsable js = isJSConstantConstructor (map fst cons) js
1416−
1417−
1418− match js = transformJS match js
1419−
1420−
1421−elimConds :: [JS] -> [JS]
1422−elimConds js =
1423− let (conds, rest) = partition isCond js in
1424− foldl' eraseCond rest conds
1425− where
1426− isCond :: JS -> Bool
1427− isCond (JSAlloc
1428− fun (Just (JSFunction args (JSCond
1429− [ (JSBinOp "==" (JSNum (JSInt tag)) (JSProj (JSIdent _) "tag"), JSReturn t)
1430− , (JSNoop, JSReturn f)
1431− ])))
1432− )
1433− | isJSConstant t && isJSConstant f =
1434− True
1435−
1436− | JSIdent _ <- t
1437− , JSIdent _ <- f =
1438− True
1439−
1440− isCond (JSAlloc
1441− fun (Just (JSFunction args (JSCond
1442− [ (JSBinOp "==" (JSIdent _) c, JSReturn t)
1443− , (JSNoop, JSReturn f)
1444− ])))
1445− )
1446− | isJSConstant t && isJSConstant f && isJSConstant c =
1447− True
1448−
1449− | JSIdent _ <- t
1450− , JSIdent _ <- f
1451− , isJSConstant c =
1452− True
1453−
1454− isCond _ = False
1455−
1456−
1457− eraseCond :: [JS] -> JS -> [JS]
1458− eraseCond js (JSAlloc
1459− fun (Just (JSFunction args (JSCond
1460− [ (c, JSReturn t)
1461− , (_, JSReturn f)
1462− ])
1463− )
1464− )) = map (inlineFunction fun args (JSTernary c t f)) js
1465−
1466−
1467−removeUselessCons :: [JS] -> [JS]
1468−removeUselessCons js =
1469− let (cons, rest) = partition isUseless js in
1470− foldl' eraseCon rest cons
1471− where
1472− isUseless :: JS -> Bool
1473− isUseless (JSAlloc fun (Just JSNull)) = True
1474− isUseless (JSAlloc fun (Just (JSIdent _))) = True
1475− isUseless _ = False
1476−
1477−
1478− eraseCon :: [JS] -> JS -> [JS]
1479− eraseCon js (JSAlloc fun (Just val)) = map (jsSubst (JSIdent fun) val) js
1480−
1481−
1482−getGlobalCons :: JS -> [(String, JS)]
1483−getGlobalCons js = foldJS match (++) [] js
1484− where
1485− match :: JS -> [(String, JS)]
1486− match js
1487− | (JSAlloc name (Just con@(JSNew "__IDRRT__Con" _))) <- js =
1488− [(name, con)]
1489− | (JSAlloc name (Just con@(JSIdent _))) <- js =
1490− [(name, con)]
1491− | otherwise =
1492− []
1493−
1494−
1495−getIncludes :: [FilePath] -> IO [String]
1496−getIncludes = mapM readFile
1497−
1498−codegenJavaScript :: CodeGenerator
1499−codegenJavaScript ci = codegenJS_all JavaScript (simpleDecls ci)
1500− (includes ci) (outputFile ci) (outputType ci)
1501−
1502−codegenNode :: CodeGenerator
1503−codegenNode ci = codegenJS_all Node (simpleDecls ci)
1504− (includes ci) (outputFile ci) (outputType ci)
1505−
1506−codegenJS_all
1507− :: JSTarget
1508− -> [(Name, SDecl)]
1509− -> [FilePath]
1510− -> FilePath
1511− -> OutputType
1512− -> IO ()
1513−codegenJS_all target definitions includes filename outputType = do
1514− let (header, rt) = case target of
1515− Node ->
1516− ("#!/usr/bin/env node\n", "-node")
1517− JavaScript ->
1518− ("", "-browser")
1519− included <- getIncludes includes
1520− path <- (++) <$> getDataDir <*> (pure "/jsrts/")
1521− idrRuntime <- readFile $ path ++ "Runtime-common.js"
1522− tgtRuntime <- readFile $ concat [path, "Runtime", rt, ".js"]
1523− jsbn <- readFile $ path ++ "jsbn/jsbn.js"
1524− writeFile filename $ header ++ (
1525− intercalate "\n" $ included ++ runtime jsbn idrRuntime tgtRuntime ++ functions
1526− )
1527−
1528− setPermissions filename (emptyPermissions { readable = True
1529− , executable = target == Node
1530− , writable = True
1531− })
1532− where
1533− def :: [(String, SDecl)]
1534− def = map (first translateNamespace) definitions
1535−
1536−
1537− checkForBigInt :: [JS] -> Bool
1538− checkForBigInt js = occur
1539− where
1540− occur :: Bool
1541− occur = or $ map (foldJS match (||) False) js
1542−
1543− match :: JS -> Bool
1544− match (JSIdent "__IDRRT__bigInt") = True
1545− match (JSWord (JSWord64 _)) = True
1546− match (JSNum (JSInteger _)) = True
1547− match js = False
1548−
1549−
1550− runtime :: String -> String -> String -> [String]
1551− runtime jsbn idrRuntime tgtRuntime =
1552− if checkForBigInt optimized
1553− then [jsbn, idrRuntime, tgtRuntime]
1554− else [idrRuntime, tgtRuntime]
1555−
1556−
1557− optimized :: [JS]
1558− optimized = translate >>> optimize $ def
1559− where
1560− translate p =
1561− prelude ++ concatMap translateDeclaration p ++ [mainLoop, invokeLoop]
1562− optimize p =
1563− foldl' (flip ($)) p opt
1564−
1565− opt =
1566− [ removeEval
1567− , map inlineJS
1568− , removeIDs
1569− , reduceJS
1570− , map reduceConstants
1571− , initConstructors
1572− , map removeAllocations
1573− , elimDeadLoop
1574− , map elimDuplicateEvals
1575− , optimizeRuntimeCalls "__IDR__mEVAL0" "__IDRRT__EVALTC"
1576− , optimizeRuntimeCalls "__IDR__mAPPLY0" "__IDRRT__APPLYTC"
1577− , map removeInstanceChecks
1578− , inlineFunctions
1579− , map reduceContinuations
1580− , extractLocalConstructors
1581− , unfoldLookupTable
1582− , evalCons
1583− , elimConds
1584− , removeUselessCons
1585− ]
1586−
1587− functions :: [String]
1588− functions = map compileJS optimized
1589−
1590− prelude :: [JS]
1591− prelude =
1592− [ JSAnnotation JSConstructor $
1593− JSAlloc (idrRTNamespace ++ "Cont") (Just $ JSFunction ["k"] (
1594− JSAssign (JSProj JSThis "k") (JSIdent "k")
1595− ))
1596− , JSAnnotation JSConstructor $
1597− JSAlloc (idrRTNamespace ++ "Con") (Just $ JSFunction ["tag", "vars"] (
1598− JSSeq [ JSAssign (JSProj JSThis "tag") (JSIdent "tag")
1599− , JSAssign (JSProj JSThis "vars") (JSIdent "vars")
1600− ]
1601− ))
1602− ]
1603−
1604− mainLoop :: JS
1605− mainLoop =
1606− JSAlloc "main" $ Just $ JSFunction [] (
1607− case target of
1608− Node -> mainFun
1609− JavaScript -> JSCond [ (exists document `jsAnd` isReady, mainFun)
1610− , (exists window, windowMainFun)
1611− , (JSTrue, mainFun)
1612− ]
1613− )
1614− where
1615− exists :: JS -> JS
1616− exists js = (JSPreOp "typeof " js) `jsNotEq` JSString "undefined"
1617−
1618− mainFun :: JS
1619− mainFun = jsTailcall $ jsCall runMain []
1620−
1621− window :: JS
1622− window = JSIdent "window"
1623−
1624− document :: JS
1625− document = JSIdent "document"
1626−
1627− windowMainFun :: JS
1628− windowMainFun = jsMeth window "addEventListener" [
1629− JSString "DOMContentLoaded"
1630− , JSFunction [] ( mainFun )
1631− , JSFalse
1632− ]
1633−
1634− isReady :: JS
1635− isReady = JSParens $ readyState `jsEq` JSString "complete" `jsOr` readyState `jsEq` JSString "loaded"
1636−
1637− readyState :: JS
1638− readyState = JSProj (JSIdent "document") "readyState"
1639−
1640−
1641− runMain :: String
1642− runMain = idrNamespace ++ translateName (sMN 0 "runMain")
1643−
1644−
1645− invokeLoop :: JS
1646− invokeLoop = jsCall "main" []
1647−
1648−
1649−translateIdentifier :: String -> String
1650−translateIdentifier =
1651− replaceReserved . concatMap replaceBadChars
1652− where replaceBadChars :: Char -> String
1653− replaceBadChars c
1654− | ' ' <- c = "_"
1655− | '_' <- c = "__"
1656− | isDigit c = '_' : show (ord c)
1657− | not (isLetter c && isAscii c) = '_' : show (ord c)
1658− | otherwise = [c]
1659− replaceReserved s
1660− | s `elem` reserved = '_' : s
1661− | otherwise = s
1662−
1663−
1664− reserved = [ "break"
1665− , "case"
1666− , "catch"
1667− , "continue"
1668− , "debugger"
1669− , "default"
1670− , "delete"
1671− , "do"
1672− , "else"
1673− , "finally"
1674− , "for"
1675− , "function"
1676− , "if"
1677− , "in"
1678− , "instanceof"
1679− , "new"
1680− , "return"
1681− , "switch"
1682− , "this"
1683− , "throw"
1684− , "try"
1685− , "typeof"
1686− , "var"
1687− , "void"
1688− , "while"
1689− , "with"
1690−
1691− , "class"
1692− , "enum"
1693− , "export"
1694− , "extends"
1695− , "import"
1696− , "super"
1697−
1698− , "implements"
1699− , "interface"
1700− , "let"
1701− , "package"
1702− , "private"
1703− , "protected"
1704− , "public"
1705− , "static"
1706− , "yield"
1707− ]
1708−
1709−
1710−translateNamespace :: Name -> String
1711−translateNamespace (UN _) = idrNamespace
1712−translateNamespace (NS _ ns) = idrNamespace ++ concatMap (translateIdentifier . str) ns
1713−translateNamespace (MN _ _) = idrNamespace
1714−translateNamespace (SN name) = idrNamespace ++ translateSpecialName name
1715−translateNamespace NErased = idrNamespace
1716−
1717−
1718−translateName :: Name -> String
1719−translateName (UN name) = 'u' : translateIdentifier (str name)
1720−translateName (NS name _) = 'n' : translateName name
1721−translateName (MN i name) = 'm' : translateIdentifier (str name) ++ show i
1722−translateName (SN name) = 's' : translateSpecialName name
1723−translateName NErased = "e"
1724−
1725−
1726−translateSpecialName :: SpecialName -> String
1727−translateSpecialName name
1728− | WhereN i m n <- name =
1729− 'w' : translateName m ++ translateName n ++ show i
1730− | InstanceN n s <- name =
1731− 'i' : translateName n ++ concatMap (translateIdentifier . str) s
1732− | ParentN n s <- name =
1733− 'p' : translateName n ++ translateIdentifier (str s)
1734− | MethodN n <- name =
1735− 'm' : translateName n
1736− | CaseN n <- name =
1737− 'c' : translateName n
1738−
1739−
1740−translateConstant :: Const -> JS
1741−translateConstant (I i) = JSNum (JSInt i)
1742−translateConstant (Fl f) = JSNum (JSFloat f)
1743−translateConstant (Ch c) = JSString $ translateChar c
1744−translateConstant (Str s) = JSString $ concatMap translateChar s
1745−translateConstant (AType (ATInt ITNative)) = JSType JSIntTy
1746−translateConstant StrType = JSType JSStringTy
1747−translateConstant (AType (ATInt ITBig)) = JSType JSIntegerTy
1748−translateConstant (AType ATFloat) = JSType JSFloatTy
1749−translateConstant (AType (ATInt ITChar)) = JSType JSCharTy
1750−translateConstant PtrType = JSType JSPtrTy
1751−translateConstant Forgot = JSType JSForgotTy
1752−translateConstant (BI i) = jsBigInt $ JSString (show i)
1753−translateConstant (B8 b) = JSWord (JSWord8 b)
1754−translateConstant (B16 b) = JSWord (JSWord16 b)
1755−translateConstant (B32 b) = JSWord (JSWord32 b)
1756−translateConstant (B64 b) = JSWord (JSWord64 b)
1757−translateConstant c =
1758− jsError $ "Unimplemented Constant: " ++ show c
1759−
1760−
1761−translateChar :: Char -> String
1762−translateChar ch
1763− | '\a' <- ch = "\\u0007"
1764− | '\b' <- ch = "\\b"
1765− | '\f' <- ch = "\\f"
1766− | '\n' <- ch = "\\n"
1767− | '\r' <- ch = "\\r"
1768− | '\t' <- ch = "\\t"
1769− | '\v' <- ch = "\\v"
1770− | '\SO' <- ch = "\\u000E"
1771− | '\DEL' <- ch = "\\u007F"
1772− | '\\' <- ch = "\\\\"
1773− | '\"' <- ch = "\\\""
1774− | '\'' <- ch = "\\\'"
1775− | ch `elem` asciiTab = "\\u00" ++ fill (showIntAtBase 16 intToDigit (ord ch) "")
1776− | otherwise = [ch]
1777− where
1778− fill :: String -> String
1779− fill s = if length s == 1
1780− then '0' : s
1781− else s
1782−
1783− asciiTab =
1784− ['\NUL', '\SOH', '\STX', '\ETX', '\EOT', '\ENQ', '\ACK', '\BEL',
1785− '\BS', '\HT', '\LF', '\VT', '\FF', '\CR', '\SO', '\SI',
1786− '\DLE', '\DC1', '\DC2', '\DC3', '\DC4', '\NAK', '\SYN', '\ETB',
1787− '\CAN', '\EM', '\SUB', '\ESC', '\FS', '\GS', '\RS', '\US']
1788−
1789−
1790−translateDeclaration :: (String, SDecl) -> [JS]
1791−translateDeclaration (path, SFun name params stackSize body)
1792− | (MN _ ap) <- name
1793− , (SChkCase var cases) <- body
1794− , ap == txt "APPLY" =
1795− [ lookupTable "APPLY" [] var cases
1796− , jsDecl $ JSFunction ["mfn0", "marg0"] (JSReturn $
1797− JSTernary (
1798− (JSIdent "mfn0" `jsInstanceOf` jsCon) `jsAnd`
1799− (hasProp (idrLTNamespace ++ "APPLY") "mfn0")
1800− ) (JSApp
1801− (JSIndex
1802− (JSIdent (idrLTNamespace ++ "APPLY"))
1803− (JSProj (JSIdent "mfn0") "tag")
1804− )
1805− [JSIdent "mfn0", JSIdent "marg0"]
1806− ) JSNull
1807− )
1808− ]
1809−
1810− | (MN _ ev) <- name
1811− , (SChkCase var cases) <- body
1812− , ev == txt "EVAL" =
1813− [ lookupTable "EVAL" [] var cases
1814− , jsDecl $ JSFunction ["marg0"] (JSReturn $
1815− JSTernary (
1816− (JSIdent "marg0" `jsInstanceOf` jsCon) `jsAnd`
1817− (hasProp (idrLTNamespace ++ "EVAL") "marg0")
1818− ) (JSApp
1819− (JSIndex
1820− (JSIdent (idrLTNamespace ++ "EVAL"))
1821− (JSProj (JSIdent "marg0") "tag")
1822− )
1823− [JSIdent "marg0"]
1824− ) (JSIdent "marg0")
1825− )
1826− ]
1827− | otherwise =
1828− let fun = translateExpression body in
1829− [jsDecl $ jsFun fun]
1830−
1831− where
1832− hasProp :: String -> String -> JS
1833− hasProp table var =
1834− JSIndex (JSIdent table) (JSProj (JSIdent var) "tag")
1835−
1836−
1837− caseFun :: [(LVar, String)] -> LVar -> SAlt -> JS
1838− caseFun aux var cse =
1839− let (JSReturn c) = translateCase (Just (translateVariableName var)) cse in
1840− jsFunAux aux c
1841−
1842−
1843− getTag :: SAlt -> Maybe Int
1844− getTag (SConCase _ tag _ _ _) = Just tag
1845− getTag _ = Nothing
1846−
1847−
1848− lookupTable :: String -> [(LVar, String)] -> LVar -> [SAlt] -> JS
1849− lookupTable table aux var cases =
1850− JSAlloc (idrLTNamespace ++ table) $ Just (
1851− JSApp (JSFunction [] (
1852− JSSeq $ [
1853− JSAlloc "t" $ Just (JSArray [])
1854− ] ++ assignEntries (catMaybes $ map (lookupEntry aux var) cases) ++ [
1855− JSReturn (JSIdent "t")
1856− ]
1857− )) []
1858− )
1859− where
1860− assignEntries :: [(Int, JS)] -> [JS]
1861− assignEntries entries =
1862− map (\(tag, fun) ->
1863− JSAssign (JSIndex (JSIdent "t") (JSNum $ JSInt tag)) fun
1864− ) entries
1865−
1866−
1867− lookupEntry :: [(LVar, String)] -> LVar -> SAlt -> Maybe (Int, JS)
1868− lookupEntry aux var alt = do
1869− tag <- getTag alt
1870− return (tag, caseFun aux var alt)
1871−
1872−
1873− jsDecl :: JS -> JS
1874− jsDecl = JSAlloc (path ++ translateName name) . Just
1875−
1876−
1877− jsFun body = jsFunAux [] body
1878−
1879−
1880− jsFunAux :: [(LVar, String)] -> JS -> JS
1881− jsFunAux aux body =
1882− JSFunction (p ++ map snd aux) (
1883− JSSeq $
1884− zipWith assignVar [0..] p ++
1885− map assignAux aux ++
1886− [JSReturn body]
1887− )
1888− where
1889− assignVar :: Int -> String -> JS
1890− assignVar n s = JSAlloc (jsVar n) (Just $ JSIdent s)
1891−
1892−
1893− assignAux :: (LVar, String) -> JS
1894− assignAux (Loc var, val) =
1895− JSAlloc (jsVar var) (Just $ JSIdent val)
1896−
1897−
1898− p :: [String]
1899− p = map translateName params
1900−
1901−
1902−translateVariableName :: LVar -> String
1903−translateVariableName (Loc i) =
1904− jsVar i
1905−
1906−
1907−translateExpression :: SExp -> JS
1908−translateExpression (SLet name value body) =
1909− jsLet (translateVariableName name) (
1910− translateExpression value
1911− ) (translateExpression body)
1912−
1913−translateExpression (SConst cst) =
1914− translateConstant cst
1915−
1916−translateExpression (SV var) =
1917− JSVar var
1918−
1919−translateExpression (SApp tc name vars)
1920− | False <- tc =
1921− jsTailcall $ translateFunctionCall name vars
1922− | True <- tc =
1923− JSNew (idrRTNamespace ++ "Cont") [JSFunction [] (
1924− JSReturn $ translateFunctionCall name vars
1925− )]
1926− where
1927− translateFunctionCall name vars =
1928− jsCall (translateNamespace name ++ translateName name) (map JSVar vars)
1929−
1930−translateExpression (SOp op vars)
1931− | LNoOp <- op = JSVar (last vars)
1932−
1933− | (LZExt (ITFixed IT8) ITNative) <- op = jsUnPackBits $ JSVar (last vars)
1934− | (LZExt (ITFixed IT16) ITNative) <- op = jsUnPackBits $ JSVar (last vars)
1935− | (LZExt (ITFixed IT32) ITNative) <- op = jsUnPackBits $ JSVar (last vars)
1936−
1937− | (LZExt _ ITBig) <- op = jsBigInt $ jsCall "String" [JSVar (last vars)]
1938− | (LPlus (ATInt ITBig)) <- op
1939− , (lhs:rhs:_) <- vars = invokeMeth lhs "add" [rhs]
1940− | (LMinus (ATInt ITBig)) <- op
1941− , (lhs:rhs:_) <- vars = invokeMeth lhs "subtract" [rhs]
1942− | (LTimes (ATInt ITBig)) <- op
1943− , (lhs:rhs:_) <- vars = invokeMeth lhs "multiply" [rhs]
1944− | (LSDiv (ATInt ITBig)) <- op
1945− , (lhs:rhs:_) <- vars = invokeMeth lhs "divide" [rhs]
1946− | (LSRem (ATInt ITBig)) <- op
1947− , (lhs:rhs:_) <- vars = invokeMeth lhs "mod" [rhs]
1948− | (LEq (ATInt ITBig)) <- op
1949− , (lhs:rhs:_) <- vars = invokeMeth lhs "equals" [rhs]
1950− | (LSLt (ATInt ITBig)) <- op
1951− , (lhs:rhs:_) <- vars = invokeMeth lhs "lesser" [rhs]
1952− | (LSLe (ATInt ITBig)) <- op
1953− , (lhs:rhs:_) <- vars = invokeMeth lhs "lesserOrEquals" [rhs]
1954− | (LSGt (ATInt ITBig)) <- op
1955− , (lhs:rhs:_) <- vars = invokeMeth lhs "greater" [rhs]
1956− | (LSGe (ATInt ITBig)) <- op
1957− , (lhs:rhs:_) <- vars = invokeMeth lhs "greaterOrEquals" [rhs]
1958−
1959− | (LPlus ATFloat) <- op
1960− , (lhs:rhs:_) <- vars = translateBinaryOp "+" lhs rhs
1961− | (LMinus ATFloat) <- op
1962− , (lhs:rhs:_) <- vars = translateBinaryOp "-" lhs rhs
1963− | (LTimes ATFloat) <- op
1964− , (lhs:rhs:_) <- vars = translateBinaryOp "*" lhs rhs
1965− | (LSDiv ATFloat) <- op
1966− , (lhs:rhs:_) <- vars = translateBinaryOp "/" lhs rhs
1967− | (LEq ATFloat) <- op
1968− , (lhs:rhs:_) <- vars = translateBinaryOp "==" lhs rhs
1969− | (LSLt ATFloat) <- op
1970− , (lhs:rhs:_) <- vars = translateBinaryOp "<" lhs rhs
1971− | (LSLe ATFloat) <- op
1972− , (lhs:rhs:_) <- vars = translateBinaryOp "<=" lhs rhs
1973− | (LSGt ATFloat) <- op
1974− , (lhs:rhs:_) <- vars = translateBinaryOp ">" lhs rhs
1975− | (LSGe ATFloat) <- op
1976− , (lhs:rhs:_) <- vars = translateBinaryOp ">=" lhs rhs
1977−
1978− | (LPlus (ATInt ITChar)) <- op
1979− , (lhs:rhs:_) <- vars =
1980− jsCall "__IDRRT__fromCharCode" [
1981− JSBinOp "+" (
1982− jsCall "__IDRRT__charCode" [JSVar lhs]
1983− ) (
1984− jsCall "__IDRRT__charCode" [JSVar rhs]
1985− )
1986− ]
1987−
1988− | (LTrunc (ITFixed IT16) (ITFixed IT8)) <- op
1989− , (arg:_) <- vars =
1990− jsPackUBits8 (
1991− JSBinOp "&" (jsUnPackBits $ JSVar arg) (JSNum (JSInt 0xFF))
1992− )
1993−
1994− | (LTrunc (ITFixed IT32) (ITFixed IT16)) <- op
1995− , (arg:_) <- vars =
1996− jsPackUBits16 (
1997− JSBinOp "&" (jsUnPackBits $ JSVar arg) (JSNum (JSInt 0xFFFF))
1998− )
1999−
2000− | (LTrunc (ITFixed IT64) (ITFixed IT32)) <- op
2001− , (arg:_) <- vars =
2002− jsPackUBits32 (
2003− jsMeth (jsMeth (JSVar arg) "and" [
2004− jsBigInt (JSString $ show 0xFFFFFFFF)
2005− ]) "intValue" []
2006− )
2007−
2008− | (LTrunc ITBig (ITFixed IT64)) <- op
2009− , (arg:_) <- vars =
2010− jsMeth (JSVar arg) "and" [
2011− jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
2012− ]
2013−
2014− | (LLSHR (ITFixed IT8)) <- op
2015− , (lhs:rhs:_) <- vars =
2016− jsPackUBits8 (
2017− JSBinOp ">>" (jsUnPackBits $ JSVar lhs) (jsUnPackBits $ JSVar rhs)
2018− )
2019−
2020− | (LLSHR (ITFixed IT16)) <- op
2021− , (lhs:rhs:_) <- vars =
2022− jsPackUBits16 (
2023− JSBinOp ">>" (jsUnPackBits $ JSVar lhs) (jsUnPackBits $ JSVar rhs)
2024− )
2025−
2026− | (LLSHR (ITFixed IT32)) <- op
2027− , (lhs:rhs:_) <- vars =
2028− jsPackUBits32 (
2029− JSBinOp ">>" (jsUnPackBits $ JSVar lhs) (jsUnPackBits $ JSVar rhs)
2030− )
2031−
2032− | (LLSHR (ITFixed IT64)) <- op
2033− , (lhs:rhs:_) <- vars =
2034− jsMeth (JSVar lhs) "shiftRight" [JSVar rhs]
2035−
2036− | (LSHL (ITFixed IT8)) <- op
2037− , (lhs:rhs:_) <- vars =
2038− jsPackUBits8 (
2039− JSBinOp "<<" (jsUnPackBits $ JSVar lhs) (jsUnPackBits $ JSVar rhs)
2040− )
2041−
2042− | (LSHL (ITFixed IT16)) <- op
2043− , (lhs:rhs:_) <- vars =
2044− jsPackUBits16 (
2045− JSBinOp "<<" (jsUnPackBits $ JSVar lhs) (jsUnPackBits $ JSVar rhs)
2046− )
2047−
2048− | (LSHL (ITFixed IT32)) <- op
2049− , (lhs:rhs:_) <- vars =
2050− jsPackUBits32 (
2051− JSBinOp "<<" (jsUnPackBits $ JSVar lhs) (jsUnPackBits $ JSVar rhs)
2052− )
2053−
2054− | (LSHL (ITFixed IT64)) <- op
2055− , (lhs:rhs:_) <- vars =
2056− jsMeth (jsMeth (JSVar lhs) "shiftLeft" [JSVar rhs]) "and" [
2057− jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
2058− ]
2059−
2060− | (LAnd (ITFixed IT8)) <- op
2061− , (lhs:rhs:_) <- vars =
2062− jsPackUBits8 (
2063− JSBinOp "&" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2064− )
2065−
2066− | (LAnd (ITFixed IT16)) <- op
2067− , (lhs:rhs:_) <- vars =
2068− jsPackUBits16 (
2069− JSBinOp "&" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2070− )
2071−
2072− | (LAnd (ITFixed IT32)) <- op
2073− , (lhs:rhs:_) <- vars =
2074− jsPackUBits32 (
2075− JSBinOp "&" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2076− )
2077−
2078− | (LAnd (ITFixed IT64)) <- op
2079− , (lhs:rhs:_) <- vars =
2080− jsMeth (JSVar lhs) "and" [JSVar rhs]
2081−
2082− | (LOr (ITFixed IT8)) <- op
2083− , (lhs:rhs:_) <- vars =
2084− jsPackUBits8 (
2085− JSBinOp "|" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2086− )
2087−
2088− | (LOr (ITFixed IT16)) <- op
2089− , (lhs:rhs:_) <- vars =
2090− jsPackUBits16 (
2091− JSBinOp "|" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2092− )
2093−
2094− | (LOr (ITFixed IT32)) <- op
2095− , (lhs:rhs:_) <- vars =
2096− jsPackUBits32 (
2097− JSBinOp "|" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2098− )
2099−
2100− | (LOr (ITFixed IT64)) <- op
2101− , (lhs:rhs:_) <- vars =
2102− jsMeth (JSVar lhs) "or" [JSVar rhs]
2103−
2104− | (LXOr (ITFixed IT8)) <- op
2105− , (lhs:rhs:_) <- vars =
2106− jsPackUBits8 (
2107− JSBinOp "^" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2108− )
2109−
2110− | (LXOr (ITFixed IT16)) <- op
2111− , (lhs:rhs:_) <- vars =
2112− jsPackUBits16 (
2113− JSBinOp "^" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2114− )
2115−
2116− | (LXOr (ITFixed IT32)) <- op
2117− , (lhs:rhs:_) <- vars =
2118− jsPackUBits32 (
2119− JSBinOp "^" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2120− )
2121−
2122− | (LXOr (ITFixed IT64)) <- op
2123− , (lhs:rhs:_) <- vars =
2124− jsMeth (JSVar lhs) "xor" [JSVar rhs]
2125−
2126− | (LPlus (ATInt (ITFixed IT8))) <- op
2127− , (lhs:rhs:_) <- vars =
2128− jsPackUBits8 (
2129− JSBinOp "+" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2130− )
2131−
2132− | (LPlus (ATInt (ITFixed IT16))) <- op
2133− , (lhs:rhs:_) <- vars =
2134− jsPackUBits16 (
2135− JSBinOp "+" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2136− )
2137−
2138− | (LPlus (ATInt (ITFixed IT32))) <- op
2139− , (lhs:rhs:_) <- vars =
2140− jsPackUBits32 (
2141− JSBinOp "+" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2142− )
2143−
2144− | (LPlus (ATInt (ITFixed IT64))) <- op
2145− , (lhs:rhs:_) <- vars =
2146− jsMeth (jsMeth (JSVar lhs) "add" [JSVar rhs]) "and" [
2147− jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
2148− ]
2149−
2150− | (LMinus (ATInt (ITFixed IT8))) <- op
2151− , (lhs:rhs:_) <- vars =
2152− jsPackUBits8 (
2153− JSBinOp "-" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2154− )
2155−
2156− | (LMinus (ATInt (ITFixed IT16))) <- op
2157− , (lhs:rhs:_) <- vars =
2158− jsPackUBits16 (
2159− JSBinOp "-" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2160− )
2161−
2162− | (LMinus (ATInt (ITFixed IT32))) <- op
2163− , (lhs:rhs:_) <- vars =
2164− jsPackUBits32 (
2165− JSBinOp "-" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2166− )
2167−
2168− | (LMinus (ATInt (ITFixed IT64))) <- op
2169− , (lhs:rhs:_) <- vars =
2170− jsMeth (jsMeth (JSVar lhs) "subtract" [JSVar rhs]) "and" [
2171− jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
2172− ]
2173−
2174− | (LTimes (ATInt (ITFixed IT8))) <- op
2175− , (lhs:rhs:_) <- vars =
2176− jsPackUBits8 (
2177− JSBinOp "*" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2178− )
2179−
2180− | (LTimes (ATInt (ITFixed IT16))) <- op
2181− , (lhs:rhs:_) <- vars =
2182− jsPackUBits16 (
2183− JSBinOp "*" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2184− )
2185−
2186− | (LTimes (ATInt (ITFixed IT32))) <- op
2187− , (lhs:rhs:_) <- vars =
2188− jsPackUBits32 (
2189− JSBinOp "*" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2190− )
2191−
2192− | (LTimes (ATInt (ITFixed IT64))) <- op
2193− , (lhs:rhs:_) <- vars =
2194− jsMeth (jsMeth (JSVar lhs) "multiply" [JSVar rhs]) "and" [
2195− jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
2196− ]
2197−
2198− | (LEq (ATInt (ITFixed IT8))) <- op
2199− , (lhs:rhs:_) <- vars =
2200− jsPackUBits8 (
2201− JSBinOp "==" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2202− )
2203−
2204− | (LEq (ATInt (ITFixed IT16))) <- op
2205− , (lhs:rhs:_) <- vars =
2206− jsPackUBits16 (
2207− JSBinOp "==" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2208− )
2209−
2210− | (LEq (ATInt (ITFixed IT32))) <- op
2211− , (lhs:rhs:_) <- vars =
2212− jsPackUBits32 (
2213− JSBinOp "==" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2214− )
2215−
2216− | (LEq (ATInt (ITFixed IT64))) <- op
2217− , (lhs:rhs:_) <- vars =
2218− jsMeth (jsMeth (JSVar lhs) "equals" [JSVar rhs]) "and" [
2219− jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
2220− ]
2221−
2222− | (LLt (ITFixed IT8)) <- op
2223− , (lhs:rhs:_) <- vars =
2224− jsPackUBits8 (
2225− JSBinOp "<" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2226− )
2227−
2228− | (LLt (ITFixed IT16)) <- op
2229− , (lhs:rhs:_) <- vars =
2230− jsPackUBits16 (
2231− JSBinOp "<" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2232− )
2233−
2234− | (LLt (ITFixed IT32)) <- op
2235− , (lhs:rhs:_) <- vars =
2236− jsPackUBits32 (
2237− JSBinOp "<" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2238− )
2239−
2240− | (LLt (ITFixed IT64)) <- op
2241− , (lhs:rhs:_) <- vars = invokeMeth lhs "lesser" [rhs]
2242−
2243− | (LLe (ITFixed IT8)) <- op
2244− , (lhs:rhs:_) <- vars =
2245− jsPackUBits8 (
2246− JSBinOp "<=" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2247− )
2248−
2249− | (LLe (ITFixed IT16)) <- op
2250− , (lhs:rhs:_) <- vars =
2251− jsPackUBits16 (
2252− JSBinOp "<=" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2253− )
2254−
2255− | (LLe (ITFixed IT32)) <- op
2256− , (lhs:rhs:_) <- vars =
2257− jsPackUBits32 (
2258− JSBinOp "<=" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2259− )
2260−
2261− | (LLe (ITFixed IT64)) <- op
2262− , (lhs:rhs:_) <- vars = invokeMeth lhs "lesserOrEquals" [rhs]
2263−
2264− | (LGt (ITFixed IT8)) <- op
2265− , (lhs:rhs:_) <- vars =
2266− jsPackUBits8 (
2267− JSBinOp ">" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2268− )
2269−
2270− | (LGt (ITFixed IT16)) <- op
2271− , (lhs:rhs:_) <- vars =
2272− jsPackUBits16 (
2273− JSBinOp ">" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2274− )
2275− | (LGt (ITFixed IT32)) <- op
2276− , (lhs:rhs:_) <- vars =
2277− jsPackUBits32 (
2278− JSBinOp ">" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2279− )
2280−
2281− | (LGt (ITFixed IT64)) <- op
2282− , (lhs:rhs:_) <- vars = invokeMeth lhs "greater" [rhs]
2283−
2284− | (LGe (ITFixed IT8)) <- op
2285− , (lhs:rhs:_) <- vars =
2286− jsPackUBits8 (
2287− JSBinOp ">=" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2288− )
2289−
2290− | (LGe (ITFixed IT16)) <- op
2291− , (lhs:rhs:_) <- vars =
2292− jsPackUBits16 (
2293− JSBinOp ">=" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2294− )
2295− | (LGe (ITFixed IT32)) <- op
2296− , (lhs:rhs:_) <- vars =
2297− jsPackUBits32 (
2298− JSBinOp ">=" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2299− )
2300−
2301− | (LGe (ITFixed IT64)) <- op
2302− , (lhs:rhs:_) <- vars = invokeMeth lhs "greaterOrEquals" [rhs]
2303−
2304− | (LUDiv (ITFixed IT8)) <- op
2305− , (lhs:rhs:_) <- vars =
2306− jsPackUBits8 (
2307− JSBinOp "/" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2308− )
2309−
2310− | (LUDiv (ITFixed IT16)) <- op
2311− , (lhs:rhs:_) <- vars =
2312− jsPackUBits16 (
2313− JSBinOp "/" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2314− )
2315−
2316− | (LUDiv (ITFixed IT32)) <- op
2317− , (lhs:rhs:_) <- vars =
2318− jsPackUBits32 (
2319− JSBinOp "/" (jsUnPackBits (JSVar lhs)) (jsUnPackBits (JSVar rhs))
2320− )
2321−
2322− | (LUDiv (ITFixed IT64)) <- op
2323− , (lhs:rhs:_) <- vars = invokeMeth lhs "divide" [rhs]
2324−
2325− | (LSDiv (ATInt (ITFixed IT8))) <- op
2326− , (lhs:rhs:_) <- vars =
2327− jsPackSBits8 (
2328− JSBinOp "/" (
2329− jsUnPackBits $ jsPackSBits8 $ jsUnPackBits (JSVar lhs)
2330− ) (
2331− jsUnPackBits $ jsPackSBits8 $ jsUnPackBits (JSVar rhs)
2332− )
2333− )
2334−
2335− | (LSDiv (ATInt (ITFixed IT16))) <- op
2336− , (lhs:rhs:_) <- vars =
2337− jsPackSBits16 (
2338− JSBinOp "/" (
2339− jsUnPackBits $ jsPackSBits16 $ jsUnPackBits (JSVar lhs)
2340− ) (
2341− jsUnPackBits $ jsPackSBits16 $ jsUnPackBits (JSVar rhs)
2342− )
2343− )
2344−
2345− | (LSDiv (ATInt (ITFixed IT32))) <- op
2346− , (lhs:rhs:_) <- vars =
2347− jsPackSBits32 (
2348− JSBinOp "/" (
2349− jsUnPackBits $ jsPackSBits32 $ jsUnPackBits (JSVar lhs)
2350− ) (
2351− jsUnPackBits $ jsPackSBits32 $ jsUnPackBits (JSVar rhs)
2352− )
2353− )
2354−
2355− | (LSDiv (ATInt (ITFixed IT64))) <- op
2356− , (lhs:rhs:_) <- vars = invokeMeth lhs "divide" [rhs]
2357−
2358− | (LSRem (ATInt (ITFixed IT8))) <- op
2359− , (lhs:rhs:_) <- vars =
2360− jsPackSBits8 (
2361− JSBinOp "%" (
2362− jsUnPackBits $ jsPackSBits8 $ jsUnPackBits (JSVar lhs)
2363− ) (
2364− jsUnPackBits $ jsPackSBits8 $ jsUnPackBits (JSVar rhs)
2365− )
2366− )
2367−
2368− | (LSRem (ATInt (ITFixed IT16))) <- op
2369− , (lhs:rhs:_) <- vars =
2370− jsPackSBits16 (
2371− JSBinOp "%" (
2372− jsUnPackBits $ jsPackSBits16 $ jsUnPackBits (JSVar lhs)
2373− ) (
2374− jsUnPackBits $ jsPackSBits16 $ jsUnPackBits (JSVar rhs)
2375− )
2376− )
2377−
2378− | (LSRem (ATInt (ITFixed IT32))) <- op
2379− , (lhs:rhs:_) <- vars =
2380− jsPackSBits32 (
2381− JSBinOp "%" (
2382− jsUnPackBits $ jsPackSBits32 $ jsUnPackBits (JSVar lhs)
2383− ) (
2384− jsUnPackBits $ jsPackSBits32 $ jsUnPackBits (JSVar rhs)
2385− )
2386− )
2387−
2388− | (LSRem (ATInt (ITFixed IT64))) <- op
2389− , (lhs:rhs:_) <- vars = invokeMeth lhs "mod" [rhs]
2390−
2391− | (LCompl (ITFixed IT8)) <- op
2392− , (arg:_) <- vars =
2393− jsPackSBits8 $ JSPreOp "~" $ jsUnPackBits (JSVar arg)
2394−
2395− | (LCompl (ITFixed IT16)) <- op
2396− , (arg:_) <- vars =
2397− jsPackSBits16 $ JSPreOp "~" $ jsUnPackBits (JSVar arg)
2398−
2399− | (LCompl (ITFixed IT32)) <- op
2400− , (arg:_) <- vars =
2401− jsPackSBits32 $ JSPreOp "~" $ jsUnPackBits (JSVar arg)
2402−
2403− | (LCompl (ITFixed IT64)) <- op
2404− , (arg:_) <- vars =
2405− invokeMeth arg "not" []
2406−
2407− | (LPlus _) <- op
2408− , (lhs:rhs:_) <- vars = translateBinaryOp "+" lhs rhs
2409− | (LMinus _) <- op
2410− , (lhs:rhs:_) <- vars = translateBinaryOp "-" lhs rhs
2411− | (LTimes _) <- op
2412− , (lhs:rhs:_) <- vars = translateBinaryOp "*" lhs rhs
2413− | (LSDiv _) <- op
2414− , (lhs:rhs:_) <- vars = translateBinaryOp "/" lhs rhs
2415− | (LSRem _) <- op
2416− , (lhs:rhs:_) <- vars = translateBinaryOp "%" lhs rhs
2417− | (LEq _) <- op
2418− , (lhs:rhs:_) <- vars = translateBinaryOp "==" lhs rhs
2419− | (LSLt _) <- op
2420− , (lhs:rhs:_) <- vars = translateBinaryOp "<" lhs rhs
2421− | (LSLe _) <- op
2422− , (lhs:rhs:_) <- vars = translateBinaryOp "<=" lhs rhs
2423− | (LSGt _) <- op
2424− , (lhs:rhs:_) <- vars = translateBinaryOp ">" lhs rhs
2425− | (LSGe _) <- op
2426− , (lhs:rhs:_) <- vars = translateBinaryOp ">=" lhs rhs
2427− | (LAnd _) <- op
2428− , (lhs:rhs:_) <- vars = translateBinaryOp "&" lhs rhs
2429− | (LOr _) <- op
2430− , (lhs:rhs:_) <- vars = translateBinaryOp "|" lhs rhs
2431− | (LXOr _) <- op
2432− , (lhs:rhs:_) <- vars = translateBinaryOp "^" lhs rhs
2433− | (LSHL _) <- op
2434− , (lhs:rhs:_) <- vars = translateBinaryOp "<<" rhs lhs
2435− | (LASHR _) <- op
2436− , (lhs:rhs:_) <- vars = translateBinaryOp ">>" rhs lhs
2437− | (LCompl _) <- op
2438− , (arg:_) <- vars = JSPreOp "~" (JSVar arg)
2439−
2440− | LStrConcat <- op
2441− , (lhs:rhs:_) <- vars = invokeMeth lhs "concat" [rhs]
2442− | LStrEq <- op
2443− , (lhs:rhs:_) <- vars = translateBinaryOp "==" lhs rhs
2444− | LStrLt <- op
2445− , (lhs:rhs:_) <- vars = translateBinaryOp "<" lhs rhs
2446− | LStrLen <- op
2447− , (arg:_) <- vars = JSProj (JSVar arg) "length"
2448−
2449− | (LStrInt ITNative) <- op
2450− , (arg:_) <- vars = jsCall "parseInt" [JSVar arg]
2451− | (LIntStr ITNative) <- op
2452− , (arg:_) <- vars = jsCall "String" [JSVar arg]
2453− | (LSExt ITNative ITBig) <- op
2454− , (arg:_) <- vars = jsBigInt $ jsCall "String" [JSVar arg]
2455− | (LTrunc ITBig ITNative) <- op
2456− , (arg:_) <- vars = jsMeth (JSVar arg) "intValue" []
2457− | (LIntStr ITBig) <- op
2458− , (arg:_) <- vars = jsMeth (JSVar arg) "toString" []
2459− | (LStrInt ITBig) <- op
2460− , (arg:_) <- vars = jsBigInt $ JSVar arg
2461− | LFloatStr <- op
2462− , (arg:_) <- vars = jsCall "String" [JSVar arg]
2463− | LStrFloat <- op
2464− , (arg:_) <- vars = jsCall "parseFloat" [JSVar arg]
2465− | (LIntFloat ITNative) <- op
2466− , (arg:_) <- vars = JSVar arg
2467− | (LFloatInt ITNative) <- op
2468− , (arg:_) <- vars = JSVar arg
2469− | (LChInt ITNative) <- op
2470− , (arg:_) <- vars = jsCall "__IDRRT__charCode" [JSVar arg]
2471− | (LIntCh ITNative) <- op
2472− , (arg:_) <- vars = jsCall "__IDRRT__fromCharCode" [JSVar arg]
2473−
2474− | LFExp <- op
2475− , (arg:_) <- vars = jsCall "Math.exp" [JSVar arg]
2476− | LFLog <- op
2477− , (arg:_) <- vars = jsCall "Math.log" [JSVar arg]
2478− | LFSin <- op
2479− , (arg:_) <- vars = jsCall "Math.sin" [JSVar arg]
2480− | LFCos <- op
2481− , (arg:_) <- vars = jsCall "Math.cos" [JSVar arg]
2482− | LFTan <- op
2483− , (arg:_) <- vars = jsCall "Math.tan" [JSVar arg]
2484− | LFASin <- op
2485− , (arg:_) <- vars = jsCall "Math.asin" [JSVar arg]
2486− | LFACos <- op
2487− , (arg:_) <- vars = jsCall "Math.acos" [JSVar arg]
2488− | LFATan <- op
2489− , (arg:_) <- vars = jsCall "Math.atan" [JSVar arg]
2490− | LFSqrt <- op
2491− , (arg:_) <- vars = jsCall "Math.sqrt" [JSVar arg]
2492− | LFFloor <- op
2493− , (arg:_) <- vars = jsCall "Math.floor" [JSVar arg]
2494− | LFCeil <- op
2495− , (arg:_) <- vars = jsCall "Math.ceil" [JSVar arg]
2496−
2497− | LStrCons <- op
2498− , (lhs:rhs:_) <- vars = invokeMeth lhs "concat" [rhs]
2499− | LStrHead <- op
2500− , (arg:_) <- vars = JSIndex (JSVar arg) (JSNum (JSInt 0))
2501− | LStrRev <- op
2502− , (arg:_) <- vars = JSProj (JSVar arg) "split('').reverse().join('')"
2503− | LStrIndex <- op
2504− , (lhs:rhs:_) <- vars = JSIndex (JSVar lhs) (JSVar rhs)
2505− | LStrTail <- op
2506− , (arg:_) <- vars = let v = translateVariableName arg in
2507− JSApp (JSProj (JSIdent v) "substr") [
2508− JSNum (JSInt 1),
2509− JSBinOp "-" (JSProj (JSIdent v) "length") (JSNum (JSInt 1))
2510− ]
2511− | LSystemInfo <- op
2512− , (arg:_) <- vars = jsCall "__IDRRT__systemInfo" [JSVar arg]
2513− | LNullPtr <- op
2514− , (_) <- vars = JSNull
2515−
2516− where
2517− translateBinaryOp :: String -> LVar -> LVar -> JS
2518− translateBinaryOp f lhs rhs = JSParens $ JSBinOp f (JSVar lhs) (JSVar rhs)
2519−
2520−
2521− invokeMeth :: LVar -> String -> [LVar] -> JS
2522− invokeMeth obj meth args = jsMeth (JSVar obj) meth (map JSVar args)
2523−
2524−translateExpression (SError msg) =
2525− jsError msg
2526−
2527−translateExpression (SForeign _ _ "putStr" [(FString, var)]) =
2528− jsCall (idrRTNamespace ++ "print") [JSVar var]
2529−
2530−translateExpression (SForeign _ _ "isNull" [(FPtr, var)]) =
2531− JSBinOp "==" (JSVar var) JSNull
2532−
2533−translateExpression (SForeign _ _ "idris_eqPtr" [(FPtr, lhs),(FPtr, rhs)]) =
2534− JSBinOp "==" (JSVar lhs) (JSVar rhs)
2535−
2536−translateExpression (SForeign _ _ "idris_time" []) =
2537− JSRaw "(new Date()).getTime()"
2538−
2539−translateExpression (SForeign _ _ fun args) =
2540− JSFFI fun (map generateWrapper args)
2541− where
2542− generateWrapper (ffunc, name)
2543− | FFunction <- ffunc =
2544− JSApp (
2545− JSIdent $ idrRTNamespace ++ "ffiWrap"
2546− ) [JSIdent $ translateVariableName name]
2547− | FFunctionIO <- ffunc =
2548− JSApp (
2549− JSIdent $ idrRTNamespace ++ "ffiWrap"
2550− ) [JSIdent $ translateVariableName name]
2551−
2552− generateWrapper (_, name) =
2553− JSIdent $ translateVariableName name
2554−
2555−translateExpression patterncase
2556− | (SChkCase var cases) <- patterncase = caseHelper var cases "chk"
2557− | (SCase var cases) <- patterncase = caseHelper var cases "cse"
2558− where
2559− caseHelper var cases param =
2560− JSApp (JSFunction [param] (
2561− JSCond $ map (expandCase param . translateCaseCond param) cases
2562− )) [JSVar var]
2563−
2564−
2565− expandCase :: String -> (Cond, JS) -> (JS, JS)
2566− expandCase _ (RawCond cond, branch) = (cond, branch)
2567− expandCase _ (CaseCond DefaultCase, branch) = (JSTrue , branch)
2568− expandCase var (CaseCond caseTy, branch)
2569− | ConCase tag <- caseTy =
2570− let checkCon = JSIdent var `jsInstanceOf` jsCon
2571− checkTag = (JSNum $ JSInt tag) `jsEq` jsTag (JSIdent var) in
2572− (checkCon `jsAnd` checkTag, branch)
2573−
2574− | TypeCase ty <- caseTy =
2575− let checkTy = JSIdent var `jsInstanceOf` jsType
2576− checkTag = jsTypeTag (JSIdent var) `jsEq` JSType ty in
2577− (checkTy `jsAnd` checkTag, branch)
2578−
2579−translateExpression (SCon i name vars) =
2580− JSNew (idrRTNamespace ++ "Con") [ JSNum $ JSInt i
2581− , JSArray $ map JSVar vars
2582− ]
2583−
2584−translateExpression (SUpdate var@(Loc i) e) =
2585− JSAssign (JSVar var) (translateExpression e)
2586−
2587−translateExpression (SProj var i) =
2588− JSIndex (JSProj (JSVar var) "vars") (JSNum $ JSInt i)
2589−
2590−translateExpression SNothing = JSNull
2591−
2592−translateExpression e =
2593− jsError $ "Not yet implemented: " ++ filter (/= '\'') (show e)
2594−
2595−
2596−data CaseType = ConCase Int
2597− | TypeCase JSType
2598− | DefaultCase
2599− deriving Eq
2600−
2601−
2602−data Cond = CaseCond CaseType
2603− | RawCond JS
2604−
2605−
2606−translateCaseCond :: String -> SAlt -> (Cond, JS)
2607−translateCaseCond _ cse@(SDefaultCase _) =
2608− (CaseCond DefaultCase, translateCase Nothing cse)
2609−
2610−translateCaseCond var cse@(SConstCase ty _)
2611− | StrType <- ty = matchHelper JSStringTy
2612− | PtrType <- ty = matchHelper JSPtrTy
2613− | Forgot <- ty = matchHelper JSForgotTy
2614− | (AType ATFloat) <- ty = matchHelper JSFloatTy
2615− | (AType (ATInt ITBig)) <- ty = matchHelper JSIntegerTy
2616− | (AType (ATInt ITNative)) <- ty = matchHelper JSIntTy
2617− | (AType (ATInt ITChar)) <- ty = matchHelper JSCharTy
2618− where
2619− matchHelper :: JSType -> (Cond, JS)
2620− matchHelper ty = (CaseCond $ TypeCase ty, translateCase Nothing cse)
2621−
2622−translateCaseCond var cse@(SConstCase cst@(BI _) _) =
2623− let cond = jsMeth (JSIdent var) "equals" [translateConstant cst] in
2624− (RawCond cond, translateCase Nothing cse)
2625−
2626−translateCaseCond var cse@(SConstCase cst _) =
2627− let cond = JSIdent var `jsEq` translateConstant cst in
2628− (RawCond cond, translateCase Nothing cse)
2629−
2630−translateCaseCond var cse@(SConCase _ tag _ _ _) =
2631− (CaseCond $ ConCase tag, translateCase (Just var) cse)
1303+ | (LSRem (ATInt (ITFixed IT64))) <- op
1304+ , (lhs:rhs:_) <- args = invokeMeth lhs "mod" [rhs]
1305+
1306+ | (LCompl (ITFixed IT8)) <- op
1307+ , (arg:_) <- args =
1308+ jsPackSBits8 $ JSPreOp "~" $ jsUnPackBits (translateReg arg)
1309+
1310+ | (LCompl (ITFixed IT16)) <- op
1311+ , (arg:_) <- args =
1312+ jsPackSBits16 $ JSPreOp "~" $ jsUnPackBits (translateReg arg)
1313+
1314+ | (LCompl (ITFixed IT32)) <- op
1315+ , (arg:_) <- args =
1316+ jsPackSBits32 $ JSPreOp "~" $ jsUnPackBits (translateReg arg)
1317+
1318+ | (LCompl (ITFixed IT64)) <- op
1319+ , (arg:_) <- args =
1320+ invokeMeth arg "not" []
1321+
1322+ | (LPlus _) <- op
1323+ , (lhs:rhs:_) <- args = translateBinaryOp "+" lhs rhs
1324+ | (LMinus _) <- op
1325+ , (lhs:rhs:_) <- args = translateBinaryOp "-" lhs rhs
1326+ | (LTimes _) <- op
1327+ , (lhs:rhs:_) <- args = translateBinaryOp "*" lhs rhs
1328+ | (LSDiv _) <- op
1329+ , (lhs:rhs:_) <- args = translateBinaryOp "/" lhs rhs
1330+ | (LSRem _) <- op
1331+ , (lhs:rhs:_) <- args = translateBinaryOp "%" lhs rhs
1332+ | (LEq _) <- op
1333+ , (lhs:rhs:_) <- args = translateBinaryOp "==" lhs rhs
1334+ | (LSLt _) <- op
1335+ , (lhs:rhs:_) <- args = translateBinaryOp "<" lhs rhs
1336+ | (LSLe _) <- op
1337+ , (lhs:rhs:_) <- args = translateBinaryOp "<=" lhs rhs
1338+ | (LSGt _) <- op
1339+ , (lhs:rhs:_) <- args = translateBinaryOp ">" lhs rhs
1340+ | (LSGe _) <- op
1341+ , (lhs:rhs:_) <- args = translateBinaryOp ">=" lhs rhs
1342+ | (LAnd _) <- op
1343+ , (lhs:rhs:_) <- args = translateBinaryOp "&" lhs rhs
1344+ | (LOr _) <- op
1345+ , (lhs:rhs:_) <- args = translateBinaryOp "|" lhs rhs
1346+ | (LXOr _) <- op
1347+ , (lhs:rhs:_) <- args = translateBinaryOp "^" lhs rhs
1348+ | (LSHL _) <- op
1349+ , (lhs:rhs:_) <- args = translateBinaryOp "<<" rhs lhs
1350+ | (LASHR _) <- op
1351+ , (lhs:rhs:_) <- args = translateBinaryOp ">>" rhs lhs
1352+ | (LCompl _) <- op
1353+ , (arg:_) <- args = JSPreOp "~" (translateReg arg)
1354+
1355+ | LStrConcat <- op
1356+ , (lhs:rhs:_) <- args = translateBinaryOp "+" lhs rhs
1357+ | LStrEq <- op
1358+ , (lhs:rhs:_) <- args = translateBinaryOp "==" lhs rhs
1359+ | LStrLt <- op
1360+ , (lhs:rhs:_) <- args = translateBinaryOp "<" lhs rhs
1361+ | LStrLen <- op
1362+ , (arg:_) <- args = JSProj (translateReg arg) "length"
1363+ | (LStrInt ITNative) <- op
1364+ , (arg:_) <- args = jsCall "parseInt" [translateReg arg]
1365+ | (LIntStr ITNative) <- op
1366+ , (arg:_) <- args = jsCall "String" [translateReg arg]
1367+ | (LSExt ITNative ITBig) <- op
1368+ , (arg:_) <- args = jsBigInt $ jsCall "String" [translateReg arg]
1369+ | (LTrunc ITBig ITNative) <- op
1370+ , (arg:_) <- args = jsMeth (translateReg arg) "intValue" []
1371+ | (LIntStr ITBig) <- op
1372+ , (arg:_) <- args = jsMeth (translateReg arg) "toString" []
1373+ | (LStrInt ITBig) <- op
1374+ , (arg:_) <- args = jsBigInt $ translateReg arg
1375+ | LFloatStr <- op
1376+ , (arg:_) <- args = jsCall "String" [translateReg arg]
1377+ | LStrFloat <- op
1378+ , (arg:_) <- args = jsCall "parseFloat" [translateReg arg]
1379+ | (LIntFloat ITNative) <- op
1380+ , (arg:_) <- args = translateReg arg
1381+ | (LFloatInt ITNative) <- op
1382+ , (arg:_) <- args = translateReg arg
1383+ | (LChInt ITNative) <- op
1384+ , (arg:_) <- args = jsCall "i$charCode" [translateReg arg]
1385+ | (LIntCh ITNative) <- op
1386+ , (arg:_) <- args = jsCall "i$fromCharCode" [translateReg arg]
1387+
1388+ | LFExp <- op
1389+ , (arg:_) <- args = jsCall "Math.exp" [translateReg arg]
1390+ | LFLog <- op
1391+ , (arg:_) <- args = jsCall "Math.log" [translateReg arg]
1392+ | LFSin <- op
1393+ , (arg:_) <- args = jsCall "Math.sin" [translateReg arg]
1394+ | LFCos <- op
1395+ , (arg:_) <- args = jsCall "Math.cos" [translateReg arg]
1396+ | LFTan <- op
1397+ , (arg:_) <- args = jsCall "Math.tan" [translateReg arg]
1398+ | LFASin <- op
1399+ , (arg:_) <- args = jsCall "Math.asin" [translateReg arg]
1400+ | LFACos <- op
1401+ , (arg:_) <- args = jsCall "Math.acos" [translateReg arg]
1402+ | LFATan <- op
1403+ , (arg:_) <- args = jsCall "Math.atan" [translateReg arg]
1404+ | LFSqrt <- op
1405+ , (arg:_) <- args = jsCall "Math.sqrt" [translateReg arg]
1406+ | LFFloor <- op
1407+ , (arg:_) <- args = jsCall "Math.floor" [translateReg arg]
1408+ | LFCeil <- op
1409+ , (arg:_) <- args = jsCall "Math.ceil" [translateReg arg]
1410+
1411+ | LStrCons <- op
1412+ , (lhs:rhs:_) <- args = invokeMeth lhs "concat" [rhs]
1413+ | LStrHead <- op
1414+ , (arg:_) <- args = JSIndex (translateReg arg) (JSNum (JSInt 0))
1415+ | LStrRev <- op
1416+ , (arg:_) <- args = JSProj (translateReg arg) "split('').reverse().join('')"
1417+ | LStrIndex <- op
1418+ , (lhs:rhs:_) <- args = JSIndex (translateReg lhs) (translateReg rhs)
1419+ | LStrTail <- op
1420+ , (arg:_) <- args =
1421+ let v = translateReg arg in
1422+ JSApp (JSProj v "substr") [
1423+ JSNum (JSInt 1),
1424+ JSBinOp "-" (JSProj v "length") (JSNum (JSInt 1))
1425+ ]
26321426
1427+ | LSystemInfo <- op
1428+ , (arg:_) <- args = jsCall "i$systemInfo" [translateReg arg]
1429+ | LNullPtr <- op
1430+ , (_) <- args = JSNull
1431+ | otherwise = JSError $ "Not implemented: " ++ show op
1432+ where
1433+ translateBinaryOp :: String -> Reg -> Reg -> JS
1434+ translateBinaryOp op lhs rhs =
1435+ JSBinOp op (translateReg lhs) (translateReg rhs)
1436+
1437+ invokeMeth :: Reg -> String -> [Reg] -> JS
1438+ invokeMeth obj meth args =
1439+ JSApp (JSProj (translateReg obj) meth) $ map translateReg args
1440+
1441+
1442+jsRESERVE :: CompileInfo -> Int -> JS
1443+jsRESERVE _ _ = JSNoop
1444+
1445+jsSTACK :: JS
1446+jsSTACK = JSIdent "i$valstack"
1447+
1448+jsCALLSTACK :: JS
1449+jsCALLSTACK = JSIdent "i$callstack"
1450+
1451+jsSTACKBASE :: JS
1452+jsSTACKBASE = JSIdent "i$valstack_base"
1453+
1454+jsSTACKTOP :: JS
1455+jsSTACKTOP = JSIdent "i$valstack_top"
1456+
1457+jsOLDBASE :: JS
1458+jsOLDBASE = JSIdent "oldbase"
1459+
1460+jsMYOLDBASE :: JS
1461+jsMYOLDBASE = JSIdent "myoldbase"
1462+
1463+jsRET :: JS
1464+jsRET = JSIdent "i$ret"
1465+
1466+jsLOC :: Int -> JS
1467+jsLOC 0 = JSIndex jsSTACK jsSTACKBASE
1468+jsLOC n = JSIndex jsSTACK (JSBinOp "+" jsSTACKBASE (JSNum (JSInt n)))
1469+
1470+jsTOP :: Int -> JS
1471+jsTOP 0 = JSIndex jsSTACK jsSTACKTOP
1472+jsTOP n = JSIndex jsSTACK (JSBinOp "+" jsSTACKTOP (JSNum (JSInt n)))
1473+
1474+jsPUSH :: [JS] -> JS
1475+jsPUSH args = JSApp (JSProj jsCALLSTACK "push") args
1476+
1477+jsPOP :: JS
1478+jsPOP = JSApp (JSProj jsCALLSTACK "pop") []
1479+
1480+translateBC :: CompileInfo -> BC -> JS
1481+translateBC info bc
1482+ | ASSIGN r1 r2 <- bc = jsASSIGN info r1 r2
1483+ | ASSIGNCONST r c <- bc = jsASSIGNCONST info r c
1484+ | UPDATE r1 r2 <- bc = jsASSIGN info r1 r2
1485+ | ADDTOP n <- bc = jsADDTOP info n
1486+ | NULL r <- bc = jsNULL info r
1487+ | CALL n <- bc = jsCALL info n
1488+ | TAILCALL n <- bc = jsTAILCALL info n
1489+ | FOREIGNCALL r _ _ n a <- bc = jsFOREIGN info r n a
1490+ | TOPBASE n <- bc = jsTOPBASE info n
1491+ | BASETOP n <- bc = jsBASETOP info n
1492+ | STOREOLD <- bc = jsSTOREOLD info
1493+ | SLIDE n <- bc = jsSLIDE info n
1494+ | REBASE <- bc = jsREBASE info
1495+ | RESERVE n <- bc = jsRESERVE info n
1496+ | MKCON r t rs <- bc = jsMKCON info r t rs
1497+ | CASE s r c d <- bc = jsCASE info s r c d
1498+ | CONSTCASE r c d <- bc = jsCONSTCASE info r c d
1499+ | PROJECT r l a <- bc = jsPROJECT info r l a
1500+ | OP r o a <- bc = jsOP info r o a
1501+ | ERROR e <- bc = jsERROR info e
1502+ | otherwise = JSRaw $ show bc
1503+ {- PROJECTINTO _ _ _ <- bc = undefined -}
26331504
2634−translateCase :: Maybe String -> SAlt -> JS
2635−translateCase _ (SDefaultCase e) = JSReturn $ translateExpression e
2636−translateCase _ (SConstCase _ e) = JSReturn $ translateExpression e
2637−translateCase (Just var) (SConCase a _ _ vars e) =
2638− let params = map jsVar [a .. (a + length vars)] in
2639− JSReturn $ jsMeth (JSFunction params (JSReturn $ translateExpression e)) "apply" [
2640− JSThis, JSProj (JSIdent var) "vars"
2641− ]