on master help sign in
Merge remote-tracking branch 'upstream/master' into quasiquote
79a43c8David Raymond Christiansen
CHANGELOG+2
@@ -8,11 +8,13 @@ New in 0.9.14:
8* Allow dependent function syntax to be overridden in dsl blocks, similarly to
8* Allow dependent function syntax to be overridden in dsl blocks, similarly to
9 functions and let. The keyword for this is "pi".
9 functions and let. The keyword for this is "pi".
10* Experimental 'neweffects' library, with simplified API
10* Experimental 'neweffects' library, with simplified API
11+* All new JavaScript backend (avoids callstack overflows)
11* Quasiquotes and quasiquote patterns allow easier work with reflected terms.
12* Quasiquotes and quasiquote patterns allow easier work with reflected terms.
12 `(EXPR) quasiquotes EXPR, causing the elaborator to be used to produce a reflected
13 `(EXPR) quasiquotes EXPR, causing the elaborator to be used to produce a reflected
13 version of it. Subterms prefixed with ~ are unquoted - on the RHS, they are reflected
14 version of it. Subterms prefixed with ~ are unquoted - on the RHS, they are reflected
14 terms to splice in, while on the LHS they are patterns.
15 terms to splice in, while on the LHS they are patterns.
15
16
17+
16New in 0.9.13:
18New in 0.9.13:
17--------------
19--------------
18* IDE support for retrieving structured information about metavariables
20* IDE support for retrieving structured information about metavariables
jsrts/Runtime-browser.js+9−9
@@ -1,14 +1,14 @@
1−var __IDRRT__print = function(s) {
1+var i$putStr = function(s) {
2 console.log(s);
2 console.log(s);
3};
3};
4
4
5
5
6−var __IDRRT__systemInfo = function(index) {
6+var i$systemInfo = function(index) {
7− switch(index) {
7+ switch(index) {
8− case 0:
8+ case 0:
9− return "javascript";
9+ return "javascript";
10− case 1:
10+ case 1:
11− return navigator.platform;
11+ return navigator.platform;
12− }
12+ }
13− return "";
13+ return "";
14}
14}
jsrts/Runtime-common.js+78−37
@@ -1,51 +1,92 @@
1/** @constructor */
1/** @constructor */
2−var __IDRRT__Type = function(type) {
2+var i$VM = function() {
3− this.type = type;
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 = [];
4−};
11+}
5−
12+
6−var __IDRRT__Int = new __IDRRT__Type('Int');
13+var i$vm;
7−var __IDRRT__Char = new __IDRRT__Type('Char');
14+var i$valstack;
8−var __IDRRT__String = new __IDRRT__Type('String');
15+var i$valstack_top;
9−var __IDRRT__Integer = new __IDRRT__Type('Integer');
16+var i$valstack_base;
10−var __IDRRT__Float = new __IDRRT__Type('Float');
17+var i$ret;
11−var __IDRRT__Ptr = new __IDRRT__Type('Pointer');
18+var i$callstack;
12−var __IDRRT__Forgot = new __IDRRT__Type('Forgot');
19+
13−
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+
14−var __IDRRT__ffiWrap = function(fid) {
52+var i$ffiWrap = function(fid,oldbase,myoldbase) {
15− return function(){
53+ return function() {
54+ i$callstack = [];
55+
16 var res = fid;
56 var res = fid;
17− var i = 0;
57+
18− var arg;
19− while (res instanceof __IDRRT__Con){
20− arg = arguments[i];
58+ for(var i = 0; i < arguments.length; ++i) {
21− res = __IDRRT__tailcall(function(){
59+ while (res instanceof i$CON) {
22− return __IDR__mAPPLY0(res, arg);
60+ i$valstack_top += 1;
23− });
61+ i$valstack[i$valstack_top] = res;
24− ++i;
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+ }
25 }
73 }
26− return res;
27− }
28−};
29
74
30−var __IDRRT__tailcall = function(k) {
75+ i$callstack = i$vm.callstack;
31− var ret = k();
32− while (ret instanceof __IDRRT__Cont)
33− ret = ret.k();
34
76
35− return ret;
77+ return i$ret;
78+ }
36−};
79+}
37
80
38−var __IDRRT__charCode = function(str) {
81+var i$charCode = function(str) {
39− var type = typeof str;
40− if (type == "string")
82+ if (typeof str == "string")
41 return str.charCodeAt(0);
83 return str.charCodeAt(0);
42 else
84 else
43 return str;
85 return str;
44}
86}
45
87
46−var __IDRRT__fromCharCode = function(chr) {
88+var i$fromCharCode = function(chr) {
47− var type = typeof chr;
48− if (type == "string")
89+ if (typeof chr == "string")
49 return chr;
90 return chr;
50 else
91 else
51 return String.fromCharCode(chr);
92 return String.fromCharCode(chr);
jsrts/Runtime-node.js+8−8
@@ -1,17 +1,17 @@
1−var __IDRRT__print = (function() {
1+var i$putStr = (function() {
2 var util = require('util');
2 var util = require('util');
3 return function(s) {
3 return function(s) {
4 util.print(s);
4 util.print(s);
5 };
5 };
6})();
6})();
7
7
8−var __IDRRT__systemInfo = function(index) {
8+var i$systemInfo = function(index) {
9− var os = require('os')
9+ var os = require('os')
10 switch(index) {
10 switch(index) {
11− case 0:
11+ case 0:
12− return "node";
12+ return "node";
13− case 1:
13+ case 1:
14− return os.platform();
14+ return os.platform();
15 }
15 }
16− return "";
16+ return "";
17}
17}
src/IRTS/CodegenJavaScript.hs+1176−2313
@@ -1,5 +1,4 @@
1{-# LANGUAGE PatternGuards #-}
1{-# LANGUAGE PatternGuards #-}
2−
3module IRTS.CodegenJavaScript (codegenJavaScript, codegenNode, JSTarget(..)) where
2module IRTS.CodegenJavaScript (codegenJavaScript, codegenNode, JSTarget(..)) where
4
3
5import Idris.AbsSyntax hiding (TypeCase)
4import Idris.AbsSyntax hiding (TypeCase)
@@ -12,12 +11,15 @@ import Paths_idris
12import Util.System
11import Util.System
13
12
14import Control.Arrow
13import Control.Arrow
14+import Control.Monad (mapM)
15import Control.Applicative ((<$>), (<*>), pure)
15import Control.Applicative ((<$>), (<*>), pure)
16+import Control.Monad.RWS hiding (mapM)
16import Data.Char
17import Data.Char
17import Numeric
18import Numeric
18import Data.List
19import Data.List
19import Data.Maybe
20import Data.Maybe
20import Data.Word
21import Data.Word
22+import Data.Traversable hiding (mapM)
21import System.IO
23import System.IO
22import System.Directory
24import System.Directory
23
25
@@ -28,6 +30,30 @@ idrRTNamespace = "__IDRRT__"
28idrLTNamespace = "__IDRLT__"
30idrLTNamespace = "__IDRLT__"
29idrCTRNamespace = "__IDRCTR__"
31idrCTRNamespace = "__IDRCTR__"
30
32
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+
31
57
32data JSTarget = Node | JavaScript deriving Eq
58data JSTarget = Node | JavaScript deriving Eq
33
59
@@ -45,6 +71,7 @@ data JSType = JSIntTy
45data JSInteger = JSBigZero
71data JSInteger = JSBigZero
46 | JSBigOne
72 | JSBigOne
47 | JSBigInt Integer
73 | JSBigInt Integer
74+ | JSBigIntExpr JS
48 deriving Eq
75 deriving Eq
49
76
50
77
@@ -81,8 +108,8 @@ data JS = JSRaw String
81 | JSPreOp String JS
108 | JSPreOp String JS
82 | JSPostOp String JS
109 | JSPostOp String JS
83 | JSProj JS String
110 | JSProj JS String
84− | JSVar LVar
85 | JSNull
111 | JSNull
112+ | JSUndefined
86 | JSThis
113 | JSThis
87 | JSTrue
114 | JSTrue
88 | JSFalse
115 | JSFalse
@@ -93,6 +120,7 @@ data JS = JSRaw String
93 | JSAssign JS JS
120 | JSAssign JS JS
94 | JSAlloc String (Maybe JS)
121 | JSAlloc String (Maybe JS)
95 | JSIndex JS JS
122 | JSIndex JS JS
123+ | JSSwitch JS [(JS, JS)] (Maybe JS)
96 | JSCond [(JS, JS)]
124 | JSCond [(JS, JS)]
97 | JSTernary JS JS JS
125 | JSTernary JS JS JS
98 | JSParens JS
126 | JSParens JS
@@ -105,7 +133,6 @@ data JS = JSRaw String
105
133
106data FFI = FFICode Char | FFIArg Int | FFIError String
134data FFI = FFICode Char | FFIArg Int | FFIError String
107
135
108−
109ffi :: String -> [String] -> String
136ffi :: String -> [String] -> String
110ffi code args = let parsed = ffiParse code in
137ffi code args = let parsed = ffiParse code in
111 case ffiError parsed of
138 case ffiError parsed of
@@ -137,30 +164,32 @@ ffi code args = let parsed = ffiParse code in
137 | i < length args && i >= 0 = args !! i ++ renderFFI fs args
164 | i < length args && i >= 0 = args !! i ++ renderFFI fs args
138 | otherwise = error "FFI - Argument index out of bounds"
165 | otherwise = error "FFI - Argument index out of bounds"
139
166
140−
141compileJS :: JS -> String
167compileJS :: JS -> String
142−compileJS JSNoop = ""
168+compileJS = compileJS' 0
143
169
144−compileJS (JSAnnotation annotation js) =
170+compileJS' :: Int -> JS -> String
145− "/** @" ++ show annotation ++ " */\n" ++ compileJS js
171+compileJS' indent JSNoop = ""
146
172
147−compileJS (JSFFI raw args) =
173+compileJS' indent (JSAnnotation annotation js) =
148− ffi raw (map compileJS args)
174+ "/** @" ++ show annotation ++ " */\n" ++ compileJS' indent js
149
175
176+compileJS' indent (JSFFI raw args) =
177+ ffi raw (map (compileJS' indent) args)
178+
150−compileJS (JSRaw code) =
179+compileJS' indent (JSRaw code) =
151 code
180 code
152
181
153−compileJS (JSIdent ident) =
182+compileJS' indent (JSIdent ident) =
154 ident
183 ident
155
184
156−compileJS (JSFunction args body) =
185+compileJS' indent (JSFunction args body) =
157− "function("
186+ replicate indent ' ' ++ "function("
158 ++ intercalate "," args
187 ++ intercalate "," args
159 ++ "){\n"
188 ++ "){\n"
160− ++ compileJS body
189+ ++ compileJS' (indent + 2) body
161− ++ "\n}"
190+ ++ "\n}\n"
162
191
163−compileJS (JSType ty)
192+compileJS' indent (JSType ty)
164 | JSIntTy <- ty = idrRTNamespace ++ "Int"
193 | JSIntTy <- ty = idrRTNamespace ++ "Int"
165 | JSStringTy <- ty = idrRTNamespace ++ "String"
194 | JSStringTy <- ty = idrRTNamespace ++ "String"
166 | JSIntegerTy <- ty = idrRTNamespace ++ "Integer"
195 | JSIntegerTy <- ty = idrRTNamespace ++ "Integer"
@@ -169,2473 +198,1307 @@ compileJS (JSType ty)
169 | JSPtrTy <- ty = idrRTNamespace ++ "Ptr"
198 | JSPtrTy <- ty = idrRTNamespace ++ "Ptr"
170 | JSForgotTy <- ty = idrRTNamespace ++ "Forgot"
199 | JSForgotTy <- ty = idrRTNamespace ++ "Forgot"
171
200
172−compileJS (JSSeq seq) =
201+compileJS' indent (JSSeq seq) =
173− intercalate ";\n" (map compileJS seq)
202+ intercalate ";\n" (
203+ map (
204+ ((replicate indent ' ') ++) . (compileJS' indent)
205+ ) $ filter (/= JSNoop) seq
206+ ) ++ ";"
174
207
175−compileJS (JSReturn val) =
208+compileJS' indent (JSReturn val) =
176− "return " ++ compileJS val
209+ "return " ++ compileJS' indent val
177
210
178−compileJS (JSApp lhs rhs)
211+compileJS' indent (JSApp lhs rhs)
179 | JSFunction {} <- lhs =
212 | JSFunction {} <- lhs =
180− concat ["(", compileJS lhs, ")(", args, ")"]
213+ concat ["(", compileJS' indent lhs, ")(", args, ")"]
181 | otherwise =
214 | otherwise =
182− concat [compileJS lhs, "(", args, ")"]
215+ concat [compileJS' indent lhs, "(", args, ")"]
183 where args :: String
216 where args :: String
184− args = intercalate "," $ map compileJS rhs
217+ args = intercalate "," $ map (compileJS' 0) rhs
185
218
186−compileJS (JSNew name args) =
219+compileJS' indent (JSNew name args) =
187− "new " ++ name ++ "(" ++ intercalate "," (map compileJS args) ++ ")"
220+ "new " ++ name ++ "(" ++ intercalate "," (map (compileJS' 0) args) ++ ")"
188
221
189−compileJS (JSError exc) =
222+compileJS' indent (JSError exc) =
190 "throw new Error(\"" ++ exc ++ "\")"
223 "throw new Error(\"" ++ exc ++ "\")"
191
224
192−compileJS (JSBinOp op lhs rhs) =
225+compileJS' indent (JSBinOp op lhs rhs) =
193− compileJS lhs ++ " " ++ op ++ " " ++ compileJS rhs
226+ compileJS' indent lhs ++ " " ++ op ++ " " ++ compileJS' indent rhs
194
227
195−compileJS (JSPreOp op val) =
228+compileJS' indent (JSPreOp op val) =
196− op ++ compileJS val
229+ op ++ compileJS' indent val
197
230
198−compileJS (JSProj obj field)
231+compileJS' indent (JSProj obj field)
199 | JSFunction {} <- obj =
232 | JSFunction {} <- obj =
200− concat ["(", compileJS obj, ").", field]
233+ concat ["(", compileJS' indent obj, ").", field]
201 | JSAssign {} <- obj =
234 | JSAssign {} <- obj =
202− concat ["(", compileJS obj, ").", field]
235+ concat ["(", compileJS' indent obj, ").", field]
203 | otherwise =
236 | otherwise =
204− compileJS obj ++ '.' : field
237+ compileJS' indent obj ++ '.' : field
205−
206−compileJS (JSVar var) =
207− translateVariableName var
208
238
209−compileJS JSNull =
239+compileJS' indent JSNull =
210 "null"
240 "null"
211
241
212−compileJS JSThis =
242+compileJS' indent JSUndefined =
243+ "undefined"
244+
245+compileJS' indent JSThis =
213 "this"
246 "this"
214
247
215−compileJS JSTrue =
248+compileJS' indent JSTrue =
216 "true"
249 "true"
217
250
218−compileJS JSFalse =
251+compileJS' indent JSFalse =
219 "false"
252 "false"
220
253
221−compileJS (JSArray elems) =
254+compileJS' indent (JSArray elems) =
222− "[" ++ intercalate "," (map compileJS elems) ++ "]"
255+ "[" ++ intercalate "," (map (compileJS' 0) elems) ++ "]"
223
256
224−compileJS (JSString str) =
257+compileJS' indent (JSString str) =
225 "\"" ++ str ++ "\""
258 "\"" ++ str ++ "\""
226
259
227−compileJS (JSNum num)
260+compileJS' indent (JSNum num)
228− | JSInt i <- num = show i
261+ | JSInt i <- num = show i
229− | JSFloat f <- num = show f
262+ | JSFloat f <- num = show f
230− | JSInteger JSBigZero <- num = "__IDRRT__ZERO"
263+ | JSInteger JSBigZero <- num = "__IDRRT__ZERO"
231− | JSInteger JSBigOne <- num = "__IDRRT__ONE"
264+ | JSInteger JSBigOne <- num = "__IDRRT__ONE"
232− | JSInteger (JSBigInt i) <- num = show i
265+ | JSInteger (JSBigInt i) <- num = show i
266+ | JSInteger (JSBigIntExpr e) <- num = "__IDRRT__bigInt(" ++ compileJS' indent e ++ ")"
233
267
234−compileJS (JSAssign lhs rhs) =
268+compileJS' indent (JSAssign lhs rhs) =
235− compileJS lhs ++ "=" ++ compileJS rhs
269+ compileJS' indent lhs ++ " = " ++ compileJS' indent rhs
236
270
237−compileJS (JSAlloc name val) =
271+compileJS' indent (JSAlloc name val) =
238− "var " ++ name ++ maybe "" ((" = " ++) . compileJS) val
272+ "var " ++ name ++ maybe "" ((" = " ++) . compileJS' indent) val
239
273
240−compileJS (JSIndex lhs rhs) =
274+compileJS' indent (JSIndex lhs rhs) =
241− compileJS lhs ++ "[" ++ compileJS rhs ++ "]"
275+ compileJS' indent lhs ++ "[" ++ compileJS' indent rhs ++ "]"
242
276
243−compileJS (JSCond branches) =
277+compileJS' indent (JSCond branches) =
244 intercalate " else " $ map createIfBlock branches
278 intercalate " else " $ map createIfBlock branches
245 where
279 where
280+ createIfBlock (JSNoop, e@(JSSeq _)) =
281+ "{\n"
282+ ++ compileJS' (indent + 2) e
283+ ++ "\n" ++ replicate indent ' ' ++ "}"
246 createIfBlock (JSNoop, e) =
284 createIfBlock (JSNoop, e) =
247 "{\n"
285 "{\n"
248− ++ compileJS e
286+ ++ compileJS' (indent + 2) e
249− ++ ";\n}"
287+ ++ ";\n" ++ replicate indent ' ' ++ "}"
288+ createIfBlock (cond, e@(JSSeq _)) =
289+ "if (" ++ compileJS' indent cond ++") {\n"
290+ ++ compileJS' (indent + 2) e
291+ ++ "\n" ++ replicate indent ' ' ++ "}"
250 createIfBlock (cond, e) =
292 createIfBlock (cond, e) =
251− "if (" ++ compileJS cond ++") {\n"
293+ "if (" ++ compileJS' indent cond ++") {\n"
252− ++ compileJS e
294+ ++ replicate (indent + 2) ' ' ++ compileJS' (indent + 2) e
253− ++ ";\n}"
295+ ++ ";\n" ++ replicate indent ' ' ++ "}"
254−
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+
255−compileJS (JSTernary cond true false) =
320+compileJS' indent (JSTernary cond true false) =
256− let c = compileJS cond
321+ let c = compileJS' indent cond
257− t = compileJS true
322+ t = compileJS' indent true
258− f = compileJS false in
323+ f = compileJS' indent false in
259 "(" ++ c ++ ")?(" ++ t ++ "):(" ++ f ++ ")"
324 "(" ++ c ++ ")?(" ++ t ++ "):(" ++ f ++ ")"
260
325
261−compileJS (JSParens js) =
326+compileJS' indent (JSParens js) =
262− "(" ++ compileJS js ++ ")"
327+ "(" ++ compileJS' indent js ++ ")"
263
328
264−compileJS (JSWhile cond body) =
329+compileJS' indent (JSWhile cond body) =
265− "while (" ++ compileJS cond ++ ") {\n"
330+ "while (" ++ compileJS' indent cond ++ ") {\n"
266− ++ compileJS body
331+ ++ compileJS' (indent + 2) body
267− ++ "\n}"
332+ ++ "\n" ++ replicate indent ' ' ++ "}"
268
333
269−compileJS (JSWord word)
334+compileJS' indent (JSWord word)
270 | JSWord8 b <- word = "new Uint8Array([" ++ show b ++ "])"
335 | JSWord8 b <- word = "new Uint8Array([" ++ show b ++ "])"
271 | JSWord16 b <- word = "new Uint16Array([" ++ show b ++ "])"
336 | JSWord16 b <- word = "new Uint16Array([" ++ show b ++ "])"
272 | JSWord32 b <- word = "new Uint32Array([" ++ show b ++ "])"
337 | JSWord32 b <- word = "new Uint32Array([" ++ show b ++ "])"
273 | JSWord64 b <- word = idrRTNamespace ++ "bigInt(\"" ++ show b ++ "\")"
338 | JSWord64 b <- word = idrRTNamespace ++ "bigInt(\"" ++ show b ++ "\")"
274
339
340+codegenJavaScript :: CodeGenerator
341+codegenJavaScript ci = codegenJS_all JavaScript (simpleDecls ci)
342+ (includes ci) (outputFile ci) (outputType ci)
275
343
276−jsTailcall :: JS -> JS
344+codegenNode :: CodeGenerator
277−jsTailcall call =
345+codegenNode ci = codegenJS_all Node (simpleDecls ci)
278− jsCall (idrRTNamespace ++ "tailcall") [
346+ (includes ci) (outputFile ci) (outputType ci)
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−
325
347
326−jsBigInt :: JS -> JS
348+codegenJS_all
327−jsBigInt (JSString "0") = JSNum $ JSInteger JSBigZero
349+ :: JSTarget
328−jsBigInt (JSString "1") = JSNum $ JSInteger JSBigOne
350+ -> [(Name, SDecl)]
329−jsBigInt val = JSApp (JSIdent $ idrRTNamespace ++ "bigInt") [val]
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")
330
363
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+ )
331
388
332−jsVar :: Int -> String
389+ jsMain :: JS
333−jsVar = ("__var_" ++) . show
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+ ]
334
432
433+ invokeMain :: String
434+ invokeMain = compileJS $ JSApp (JSIdent "main") []
335
435
336−jsLet :: String -> JS -> JS -> JS
436+collectSplitFunctions :: (JS, [(Int,JS)]) -> [JS]
337−jsLet name value body =
437+collectSplitFunctions (fun, splits) = map generateSplitFunction splits ++ [fun]
338− JSApp (
438+ where
339− JSFunction [name] (
439+ generateSplitFunction :: (Int,JS) -> JS
340− JSReturn body
440+ generateSplitFunction (depth, JSAlloc name fun) =
341− )
441+ JSAlloc (name ++ "$" ++ show depth) fun
342− ) [value]
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
343
533
534+ isCase :: BC -> Bool
535+ isCase bc
536+ | CASE _ _ _ _ <- bc = True
537+ | otherwise = False
344
538
345−jsError :: String -> JS
539+ defaultCase :: [BC] -> [BC]
346−jsError err = JSApp (JSFunction [] (JSError err)) []
540+ defaultCase ((CASE _ _ _ (Just d)):_) = d
347
541
348−jsUnPackBits :: JS -> JS
542+ caseReg :: [BC] -> Reg
349−jsUnPackBits js = JSIndex js $ JSNum (JSInt 0)
543+ caseReg ((CASE _ r _ _):_) = r
350
544
545+ allocCaseFunctions :: [BC] -> [JS]
546+ allocCaseFunctions ((CASE _ _ c _):_) = splitBranches c
547+ allocCaseFunctions _ = []
351
548
352−jsPackUBits8 :: JS -> JS
549+ splitBranches :: [(Int, [BC])] -> [JS]
353−jsPackUBits8 js = JSNew "Uint8Array" [JSArray [js]]
550+ splitBranches = map prepBranch
354
551
355−jsPackUBits16 :: JS -> JS
552+ prepBranch :: (Int, [BC]) -> JS
356−jsPackUBits16 js = JSNew "Uint16Array" [JSArray [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+ )
357
560
358−jsPackUBits32 :: JS -> JS
561+translateDecl info (name, bc) =
359−jsPackUBits32 js = JSNew "Uint32Array" [JSArray [js]]
562+ [ JSAlloc (
563+ translateName name
564+ ) (Just $ JSFunction ["oldbase"] (
565+ JSSeq $ JSAlloc "myoldbase" Nothing : map (translateBC info)bc
566+ )
567+ )
568+ ]
360
569
361−jsPackSBits8 :: JS -> JS
362−jsPackSBits8 js = JSNew "Int8Array" [JSArray [js]]
363
570
364−jsPackSBits16 :: JS -> JS
571+translateReg :: Reg -> JS
365−jsPackSBits16 js = JSNew "Int16Array" [JSArray [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
366
577
367−jsPackSBits32 :: JS -> JS
578+translateConstant :: Const -> JS
368−jsPackSBits32 js = JSNew "Int32Array" [JSArray [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
369
599
370
600
371−foldJS :: (JS -> a) -> (a -> a -> a) -> a -> JS -> a
601+translateChar :: Char -> String
372−foldJS tr add acc js =
602+translateChar ch
373− fold js
603+ | '\a' <- ch = "\\u0007"
374− where
604+ | '\b' <- ch = "\\b"
375− fold js
605+ | '\f' <- ch = "\\f"
376− | JSFunction args body <- js =
606+ | '\n' <- ch = "\\n"
377− add (tr js) (fold body)
607+ | '\r' <- ch = "\\r"
378− | JSSeq seq <- js =
608+ | '\t' <- ch = "\\t"
379− add (tr js) $ foldl' add acc (map fold seq)
609+ | '\v' <- ch = "\\v"
380− | JSReturn ret <- js =
610+ | '\SO' <- ch = "\\u000E"
381− add (tr js) (fold ret)
611+ | '\DEL' <- ch = "\\u007F"
382− | JSApp lhs rhs <- js =
612+ | '\\' <- ch = "\\\\"
383− add (tr js) $ add (fold lhs) (foldl' add acc $ map fold rhs)
613+ | '\"' <- ch = "\\\""
384− | JSNew _ args <- js =
614+ | '\'' <- ch = "\\\'"
385− add (tr js) $ foldl' add acc $ map fold args
615+ | ch `elem` asciiTab = "\\u00" ++ fill (showIntAtBase 16 intToDigit (ord ch) "")
386− | JSBinOp _ lhs rhs <- js =
616+ | otherwise = [ch]
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)
448 where
617 where
449− move :: ([JS], [JS]) -> [JS]
618+ fill :: String -> String
450− move (front, js@(JSAnnotation _ (JSAlloc name _)):back)
619+ fill s = if length s == 1
451− | name == decl = js : front ++ back
620+ then '0' : s
452−
621+ else s
453− move (front, js@(JSAlloc name _):back)
454− | name == decl = js : front ++ back
455
622
456− move (front, js:back) =
623+ asciiTab =
457− move (front ++ [js], back)
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']
458
628
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) ++ "_"
459
633
460−jsSubst :: JS -> JS -> JS -> JS
634+jsASSIGN :: CompileInfo -> Reg -> Reg -> JS
461−jsSubst var new old
635+jsASSIGN _ r1 r2 = JSAssign (translateReg r1) (translateReg r2)
462− | var == old = new
463
636
464−jsSubst (JSIdent var) new (JSVar old)
637+jsASSIGNCONST :: CompileInfo -> Reg -> Const -> JS
465− | var == translateVariableName old = new
638+jsASSIGNCONST _ r c = JSAssign (translateReg r) (translateConstant c)
466− | otherwise = JSVar old
467
639
468−jsSubst var new old@(JSIdent _)
640+jsCALL :: CompileInfo -> Name -> JS
469− | var == old = new
641+jsCALL _ n =
470− | otherwise = old
642+ JSApp (
643+ JSIdent "i$CALL"
644+ ) [JSIdent (translateName n), JSArray [jsMYOLDBASE]]
471
645
472−jsSubst var new (JSArray fields) =
646+jsTAILCALL :: CompileInfo -> Name -> JS
473− JSArray (map (jsSubst var new) fields)
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+ )
474
661
475−jsSubst var new (JSNew con vals) =
662+ | n == "isNull"
476− JSNew con $ map (jsSubst var new) vals
663+ , [(FPtr, arg)] <- args =
664+ JSAssign (
665+ translateReg reg
666+ ) (
667+ JSBinOp "==" (translateReg arg) JSNull
668+ )
477
669
478−jsSubst (JSIdent var) new (JSApp (JSProj (JSFunction args body) "apply") vals)
670+ | n == "idris_eqPtr"
479− | var `notElem` args =
671+ , [(_, lhs),(_, rhs)] <- args =
480− JSApp (JSProj (JSFunction args (jsSubst (JSIdent var) new body)) "apply") (
672+ JSAssign (
481− map (jsSubst (JSIdent var) new) vals
673+ translateReg reg
674+ ) (
675+ JSBinOp "==" (translateReg lhs) (translateReg rhs)
482 )
676 )
483 | otherwise =
677 | otherwise =
484− JSApp (JSProj (JSFunction args body) "apply") (
678+ JSAssign (
485− map (jsSubst (JSIdent var) new) vals
679+ translateReg reg
486− )
680+ ) (
487−
681+ JSFFI n (map generateWrapper args)
488−jsSubst (JSIdent var) new (JSApp (JSFunction [arg] body) vals)
682+ )
489− | var /= arg =
683+ where
490− JSApp (JSFunction [arg] (
684+ generateWrapper :: (FType, Reg) -> JS
491− jsSubst (JSIdent var) new body
685+ generateWrapper (ty, reg)
492− )) $ map (jsSubst (JSIdent var) new) vals
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
493 | otherwise =
709 | otherwise =
494− JSApp (JSFunction [arg] (
710+ JSBinOp "+=" jsSTACKTOP (JSNum (JSInt n))
495− body
496− )) $ map (jsSubst (JSIdent var) new) vals
497
711
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)))
499
715
500
716
501−removeAllocations :: JS -> JS
717+jsBASETOP :: CompileInfo -> Int -> JS
502−removeAllocations (JSSeq body) =
718+jsBASETOP _ 0 = JSAssign jsSTACKBASE jsSTACKTOP
503− let opt = removeHelper (map removeAllocations body) in
719+jsBASETOP _ n = JSAssign jsSTACKBASE (JSBinOp "+" jsSTACKTOP (JSNum (JSInt n)))
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
553
720
554− inlineJSLet js = transformJS inlineJSLet js
721+jsNULL :: CompileInfo -> Reg -> JS
722+jsNULL _ r = JSAssign (translateReg r) JSNull
555
723
724+jsERROR :: CompileInfo -> String -> JS
725+jsERROR _ = JSError
556
726
557− inlineCaseMatch (JSReturn (JSApp (JSFunction ["cse"] body) [val]))
727+jsSLIDE :: CompileInfo -> Int -> JS
558− | opt <- inlineCaseMatch val =
728+jsSLIDE _ n = JSApp (JSIdent "i$SLIDE") [JSNum (JSInt n)]
559− inlineCaseMatch $ jsSubst (JSIdent "cse") opt body
560
729
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+ )
562
743
744+jsInstanceOf :: JS -> String -> JS
745+jsInstanceOf obj cls = JSBinOp "instanceof" obj (JSIdent cls)
563
746
564− inlineApply js
747+jsOr :: JS -> JS -> JS
565− | JSApp (
748+jsOr lhs rhs = JSBinOp "||" lhs rhs
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)
581
749
582− inlineApply js = transformJS inlineApply js
750+jsAnd :: JS -> JS -> JS
751+jsAnd lhs rhs = JSBinOp "&&" lhs rhs
583
752
753+jsMeth :: JS -> String -> [JS] -> JS
754+jsMeth obj meth args = JSApp (JSProj obj meth) args
584
755
585− inlineError (JSReturn (JSApp (JSFunction [] error@(JSError _)) [])) =
756+jsCall :: String -> [JS] -> JS
586− inlineError error
757+jsCall fun args = JSApp (JSIdent fun) args
587
758
588− inlineError js = transformJS inlineError js
759+jsTypeOf :: JS -> JS
760+jsTypeOf js = JSPreOp "typeof " js
589
761
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
590
766
591− inlineAssign (JSAssign lhs rhs)
767+jsNotEq :: JS -> JS -> JS
592− | JSVar _ <- lhs
768+jsNotEq lhs rhs = JSBinOp "!=" lhs rhs
593− , JSVar _ <- rhs
594− , lhs == rhs =
595− lhs
596
769
597− inlineAssign (JSAssign lhs rhs)
770+jsIsNumber :: JS -> JS
598− | JSIdent _ <- lhs
771+jsIsNumber js = (jsTypeOf js) `jsEq` (JSString "number")
599− , JSIdent _ <- rhs
600− , lhs == rhs =
601− lhs
602
772
603− inlineAssign js = transformJS inlineAssign js
773+jsIsNull :: JS -> JS
774+jsIsNull js = JSBinOp "==" js JSNull
604
775
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
605
780
606−removeEval :: [JS] -> [JS]
781+jsUnPackBits :: JS -> JS
607−removeEval js =
782+jsUnPackBits js = JSIndex js $ JSNum (JSInt 0)
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)
628
783
784+jsPackUBits8 :: JS -> JS
785+jsPackUBits8 js = JSNew "Uint8Array" [JSArray [js]]
629
786
630− checkEval' :: JS -> (Maybe JS, Bool)
787+jsPackUBits16 :: JS -> JS
631− checkEval' (JSAlloc "__IDRLT__EVAL" (Just (JSApp (JSFunction [] (
788+jsPackUBits16 js = JSNew "Uint16Array" [JSArray [js]]
632− JSSeq [ _
633− , JSReturn (JSIdent "t")
634− ]
635− )) []))) = (Nothing, True)
636
789
637− checkEval' js = (Just js, False)
790+jsPackUBits32 :: JS -> JS
791+jsPackUBits32 js = JSNew "Uint32Array" [JSArray [js]]
638
792
793+jsPackSBits8 :: JS -> JS
794+jsPackSBits8 js = JSNew "Int8Array" [JSArray [js]]
639
795
640−reduceJS :: [JS] -> [JS]
796+jsPackSBits16 :: JS -> JS
641−reduceJS js = moveJSDeclToTop "__IDRRT__Con" $ reduceLoop [] ([], js)
797+jsPackSBits16 js = JSNew "Int16Array" [JSArray [js]]
642
798
799+jsPackSBits32 :: JS -> JS
800+jsPackSBits32 js = JSNew "Int32Array" [JSArray [js]]
643
801
644−funName :: JS -> String
802+jsCASE :: CompileInfo -> Bool -> Reg -> [(Int, [BC])] -> Maybe [BC] -> JS
645−funName (JSAlloc fun _) = fun
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+ ]
646
840
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+ ]
647
902
648−elimDeadLoop :: [JS] -> [JS]
903+ | (LTrunc (ITFixed IT16) (ITFixed IT8)) <- op
649−elimDeadLoop js
904+ , (arg:_) <- args =
650− | ret <- deadEvalApplyCases js
905+ jsPackUBits8 (
651− , ret /= js = elimDeadLoop ret
906+ JSBinOp "&" (jsUnPackBits $ translateReg arg) (JSNum (JSInt 0xFF))
652− | otherwise = js
907+ )
653
908
909+ | (LTrunc (ITFixed IT32) (ITFixed IT16)) <- op
910+ , (arg:_) <- args =
911+ jsPackUBits16 (
912+ JSBinOp "&" (jsUnPackBits $ translateReg arg) (JSNum (JSInt 0xFFFF))
913+ )
654
914
655−deadEvalApplyCases :: [JS] -> [JS]
915+ | (LTrunc (ITFixed IT64) (ITFixed IT32)) <- op
656−deadEvalApplyCases js =
916+ , (arg:_) <- args =
657− let tags = sort $ nub $ concatMap (getTags) js in
917+ jsPackUBits32 (
658− map (removeHelper tags) js
918+ jsMeth (jsMeth (translateReg arg) "and" [
659− where
919+ jsBigInt (JSString $ show 0xFFFFFFFF)
660− getTags :: JS -> [Int]
920+ ]) "intValue" []
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− )
921+ )
675
922
676− removeHelper _ js = js
923+ | (LTrunc ITBig (ITFixed IT64)) <- op
924+ , (arg:_) <- args =
925+ jsMeth (translateReg arg) "and" [
926+ jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
927+ ]
677
928
929+ | (LLSHR (ITFixed IT8)) <- op
930+ , (lhs:rhs:_) <- args =
931+ jsPackUBits8 (
932+ JSBinOp ">>" (jsUnPackBits $ translateReg lhs) (jsUnPackBits $ translateReg rhs)
933+ )
678
934
679− remover :: [Int] -> [JS] -> [JS]
935+ | (LLSHR (ITFixed IT16)) <- op
680− remover tags (
936+ , (lhs:rhs:_) <- args =
681− j@(JSAssign ((JSIndex (JSIdent "t") (JSNum (JSInt tag)))) _):js
937+ jsPackUBits16 (
938+ JSBinOp ">>" (jsUnPackBits $ translateReg lhs) (jsUnPackBits $ translateReg rhs)
682 )
939 )
683− | tag `notElem` tags = remover tags js
684
940
685− remover tags (j:js) = j : remover tags js
941+ | (LLSHR (ITFixed IT32)) <- op
686− remover _ [] = []
942+ , (lhs:rhs:_) <- args =
943+ jsPackUBits32 (
944+ JSBinOp ">>" (jsUnPackBits $ translateReg lhs) (jsUnPackBits $ translateReg rhs)
945+ )
687
946
947+ | (LLSHR (ITFixed IT64)) <- op
948+ , (lhs:rhs:_) <- args =
949+ jsMeth (translateReg lhs) "shiftRight" [translateReg rhs]
688
950
689−initConstructors :: [JS] -> [JS]
951+ | (LSHL (ITFixed IT8)) <- op
690−initConstructors js =
952+ , (lhs:rhs:_) <- args =
691− let tags = nub $ sort $ concat (map getTags js) in
953+ jsPackUBits8 (
692− rearrangePrelude $ map createConstant tags ++ replaceConstructors tags js
954+ JSBinOp "<<" (jsUnPackBits $ translateReg lhs) (jsUnPackBits $ translateReg rhs)
693− where
955+ )
694− rearrangePrelude :: [JS] -> [JS]
695− rearrangePrelude = moveJSDeclToTop $ idrRTNamespace ++ "Con"
696
956
957+ | (LSHL (ITFixed IT16)) <- op
958+ , (lhs:rhs:_) <- args =
959+ jsPackUBits16 (
960+ JSBinOp "<<" (jsUnPackBits $ translateReg lhs) (jsUnPackBits $ translateReg rhs)
961+ )
697
962
698− getTags :: JS -> [Int]
963+ | (LSHL (ITFixed IT32)) <- op
699− getTags = foldJS match (++) []
964+ , (lhs:rhs:_) <- args =
700− where
965+ jsPackUBits32 (
701− match js
966+ JSBinOp "<<" (jsUnPackBits $ translateReg lhs) (jsUnPackBits $ translateReg rhs)
702− | JSNew "__IDRRT__Con" [JSNum (JSInt tag), JSArray []] <- js = [tag]
967+ )
703− | otherwise = []
704
968
969+ | (LSHL (ITFixed IT64)) <- op
970+ , (lhs:rhs:_) <- args =
971+ jsMeth (jsMeth (translateReg lhs) "shiftLeft" [translateReg rhs]) "and" [
972+ jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
973+ ]
705
974
706− replaceConstructors :: [Int] -> [JS] -> [JS]
975+ | (LAnd (ITFixed IT8)) <- op
707− replaceConstructors tags js = map (replaceHelper tags) js
976+ , (lhs:rhs:_) <- args =
708− where
977+ jsPackUBits8 (
709− replaceHelper :: [Int] -> JS -> JS
978+ JSBinOp "&" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
710− replaceHelper tags (JSNew "__IDRRT__Con" [JSNum (JSInt tag), JSArray []])
979+ )
711− | tag `elem` tags = JSIdent (idrCTRNamespace ++ show tag)
712
980
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+ )
714
986
987+ | (LAnd (ITFixed IT32)) <- op
988+ , (lhs:rhs:_) <- args =
989+ jsPackUBits32 (
990+ JSBinOp "&" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
991+ )
715
992
716− createConstant :: Int -> JS
993+ | (LAnd (ITFixed IT64)) <- op
717− createConstant tag =
994+ , (lhs:rhs:_) <- args =
718− JSAlloc (idrCTRNamespace ++ show tag) (Just (
995+ jsMeth (translateReg lhs) "and" [translateReg rhs]
719− JSNew (idrRTNamespace ++ "Con") [JSNum (JSInt tag), JSArray []]
720− ))
721
996
997+ | (LOr (ITFixed IT8)) <- op
998+ , (lhs:rhs:_) <- args =
999+ jsPackUBits8 (
1000+ JSBinOp "|" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1001+ )
722
1002
723−removeIDs :: [JS] -> [JS]
1003+ | (LOr (ITFixed IT16)) <- op
724−removeIDs js =
1004+ , (lhs:rhs:_) <- args =
725− case partition isID js of
1005+ jsPackUBits16 (
726− ([], rest) -> rest
1006+ JSBinOp "|" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
727− (ids, rest) -> removeIDs $ map (removeIDCall (map idFor ids)) rest
1007+ )
728− where isID :: JS -> Bool
729− isID (JSAlloc _ (Just (JSFunction _ (JSSeq body))))
730− | JSReturn (JSVar _) <- last body = True
731
1008
732− isID _ = False
1009+ | (LOr (ITFixed IT32)) <- op
1010+ , (lhs:rhs:_) <- args =
1011+ jsPackUBits32 (
1012+ JSBinOp "|" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1013+ )
733
1014
1015+ | (LOr (ITFixed IT64)) <- op
1016+ , (lhs:rhs:_) <- args =
1017+ jsMeth (translateReg lhs) "or" [translateReg rhs]
734
1018
735− idFor :: JS -> (String, Int)
1019+ | (LXOr (ITFixed IT8)) <- op
736− idFor (JSAlloc fun (Just (JSFunction _ (JSSeq body))))
1020+ , (lhs:rhs:_) <- args =
737− | JSReturn (JSVar (Loc pos)) <- last body = (fun, pos)
1021+ jsPackUBits8 (
1022+ JSBinOp "^" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1023+ )
738
1024
1025+ | (LXOr (ITFixed IT16)) <- op
1026+ , (lhs:rhs:_) <- args =
1027+ jsPackUBits16 (
1028+ JSBinOp "^" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1029+ )
739
1030
740− removeIDCall :: [(String, Int)] -> JS -> JS
1031+ | (LXOr (ITFixed IT32)) <- op
741− removeIDCall ids (JSApp (JSIdent "__IDRRT__tailcall") [JSFunction [] (
1032+ , (lhs:rhs:_) <- args =
742− JSReturn (JSApp (JSIdent fun) args)
1033+ jsPackUBits32 (
743− )])
1034+ JSBinOp "^" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
744− | Just pos <- lookup fun ids
1035+ )
745− , pos < length args = removeIDCall ids (args !! pos)
746
1036
747− removeIDCall ids (JSNew _ [JSFunction [] (
1037+ | (LXOr (ITFixed IT64)) <- op
748− JSReturn (JSApp (JSIdent fun) args)
1038+ , (lhs:rhs:_) <- args =
749− )])
1039+ jsMeth (translateReg lhs) "xor" [translateReg rhs]
750− | Just pos <- lookup fun ids
751− , pos < length args = removeIDCall ids (args !! pos)
752
1040
753− removeIDCall ids js@(JSApp id@(JSIdent fun) args)
1041+ | (LPlus (ATInt (ITFixed IT8))) <- op
754− | Just pos <- lookup fun ids
1042+ , (lhs:rhs:_) <- args =
755− , pos < length args = removeIDCall ids (args !! pos)
1043+ jsPackUBits8 (
1044+ JSBinOp "+" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1045+ )
756
1046
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+ )
758
1052
1053+ | (LPlus (ATInt (ITFixed IT32))) <- op
1054+ , (lhs:rhs:_) <- args =
1055+ jsPackUBits32 (
1056+ JSBinOp "+" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1057+ )
759
1058
760−inlineFunction :: String -> [String] -> JS -> JS -> JS
1059+ | (LPlus (ATInt (ITFixed IT64))) <- op
761−inlineFunction fun args body js = inline' js
1060+ , (lhs:rhs:_) <- args =
762− where
1061+ jsMeth (jsMeth (translateReg lhs) "add" [translateReg rhs]) "and" [
763− inline' :: JS -> JS
1062+ jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
764− inline' (JSApp (JSIdent name) vals)
1063+ ]
765− | name == fun =
766− let (js, phs) = insertPlaceHolders args body in
767− inline' $ foldr (uncurry jsSubst) js (zip phs vals)
768
1064
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+ )
770
1070
771− insertPlaceHolders :: [String] -> JS -> (JS, [JS])
1071+ | (LMinus (ATInt (ITFixed IT16))) <- op
772− insertPlaceHolders args body = insertPlaceHolders' args body []
1072+ , (lhs:rhs:_) <- args =
773− where
1073+ jsPackUBits16 (
774− insertPlaceHolders' :: [String] -> JS -> [JS] -> (JS, [JS])
1074+ JSBinOp "-" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
775− insertPlaceHolders' (a:as) body ph
1075+ )
776− | (body', ph') <- insertPlaceHolders' as body ph =
777− let phvar = JSIdent $ "__PH_" ++ show (length ph') in
778− (jsSubst (JSIdent a) phvar body', phvar : ph')
779
1076
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+ )
781
1082
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+ ]
782
1088
783−inlineFunctions :: [JS] -> [JS]
1089+ | (LTimes (ATInt (ITFixed IT8))) <- op
784−inlineFunctions js =
1090+ , (lhs:rhs:_) <- args =
785− inlineHelper ([], js)
1091+ jsPackUBits8 (
786− where
1092+ JSBinOp "*" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
787− inlineHelper :: ([JS], [JS]) -> [JS]
1093+ )
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)
796
1094
797− inlineHelper (front, next:back) = inlineHelper (front ++ [next], back)
1095+ | (LTimes (ATInt (ITFixed IT16))) <- op
798− inlineHelper (front, []) = front
1096+ , (lhs:rhs:_) <- args =
1097+ jsPackUBits16 (
1098+ JSBinOp "*" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1099+ )
799
1100
1101+ | (LTimes (ATInt (ITFixed IT32))) <- op
1102+ , (lhs:rhs:_) <- args =
1103+ jsPackUBits32 (
1104+ JSBinOp "*" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1105+ )
800
1106
801− inlineAble :: Int -> String -> [String] -> JS -> Maybe JS
1107+ | (LTimes (ATInt (ITFixed IT64))) <- op
802− inlineAble 1 fun args (JSReturn body)
1108+ , (lhs:rhs:_) <- args =
803− | nonRecur fun body =
1109+ jsMeth (jsMeth (translateReg lhs) "multiply" [translateReg rhs]) "and" [
804− if all (<= 1) (map ($ body) (map countIDOccurences args))
1110+ jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
805− then Just body
1111+ ]
806− else Nothing
807
1112
808− inlineAble _ _ _ _ = Nothing
1113+ | (LEq (ATInt (ITFixed IT8))) <- op
1114+ , (lhs:rhs:_) <- args =
1115+ jsPackUBits8 (
1116+ JSBinOp "==" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1117+ )
809
1118
1119+ | (LEq (ATInt (ITFixed IT16))) <- op
1120+ , (lhs:rhs:_) <- args =
1121+ jsPackUBits16 (
1122+ JSBinOp "==" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1123+ )
810
1124
811− nonRecur :: String -> JS -> Bool
1125+ | (LEq (ATInt (ITFixed IT32))) <- op
812− nonRecur name body = countInvokations name body == 0
1126+ , (lhs:rhs:_) <- args =
1127+ jsPackUBits32 (
1128+ JSBinOp "==" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1129+ )
813
1130
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+ ]
814
1136
815− countAll :: String -> [JS] -> Int
1137+ | (LLt (ITFixed IT8)) <- op
816− countAll name js = sum $ map (countInvokations name) js
1138+ , (lhs:rhs:_) <- args =
1139+ jsPackUBits8 (
1140+ JSBinOp "<" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1141+ )
817
1142
1143+ | (LLt (ITFixed IT16)) <- op
1144+ , (lhs:rhs:_) <- args =
1145+ jsPackUBits16 (
1146+ JSBinOp "<" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1147+ )
818
1148
819− countIDOccurences :: String -> JS -> Int
1149+ | (LLt (ITFixed IT32)) <- op
820− countIDOccurences name = foldJS match (+) 0
1150+ , (lhs:rhs:_) <- args =
821− where
1151+ jsPackUBits32 (
822− match :: JS -> Int
1152+ JSBinOp "<" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
823− match js
1153+ )
824− | JSIdent ident <- js
825− , name == ident = 1
826− | otherwise = 0
827
1154
1155+ | (LLt (ITFixed IT64)) <- op
1156+ , (lhs:rhs:_) <- args = invokeMeth lhs "lesser" [rhs]
828
1157
829− countInvokations :: String -> JS -> Int
1158+ | (LLe (ITFixed IT8)) <- op
830− countInvokations name = foldJS match (+) 0
1159+ , (lhs:rhs:_) <- args =
831− where
1160+ jsPackUBits8 (
832− match :: JS -> Int
1161+ JSBinOp "<=" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
833− match js
1162+ )
834− | JSApp (JSIdent ident) _ <- js
835− , name == ident = 1
836− | JSNew con _ <- js
837− , name == con = 1
838− | otherwise = 0
839
1163
1164+ | (LLe (ITFixed IT16)) <- op
1165+ , (lhs:rhs:_) <- args =
1166+ jsPackUBits16 (
1167+ JSBinOp "<=" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1168+ )
840
1169
841−reduceContinuations :: JS -> JS
1170+ | (LLe (ITFixed IT32)) <- op
842−reduceContinuations = inlineTC . reduceJS
1171+ , (lhs:rhs:_) <- args =
843− where
1172+ jsPackUBits32 (
844− reduceJS :: JS -> JS
1173+ JSBinOp "<=" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
845− reduceJS (JSNew "__IDRRT__Cont" [JSFunction [] (
1174+ )
846− JSReturn js@(JSNew "__IDRRT__Cont" [JSFunction [] body])
847− )]) = reduceJS js
848
1175
849− reduceJS js = transformJS reduceJS js
1176+ | (LLe (ITFixed IT64)) <- op
1177+ , (lhs:rhs:_) <- args = invokeMeth lhs "lesserOrEquals" [rhs]
850
1178
1179+ | (LGt (ITFixed IT8)) <- op
1180+ , (lhs:rhs:_) <- args =
1181+ jsPackUBits8 (
1182+ JSBinOp ">" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1183+ )
851
1184
852− inlineTC :: JS -> JS
1185+ | (LGt (ITFixed IT16)) <- op
853− inlineTC js
1186+ , (lhs:rhs:_) <- args =
854− | JSApp (JSIdent "__IDRRT__tailcall") [JSFunction [] (
1187+ jsPackUBits16 (
855− JSReturn (JSNew "__IDRRT__Cont" [JSFunction [] (
1188+ JSBinOp ">" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
856− JSReturn ret@(JSApp (JSIdent "__IDRRT__tailcall") [JSFunction [] (
1189+ )
857− JSReturn (JSNew "__IDRRT__Cont" _)
1190+ | (LGt (ITFixed IT32)) <- op
858− )])
1191+ , (lhs:rhs:_) <- args =
859− )])
1192+ jsPackUBits32 (
860− )] <- js = inlineTC ret
1193+ JSBinOp ">" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1194+ )
861
1195
862− inlineTC js = transformJS inlineTC js
1196+ | (LGt (ITFixed IT64)) <- op
1197+ , (lhs:rhs:_) <- args = invokeMeth lhs "greater" [rhs]
863
1198
1199+ | (LGe (ITFixed IT8)) <- op
1200+ , (lhs:rhs:_) <- args =
1201+ jsPackUBits8 (
1202+ JSBinOp ">=" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1203+ )
864
1204
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+ )
865
1215
1216+ | (LGe (ITFixed IT64)) <- op
1217+ , (lhs:rhs:_) <- args = invokeMeth lhs "greaterOrEquals" [rhs]
866
1218
867−reduceConstant :: JS -> JS
1219+ | (LUDiv (ITFixed IT8)) <- op
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 =
1220+ , (lhs:rhs:_) <- args =
874− JSParens $ JSBinOp op (reduceConstant lhs) (reduceConstant rhs)
1221+ jsPackUBits8 (
1222+ JSBinOp "/" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1223+ )
875
1224
876− | JSApp (JSProj lhs op) [rhs] <- val
1225+ | (LUDiv (ITFixed IT16)) <- op
877− , op `elem` [ "subtract"
1226+ , (lhs:rhs:_) <- args =
878− , "add"
1227+ jsPackUBits16 (
879− , "multiply"
1228+ JSBinOp "/" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
880− , "divide"
1229+ )
881− , "mod"
882− , "equals"
883− , "lesser"
884− , "lesserOrEquals"
885− , "greater"
886− , "greaterOrEquals"
887− ] = val
888
1230
889−reduceConstant (JSApp ident [(JSParens js)]) =
1231+ | (LUDiv (ITFixed IT32)) <- op
890− JSApp ident [reduceConstant js]
1232+ , (lhs:rhs:_) <- args =
1233+ jsPackUBits32 (
1234+ JSBinOp "/" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1235+ )
891
1236
892−reduceConstant js = transformJS reduceConstant js
1237+ | (LUDiv (ITFixed IT64)) <- op
1238+ , (lhs:rhs:_) <- args = invokeMeth lhs "divide" [rhs]
893
1239
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+ )
894
1249
895−reduceConstants :: JS -> JS
1250+ | (LSDiv (ATInt (ITFixed IT16))) <- op
896−reduceConstants js
1251+ , (lhs:rhs:_) <- args =
897− | ret <- reduceConstant js
1252+ jsPackSBits16 (
898− , ret /= js = reduceConstants ret
1253+ JSBinOp "/" (
899− | otherwise = js
1254+ jsUnPackBits $ jsPackSBits16 $ jsUnPackBits (translateReg lhs)
1255+ ) (
1256+ jsUnPackBits $ jsPackSBits16 $ jsUnPackBits (translateReg rhs)
1257+ )
1258+ )
900
1259
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+ )
901
1269
902−elimDuplicateEvals :: JS -> JS
1270+ | (LSDiv (ATInt (ITFixed IT64))) <- op
903−elimDuplicateEvals (JSAlloc fun (Just (JSFunction args (JSSeq seq)))) =
1271+ , (lhs:rhs:_) <- args = invokeMeth lhs "divide" [rhs]
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 [] = []
912
1272
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+ )
914
1282
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+ )
915
1292
916−optimizeRuntimeCalls :: String -> String -> [JS] -> [JS]
1293+ | (LSRem (ATInt (ITFixed IT32))) <- op
917−optimizeRuntimeCalls fun tc js =
1294+ , (lhs:rhs:_) <- args =
918− optTC tc : map optHelper js
1295+ jsPackSBits32 (
919− where
1296+ JSBinOp "%" (
920− optHelper :: JS -> JS
1297+ jsUnPackBits $ jsPackSBits32 $ jsUnPackBits (translateReg lhs)
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"
1373 ) (
1298 ) (
1374− JSNum (JSInt idx)
1299+ jsUnPackBits $ jsPackSBits32 $ jsUnPackBits (translateReg rhs)
1375 )
1300 )
1376 )
1301 )
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)
1391
1302
1392− match js = transformJS match js
1303+ | (LSRem (ATInt (ITFixed IT64))) <- op
1393−
1304+ , (lhs:rhs:_) <- args = invokeMeth lhs "mod" [rhs]
1394−
1305+
1395− collapseCont :: JS -> JS
1306+ | (LCompl (ITFixed IT8)) <- op
1396− collapseCont js = transformJS match js
1307+ , (arg:_) <- args =
1397− where
1308+ jsPackSBits8 $ JSPreOp "~" $ jsUnPackBits (translateReg arg)
1398− match :: JS -> JS
1309+
1399− match (JSNew "__IDRRT__Cont" [JSFunction [] (
1310+ | (LCompl (ITFixed IT16)) <- op
1400− JSReturn ret@(JSNew "__IDRRT__Cont" [JSFunction [] _])
1311+ , (arg:_) <- args =
1401− )]) = collapseCont ret
1312+ jsPackSBits16 $ JSPreOp "~" $ jsUnPackBits (translateReg arg)
1402−
1313+
1403−
1314+ | (LCompl (ITFixed IT32)) <- op
1404− match (JSNew "__IDRRT__Cont" [JSFunction [] (
1315+ , (arg:_) <- args =
1405− JSReturn (JSIdent name)
1316+ jsPackSBits32 $ JSPreOp "~" $ jsUnPackBits (translateReg arg)
1406− )]) = JSIdent name
1317+
1407−
1318+ | (LCompl (ITFixed IT64)) <- op
1408− match (JSNew "__IDRRT__Cont" [JSFunction [] (
1319+ , (arg:_) <- args =
1409− JSReturn ret@(JSNew "__IDRRT__Con" [_, _, _, JSArray args])
1320+ invokeMeth arg "not" []
1410− )])
1321+
1411− | all collapsable args = ret
1322+ | (LPlus _) <- op
1412− where
1323+ , (lhs:rhs:_) <- args = translateBinaryOp "+" lhs rhs
1413− collapsable :: JS -> Bool
1324+ | (LMinus _) <- op
1414− collapsable (JSIdent _) = True
1325+ , (lhs:rhs:_) <- args = translateBinaryOp "-" lhs rhs
1415− collapsable js = isJSConstantConstructor (map fst cons) js
1326+ | (LTimes _) <- op
1416−
1327+ , (lhs:rhs:_) <- args = translateBinaryOp "*" lhs rhs
1417−
1328+ | (LSDiv _) <- op
1418− match js = transformJS match js
1329+ , (lhs:rhs:_) <- args = translateBinaryOp "/" lhs rhs
1419−
1330+ | (LSRem _) <- op
1420−
1331+ , (lhs:rhs:_) <- args = translateBinaryOp "%" lhs rhs
1421−elimConds :: [JS] -> [JS]
1332+ | (LEq _) <- op
1422−elimConds js =
1333+ , (lhs:rhs:_) <- args = translateBinaryOp "==" lhs rhs
1423− let (conds, rest) = partition isCond js in
1334+ | (LSLt _) <- op
1424− foldl' eraseCond rest conds
1335+ , (lhs:rhs:_) <- args = translateBinaryOp "<" lhs rhs
1425− where
1336+ | (LSLe _) <- op
1426− isCond :: JS -> Bool
1337+ , (lhs:rhs:_) <- args = translateBinaryOp "<=" lhs rhs
1427− isCond (JSAlloc
1338+ | (LSGt _) <- op
1428− fun (Just (JSFunction args (JSCond
1339+ , (lhs:rhs:_) <- args = translateBinaryOp ">" lhs rhs
1429− [ (JSBinOp "==" (JSNum (JSInt tag)) (JSProj (JSIdent _) "tag"), JSReturn t)
1340+ | (LSGe _) <- op
1430− , (JSNoop, JSReturn f)
1341+ , (lhs:rhs:_) <- args = translateBinaryOp ">=" lhs rhs
1431− ])))
1342+ | (LAnd _) <- op
1432− )
1343+ , (lhs:rhs:_) <- args = translateBinaryOp "&" lhs rhs
1433− | isJSConstant t && isJSConstant f =
1344+ | (LOr _) <- op
1434− True
1345+ , (lhs:rhs:_) <- args = translateBinaryOp "|" lhs rhs
1435−
1346+ | (LXOr _) <- op
1436− | JSIdent _ <- t
1347+ , (lhs:rhs:_) <- args = translateBinaryOp "^" lhs rhs
1437− , JSIdent _ <- f =
1348+ | (LSHL _) <- op
1438− True
1349+ , (lhs:rhs:_) <- args = translateBinaryOp "<<" rhs lhs
1439−
1350+ | (LASHR _) <- op
1440− isCond (JSAlloc
1351+ , (lhs:rhs:_) <- args = translateBinaryOp ">>" rhs lhs
1441− fun (Just (JSFunction args (JSCond
1352+ | (LCompl _) <- op
1442− [ (JSBinOp "==" (JSIdent _) c, JSReturn t)
1353+ , (arg:_) <- args = JSPreOp "~" (translateReg arg)
1443− , (JSNoop, JSReturn f)
1354+
1444− ])))
1355+ | LStrConcat <- op
1445− )
1356+ , (lhs:rhs:_) <- args = translateBinaryOp "+" lhs rhs
1446− | isJSConstant t && isJSConstant f && isJSConstant c =
1357+ | LStrEq <- op
1447− True
1358+ , (lhs:rhs:_) <- args = translateBinaryOp "==" lhs rhs
1448−
1359+ | LStrLt <- op
1449− | JSIdent _ <- t
1360+ , (lhs:rhs:_) <- args = translateBinaryOp "<" lhs rhs
1450− , JSIdent _ <- f
1361+ | LStrLen <- op
1451− , isJSConstant c =
1362+ , (arg:_) <- args = JSProj (translateReg arg) "length"
1452− True
1363+ | (LStrInt ITNative) <- op
1453−
1364+ , (arg:_) <- args = jsCall "parseInt" [translateReg arg]
1454− isCond _ = False
1365+ | (LIntStr ITNative) <- op
1455−
1366+ , (arg:_) <- args = jsCall "String" [translateReg arg]
1456−
1367+ | (LSExt ITNative ITBig) <- op
1457− eraseCond :: [JS] -> JS -> [JS]
1368+ , (arg:_) <- args = jsBigInt $ jsCall "String" [translateReg arg]
1458− eraseCond js (JSAlloc
1369+ | (LTrunc ITBig ITNative) <- op
1459− fun (Just (JSFunction args (JSCond
1370+ , (arg:_) <- args = jsMeth (translateReg arg) "intValue" []
1460− [ (c, JSReturn t)
1371+ | (LIntStr ITBig) <- op
1461− , (_, JSReturn f)
1372+ , (arg:_) <- args = jsMeth (translateReg arg) "toString" []
1462− ])
1373+ | (LStrInt ITBig) <- op
1463− )
1374+ , (arg:_) <- args = jsBigInt $ translateReg arg
1464− )) = map (inlineFunction fun args (JSTernary c t f)) js
1375+ | LFloatStr <- op
1465−
1376+ , (arg:_) <- args = jsCall "String" [translateReg arg]
1466−
1377+ | LStrFloat <- op
1467−removeUselessCons :: [JS] -> [JS]
1378+ , (arg:_) <- args = jsCall "parseFloat" [translateReg arg]
1468−removeUselessCons js =
1379+ | (LIntFloat ITNative) <- op
1469− let (cons, rest) = partition isUseless js in
1380+ , (arg:_) <- args = translateReg arg
1470− foldl' eraseCon rest cons
1381+ | (LFloatInt ITNative) <- op
1471− where
1382+ , (arg:_) <- args = translateReg arg
1472− isUseless :: JS -> Bool
1383+ | (LChInt ITNative) <- op
1473− isUseless (JSAlloc fun (Just JSNull)) = True
1384+ , (arg:_) <- args = jsCall "i$charCode" [translateReg arg]
1474− isUseless (JSAlloc fun (Just (JSIdent _))) = True
1385+ | (LIntCh ITNative) <- op
1475− isUseless _ = False
1386+ , (arg:_) <- args = jsCall "i$fromCharCode" [translateReg arg]
1476−
1387+
1477−
1388+ | LFExp <- op
1478− eraseCon :: [JS] -> JS -> [JS]
1389+ , (arg:_) <- args = jsCall "Math.exp" [translateReg arg]
1479− eraseCon js (JSAlloc fun (Just val)) = map (jsSubst (JSIdent fun) val) js
1390+ | LFLog <- op
1480−
1391+ , (arg:_) <- args = jsCall "Math.log" [translateReg arg]
1481−
1392+ | LFSin <- op
1482−getGlobalCons :: JS -> [(String, JS)]
1393+ , (arg:_) <- args = jsCall "Math.sin" [translateReg arg]
1483−getGlobalCons js = foldJS match (++) [] js
1394+ | LFCos <- op
1484− where
1395+ , (arg:_) <- args = jsCall "Math.cos" [translateReg arg]
1485− match :: JS -> [(String, JS)]
1396+ | LFTan <- op
1486− match js
1397+ , (arg:_) <- args = jsCall "Math.tan" [translateReg arg]
1487− | (JSAlloc name (Just con@(JSNew "__IDRRT__Con" _))) <- js =
1398+ | LFASin <- op
1488− [(name, con)]
1399+ , (arg:_) <- args = jsCall "Math.asin" [translateReg arg]
1489− | (JSAlloc name (Just con@(JSIdent _))) <- js =
1400+ | LFACos <- op
1490− [(name, con)]
1401+ , (arg:_) <- args = jsCall "Math.acos" [translateReg arg]
1491− | otherwise =
1402+ | LFATan <- op
1492− []
1403+ , (arg:_) <- args = jsCall "Math.atan" [translateReg arg]
1493−
1404+ | LFSqrt <- op
1494−
1405+ , (arg:_) <- args = jsCall "Math.sqrt" [translateReg arg]
1495−getIncludes :: [FilePath] -> IO [String]
1406+ | LFFloor <- op
1496−getIncludes = mapM readFile
1407+ , (arg:_) <- args = jsCall "Math.floor" [translateReg arg]
1497−
1408+ | LFCeil <- op
1498−codegenJavaScript :: CodeGenerator
1409+ , (arg:_) <- args = jsCall "Math.ceil" [translateReg arg]
1499−codegenJavaScript ci = codegenJS_all JavaScript (simpleDecls ci)
1410+
1500− (includes ci) (outputFile ci) (outputType ci)
1411+ | LStrCons <- op
1501−
1412+ , (lhs:rhs:_) <- args = invokeMeth lhs "concat" [rhs]
1502−codegenNode :: CodeGenerator
1413+ | LStrHead <- op
1503−codegenNode ci = codegenJS_all Node (simpleDecls ci)
1414+ , (arg:_) <- args = JSIndex (translateReg arg) (JSNum (JSInt 0))
1504− (includes ci) (outputFile ci) (outputType ci)
1415+ | LStrRev <- op
1505−
1416+ , (arg:_) <- args = JSProj (translateReg arg) "split('').reverse().join('')"
1506−codegenJS_all
1417+ | LStrIndex <- op
1507− :: JSTarget
1418+ , (lhs:rhs:_) <- args = JSIndex (translateReg lhs) (translateReg rhs)
1508− -> [(Name, SDecl)]
1419+ | LStrTail <- op
1509− -> [FilePath]
1420+ , (arg:_) <- args =
1510− -> FilePath
1421+ let v = translateReg arg in
1511− -> OutputType
1422+ JSApp (JSProj v "substr") [
1512− -> IO ()
1423+ JSNum (JSInt 1),
1513−codegenJS_all target definitions includes filename outputType = do
1424+ JSBinOp "-" (JSProj v "length") (JSNum (JSInt 1))
1514− let (header, rt) = case target of
1425+ ]
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)
2632
1426
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 -}
2633
1504
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− ]