javascript_writer.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. from visitor import Visitor
  2. from generic_language_constructs import *
  3. class JavascriptWriter(CLikeWriterBase):
  4. def __init__(self, outputter):
  5. self.out = outputter
  6. ### VISIT METHODS ###
  7. def visit_ArrayContains(self, a):
  8. array = a.getArrayExpression()
  9. el = a.getElementExpression()
  10. self.out.extendWrite("(")
  11. array.accept(self)
  12. self.out.extendWrite(".indexOf(")
  13. el.accept(self)
  14. self.out.extendWrite(") !== -1)")
  15. def visit_ArrayExpression(self, a):
  16. elements = a.getElements()
  17. if len(elements) == 0:
  18. self.out.extendWrite("new Array()")
  19. else:
  20. self.out.extendWrite("[")
  21. self.writeCommaSeparated(elements)
  22. self.out.extendWrite("]")
  23. def visit_ArrayIndexOf(self, a):
  24. array = a.getArrayExpression()
  25. el = a.getElementExpression()
  26. array.accept(self)
  27. self.out.extendWrite(".indexOf(")
  28. el.accept(self)
  29. self.out.extendWrite(")")
  30. def visit_ArrayLength(self, a):
  31. a.getArrayExpression().accept(self)
  32. self.out.extendWrite(".length")
  33. def visit_ArrayPushBack(self, a):
  34. array = a.getArrayExpression()
  35. el = a.getElementExpression()
  36. array.accept(self)
  37. self.out.extendWrite(".push(")
  38. el.accept(self)
  39. self.out.extendWrite(")")
  40. def visit_AST(self, ast):
  41. self.writeAll(ast.getEntries())
  42. def visit_Class(self, c):
  43. class_name = c.getIdentifier()
  44. constructor = c.getConstructor()
  45. super_classes = c.getSuperClassIdentifierList()
  46. description = c.getDescription()
  47. self.out.write()
  48. if description:
  49. self.writeComment(description)
  50. constructor.accept(self)
  51. if super_classes:
  52. self.out.write(class_name + ".prototype = new Object();")
  53. self.out.write("(function() {")
  54. self.out.indent()
  55. for s in super_classes:
  56. # workaround for multiple inheritance
  57. self.out.write("var proto = new " + s + "();")
  58. self.out.write("for (prop in proto) {")
  59. self.out.indent()
  60. self.out.write(class_name + ".prototype[prop] = proto[prop];")
  61. self.out.dedent()
  62. self.out.write("}")
  63. self.out.dedent()
  64. self.out.write("})();")
  65. self.writeAll(c.getMembers())
  66. def visit_Constructor(self, constructor):
  67. class_name = constructor.getClass().getIdentifier()
  68. parameters = constructor.getFormalParameters()
  69. body = constructor.getBody()
  70. self.out.write("var " + class_name + " = function")
  71. parameters.accept(self)
  72. body.accept(self)
  73. self.out.extendWrite(";")
  74. def visit_EqualsOperator(self, e):
  75. self.out.extendWrite(" === ")
  76. def visit_ForLoopBody(self, body):
  77. for_loop = body.getForLoop()
  78. collection_expr = for_loop.getCollectionExpression()
  79. iterator_identifier = for_loop.getIteratorIdentifier()
  80. self.out.extendWrite(" {")
  81. self.out.indent()
  82. self.out.write("if (!")
  83. collection_expr.accept(self)
  84. self.out.extendWrite(".hasOwnProperty(" + iterator_identifier + ")) continue;")
  85. self.writeAll(body.getEntries())
  86. self.out.dedent()
  87. self.out.write("}")
  88. def visit_ForLoopCurrentElement(self, el):
  89. collection = el.getCollectionExpression()
  90. iterator = el.getIteratorIdentifier()
  91. collection.accept(self)
  92. self.out.extendWrite("["+iterator+"]")
  93. def visit_ForLoopIterateArray(self, loop):
  94. collection = loop.getCollectionExpression()
  95. iterator = loop.getIteratorIdentifier()
  96. body = loop.getBody()
  97. self.out.write("for (var " + iterator + " in ")
  98. collection.accept(self)
  99. self.out.extendWrite(")")
  100. body.accept(self)
  101. def visit_ForLoopIterateMapValues(self, loop):
  102. collection = loop.getCollectionExpression()
  103. iterator = loop.getIteratorIdentifier()
  104. body = loop.getBody()
  105. self.out.write("for (var " + iterator + " in ")
  106. collection.accept(self)
  107. self.out.extendWrite(")")
  108. body.accept(self)
  109. def visit_FormalParameter(self, parameter):
  110. self.out.extendWrite(parameter.getIdentifier())
  111. def visit_IncludeStatement(self, i):
  112. pass # javascript doesn't have an include mechanism
  113. def visit_LocalVariableDeclaration(self, decl):
  114. identifier = decl.getIdentifier()
  115. init_value = decl.getInitValue()
  116. self.out.extendWrite("var " + identifier)
  117. if init_value:
  118. self.out.extendWrite(" = ")
  119. init_value.accept(self)
  120. def visit_LogStatement(self, l):
  121. self.out.write("console.log(\"" + l.getMessage() + "\");")
  122. def visit_MapExpression(self, m):
  123. elements = m.getElements()
  124. if len(elements) == 0:
  125. self.out.extendWrite("new Object()")
  126. else:
  127. self.out.extendWrite("{")
  128. keys = elements.keys()
  129. for i in range(len(keys)):
  130. if i != 0:
  131. self.out.extendWrite(", ")
  132. self.out.extendWrite(keys[i] + " : ")
  133. self.out.extendWrite(" : ")
  134. elements[keys[i]].accept(self)
  135. self.out.extendWrite("}")
  136. def visit_MapIndexedExpression(self, i):
  137. m = i.getMapExpression()
  138. key = i.getKeyExpression()
  139. m.accept(self)
  140. self.out.extendWrite("[")
  141. key.accept(self)
  142. self.out.extendWrite("]")
  143. def visit_MapRemoveElement(self, stmt):
  144. map_expr = stmt.getMapExpression()
  145. key_expr = stmt.getKeyExpression()
  146. self.out.write("delete ") # this is a statement, not an expression
  147. map_expr.accept(self)
  148. self.out.extendWrite("[")
  149. key_expr.accept(self)
  150. self.out.extendWrite("];")
  151. def visit_Method(self, method):
  152. class_name = method.getClass().getIdentifier()
  153. method_name = method.getIdentifier()
  154. description = method.getDescription()
  155. body = method.getBody()
  156. parameters = method.getFormalParameters()
  157. self.out.write()
  158. if description:
  159. self.writeComment(description)
  160. self.writeDescription(method)
  161. self.out.write(class_name + ".prototype." + method_name + " = function")
  162. parameters.accept(self)
  163. body.accept(self)
  164. self.out.extendWrite(";")
  165. def visit_MethodBody(self, body):
  166. method = body.getMethod()
  167. formal_parameters = method.getFormalParameters()
  168. formal_parameter_list = formal_parameters.getParameterList()
  169. self.out.extendWrite(" {")
  170. self.out.indent()
  171. # check for undefined parameters and replace them with default values
  172. for p in formal_parameter_list:
  173. p_id = p.getIdentifier()
  174. p_default = p.getDefaultValue()
  175. if p_default:
  176. self.out.write("if (" + p_id + " === undefined) " + p_id + " = ")
  177. p_default.accept(self)
  178. self.out.extendWrite(";")
  179. self.writeAll(body.getEntries())
  180. self.out.dedent()
  181. self.out.write("}")
  182. def visit_NoneExpression(self, n):
  183. self.out.extendWrite("null")
  184. def visit_Package(self, package):
  185. name = package.getIdentifier()
  186. description = package.getDescription()
  187. self.writeComment("package \"" + name + "\"")
  188. if description:
  189. self.writeComment(description)
  190. self.out.write("var " + name + " = {};")
  191. self.out.write("(function() {")
  192. for d in package.getDeclarations():
  193. d_id = d.getIdentifier()
  194. d.accept(self)
  195. self.out.write()
  196. self.out.write("// add symbol '" + d_id + "' to package '" + name + "'")
  197. self.out.write(name + "." + d_id + " = " + d_id + ";")
  198. self.out.write("})();")
  199. def visit_RuntimeModuleIdentifier(self, r):
  200. self.out.extendWrite("javascript_runtime")
  201. def visit_StaticAttribute(self, attr):
  202. name = attr.getIdentifier()
  203. init_value = attr.getInitValue()
  204. class_name = attr.getClass().getIdentifier()
  205. if init_value:
  206. self.out.write(class_name + ".prototype." + name + " = ")
  207. init_value.accept(self)
  208. self.out.extendWrite(";")
  209. else:
  210. self.out.write(class_name + ".prototype." + name + " = null;")
  211. def visit_SuperClassConstructorCall(self, call):
  212. super_class = call.getSuperClassIdentifier()
  213. params = call.getActualParameters()
  214. param_list = [Literal("this")] + params.getParameterList()
  215. params = ActualParameters(param_list)
  216. self.out.extendWrite(super_class)
  217. self.out.extendWrite(".call")
  218. params.accept(self)
  219. def visit_SuperClassDestructorCall(self, call):
  220. pass # Javascript doesn't have destructors
  221. def visit_SuperClassMethodCall(self, call):
  222. super_class = call.getSuperClassIdentifier()
  223. method_name = call.getMethodIdentifier()
  224. params = call.getActualParameters()
  225. param_list = [Literal("this")] + params.getParameterList()
  226. params = ActualParameters(param_list)
  227. self.out.extendWrite(super_class)
  228. self.out.extendWrite(".prototype." + method_name + ".call")
  229. params.accept(self)
  230. def visit_ThrowExceptionStatement(self, stmt):
  231. self.out.write("throw new Error(")
  232. stmt.getExpression().accept(self)
  233. self.out.extendWrite(");")