1{-# LANGUAGE PatternGuards #-}
3module IRTS.CodegenJavaScript (codegenJavaScript) where
9import IRTS.CodegenCommon
17import qualified Data.Map as Map
21idrNamespace = "__IDR__"
28codegenJavaScript definitions filename outputType = do
30 idrRuntime <- readFile (path ++ "/js/Runtime.js")
31 writeFile filename (idrRuntime ++ modules ++ functions ++ mainLoop)
33 def = map (first translateNamespace) definitions
35 functions = concatMap translateDeclaration def
38 mainLoop = intercalate "\n" [ "\nfunction main() {"
39 , createTailcall "__IDR__.runMain0()"
44 concatMap allocMod mods
46 allocMod m = intercalate "." m ++ " = {};\n"
47 sortMods a b = compare (length a) (length b)
50 drop 1 $ sortBy sortMods $ nub $ concatMap (inits . fst) def
52translateIdentifier :: String -> String
54 replaceReserved . concatMap replaceBadChars
55 where replaceBadChars :: Char -> String
57 | isDigit c = "_" ++ [c] ++ "_"
58 | not (isLetter c && isAscii c) = '_' : show (ord c)
61 | s `elem` reserved = '_' : s
108translateNamespace :: Name -> [String]
109translateNamespace (UN _) = [idrNamespace]
110translateNamespace (NS _ ns) = idrNamespace : map translateIdentifier ns
111translateNamespace (MN _ _) = [idrNamespace]
113translateName :: Name -> String
114translateName (UN name) = translateIdentifier name
115translateName (NS name _) = translateName name
116translateName (MN i name) = translateIdentifier name ++ show i
118translateConstant :: Const -> String
119translateConstant (I i) = show i
120translateConstant (BI i) = "__IDRRT__.bigInt('" ++ show i ++ "')"
121translateConstant (Fl f) = show f
122translateConstant (Ch c) = show c
123translateConstant (Str s) = show s
124translateConstant IType = "__IDRRT__.Int"
125translateConstant ChType = "__IDRRT__.Char"
126translateConstant StrType = "__IDRRT__.String"
127translateConstant BIType = "__IDRRT__.Integer"
128translateConstant FlType = "__IDRRT__.Float"
129translateConstant Forgot = "__IDRRT__.Forgot"
131 "(function(){throw 'Unimplemented Const: " ++ show c ++ "';})()"
133translateParameterlist =
134 map translateParameter
135 where translateParameter (MN i name) = translateIdentifier name ++ show i
136 translateParameter (UN name) = translateIdentifier name
138translateDeclaration :: ([String], SDecl) -> String
139translateDeclaration (path, SFun name params stackSize body) =
140 intercalate "." (path ++ [translateName name])
144 ++ concatMap assignVar (zip [0..] p)
145 ++ concatMap allocVar [numP..(numP+stackSize-1)]
147 ++ translateExpression body
153 allocVar :: Int -> String
154 allocVar n = "var __var_" ++ show n ++ ";\n"
156 assignVar :: (Int, String) -> String
157 assignVar (n, s) = "var __var_" ++ show n ++ " = " ++ s ++ ";\n"
160 p = translateParameterlist params
162translateVariableName :: LVar -> String
163translateVariableName (Loc i) =
166translateExpression :: SExp -> String
167translateExpression (SLet name value body) =
169 ++ translateVariableName name
171 ++ translateExpression body
173 ++ translateExpression value
176translateExpression (SConst cst) =
177 translateConstant cst
179translateExpression (SV var) =
180 translateVariableName var
182translateExpression (SApp False name vars) =
183 createTailcall $ translateFunctionCall name vars
185translateExpression (SApp True name vars) =
186 "new __IDRRT__.Tailcall("
188 ++ "return " ++ translateFunctionCall name vars
191translateExpression (SOp op vars)
193 , (lhs:rhs:_) <- vars = translateBinaryOp "+" lhs rhs
195 , (lhs:rhs:_) <- vars = translateBinaryOp "-" lhs rhs
197 , (lhs:rhs:_) <- vars = translateBinaryOp "*" lhs rhs
199 , (lhs:rhs:_) <- vars = translateBinaryOp "/" lhs rhs
201 , (lhs:rhs:_) <- vars = translateBinaryOp "%" lhs rhs
203 , (lhs:rhs:_) <- vars = translateBinaryOp "==" lhs rhs
205 , (lhs:rhs:_) <- vars = translateBinaryOp "<" lhs rhs
207 , (lhs:rhs:_) <- vars = translateBinaryOp "<=" lhs rhs
209 , (lhs:rhs:_) <- vars = translateBinaryOp ">" lhs rhs
211 , (lhs:rhs:_) <- vars = translateBinaryOp ">=" lhs rhs
213 , (lhs:rhs:_) <- vars = translateBinaryOp "&" lhs rhs
215 , (lhs:rhs:_) <- vars = translateBinaryOp "|" lhs rhs
217 , (lhs:rhs:_) <- vars = translateBinaryOp "^" lhs rhs
219 , (lhs:rhs:_) <- vars = translateBinaryOp "<<" rhs lhs
221 , (lhs:rhs:_) <- vars = translateBinaryOp ">>" rhs lhs
223 , (arg:_) <- vars = '~' : translateVariableName arg
226 , (lhs:rhs:_) <- vars = translateBinaryOp ".add(" lhs rhs ++ ")"
228 , (lhs:rhs:_) <- vars = translateBinaryOp ".minus(" lhs rhs ++ ")"
230 , (lhs:rhs:_) <- vars = translateBinaryOp ".times(" lhs rhs ++ ")"
232 , (lhs:rhs:_) <- vars = translateBinaryOp ".divide(" lhs rhs ++ ")"
234 , (lhs:rhs:_) <- vars = translateBinaryOp ".mod(" lhs rhs ++ ")"
236 , (lhs:rhs:_) <- vars = translateBinaryOp ".equals(" lhs rhs ++ ")"
238 , (lhs:rhs:_) <- vars = translateBinaryOp ".lesser(" lhs rhs ++ ")"
240 , (lhs:rhs:_) <- vars = translateBinaryOp ".lesserOrEquals(" lhs rhs ++ ")"
242 , (lhs:rhs:_) <- vars = translateBinaryOp ".greater(" lhs rhs ++ ")"
244 , (lhs:rhs:_) <- vars = translateBinaryOp ".greaterOrEquals(" lhs rhs ++ ")"
247 , (lhs:rhs:_) <- vars = translateBinaryOp "+" lhs rhs
249 , (lhs:rhs:_) <- vars = translateBinaryOp "-" lhs rhs
251 , (lhs:rhs:_) <- vars = translateBinaryOp "*" lhs rhs
253 , (lhs:rhs:_) <- vars = translateBinaryOp "/" lhs rhs
255 , (lhs:rhs:_) <- vars = translateBinaryOp "==" lhs rhs
257 , (lhs:rhs:_) <- vars = translateBinaryOp "<" lhs rhs
259 , (lhs:rhs:_) <- vars = translateBinaryOp "<=" lhs rhs
261 , (lhs:rhs:_) <- vars = translateBinaryOp ">" lhs rhs
263 , (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 , (arg:_) <- vars = translateVariableName arg ++ ".length"
275 , (arg:_) <- vars = "parseInt(" ++ translateVariableName arg ++ ")"
277 , (arg:_) <- vars = "String(" ++ translateVariableName arg ++ ")"
279 , (arg:_) <- vars = "__IDRRT__.bigInt(" ++ translateVariableName arg ++ ")"
281 , (arg:_) <- vars = translateVariableName arg ++ ".valueOf()"
283 , (arg:_) <- vars = translateVariableName arg ++ ".toString()"
285 , (arg:_) <- vars = "__IDRRT__.bigInt(" ++ translateVariableName arg ++ ")"
287 , (arg:_) <- vars = "String(" ++ translateVariableName arg ++ ")"
289 , (arg:_) <- vars = "parseFloat(" ++ translateVariableName arg ++ ")"
291 , (arg:_) <- vars = translateVariableName arg
293 , (arg:_) <- vars = translateVariableName arg
295 , (arg:_) <- vars = translateVariableName arg ++ ".charCodeAt(0)"
298 "String.fromCharCode(" ++ translateVariableName arg ++ ")"
301 , (arg:_) <- vars = "Math.exp(" ++ translateVariableName arg ++ ")"
303 , (arg:_) <- vars = "Math.log(" ++ translateVariableName arg ++ ")"
305 , (arg:_) <- vars = "Math.sin(" ++ translateVariableName arg ++ ")"
307 , (arg:_) <- vars = "Math.cos(" ++ translateVariableName arg ++ ")"
309 , (arg:_) <- vars = "Math.tan(" ++ translateVariableName arg ++ ")"
311 , (arg:_) <- vars = "Math.asin(" ++ translateVariableName arg ++ ")"
313 , (arg:_) <- vars = "Math.acos(" ++ translateVariableName arg ++ ")"
315 , (arg:_) <- vars = "Math.atan(" ++ translateVariableName arg ++ ")"
317 , (arg:_) <- vars = "Math.sqrt(" ++ translateVariableName arg ++ ")"
319 , (arg:_) <- vars = "Math.floor(" ++ translateVariableName arg ++ ")"
321 , (arg:_) <- vars = "Math.ceil(" ++ translateVariableName arg ++ ")"
324 , (lhs:rhs:_) <- vars = translateBinaryOp "+" lhs rhs
326 , (arg:_) <- vars = translateVariableName arg ++ "[0]"
328 , (arg:_) <- vars = let v = translateVariableName arg in
329 v ++ "split('').reverse().join('')"
331 , (lhs:rhs:_) <- vars = let l = translateVariableName lhs
332 r = translateVariableName rhs in
335 , (arg:_) <- vars = let v = translateVariableName arg in
336 v ++ ".substr(1," ++ v ++ ".length-1)"
338 translateBinaryOp :: String -> LVar -> LVar -> String
339 translateBinaryOp f lhs rhs =
340 translateVariableName lhs
342 ++ translateVariableName rhs
344translateExpression (SError msg) =
345 "(function(){throw \'" ++ msg ++ "\';})();"
347translateExpression (SForeign _ _ "putStr" [(FString, var)]) =
348 "__IDRRT__.print(" ++ translateVariableName var ++ ");"
350translateExpression (SForeign _ _ fun args) =
353 ++ intercalate "," (map (translateVariableName . snd) args)
356translateExpression (SChkCase var cases) =
358 ++ intercalate " else " (map (translateCase "e") cases)
360 ++ translateVariableName var
363translateExpression (SCase var cases) =
365 ++ intercalate " else " (map (translateCase "e") cases)
367 ++ translateVariableName var
370translateExpression (SCon i name vars) =
371 concat [ "new __IDRRT__.Con("
374 , intercalate "," $ map translateVariableName vars
378translateExpression (SUpdate var e) =
379 translateVariableName var ++ " = " ++ translateExpression e
381translateExpression (SProj var i) =
382 translateVariableName var ++ ".vars[" ++ show i ++"]"
384translateExpression SNothing = "null"
386translateExpression e =
387 "(function(){throw 'Not yet implemented: "
388 ++ filter (/= '\'') (show e)
391translateCase :: String -> SAlt -> String
392translateCase _ (SDefaultCase e) =
393 createIfBlock "true" (translateExpression e)
395translateCase var (SConstCase ty e)
396 | ChType <- ty = matchHelper "Char"
397 | StrType <- ty = matchHelper "String"
398 | IType <- ty = matchHelper "Int"
399 | BIType <- ty = matchHelper "Integer"
400 | FlType <- ty = matchHelper "Float"
401 | PtrType <- ty = matchHelper "Pointer"
402 | Forgot <- ty = matchHelper "Forgot"
404 matchHelper tyName = translateTypeMatch var tyName e
406translateCase var (SConstCase cst@(BI _) e) =
407 let cond = var ++ ".equals(" ++ translateConstant cst ++ ")" in
408 createIfBlock cond (translateExpression e)
410translateCase var (SConstCase cst e) =
411 let cond = var ++ " == " ++ translateConstant cst in
412 createIfBlock cond (translateExpression e)
414translateCase var (SConCase a i name vars e) =
415 let isCon = var ++ " instanceof __IDRRT__.Con"
416 isI = show i ++ " == " ++ var ++ ".i"
417 params = intercalate "," $ map (("__var_" ++) . show) [a..(a+length vars)]
418 args = ".apply(this," ++ var ++ ".vars)"
422 ++ "){\nreturn " ++ b ++ "\n})" ++ args
423 cond = intercalate " && " [isCon, isI] in
424 createIfBlock cond $ f (translateExpression e)
426translateTypeMatch :: String -> String -> SExp -> String
427translateTypeMatch var ty exp =
428 let e = translateExpression exp in
430 ++ " instanceof __IDRRT__.Type && "
431 ++ var ++ ".type == '"++ ty ++"'") e
434createIfBlock cond e =
435 "if (" ++ cond ++") {\n"
440 "__IDRRT__.tailcall(function(){return " ++ call ++ "})"
442translateFunctionCall name vars =
443 concat (intersperse "." $ translateNamespace name)
445 ++ translateName name
447 ++ 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