semantics_visitor.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  1. import hutnparser as hp
  2. import symbol_table as st
  3. import sys
  4. import types_mv
  5. from declare_functions_visitor import DeclareFunctionsVisitor
  6. from visitor import Visitor
  7. class SemanticsVisitor(Visitor):
  8. def __init__(self, args):
  9. Visitor.__init__(self, args)
  10. self.symbol_table = st.SymbolTable()
  11. # there is only one input file, list is for sharing it among visitors
  12. self.inputfiles = []
  13. # Count whether we are in a while or not
  14. self.while_counter = 0
  15. # inherited attribute, set in funcdecl and used in return,
  16. # to ensure that (returned type == declared type)
  17. self.current_funcdecl = None
  18. self.declare_functions_visitor =\
  19. DeclareFunctionsVisitor(self.symbol_table, self.inputfiles)
  20. @staticmethod
  21. def incompatible_types(l_type, r_type):
  22. if type(l_type) != type(r_type):
  23. if types_mv.Void in (type(l_type), type(r_type)):
  24. return True
  25. if types_mv.Element in (type(l_type), type(r_type)):
  26. return False
  27. if l_type.isNotNumber() or r_type.isNotNumber():
  28. return True
  29. return False
  30. def do_check_binary_ops_arithmetic(self, l, r):
  31. l_type, r_type = self.get_type(l), self.get_type(r)
  32. if SemanticsVisitor.incompatible_types(l_type, r_type):
  33. raise RuntimeError(
  34. "{}:{}:{}: error: invalid operands to binary operator "
  35. "(have {} and {})".format(self.inputfiles[0],
  36. l.startpos['line'],
  37. l.startpos['column'],
  38. str(l_type),
  39. str(r_type)))
  40. def check_binary_ops_arithmetic(self, tree):
  41. l, r = tree.get_tail()[0], tree.get_tail()[2]
  42. self.do_check_binary_ops_arithmetic(l, r)
  43. def generalize_binary_ops_arithmetic(self, tree):
  44. l, r = tree.get_tail()[0], tree.get_tail()[2]
  45. l_type, r_type = self.get_type(l), self.get_type(r)
  46. return types_mv.generalize_arithmetic(l_type, r_type)
  47. def check_unary_ops_arithmetic(self, tree, operator_name):
  48. l = tree.get_tail()[1]
  49. l_type = self.get_type(l)
  50. if l_type.isNotNumber():
  51. raise RuntimeError(
  52. "{}:{}:{}: error: wrong type argument to unary {} "
  53. "({})".format(self.inputfiles[0],
  54. l.startpos['line'],
  55. l.startpos['column'],
  56. operator_name,
  57. str(l_type)))
  58. def promote_unary_ops_arithmetic(self, tree):
  59. l = tree.get_tail()[1]
  60. l_type = self.get_type(l)
  61. try:
  62. return types_mv.promote_arithmetic(l_type)
  63. except RuntimeError:
  64. raise RuntimeError(
  65. "Pathological situation in promote_unary_ops_arithmetic: "
  66. "check_unary_ops_arithmetic has not been executed")
  67. # if r_type is provided, r is not used
  68. def do_check_assignment(self, l, r, r_type = None):
  69. if r_type is not None:
  70. l_type = self.get_type(l)
  71. else:
  72. l_type, r_type = self.get_type(l), self.get_type(r)
  73. if SemanticsVisitor.incompatible_types(l_type, r_type):
  74. raise RuntimeError("{}:{}:{}: error: cannot assign a value of "
  75. "type '{}' to a variable of type '{}'"
  76. .format(self.inputfiles[0],
  77. l.startpos['line'],
  78. l.startpos['column'],
  79. str(r_type),
  80. str(l_type)))
  81. def check_assignment(self, tree):
  82. l, r = tree.get_tail()[0], tree.get_tail()[2]
  83. self.do_check_assignment(l, r)
  84. def check_return(self, tree):
  85. l = self.current_funcdecl
  86. if len(tree.get_tail()) > 2:
  87. r = tree.get_tail()[1]
  88. r_type = None
  89. else:
  90. r = None
  91. r_type = types_mv.Void()
  92. if l:
  93. self.do_check_assignment(l, r, r_type)
  94. else:
  95. raise RuntimeError(
  96. "{}:{}:{}: error: 'return' is used outside of a function"
  97. .format(self.inputfiles[0],
  98. tree.startpos['line'],
  99. tree.startpos['column']))
  100. def check_predicate(self, tree):
  101. if isinstance(self.get_type(tree), types_mv.Element):
  102. return
  103. if self.get_type(tree).isNotNumber():
  104. raise RuntimeError(
  105. "{}:{}:{}: error: predicates of type '{}' are not allowed"
  106. .format(self.inputfiles[0],
  107. tree.startpos['line'],
  108. tree.startpos['column'],
  109. self.get_type(tree)))
  110. def replace_child_binary_op_with_call(self, tree, i=0):
  111. child = tree.get_tail()[i]
  112. if len(child.get_tail()) > 1:
  113. l, op, r = child.get_tail()
  114. l_type, r_type = self.get_type(l), self.get_type(r)
  115. if type(l_type) != type(r_type):
  116. print("Error: " + str(l_type) + " <-> " + str(r_type))
  117. raise RuntimeError(
  118. "{}:{}:{}: error: children were not casted".format(
  119. self.inputfiles[0],
  120. tree.startpos['line'],
  121. tree.startpos['column']
  122. ))
  123. call_name = SemanticsVisitor.call_name_binary(l_type, op)
  124. call_tree = SemanticsVisitor.func_call(call_name, [l, r], tree)
  125. try:
  126. self.visit(call_tree)
  127. except RuntimeError:
  128. call_signature = "{0} function {1}({2}, {2})".format(
  129. str(types_mv.Boolean()), call_name, l_type)
  130. raise RuntimeError(
  131. "{}:{}:{}: error: cannot perform {}: function '{}' is "
  132. "not found".format(
  133. self.inputfiles[0],
  134. tree.startpos['line'],
  135. tree.startpos['column'],
  136. child.head,
  137. call_signature))
  138. tree.replace_child(child, call_tree)
  139. self.set_type(tree, self.get_type(tree.get_tail()[i]))
  140. def replace_child_unary_op_with_call(self, tree):
  141. child = tree.get_tail()[0]
  142. if child.head == "keep_sign":
  143. tree.replace_child(child, child.get_tail()[1])
  144. else:
  145. op, l = child.get_tail()
  146. l_type = self.get_type(l)
  147. call_name = SemanticsVisitor.call_name_unary(l_type, op)
  148. call_tree = SemanticsVisitor.func_call(call_name, [l], tree)
  149. try:
  150. self.visit(call_tree)
  151. except RuntimeError:
  152. call_signature = "{0} function {1}({2})".format(
  153. str(types_mv.Boolean()), call_name, l_type)
  154. raise RuntimeError(
  155. "{}:{}:{}: error: cannot perform {}: function '{}' is "
  156. "not found".format(
  157. self.inputfiles[0],
  158. tree.startpos['line'],
  159. tree.startpos['column'],
  160. child.head,
  161. call_signature))
  162. tree.replace_child(child, call_tree)
  163. self.set_type(tree, self.get_type(tree.get_tail()[0]))
  164. def cast_binary_ops_arithmetic(self, tree):
  165. l, op, r = tree.get_tail()
  166. l_type, r_type = self.get_type(l), self.get_type(r)
  167. if type(l_type) != type(r_type): # if two different numeric types
  168. g_type = types_mv.generalize_arithmetic(l_type, r_type)
  169. self.perform_implicit_cast(tree, l, l_type, g_type)
  170. self.perform_implicit_cast(tree, r, r_type, g_type)
  171. def cast_binary_ops_logical(self, tree):
  172. l, op, r = tree.get_tail()
  173. l_type, r_type = self.get_type(l), self.get_type(r)
  174. self.perform_implicit_cast(tree, l, l_type, types_mv.Boolean())
  175. self.perform_implicit_cast(tree, r, r_type, types_mv.Boolean())
  176. def cast_unary_ops_arithmetic(self, tree):
  177. l = tree.get_tail()[1]
  178. l_type = self.get_type(l)
  179. p_type = self.promote_unary_ops_arithmetic(tree)
  180. self.perform_implicit_cast(tree, l, l_type, p_type)
  181. @staticmethod
  182. def func_call(name, params, old_tree):
  183. startpos = old_tree.startpos
  184. endpos = old_tree.endpos
  185. inputfile = old_tree.inputfile
  186. tree = hp.Tree(
  187. "func_call",
  188. [
  189. hp.Tree("rvalue",
  190. [
  191. hp.Tree("ID", [name], startpos, endpos, inputfile)
  192. ],
  193. startpos, endpos, inputfile),
  194. # Tokens have no impact on visit_func_call. So leave them out.
  195. ],
  196. startpos, endpos, inputfile)
  197. params = [hp.Tree("expression", [p], startpos, endpos, inputfile) for p in params]
  198. tree.tail.extend(params)
  199. return hp.Tree("expression", [tree], startpos, endpos, inputfile)
  200. @staticmethod
  201. def cast_name(from_type, to_type):
  202. from_t = str(from_type)[0].lower()
  203. to_t = str(to_type)[0].lower()
  204. cast_name = "cast_{}2{}".format(from_t, to_t)
  205. return cast_name
  206. def raise_implicit_cast_error(self, from_type, to_type, tree):
  207. cast_name = SemanticsVisitor.cast_name(from_type, to_type)
  208. cast_signature = "{} function {}({})".format(
  209. str(to_type), cast_name, str(from_type))
  210. raise RuntimeError(
  211. "{}:{}:{}: error: cannot perform implicit cast from '{}'"
  212. " to '{}': function '{}' is not found".format(
  213. self.inputfiles[0],
  214. tree.startpos['line'],
  215. tree.startpos['column'],
  216. str(to_type), str(from_type),
  217. cast_signature))
  218. def perform_implicit_cast(self, tree, child, from_type, to_type):
  219. if types_mv.Element in (type(from_type), type(to_type)):
  220. return
  221. if type(from_type) == type(to_type):
  222. return
  223. cast_name = SemanticsVisitor.cast_name(from_type, to_type)
  224. cast_tree = \
  225. SemanticsVisitor.func_call(cast_name, [child], tree)
  226. try:
  227. self.visit(cast_tree)
  228. except RuntimeError:
  229. self.raise_implicit_cast_error(from_type, to_type, child)
  230. tree.replace_child(child, cast_tree)
  231. types = {
  232. "Integer": "integer",
  233. "Float": "float",
  234. "Boolean": "bool",
  235. "String": "string",
  236. "Action": "action",
  237. "Element": "element",
  238. "Type": "type"
  239. }
  240. binary_ops = {
  241. "OR": "or",
  242. "AND": "and",
  243. "EQ": "eq",
  244. "NEQ": "neq",
  245. "LT": "lt",
  246. "GT": "gt",
  247. "LE": "lte",
  248. "GE": "gte",
  249. "PLUS": "addition",
  250. "MINUS": "subtraction",
  251. "STAR": "multiplication",
  252. "SLASH": "division"
  253. }
  254. unary_ops = {
  255. "NOT": "not",
  256. "MINUS": "neg"
  257. }
  258. @staticmethod
  259. def call_name_binary(operand_type, operator):
  260. # String joins should also be possible
  261. if str(operand_type) == "String":
  262. if operator.head == "PLUS":
  263. return "string_join"
  264. if operator.head == "EQ":
  265. return "value_eq"
  266. elif operator.head == "NEQ":
  267. return "value_neq"
  268. call_name = "{}_{}".format(SemanticsVisitor.types[str(operand_type)],
  269. SemanticsVisitor.binary_ops[operator.head])
  270. return call_name
  271. @staticmethod
  272. def call_name_unary(operand_type, operator):
  273. call_name = "{}_{}".format(SemanticsVisitor.types[str(operand_type)],
  274. SemanticsVisitor.unary_ops[operator.head])
  275. return call_name
  276. def dump(self):
  277. return self.tree.get_text(with_implicit=True)
  278. # return "No code generation here"
  279. # a visit_* method for each non-terminal in the grammar
  280. def visit_start(self, tree):
  281. self.symbol_table.open_scope()
  282. self.inputfiles.append(tree.inputfile)
  283. for child in tree.get_tail():
  284. self.inputfiles[0] = child.inputfile
  285. self.declare_functions_visitor.visit(child)
  286. for child in tree.get_tail():
  287. self.inputfiles[0] = child.inputfile
  288. self.visit(child)
  289. self.inputfiles.pop()
  290. self.symbol_table.close_scope()
  291. self.tree = tree
  292. def visit_statement(self, tree):
  293. self.visit_children(tree)
  294. def visit_definition(self, tree):
  295. self.visit_vardecl(tree)
  296. def visit_vardecl(self, tree):
  297. type_spec = tree.get_child("type_specifier")
  298. var_id = tree.get_child("ID")
  299. var_type = types_mv.string_to_type(type_spec.get_text())
  300. var_name = var_id.get_text()
  301. symbol = st.Symbol(var_name, var_type,
  302. is_global=self.current_funcdecl is None)
  303. try:
  304. self.symbol_table.add(symbol)
  305. except Exception:
  306. raise RuntimeError(
  307. "{}:{}:{}: error: redeclaration of '{}'".format(
  308. self.inputfiles[0], tree.startpos['line'],
  309. tree.startpos['column'], var_name))
  310. self.set_symbol(tree, symbol)
  311. def visit_assignment(self, tree):
  312. self.visit_children(tree)
  313. self.check_assignment(tree)
  314. def visit_expression(self, tree):
  315. self.visit_children(tree)
  316. self.set_type(tree, self.get_type(tree.get_tail()[0]))
  317. def visit_binary_operation(self, tree):
  318. self.visit_children(tree)
  319. self.replace_child_binary_op_with_call(tree)
  320. def visit_disjunction(self, tree):
  321. self.visit_children(tree)
  322. if len(tree.get_tail()) == 1:
  323. self.replace_child_binary_op_with_call(tree)
  324. else:
  325. self.replace_child_binary_op_with_call(tree, 2)
  326. self.cast_binary_ops_logical(tree)
  327. self.set_type(tree, types_mv.Boolean())
  328. def visit_conjunction(self, tree):
  329. self.visit_children(tree)
  330. if len(tree.get_tail()) == 1:
  331. self.replace_child_binary_op_with_call(tree)
  332. else:
  333. self.replace_child_binary_op_with_call(tree, 2)
  334. self.cast_binary_ops_logical(tree)
  335. self.set_type(tree, types_mv.Boolean())
  336. def visit_comparison(self, tree):
  337. self.visit_children(tree)
  338. if len(tree.get_tail()) == 1:
  339. self.replace_child_binary_op_with_call(tree)
  340. else:
  341. self.replace_child_binary_op_with_call(tree, 2)
  342. self.check_binary_ops_arithmetic(tree)
  343. self.cast_binary_ops_arithmetic(tree)
  344. self.set_type(tree, types_mv.Boolean())
  345. def visit_relation(self, tree):
  346. self.visit_children(tree)
  347. if len(tree.get_tail()) == 1:
  348. self.replace_child_binary_op_with_call(tree)
  349. else:
  350. self.replace_child_binary_op_with_call(tree, 2)
  351. self.check_binary_ops_arithmetic(tree)
  352. self.cast_binary_ops_arithmetic(tree)
  353. self.set_type(tree, types_mv.Boolean())
  354. def visit_sum(self, tree):
  355. self.visit_children(tree)
  356. if len(tree.get_tail()) == 1:
  357. self.replace_child_binary_op_with_call(tree)
  358. else:
  359. self.replace_child_binary_op_with_call(tree, 2)
  360. self.check_binary_ops_arithmetic(tree)
  361. self.cast_binary_ops_arithmetic(tree)
  362. # after the cast both parameters have the same (generalized) type:
  363. self.set_type(tree, self.get_type(tree.get_tail()[0]))
  364. def visit_term(self, tree):
  365. self.visit_children(tree)
  366. if len(tree.get_tail()) == 1:
  367. self.set_type(tree, self.get_type(tree.get_tail()[0]))
  368. else:
  369. self.check_binary_ops_arithmetic(tree)
  370. self.cast_binary_ops_arithmetic(tree)
  371. # after the cast both parameters have the same (generalized) type:
  372. self.set_type(tree, self.get_type(tree.get_tail()[0]))
  373. def visit_factor(self, tree):
  374. self.visit_children(tree)
  375. if tree.get_child("primary") is not None:
  376. self.set_type(tree, self.get_type(tree.get_tail()[0]))
  377. else:
  378. self.replace_child_unary_op_with_call(tree)
  379. def visit_logical_not(self, tree):
  380. self.visit_children(tree)
  381. l = tree.get_tail()[1]
  382. l_type = self.get_type(l)
  383. self.perform_implicit_cast(tree, l, l_type, types_mv.Boolean())
  384. self.set_type(tree, self.get_type(tree.get_tail()[1]))
  385. def visit_invert_sign(self, tree):
  386. self.visit_children(tree)
  387. self.check_unary_ops_arithmetic(tree, "minus")
  388. self.cast_unary_ops_arithmetic(tree)
  389. self.set_type(tree, self.get_type(tree.get_tail()[1]))
  390. def visit_keep_sign(self, tree):
  391. self.visit_children(tree)
  392. self.check_unary_ops_arithmetic(tree, "plus")
  393. self.cast_unary_ops_arithmetic(tree)
  394. self.set_type(tree, self.get_type(tree.get_tail()[1]))
  395. def visit_primary(self, tree):
  396. self.visit_children(tree)
  397. self.set_type(tree, self.get_type(tree.get_tail()[0]))
  398. def visit_parenthesized(self, tree):
  399. self.visit_children(tree)
  400. self.set_type(tree, self.get_type(tree.get_tail()[1]))
  401. def visit_atomvalue(self, tree):
  402. self.visit_children(tree)
  403. self.set_type(tree, self.get_type(tree.get_tail()[0]))
  404. def visit_type_specifier(self, tree):
  405. self.set_type(tree, types_mv.Type())
  406. def visit_actionname(self, tree):
  407. self.set_type(tree, types_mv.Action())
  408. def visit_string(self, tree):
  409. self.set_type(tree, types_mv.String())
  410. def visit_integer(self, tree):
  411. self.set_type(tree, types_mv.Integer())
  412. def visit_float(self, tree):
  413. self.set_type(tree, types_mv.Float())
  414. # there is no such rule in the grammar, we just avoid code duplicates
  415. def visit_id(self, tree):
  416. name = tree.get_text()
  417. #TODO this is set to the function returnvalue, even if we use the function pointer...
  418. try:
  419. symbol = self.symbol_table.get(name)
  420. except KeyError:
  421. raise RuntimeError("{}:{}:{}: error: '{}' is not declared".format(
  422. self.inputfiles[0], tree.startpos['line'],
  423. tree.startpos['column'], name))
  424. self.set_type(tree, symbol.type)
  425. self.set_symbol(tree, symbol)
  426. def visit_rvalue(self, tree):
  427. if len(tree.get_tail()) > 1:
  428. # Complex: dict_read operation needed
  429. child = tree.get_tail()[0]
  430. node = tree.get_child("rvalue")
  431. expression = tree.get_child("expression")
  432. operation = "dict_read"
  433. call_tree = SemanticsVisitor.func_call(operation, [node, expression], tree)
  434. self.visit(call_tree)
  435. tree.head = call_tree.head
  436. tree._tail = call_tree.tail
  437. tree.tail = call_tree.tail
  438. self.set_type(tree, self.get_type(node))
  439. else:
  440. # Simple
  441. self.visit_id(tree)
  442. def visit_lvalue(self, tree):
  443. self.visit_id(tree)
  444. def visit_func_call(self, tree):
  445. self.visit_children(tree)
  446. symbol = self.get_symbol(tree.get_tail()[0])
  447. self.set_type(tree, symbol.type)
  448. if not symbol.is_func():
  449. if isinstance(symbol.type, types_mv.Element):
  450. sys.stderr.write("{}:{}:{}: warning: calling a variable of type "
  451. "'Element'\n".format(self.inputfiles[0],
  452. tree.startpos['line'],
  453. tree.startpos['column'],
  454. symbol.name))
  455. return # allow the call without knowing the declaration
  456. raise RuntimeError(
  457. "{}:{}:{}: error: '{}' is a variable of type '{}', not a "
  458. "function".format(self.inputfiles[0],
  459. tree.startpos['line'],
  460. tree.startpos['column'],
  461. symbol.name,
  462. symbol.type))
  463. expressions = tree.get_children("expression")
  464. if len(expressions) != len(symbol.params):
  465. raise RuntimeError(
  466. "{}:{}:{}: error: wrong number of arguments to "
  467. "function '{}'".format(self.inputfiles[0],
  468. tree.startpos['line'],
  469. tree.startpos['column'],
  470. symbol.signature()))
  471. for i in range(len(expressions)):
  472. arg_type = self.get_type(expressions[i])
  473. param_type = symbol.params[i]
  474. if SemanticsVisitor.incompatible_types(arg_type, param_type):
  475. raise RuntimeError(
  476. "{}:{}:{}: error: argument {} has type '{}' instead of "
  477. "'{}', calling function '{}'".format(
  478. self.inputfiles[0],
  479. tree.startpos['line'],
  480. tree.startpos['column'],
  481. i + 1,
  482. str(arg_type),
  483. str(param_type),
  484. symbol.signature()))
  485. if type(arg_type) != type(param_type):
  486. self.perform_implicit_cast(tree, expressions[i], arg_type,
  487. param_type)
  488. if symbol.name in ["input", "output"]:
  489. tree.head = symbol.name
  490. def visit_input(self, tree):
  491. pass # no need to visit it again
  492. def visit_output(self, tree):
  493. pass # no need to visit it again
  494. def visit_dictionary(self, tree):
  495. self.set_type(tree, types_mv.Element)
  496. def visit_list(self, tree):
  497. self.set_type(tree, types_mv.Element)
  498. def visit_dict_item(self, tree):
  499. pass
  500. def visit_ifelse(self, tree):
  501. self.visit_children(tree)
  502. expressions = tree.get_children("expression")
  503. for expression in expressions:
  504. self.check_predicate(expression)
  505. def visit_while(self, tree):
  506. self.while_counter += 1
  507. self.visit_children(tree)
  508. self.while_counter -= 1
  509. expression = tree.get_child("expression")
  510. self.check_predicate(expression)
  511. def visit_block(self, tree):
  512. self.symbol_table.open_scope()
  513. self.visit_children(tree)
  514. self.symbol_table.close_scope()
  515. def visit_func_body(self, tree):
  516. self.visit_children(tree)
  517. def visit_funcdecl(self, tree):
  518. # here we only visit the body cause the declaration is already done
  519. # by declare_functions_visitor
  520. if tree.get_child('func_body') is not None:
  521. self.current_funcdecl = tree
  522. self.symbol_table.open_scope()
  523. self.visit_children(tree)
  524. self.symbol_table.close_scope()
  525. self.current_funcdecl = None
  526. def visit_parameter(self, tree):
  527. param_id = tree.get_child("ID")
  528. type_spec = tree.get_child("type_specifier")
  529. param_type = types_mv.string_to_type(type_spec.get_text())
  530. param_name = param_id.get_text()
  531. symbol = st.Symbol(param_name, param_type, is_global=False)
  532. try:
  533. self.symbol_table.add(symbol)
  534. except Exception:
  535. raise RuntimeError(
  536. "{}:{}:{}: error: redeclaration of '{}'".format(
  537. self.inputfiles[0], tree.startpos['line'],
  538. tree.startpos['column'], param_name))
  539. self.set_symbol(tree, symbol)
  540. def visit_return(self, tree):
  541. self.visit_children(tree)
  542. self.check_return(tree)
  543. def visit_bool(self, tree):
  544. self.set_type(tree, types_mv.Boolean())
  545. def visit_break(self, tree):
  546. if self.while_counter == 0:
  547. raise RuntimeError(
  548. "{}:{}:{}: error: break outside of while".format(
  549. self.inputfiles[0], tree.startpos['line'],
  550. tree.startpos['column']))
  551. def visit_continue(self, tree):
  552. if self.while_counter == 0:
  553. raise RuntimeError(
  554. "{}:{}:{}: error: continue outside of while".format(
  555. self.inputfiles[0], tree.startpos['line'],
  556. tree.startpos['column']))