1{-# LANGUAGE PatternGuards #-}
3module IRTS.CodegenJavaScript (codegenJavaScript) where
9import IRTS.CodegenCommon
19type NamespaceName = String
21idrNamespace :: NamespaceName
22idrNamespace = "__IDR__"
29codegenJavaScript definitions filename outputType =
30 writeFile filename output
32 def = map (first translateNamespace) definitions
35 mainLoop = intercalate "\n" [ "\nfunction main() {"
36 , createTailcall "__IDR__.runMain0()"
41 output = concat [ idrRuntime
42 , concatMap (translateModule Nothing) def
48 createModule Nothing idrNamespace $ concat
49 [ "__IDR__.Type = function(type) { this.type = type; };"
50 , "__IDR__.Int = new __IDR__.Type('Int');"
51 , "__IDR__.Char = new __IDR__.Type('Char');"
52 , "__IDR__.String = new __IDR__.Type('String');"
53 , "__IDR__.Integer = new __IDR__.Type('Integer');"
54 , "__IDR__.Float = new __IDR__.Type('Float');"
55 , "__IDR__.Forgot = new __IDR__.Type('Forgot');"
57 , "__IDR__.Tailcall = function(f) { this.f = f };"
59 , "__IDR__.Con = function(i,name,vars)"
60 , "{this.i = i;this.name = name;this.vars = vars;};\n"
62 , "__IDR__.tailcall = function(f){\n"
68 ++ "if (ret instanceof __IDR__.Tailcall) {\n"
76 , "var newline_regex =/(.*)\\n$/;\n"
78 , "__IDR__.print = function(s){\n"
79 ++ "var m = s.match(newline_regex);\n"
80 ++ "console.log(m ? m[1] : s);"
84createModule :: Maybe String -> NamespaceName -> String -> String
85createModule toplevel modname body =
86 concat [header modname, body, footer modname]
88 header :: NamespaceName -> String
91 [ "\nvar " ++ modname ++ ";"
92 , "(function(" ++ modname ++ "){"
95 footer :: NamespaceName -> String
97 let m = maybe "" (++ ".") toplevel ++ modname in
105translateModule :: Maybe String -> ([String], SDecl) -> String
106translateModule toplevel ([modname], decl) =
107 let body = translateDeclaration modname decl in
108 createModule toplevel modname body
109translateModule toplevel (n:ns, decl) =
110 createModule toplevel n $ translateModule (Just n) (ns, decl)
112translateIdentifier :: String -> String
114 concatMap replaceBadChars
115 where replaceBadChars :: Char -> String
116 replaceBadChars ' ' = "_"
117 replaceBadChars '_' = "__"
118 replaceBadChars '@' = "_at"
119 replaceBadChars '[' = "_OSB"
120 replaceBadChars ']' = "_CSB"
121 replaceBadChars '(' = "_OP"
122 replaceBadChars ')' = "_CP"
123 replaceBadChars '{' = "_OB"
124 replaceBadChars '}' = "_CB"
125 replaceBadChars '!' = "_bang"
126 replaceBadChars '#' = "_hash"
127 replaceBadChars '.' = "_dot"
128 replaceBadChars ',' = "_comma"
129 replaceBadChars ':' = "_colon"
130 replaceBadChars '+' = "_plus"
131 replaceBadChars '-' = "_minus"
132 replaceBadChars '*' = "_times"
133 replaceBadChars '<' = "_lt"
134 replaceBadChars '>' = "_gt"
135 replaceBadChars '=' = "_eq"
136 replaceBadChars '|' = "_pipe"
137 replaceBadChars '&' = "_amp"
138 replaceBadChars '\'' = "_apo"
140 | isDigit c = "_" ++ [c] ++ "_"
143translateNamespace :: Name -> [String]
144translateNamespace (UN _) = [idrNamespace]
145translateNamespace (NS _ ns) = idrNamespace : map translateIdentifier ns
146translateNamespace (MN _ _) = [idrNamespace]
148translateName :: Name -> String
149translateName (UN name) = translateIdentifier name
150translateName (NS name _) = translateName name
151translateName (MN i name) = translateIdentifier name ++ show i
153translateQualifiedName :: Name -> String
154translateQualifiedName name =
155 intercalate "." (translateNamespace name) ++ "." ++ translateName name
157translateConstant :: Const -> String
158translateConstant (I i) = show i
159translateConstant (BI i) = show i
160translateConstant (Fl f) = show f
161translateConstant (Ch c) = show c
162translateConstant (Str s) = show s
163translateConstant IType = "__IDR__.Int"
164translateConstant ChType = "__IDR__.Char"
165translateConstant StrType = "__IDR__.String"
166translateConstant BIType = "__IDR__.Integer"
167translateConstant FlType = "__IDR__.Float"
168translateConstant Forgot = "__IDR__.Forgot"
170 "(function(){throw 'Unimplemented Const: " ++ show c ++ "';})()"
172translateParameterlist =
173 map translateParameter
174 where translateParameter (MN i name) = name ++ show i
175 translateParameter (UN name) = name
177translateDeclaration :: NamespaceName -> SDecl -> String
178translateDeclaration modname (SFun name params stackSize body) =
181 ++ translateName name
185 ++ concatMap assignVar (zip [0..] p)
186 ++ concatMap allocVar [numP..(numP+stackSize-1)]
188 ++ translateExpression modname body
194 allocVar :: Int -> String
195 allocVar n = "var __var_" ++ show n ++ ";\n"
197 assignVar :: (Int, String) -> String
198 assignVar (n, s) = "var __var_" ++ show n ++ " = " ++ s ++ ";\n"
201 p = translateParameterlist params
203translateVariableName :: LVar -> String
204translateVariableName (Loc i) =
207translateExpression :: NamespaceName -> SExp -> String
208translateExpression modname (SLet name value body) =
210 ++ translateVariableName name
212 ++ translateExpression modname body
214 ++ translateExpression modname value
217translateExpression _ (SConst cst) =
218 translateConstant cst
220translateExpression _ (SV var) =
221 translateVariableName var
223translateExpression modname (SApp False name vars) =
224 createTailcall $ translateFunctionCall name vars
226translateExpression modname (SApp True name vars) =
228 ++ "return new __IDR__.Tailcall("
230 ++ "return " ++ translateFunctionCall name vars
234translateExpression _ (SOp op vars)
236 , (lhs:rhs:_) <- vars = translateBinaryOp "+" lhs rhs
238 , (lhs:rhs:_) <- vars = translateBinaryOp "-" lhs rhs
240 , (lhs:rhs:_) <- vars = translateBinaryOp "*" lhs rhs
242 , (lhs:rhs:_) <- vars = translateBinaryOp "/" lhs rhs
244 , (lhs:rhs:_) <- vars = translateBinaryOp "%" lhs rhs
246 , (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
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
265 , (lhs:rhs:_) <- vars = translateBinaryOp "==" lhs rhs
267 , (lhs:rhs:_) <- vars = translateBinaryOp "<" lhs rhs
269 , (lhs:rhs:_) <- vars = translateBinaryOp "<=" lhs rhs
271 , (lhs:rhs:_) <- vars = translateBinaryOp ">" lhs rhs
273 , (lhs:rhs:_) <- vars = translateBinaryOp ">=" lhs rhs
276 , (lhs:rhs:_) <- vars = translateBinaryOp "+" lhs rhs
278 , (lhs:rhs:_) <- vars = translateBinaryOp "-" lhs rhs
280 , (lhs:rhs:_) <- vars = translateBinaryOp "*" lhs rhs
282 , (lhs:rhs:_) <- vars = translateBinaryOp "/" lhs rhs
284 , (lhs:rhs:_) <- vars = translateBinaryOp "%" lhs rhs
286 , (lhs:rhs:_) <- vars = translateBinaryOp "==" lhs rhs
288 , (lhs:rhs:_) <- vars = translateBinaryOp "<" lhs rhs
290 , (lhs:rhs:_) <- vars = translateBinaryOp "<=" lhs rhs
292 , (lhs:rhs:_) <- vars = translateBinaryOp ">" lhs rhs
294 , (lhs:rhs:_) <- vars = translateBinaryOp ">=" lhs rhs
297 , (arg:_) <- vars = translateVariableName arg ++ "[0]"
299 , (arg:_) <- vars = let v = translateVariableName arg in
300 v ++ ".substr(1," ++ v ++ ".length-1)"
302 , (lhs:rhs:_) <- vars = translateBinaryOp "+" lhs rhs
304 , (lhs:rhs:_) <- vars = translateBinaryOp "==" lhs rhs
306 , (lhs:rhs:_) <- vars = translateBinaryOp "+" lhs rhs
309 , (arg:_) <- vars = "String(" ++ translateVariableName arg ++ ");"
312 translateBinaryOp :: String -> LVar -> LVar -> String
313 translateBinaryOp f lhs rhs =
314 translateVariableName lhs
316 ++ translateVariableName rhs
318translateExpression _ (SError msg) =
319 "(function(){throw \'" ++ msg ++ "\';})();"
321translateExpression _ (SForeign _ _ "putStr" [(FString, var)]) =
322 "__IDR__.print(" ++ translateVariableName var ++ ");"
324translateExpression _ (SForeign _ _ fun args) =
327 ++ intercalate "," (map (translateVariableName . snd) args)
330translateExpression modname (SChkCase var cases) =
332 ++ intercalate " else " (map (translateCase modname "e") cases)
334 ++ translateVariableName var
337translateExpression modname (SCase var cases) =
339 ++ intercalate " else " (map (translateCase modname "e") cases)
341 ++ translateVariableName var
344translateExpression _ (SCon i name vars) =
345 concat [ "new __IDR__.Con("
348 , '\'' : translateQualifiedName name ++ "\',["
349 , intercalate "," $ map translateVariableName vars
353translateExpression modname (SUpdate var e) =
354 translateVariableName var ++ " = " ++ translateExpression modname e
356translateExpression modname (SProj var i) =
357 translateVariableName var ++ ".vars[" ++ show i ++"]"
359translateExpression _ SNothing = "null"
361translateExpression _ e =
362 "(function(){throw 'Not yet implemented: "
363 ++ filter (/= '\'') (show e)
366translateCase :: String -> String -> SAlt -> String
367translateCase modname _ (SDefaultCase e) =
368 createIfBlock "true" (translateExpression modname e)
370translateCase modname var (SConstCase ty e)
371 | ChType <- ty = matchHelper "Char"
372 | StrType <- ty = matchHelper "String"
373 | IType <- ty = matchHelper "Int"
374 | BIType <- ty = matchHelper "Integer"
375 | FlType <- ty = matchHelper "Float"
376 | Forgot <- ty = matchHelper "Forgot"
378 matchHelper tyName = translateTypeMatch modname var tyName e
380translateCase modname var (SConstCase cst e) =
381 let cond = var ++ " == " ++ translateConstant cst in
382 createIfBlock cond (translateExpression modname e)
384translateCase modname var (SConCase a i name vars e) =
385 let isCon = var ++ " instanceof __IDR__.Con"
386 isI = show i ++ " == " ++ var ++ ".i"
387 params = intercalate "," $ map (("__var_" ++) . show) [a..(a+length vars)]
388 args = ".apply(this," ++ var ++ ".vars)"
392 ++ "){\nreturn " ++ b ++ "\n})" ++ args
393 cond = intercalate " && " [isCon, isI] in
394 createIfBlock cond $ f (translateExpression modname e)
396translateTypeMatch :: String -> String -> String -> SExp -> String
397translateTypeMatch modname var ty exp =
398 let e = translateExpression modname exp in
400 ++ " instanceof __IDR__.Type && "
401 ++ var ++ ".type == '"++ ty ++"'") e
404createIfBlock cond e =
405 "if (" ++ cond ++") {\n"
410 "__IDR__.tailcall(function(){return " ++ call ++ "})"
412translateFunctionCall name vars =
413 concat (intersperse "." $ translateNamespace name)
415 ++ translateName name
417 ++ 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