Research portable Memory game | Исследовать портируемую игру Память
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CPP.py 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. from Function import *
  2. def includes():
  3. return """#include <map>
  4. #include <string>
  5. #include <vector>
  6. #include "memory.h"
  7. #include "memory_Context.h"
  8. """
  9. def replaceAnd(s):
  10. return s.replace("and", "&&")
  11. def replaceAppend(s):
  12. return s.replace(".append(", ".push_back(")
  13. def replaceComment(s):
  14. return s.replace("#", "//")
  15. def replaceLen(s):
  16. posLen = s.find("len(")
  17. posEnd = s.find(")", posLen)
  18. if (
  19. posLen == -1 or
  20. posEnd == -1
  21. ):
  22. return s
  23. before = s[:posLen]
  24. name = s[posLen + len("len("):posEnd]
  25. after = s[posEnd + len(")"):]
  26. return f"{before}{name}.size(){after}"
  27. def replaceTrue(s):
  28. return s.replace("True", "true")
  29. def translateParameter(s):
  30. # name: type -> type name
  31. parts = s.split(": ")
  32. indent = len(s) - len(s.lstrip())
  33. name = parts[0].lstrip()
  34. t = translateType(parts[1])
  35. indentation = "".join(" " * indent)
  36. return f"{indentation}{t} {name}"
  37. def translateStatement(s, state):
  38. indent = len(s) - len(s.lstrip())
  39. indentation = "".join(" " * indent)
  40. ss = s.lstrip()
  41. posColon = ss.find(": ")
  42. posComma = ss.find(", ")
  43. posComment = ss.find("# ")
  44. posCtx = ss.find("c.")
  45. posEqual = ss.find(" = ")
  46. posFor = ss.find("for ")
  47. posIn = ss.find(" in ")
  48. posRange = ss.find("range(")
  49. posRangeEnd = ss.find("):")
  50. posClosingScope = ss.find("#}")
  51. posOpenSquareBracket = ss.find("[")
  52. # # -> //
  53. if posComment != -1:
  54. return replaceComment(s)
  55. # #} -> }
  56. if posClosingScope != -1:
  57. return f"{indentation}}}"
  58. # for name in range(x, y): -> for (auto name = x; name < y; ++name) {
  59. if (
  60. posFor >= 0 and
  61. posIn >= 0 and
  62. posRange >= 0
  63. ):
  64. name = ss[posFor + len("for "):posIn]
  65. x = ss[posRange + len("range("):posComma]
  66. y = ss[posComma + len(", "):posRangeEnd]
  67. return f"{indentation}for (auto {name} = {x}; {name} < {y}; ++{name}) {{"
  68. # name: type = value -> type name = value
  69. if (
  70. posColon >= 0 and
  71. posEqual >= 0
  72. ):
  73. name = ss[:posColon]
  74. type = ss[posColon + len(": "):posEqual]
  75. t = translateType(type)
  76. value = ss[posEqual + len(" = "):]
  77. return f"{indentation}{t} {name} = {value};"
  78. # name = value -> auto name = value
  79. if (
  80. posCtx == -1 and
  81. posColon == -1 and
  82. posOpenSquareBracket == -1 and
  83. posEqual >= 0
  84. ):
  85. name = ss[:posEqual]
  86. # Skip prepending 'auto' each time variable is assigned,
  87. # only do it the first time
  88. if name not in state.varNames:
  89. state.varNames[name] = True
  90. value = ss[posEqual + len(" = "):]
  91. return f"{indentation}auto {name} = {value};"
  92. # Keep "if ("
  93. if ss == "if (":
  94. state.isIf = True
  95. return s
  96. # Keep "if not ("
  97. if ss == "if not (":
  98. state.isIfNot = True
  99. return f"{indentation}if (!("
  100. # ): -> }
  101. if ss == "):":
  102. # if
  103. if state.isIf:
  104. state.isIf = False
  105. return f"{indentation}) {{"
  106. # if not
  107. state.isIfNot = False
  108. return f"{indentation})) {{"
  109. ending = ";"
  110. if state.isIf or state.isIfNot:
  111. ending = ""
  112. # Unknown.
  113. return f"{s}{ending}"
  114. def translateType(s):
  115. # dict[X, Y] -> std::map<X, Y>
  116. if s.startswith("dict["):
  117. kv = s[len("dict["):-len("]")]
  118. parts = kv.split(", ")
  119. return f"std::map<{parts[0]}, {parts[1]}>"
  120. # str -> std::string
  121. if s == "str":
  122. return "std::string"
  123. # Unknown. Return as is.
  124. return s
  125. class CPP:
  126. def __init__(self, fn):
  127. self.fn = fn
  128. self.isIf = False
  129. self.isIfNot = False
  130. self.varNames = {}
  131. def translate(self):
  132. returnType = translateType(self.fn.returnType)
  133. # Parameters.
  134. params = []
  135. for i in range(0, len(self.fn.parameters)):
  136. p = translateParameter(self.fn.parameters[i])
  137. # Make Context passed by reference.
  138. #if "Context" in p:
  139. # p = p.replace("Context", "Context&")
  140. params.append(p)
  141. strparams = "\n".join(params)
  142. if (len(strparams) > 0):
  143. strparams += "\n"
  144. # Statements.
  145. sts = []
  146. for i in range(0, len(self.fn.statements)):
  147. s = translateStatement(self.fn.statements[i], self)
  148. s = replaceAnd(s)
  149. s = replaceAppend(s)
  150. # Replace len twice to account for double invocation.
  151. s = replaceLen(s)
  152. s = replaceLen(s)
  153. s = replaceTrue(s)
  154. sts.append(s)
  155. strstatements = "\n".join(sts)
  156. return f"""{returnType} {self.fn.name}(
  157. {strparams}) {{
  158. {strstatements}
  159. }}
  160. """