1{-# LANGUAGE PatternGuards #-}
3module IRTS.CodegenJavaScript (codegenJavaScript, JSTarget(..)) where
9import IRTS.CodegenCommon
17import qualified Data.Map as Map
19import System.Directory
22idrNamespace = "__IDR__"
23idrRTNamespace = "__IDRRT__"
25data JSTarget = Node | JavaScript deriving Eq
33codegenJavaScript target definitions filename outputType = do
34 let (header, runtime) = case target of
36 ("#!/usr/bin/env node\n", "-node")
40 idrRuntime <- readFile $ path ++ "/js/Runtime-common.js"
41 tgtRuntime <- readFile $ concat [path, "/js/Runtime", runtime, ".js"]
42 writeFile filename ( header
48 setPermissions filename (emptyPermissions { readable = True
49 , executable = target == Node
53 def = map (first translateNamespace) definitions
55 functions = concatMap translateDeclaration def
58 mainLoop = intercalate "\n" [ "\nfunction main() {"
59 , createTailcall "__IDR__runMain0()"
63translateIdentifier :: String -> String
65 replaceReserved . concatMap replaceBadChars
66 where replaceBadChars :: Char -> String
70 | isDigit c = "_" ++ [c] ++ "_"
71 | not (isLetter c && isAscii c) = '_' : show (ord c)
74 | s `elem` reserved = '_' : s
121translateNamespace :: Name -> [String]
122translateNamespace (UN _) = [idrNamespace]
123translateNamespace (NS _ ns) = idrNamespace : map translateIdentifier ns
124translateNamespace (MN _ _) = [idrNamespace]
126translateName :: Name -> String
127translateName (UN name) = translateIdentifier name
128translateName (NS name _) = translateName name
129translateName (MN i name) = translateIdentifier name ++ show i
131translateConstant :: Const -> String
132translateConstant (I i) = show i
133translateConstant (BI i) = idrRTNamespace ++ "bigInt('" ++ show i ++ "')"
134translateConstant (Fl f) = show f
135translateConstant (Ch c) = show c
136translateConstant (Str s) = show s
137translateConstant (AType (ATInt ITNative)) = idrRTNamespace ++ "Int"
138translateConstant StrType = idrRTNamespace ++ "String"
139translateConstant (AType (ATInt ITBig)) = idrRTNamespace ++ "Integer"
140translateConstant (AType ATFloat) = idrRTNamespace ++ "Float"
141translateConstant PtrType = idrRTNamespace ++ "Ptr"
142translateConstant Forgot = idrRTNamespace ++ "Forgot"
144 "(function(){throw 'Unimplemented Const: " ++ show c ++ "';})()"
146translateParameterlist =
147 map translateParameter
148 where translateParameter (MN i name) = translateIdentifier name ++ show i
149 translateParameter (UN name) = translateIdentifier name
151translateDeclaration :: (String, SDecl) -> String
152translateDeclaration (path, SFun name params stackSize body) =
153 "var " ++ concat (path ++ [translateName name])
157 ++ concatMap assignVar (zip [0..] p)
158 ++ concatMap allocVar [numP..(numP+stackSize-1)]
160 ++ translateExpression body
166 allocVar :: Int -> String
167 allocVar n = "var __var_" ++ show n ++ ";\n"
169 assignVar :: (Int, String) -> String
170 assignVar (n, s) = "var __var_" ++ show n ++ " = " ++ s ++ ";\n"
173 p = translateParameterlist params
175translateVariableName :: LVar -> String
176translateVariableName (Loc i) =
179translateExpression :: SExp -> String
180translateExpression (SLet name value body) =
182 ++ translateVariableName name
184 ++ translateExpression body
186 ++ translateExpression value
189translateExpression (SConst cst) =
190 translateConstant cst
192translateExpression (SV var) =
193 translateVariableName var
195translateExpression (SApp False name vars) =
196 createTailcall $ translateFunctionCall name vars
198translateExpression (SApp True name vars) =
199 "new " ++ idrRTNamespace ++ "Tailcall("
201 ++ "return " ++ translateFunctionCall name vars
204translateExpression (SOp op vars)
205 | LNoOp <- op = translateVariableName (last vars) ++ "/* NOOP */"
207 | (LPlus (ATInt ITBig)) <- op
208 , (lhs:rhs:_) <- vars = translateBinaryOp ".add(" lhs rhs ++ ")"
209 | (LMinus (ATInt ITBig)) <- op
210 , (lhs:rhs:_) <- vars = translateBinaryOp ".minus(" lhs rhs ++ ")"
211 | (LTimes (ATInt ITBig)) <- op
212 , (lhs:rhs:_) <- vars = translateBinaryOp ".times(" lhs rhs ++ ")"
213 | (LSDiv (ATInt ITBig)) <- op
214 , (lhs:rhs:_) <- vars = translateBinaryOp ".divide(" lhs rhs ++ ")"
215 | (LSRem (ATInt ITBig)) <- op
216 , (lhs:rhs:_) <- vars = translateBinaryOp ".mod(" lhs rhs ++ ")"
217 | (LEq (ATInt ITBig)) <- op
218 , (lhs:rhs:_) <- vars = translateBinaryOp ".equals(" lhs rhs ++ ")"
219 | (LLt (ATInt ITBig)) <- op
220 , (lhs:rhs:_) <- vars = translateBinaryOp ".lesser(" lhs rhs ++ ")"
221 | (LLe (ATInt ITBig)) <- op
222 , (lhs:rhs:_) <- vars = translateBinaryOp ".lesserOrEquals(" lhs rhs ++ ")"
223 | (LGt (ATInt ITBig)) <- op
224 , (lhs:rhs:_) <- vars = translateBinaryOp ".greater(" lhs rhs ++ ")"
225 | (LGe (ATInt ITBig)) <- op
226 , (lhs:rhs:_) <- vars = translateBinaryOp ".greaterOrEquals(" lhs rhs ++ ")"
228 | (LPlus ATFloat) <- op
229 , (lhs:rhs:_) <- vars = translateBinaryOp "+" lhs rhs
230 | (LMinus ATFloat) <- op
231 , (lhs:rhs:_) <- vars = translateBinaryOp "-" lhs rhs
232 | (LTimes ATFloat) <- op
233 , (lhs:rhs:_) <- vars = translateBinaryOp "*" lhs rhs
234 | (LSDiv ATFloat) <- op
235 , (lhs:rhs:_) <- vars = translateBinaryOp "/" lhs rhs
236 | (LEq ATFloat) <- op
237 , (lhs:rhs:_) <- vars = translateBinaryOp "==" lhs rhs
238 | (LLt ATFloat) <- op
239 , (lhs:rhs:_) <- vars = translateBinaryOp "<" lhs rhs
240 | (LLe ATFloat) <- op
241 , (lhs:rhs:_) <- vars = translateBinaryOp "<=" lhs rhs
242 | (LGt ATFloat) <- op
243 , (lhs:rhs:_) <- vars = translateBinaryOp ">" lhs rhs
244 | (LGe ATFloat) <- op
245 , (lhs:rhs:_) <- vars = translateBinaryOp ">=" lhs rhs
248 , (lhs:rhs:_) <- vars = translateBinaryOp "+" lhs rhs
250 , (lhs:rhs:_) <- vars = translateBinaryOp "-" lhs rhs
252 , (lhs:rhs:_) <- vars = translateBinaryOp "*" lhs rhs
254 , (lhs:rhs:_) <- vars = translateBinaryOp "/" lhs rhs
256 , (lhs:rhs:_) <- vars = translateBinaryOp "%" lhs rhs
258 , (lhs:rhs:_) <- vars = translateBinaryOp "==" lhs rhs
260 , (lhs:rhs:_) <- vars = translateBinaryOp "<" lhs rhs
262 , (lhs:rhs:_) <- vars = translateBinaryOp "<=" lhs rhs
264 , (lhs:rhs:_) <- vars = translateBinaryOp ">" lhs rhs
266 , (lhs:rhs:_) <- vars = translateBinaryOp ">=" lhs rhs
268 , (lhs:rhs:_) <- vars = translateBinaryOp "&" lhs rhs
270 , (lhs:rhs:_) <- vars = translateBinaryOp "|" lhs rhs
272 , (lhs:rhs:_) <- vars = translateBinaryOp "^" lhs rhs
274 , (lhs:rhs:_) <- vars = translateBinaryOp "<<" rhs lhs
276 , (lhs:rhs:_) <- vars = translateBinaryOp ">>" rhs lhs
278 , (arg:_) <- vars = '~' : translateVariableName arg
281 , (lhs:rhs:_) <- vars = translateBinaryOp "+" lhs rhs
283 , (lhs:rhs:_) <- vars = translateBinaryOp "==" lhs rhs
285 , (lhs:rhs:_) <- vars = translateBinaryOp "<" lhs rhs
287 , (arg:_) <- vars = translateVariableName arg ++ ".length"
289 | (LStrInt ITNative) <- op
290 , (arg:_) <- vars = "parseInt(" ++ translateVariableName arg ++ ")"
291 | (LIntStr ITNative) <- op
292 , (arg:_) <- vars = "String(" ++ translateVariableName arg ++ ")"
293 | (LSExt ITNative ITBig) <- op
294 , (arg:_) <- vars = idrRTNamespace ++ "bigInt(" ++ translateVariableName arg ++ ")"
295 | (LTrunc ITBig ITNative) <- op
296 , (arg:_) <- vars = translateVariableName arg ++ ".valueOf()"
297 | (LIntStr ITBig) <- op
298 , (arg:_) <- vars = translateVariableName arg ++ ".toString()"
299 | (LStrInt ITBig) <- op
300 , (arg:_) <- vars = idrRTNamespace ++ "bigInt(" ++ translateVariableName arg ++ ")"
302 , (arg:_) <- vars = "String(" ++ translateVariableName arg ++ ")"
304 , (arg:_) <- vars = "parseFloat(" ++ translateVariableName arg ++ ")"
305 | (LIntFloat ITNative) <- op
306 , (arg:_) <- vars = translateVariableName arg
307 | (LFloatInt ITNative) <- op
308 , (arg:_) <- vars = translateVariableName arg
309 | (LChInt ITNative) <- op
310 , (arg:_) <- vars = translateVariableName arg ++ ".charCodeAt(0)"
311 | (LIntCh ITNative) <- op
313 "String.fromCharCode(" ++ translateVariableName arg ++ ")"
316 , (arg:_) <- vars = "Math.exp(" ++ translateVariableName arg ++ ")"
318 , (arg:_) <- vars = "Math.log(" ++ translateVariableName arg ++ ")"
320 , (arg:_) <- vars = "Math.sin(" ++ translateVariableName arg ++ ")"
322 , (arg:_) <- vars = "Math.cos(" ++ translateVariableName arg ++ ")"
324 , (arg:_) <- vars = "Math.tan(" ++ translateVariableName arg ++ ")"
326 , (arg:_) <- vars = "Math.asin(" ++ translateVariableName arg ++ ")"
328 , (arg:_) <- vars = "Math.acos(" ++ translateVariableName arg ++ ")"
330 , (arg:_) <- vars = "Math.atan(" ++ translateVariableName arg ++ ")"
332 , (arg:_) <- vars = "Math.sqrt(" ++ translateVariableName arg ++ ")"
334 , (arg:_) <- vars = "Math.floor(" ++ translateVariableName arg ++ ")"
336 , (arg:_) <- vars = "Math.ceil(" ++ translateVariableName arg ++ ")"
339 , (lhs:rhs:_) <- vars = translateBinaryOp "+" lhs rhs
341 , (arg:_) <- vars = translateVariableName arg ++ "[0]"
343 , (arg:_) <- vars = let v = translateVariableName arg in
344 v ++ ".split('').reverse().join('')"
346 , (lhs:rhs:_) <- vars = let l = translateVariableName lhs
347 r = translateVariableName rhs in
350 , (arg:_) <- vars = let v = translateVariableName arg in
351 v ++ ".substr(1," ++ v ++ ".length-1)"
353 translateBinaryOp :: String -> LVar -> LVar -> String
354 translateBinaryOp f lhs rhs =
355 translateVariableName lhs
357 ++ translateVariableName rhs
359translateExpression (SError msg) =
360 "(function(){throw \'" ++ msg ++ "\';})()"
362translateExpression (SForeign _ _ "putStr" [(FString, var)]) =
363 idrRTNamespace ++ "print(" ++ translateVariableName var ++ ")"
365translateExpression (SForeign _ _ fun args)
366 | "[]=" `isSuffixOf` fun
367 , (obj:idx:val:[]) <- args =
368 concat [object obj, index idx, assign val]
370 | "[]" `isSuffixOf` fun
371 , (obj:idx:[]) <- args =
372 object obj ++ index idx
374 | "[" `isPrefixOf` fun && "]=" `isSuffixOf` fun
375 , (obj:val:[]) <- args =
376 concat [object obj, '[' : name ++ "]", assign val]
378 | "[" `isPrefixOf` fun && "]" `isSuffixOf` fun
380 object obj ++ '[' : name ++ "]"
382 | "." `isPrefixOf` fun, "=" `isSuffixOf` fun
383 , (obj:val:[]) <- args =
384 concat [object obj, field, assign val]
386 | "." `isPrefixOf` fun
390 | "." `isPrefixOf` fun
391 , (obj:[(FUnit, _)]) <- args =
392 concat [object obj, method, "()"]
394 | "." `isPrefixOf` fun
396 concat [object obj, method, arguments as]
398 | "[]=" `isSuffixOf` fun
399 , (idx:val:[]) <- args =
400 concat [array, index idx, assign val]
402 | "[]" `isSuffixOf` fun
406 | otherwise = fun ++ arguments args
408 name = filter (`notElem` "[]=") fun
412 object o = translateVariableName (snd o)
413 index i = "[" ++ translateVariableName (snd i) ++ "]"
414 assign v = '=' : generateWrapper v
416 '(' : intercalate "," (map generateWrapper as) ++ ")"
418 generateWrapper (ffunc, name)
419 | FFunction <- ffunc = idrRTNamespace ++ "ffiWrap(" ++ translateVariableName name ++ ")"
420 | FFunctionIO <- ffunc = idrRTNamespace ++ "ffiWrap(" ++ translateVariableName name ++ ")"
422 generateWrapper (_, name) =
423 translateVariableName name
425translateExpression (SChkCase var cases) =
427 ++ intercalate " else " (map (translateCase "e") cases)
429 ++ translateVariableName var
432translateExpression (SCase var cases) =
434 ++ intercalate " else " (map (translateCase "e") cases)
436 ++ translateVariableName var
439translateExpression (SCon i name vars) =
440 concat [ "new " ++ idrRTNamespace ++ "Con("
443 , intercalate "," $ map translateVariableName vars
447translateExpression (SUpdate var e) =
448 translateVariableName var ++ " = " ++ translateExpression e
450translateExpression (SProj var i) =
451 translateVariableName var ++ ".vars[" ++ show i ++"]"
453translateExpression SNothing = "null"
455translateExpression e =
456 "(function(){throw 'Not yet implemented: "
457 ++ filter (/= '\'') (show e)
460translateCase :: String -> SAlt -> String
461translateCase _ (SDefaultCase e) =
462 createIfBlock "true" (translateExpression e)
464translateCase var (SConstCase ty e)
465 | StrType <- ty = matchHelper "String"
466 | PtrType <- ty = matchHelper "Ptr"
467 | Forgot <- ty = matchHelper "Forgot"
468 | (AType ATFloat) <- ty = matchHelper "Float"
469 | (AType (ATInt ITBig)) <- ty = matchHelper "Integer"
470 | (AType (ATInt ITNative)) <- ty = matchHelper "Int"
471 | (AType (ATInt ITChar)) <- ty = matchHelper "Char"
473 matchHelper tyName = translateTypeMatch var tyName e
475translateCase var (SConstCase cst@(BI _) e) =
476 let cond = idrRTNamespace ++ "bigInt(" ++ var ++ ").equals(" ++ translateConstant cst ++ ")" in
477 createIfBlock cond (translateExpression e)
479translateCase var (SConstCase cst e) =
480 let cond = var ++ " == " ++ translateConstant cst in
481 createIfBlock cond (translateExpression e)
483translateCase var (SConCase a i name vars e) =
484 let isCon = var ++ " instanceof " ++ idrRTNamespace ++ "Con"
485 isI = show i ++ " == " ++ var ++ ".i"
486 params = intercalate "," $ map (("__var_" ++) . show) [a..(a+length vars)]
487 args = ".apply(this," ++ var ++ ".vars)"
491 ++ "){\nreturn " ++ b ++ "\n})" ++ args
492 cond = intercalate " && " [isCon, isI] in
493 createIfBlock cond $ f (translateExpression e)
495translateTypeMatch :: String -> String -> SExp -> String
496translateTypeMatch var ty exp =
497 let e = translateExpression exp in
499 ++ " instanceof " ++ idrRTNamespace ++ "Type && "
500 ++ var ++ ".type == '"++ ty ++"'") e
503createIfBlock cond e =
504 "if (" ++ cond ++") {\n"
509 idrRTNamespace ++ "tailcall(function(){return " ++ call ++ "})"
511translateFunctionCall name vars =
512 concat (translateNamespace name)
513 ++ translateName name
515 ++ intercalate "," (map translateVariableName vars)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list