javascript_writer.py 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. from sccd.compiler.visitor import Visitor
  2. from sccd.compiler.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 + "_idx)) continue;")
  85. self.out.write("var " + iterator_identifier + " = ")
  86. collection_expr.accept(self)
  87. self.out.extendWrite("[" + iterator_identifier + "_idx]")
  88. self.writeAll(body.getEntries())
  89. self.out.dedent()
  90. self.out.write("}")
  91. def visit_ForLoopCurrentElement(self, el):
  92. collection = el.getCollectionExpression()
  93. iterator = el.getIteratorIdentifier()
  94. collection.accept(self)
  95. self.out.extendWrite("[" + iterator + "]")
  96. def visit_ForLoopIterateArray(self, loop):
  97. collection = loop.getCollectionExpression()
  98. iterator = loop.getIteratorIdentifier()
  99. body = loop.getBody()
  100. self.out.write("for (var " + iterator + "_idx in ")
  101. collection.accept(self)
  102. self.out.extendWrite(")")
  103. body.accept(self)
  104. def visit_ForLoopIterateMapValues(self, loop):
  105. collection = loop.getCollectionExpression()
  106. iterator = loop.getIteratorIdentifier()
  107. body = loop.getBody()
  108. self.out.write("for (var " + iterator + "_idx in ")
  109. collection.accept(self)
  110. self.out.extendWrite(")")
  111. body.accept(self)
  112. def visit_FormalParameter(self, parameter):
  113. self.out.extendWrite(parameter.getIdentifier())
  114. def visit_IncludeStatement(self, i):
  115. pass # javascript doesn't have an include mechanism
  116. def visit_LocalVariableDeclaration(self, decl):
  117. identifier = decl.getIdentifier()
  118. init_value = decl.getInitValue()
  119. self.out.extendWrite("var " + identifier)
  120. if init_value:
  121. self.out.extendWrite(" = ")
  122. init_value.accept(self)
  123. def visit_LogStatement(self, l):
  124. self.out.write("console.log(\"" + l.getMessage() + "\");")
  125. def visit_MapExpression(self, m):
  126. elements = m.getElements()
  127. if len(elements) == 0:
  128. self.out.extendWrite("new Object()")
  129. else:
  130. self.out.extendWrite("{")
  131. keys = list(elements.keys())
  132. for i in range(len(keys)):
  133. if i != 0:
  134. self.out.extendWrite(", ")
  135. self.out.extendWrite(keys[i] + " : ")
  136. self.out.extendWrite(" : ")
  137. elements[keys[i]].accept(self)
  138. self.out.extendWrite("}")
  139. def visit_MapIndexedExpression(self, i):
  140. m = i.getMapExpression()
  141. key = i.getKeyExpression()
  142. m.accept(self)
  143. self.out.extendWrite("[")
  144. key.accept(self)
  145. self.out.extendWrite("]")
  146. def visit_MapRemoveElement(self, stmt):
  147. map_expr = stmt.getMapExpression()
  148. key_expr = stmt.getKeyExpression()
  149. self.out.write("delete ") # this is a statement, not an expression
  150. map_expr.accept(self)
  151. self.out.extendWrite("[")
  152. key_expr.accept(self)
  153. self.out.extendWrite("];")
  154. def visit_Method(self, method):
  155. class_name = method.getClass().getIdentifier()
  156. method_name = method.getIdentifier()
  157. description = method.getDescription()
  158. body = method.getBody()
  159. parameters = method.getFormalParameters()
  160. self.out.write()
  161. if description:
  162. self.writeComment(description)
  163. self.out.write(class_name + ".prototype." + method_name + " = function")
  164. parameters.accept(self)
  165. body.accept(self)
  166. self.out.extendWrite(";")
  167. def visit_MethodBody(self, body):
  168. method = body.getMethod()
  169. formal_parameters = method.getFormalParameters()
  170. formal_parameter_list = formal_parameters.getParameterList()
  171. self.out.extendWrite(" {")
  172. self.out.indent()
  173. # check for undefined parameters and replace them with default values
  174. for p in formal_parameter_list:
  175. p_id = p.getIdentifier()
  176. p_default = p.getDefaultValue()
  177. if p_default:
  178. self.out.write("if (" + p_id + " === undefined) " + p_id + " = ")
  179. p_default.accept(self)
  180. self.out.extendWrite(";")
  181. self.writeAll(body.getEntries())
  182. self.out.dedent()
  183. self.out.write("}")
  184. def visit_NoneExpression(self, n):
  185. self.out.extendWrite("null")
  186. def visit_Package(self, package):
  187. name = package.getIdentifier()
  188. description = package.getDescription()
  189. self.writeComment("package \"" + name + "\"")
  190. if description:
  191. self.writeComment(description)
  192. self.out.write("var " + name + " = {};")
  193. self.out.write("(function() {")
  194. for d in package.getDeclarations():
  195. d_id = d.getIdentifier()
  196. d.accept(self)
  197. self.out.write()
  198. self.out.write("// add symbol '" + d_id + "' to package '" + name + "'")
  199. self.out.write(name + "." + d_id + " = " + d_id + ";")
  200. self.out.write("})();")
  201. def visit_RuntimeModuleIdentifier(self, r):
  202. self.out.extendWrite("javascript_runtime")
  203. def visit_StaticAttribute(self, attr):
  204. name = attr.getIdentifier()
  205. init_value = attr.getInitValue()
  206. class_name = attr.getClass().getIdentifier()
  207. if init_value:
  208. self.out.write(class_name + ".prototype." + name + " = ")
  209. init_value.accept(self)
  210. self.out.extendWrite(";")
  211. else:
  212. self.out.write(class_name + ".prototype." + name + " = null;")
  213. def visit_SuperClassConstructorCall(self, call):
  214. super_class = call.getSuperClassIdentifier()
  215. params = call.getActualParameters()
  216. param_list = [Literal("this")] + params.getParameterList()
  217. params = ActualParameters(param_list)
  218. self.out.extendWrite(super_class)
  219. self.out.extendWrite(".call")
  220. params.accept(self)
  221. def visit_SuperClassDestructorCall(self, call):
  222. pass # Javascript doesn't have destructors
  223. def visit_SuperClassMethodCall(self, call):
  224. super_class = call.getSuperClassIdentifier()
  225. method_name = call.getMethodIdentifier()
  226. params = call.getActualParameters()
  227. param_list = [Literal("this")] + params.getParameterList()
  228. params = ActualParameters(param_list)
  229. self.out.extendWrite(super_class)
  230. self.out.extendWrite(".prototype." + method_name + ".call")
  231. params.accept(self)
  232. def visit_ThrowExceptionStatement(self, stmt):
  233. self.out.write("throw new Error(")
  234. stmt.getExpression().accept(self)
  235. self.out.extendWrite(");")