示例#1
0
  def load(self, board, f):
    contents = f.read()
    sizes = list(re.findall('\\GbstnTamanho{([0-9]+)}{([0-9]+)}', contents))
    if len(sizes) != 1:
      raise basic.BoardFormatException(i18n.i18n('Malformed tex board'))
    width, height = board.size = int(sizes[0][0]), int(sizes[0][1])
    board.head = (0, 0)
    board._clear_board()
    for coli in range(4):
      col = gbs_builtins.Color(coli).name()
      col_stones = re.findall('\\Gbstn' + col + '{([0-9]+)}{([0-9]+)}{([0-9]+)}' % (), contents)
      for x, y, count in col_stones:
        x, y, count = int(x), int(y), int(count)
        if x >= width or y >= height:
          raise basic.BoardFormatException(i18n.i18n('Malformed tex board'))
        board.cells[y][x].set_num_stones(coli, count)
    headers = list(re.findall('\\GbstnCabezal{([0-9]+)}{([0-9]+)}', contents))
    if len(headers) > 1:
      raise basic.BoardFormatException(i18n.i18n('Malformed tex board'))
    elif len(headers) == 1:
      x, y = int(headers[0][0]), int(headers[0][1])
      if x >= width or y >= height:
        raise basic.BoardFormatException(i18n.i18n('Malformed tex board'))

      board.head = y, x
    board.clear_changelog()
示例#2
0
 def parse_atom(self, tree):
     if tree.children[0] == 'type':
         tok = tree.children[1]
         args = tree.children[2]
         if args is None:
             args = []
         else:
             args = [self.parse_atom(a) for a in args.children]
         if tok.value in BasicTypes:
             t = BasicTypes[tok.value]
             if t.kind_arity != len(args):
                 msg = i18n.i18n('type "%s" expects %u parameters, but receives %u') % (
                       tok.value, t.kind_arity, len(args))
                 area = position.ProgramAreaNear(tok)
                 raise GbsTypeSyntaxException(msg, area)
             return t(*args)
         else:
             if tok.value in self.context.keys():
                 return self.context[tok.value]
             else:
                 """[TODO] Translate """
                 msg = i18n.i18n('Undefined type "%s".') % (tok.value,)
                 area = position.ProgramAreaNear(tok)
                 raise GbsTypeSyntaxException(msg, area)
     elif tree.children[0] == 'typeVar':
         tok = tree.children[1]
         if tok.value in self.typevars:
             return self.typevars[tok.value]
         else:
             fresh = GbsTypeVar(tok.value)
             self.typevars[tok.value] = fresh
             return fresh
示例#3
0
 def check(self, options):
     if options['src']:
         self.check_file_exists(options['src'])
     if options['from']:
         self.check_file_exists(options['from'])
     if options['lint'] not in lang.GobstonesOptions.LINT_MODES:
         raise OptionsException(i18n.i18n('%s is not a valid lint option.') % (options['lint'],))
     if not self.check_size(options['size']):
         raise OptionsException(i18n.i18n('Size %s is not a valid size. Positive integers expected.') % (str(options['size']),))
示例#4
0
 def parse(self, filename, program_text):
     # Parse gobstones script
     self.api.log(i18n.i18n('Parsing.'))
     tree = self._parse(program_text, filename)
     assert tree
     # Explode macros
     self.api.log(i18n.i18n('Exploding program macros.'))
     self.explode_macros(tree)
     return GobstonesRun().initialize(tree)
示例#5
0
 def _warn_conflict(self, nonterminal, terminal, area):
     "Emits a warning for a conflictive state."
     msg = ''
     msg += i18n.i18n('Conflictive rule for: ("%s", "%s")\n') % (
                 nonterminal, terminal)
     msg += i18n.i18n('Will choose first production:\n')
     msg += utils.indent(bnf_rule_to_str(
                     self._parse_table[(nonterminal, terminal)]))
     self.warn(ParserException(msg, area))
示例#6
0
 def _set_routine_definition_type(self, tree, prfn, name, params, body):
     """Given a context with types for the parameters and local
     variables in a routine, build the type for this routine
     and unify it with its type in the global context.
     For instance if the function "f" has a parameter "x",
     and returns an expression, take the type "s" for "x"
     from the local context, the type "t" for the returned
     expression. Build the type "s -> t" for the function
     and unify that with any type information previously
     known for "f". This requires that the body of the routine
     has already been typechecked."""
     param_types = []
     for p in params.children:
         param_types.append(self.context[p.value])
     param_types = gbs_type.GbsTupleType(param_types)
     if prfn == 'procedure':
         def_type = gbs_type.GbsProcedureType(param_types)
     elif prfn == 'function':
         return_types = self._return_type(prfn, name, params, body)
         def_type = gbs_type.GbsFunctionType(param_types, return_types)
     elif prfn == 'entrypoint' and (name.value == 'program' or name.value == 'interactive'):
         def_type = gbs_type.GbsEntryPointType()
     else:
         assert False
     expected = self.global_context[name.value].instantiate()
     try:
         gbs_type.unify(expected, def_type)
         if prfn == 'function': #[TODO] Check
             freevars = def_type.freevars()
             if len(freevars) > 0:
                 def_type = gbs_type.GbsForallType(freevars, def_type)
                 self.global_context[name.value] = def_type
         tree.type_annot = def_type
     except gbs_type.UnificationFailedException as e:
         area = position.ProgramAreaNear(tree)
         if prfn == 'procedure':
             msg = i18n.i18n(
                       'procedure "%s" should take: %s\n' +
                       'But takes: %s'
                   ) % (
                       name.value,
                       expected.paramtype(),
                       def_type.paramtype()
                   )
         else:
             msg = i18n.i18n(
                       'function "%s" should take: %s and return: %s\n' +
                       'But takes: %s and returns: %s'
                   ) % (
                       name.value,
                       expected.paramtype(), expected.restype(),
                       def_type.paramtype(), def_type.restype()
                   )
         self.error(GbsTypeInferenceException(msg, area))
示例#7
0
 def _error_conflictive_definition(self, tree, name, as_type, val):
     if val.name() == name:
         area = position.ProgramAreaNear(tree)
         l1 = i18n.i18n('"%s" is not a ' + as_type) % (name,)
         l2 = i18n.i18n(val.type() + ' "%s" defined %s') % (name, val.where())
         raise GbsLintException('\n'.join([l1, l2]), area)
     else:
         area = position.ProgramAreaNear(tree)
         msg = i18n.i18n('"%s" is too similar to ' + val.type() + ' "%s", defined %s') % (
                         name, val.name(), val.where())
         raise GbsLintException(msg, area)
示例#8
0
 def fail(msg):
     raise basic.BoardFormatException(
         i18n.i18n("Malformed gbb board")
         + "\n"
         + "  "
         + i18n.i18n("Near line:")
         + ' "'
         + orig[0].strip("\r\n")
         + '"\n'
         + "  "
         + msg
     )
示例#9
0
 def _put_from_description(self, cell, description):
   coli = 0
   for cn in gbs_builtins.COLOR_NAMES:
     if description[-1].lower() == cn[0].lower():
       count = description[:-1]
       for l in count:
         if l not in '0123456789':
           raise basic.BoardFormatException(i18n.i18n('Malformed board'))
       cell.put(coli, int(count))
       return
     coli += 1
   raise basic.BoardFormatException(i18n.i18n('Malformed board'))
示例#10
0
 def _add_index(self, varName, tree):
     var = self.symbol_table.check_not_defined_or_defined_as(tree, varName, 'atomic', ['index', 'variable', 'parameter'])
     if var is None:
         self.symbol_table.add(gbs_constructs.UserIndex(varName, tree))
     elif var.type() == 'variable':
         msg = i18n.i18n('Index of a foreach/repeatWith/repeat cannot be a variable: "%s"') % (varName,)
         area = position.ProgramAreaNear(tree)
         raise GbsLintException(msg, area)
     elif var.type() == 'parameter':
         msg = i18n.i18n('Index of a foreach/repeatWith/repeat cannot be a parameter: "%s"') % (varName,)
         area = position.ProgramAreaNear(tree)
         raise GbsLintException(msg, area)
示例#11
0
 def _add_var(self, varName, tree):
     var = self.symbol_table.check_not_defined_or_defined_as(tree, varName, 'atomic', ['variable', 'index', 'parameter'])
     if var is None:
         self.symbol_table.add(gbs_constructs.UserVariable(varName, tree))
     elif var.type() == 'index':
         msg = i18n.i18n('Cannot modify "%s": index of a foreach/repeatWith/repeat is immutable') % (varName,)
         area = position.ProgramAreaNear(tree)
         raise GbsLintException(msg, area)
     elif var.type() == 'parameter':
         msg = i18n.i18n('Cannot modify "%s": parameter is immutable') % (varName,)
         area = position.ProgramAreaNear(tree)
         raise GbsLintException(msg, area)
示例#12
0
 def parse_error(self, nonterminal, previous_token, token):
     "Raises a GbstonesParserException describing a parse error."
     area = position.ProgramAreaNear(token)
     if previous_token.type == 'lowerid' and token.type == '(':
         raise GbsParserException(i18n.i18n('Cannot call a function here'), area)
     elif previous_token.type == 'upperid' and token.type == '(':
         raise GbsParserException(i18n.i18n('Cannot call a procedure here'), area)
     elif previous_token.type == 'upperid' and token.type != '(':
         msg = i18n.i18n('Procedure name "%s" is missing a "("') % (previous_token.value,)
         raise GbsParserException(msg, area)
     elif token.type == 'EOF':
         raise GbsParserException(i18n.i18n('Premature end of input'), area)
     bnf_parser.Parser.parse_error(self, nonterminal, previous_token, token)
示例#13
0
 def build_special_key(self):
     return [
             self.build_key(i18n.i18n("K_ARROW_LEFT"), GobstonesKeys.ARROW_LEFT),
             self.build_key(i18n.i18n("K_ARROW_UP"), GobstonesKeys.ARROW_UP),
             self.build_key(i18n.i18n("K_ARROW_RIGHT"), GobstonesKeys.ARROW_RIGHT),
             self.build_key(i18n.i18n("K_ARROW_DOWN"), GobstonesKeys.ARROW_DOWN),
             self.build_key('K_ENTER', 13),
             self.build_key('K_SPACE', 32),
             self.build_key('K_DELETE', 46),
             self.build_key('K_BACKSPACE', 8),
             self.build_key('K_TAB', 9),
             self.build_key('K_ESCAPE', 27),
             ]
示例#14
0
 def check_unused_assignVarTuple1(self, tree):
   varnames = [v.value for v in tree.children[1].children]
   any_used = False
   for v in varnames:
     if v in tree.live_out:
       any_used = True
       break
   if not any_used:
     if len(varnames) == 1:
       msg = i18n.i18n('Variable "%s" defined but not used') % (varnames[0],)
     else:
       msg = i18n.i18n('Variables "(%s)" defined but not used') % (
                 ', '.join(varnames),)
     area = position.ProgramAreaNear(tree)
     raise GbsUnusedVarException(msg, area)
示例#15
0
 def check_return_arity(self, def_comp, tree, ret_arity):
     prfn = def_comp.type()
     name = def_comp.name()
     nretvals = def_comp.num_retvals()
     if nretvals != ret_arity:
         area = position.ProgramAreaNear(tree)
         if nretvals == 1:
                             l1 = i18n.i18n('Function "%s" returns one value') % (name,)
         else:
                             l1 = i18n.i18n('Function "%s" returns %i values') % (name, nretvals)
         if ret_arity == 1:
             l2 = i18n.i18n('One value is expected')
         else:
             l2 = i18n.i18n('%i values are expected') % (ret_arity,)
         raise GbsLintException('\n'.join([l1, l2]), area)
示例#16
0
    def check_constructor(self, tree):
        for child_tree in tree.children[2].children:
            self.check_expression(child_tree)

        def is_field_gen(node):
            if not len(node.children) > 0:
                return False
            if not (isinstance(node.children[0], str) and node.children[0] == 'funcCall'):
                return False
            return (isinstance(node.children[1], bnf_parser.Token)
                    and node.children[1].value == '_mk_field')

        def fstop_search(node):
            if len(node.children) > 0 and node.children[0] == 'constructor':
                self.check_constructor(node)
                return True
            else:
                return False

        fieldgens = collect_nodes_with_stop(tree, tree, is_field_gen, fstop_search)
        field_names = []
        for fieldgen in fieldgens:
            fname, fvalue = fieldgen.children[2].children
            fname = fname.children[1].value
            if not fname in field_names:
                field_names.append(fname)
            else:
                area = position.ProgramAreaNear(tree)
                msg = i18n.i18n('Repeated assignment for field "%s".') % (fname,)
                raise GbsLintException(msg, area)
示例#17
0
 def check_expression(self, tree):
     exptype = tree.children[0]
     dispatch = {
       'or': self.check_binary_op,
       'and': self.check_binary_op,
       'not': self.check_unary_op,
       'relop': self.check_binary_op,
       'addsub': self.check_binary_op,
       'mul': self.check_binary_op,
       'divmod': self.check_binary_op,
       'pow': self.check_binary_op,
       'listop': self.check_binary_op,
       'varName': self.check_varName,
       'projection' : self.check_binary_op,
       'constructor': self.check_constructor,
       'funcCall': self.check_funcCall,
       'unaryMinus': self.check_unary_op,
       'match': self.check_match,
       'literal': self.check_literal,
       'atom': self.check_atom,
       'type': self.check_type,
     }
     if exptype in dispatch:
         dispatch[exptype](tree)
     else:
         msg = i18n.i18n('Unknown expression: %s') % (exptype,)
         area = position.ProgramAreaNear(tree)
         raise GbsLintException(msg, area)
示例#18
0
 def gen_expression(self, tree):
   "Returns the GEN set of an expression."
   if tree.live_gen is not None:
     return tree.live_gen
   exptype = tree.children[0]
   dispatch = {
     'or': self.gen_binary_op,
     'and': self.gen_binary_op,
     'not': self.gen_unary_op,
     'relop': self.gen_binary_op,
     'addsub': self.gen_binary_op,
     'mul': self.gen_binary_op,
     'divmod': self.gen_binary_op,
     'pow': self.gen_binary_op,
     'listop': self.gen_binary_op,
     'projection': self.gen_binary_op_left_only,
     'constructor': self.gen_funcCall,
     'match': self.gen_match,
     'varName': self.gen_varName,
     'funcCall': self.gen_funcCall,
     'unaryMinus': self.gen_unary_op,
     'literal': self.gen_literal,
     'type': self.gen_type,
   }
   if exptype in dispatch:
       tree.live_gen = dispatch[exptype](tree)
   else:
       msg = i18n.i18n('Unknown expression: %s') % (exptype,)
       area = position.ProgramAreaNear(tree)
       raise GbsLivenessException(msg, area)
   return tree.live_gen
示例#19
0
 def compile_expression(self, tree, code):
     "Compile an expression."
     exptype = tree.children[0]
     dispatch = {
       'or': self.compile_or,
       'and': self.compile_and,
       'not': self.compile_not,
       'relop': self.compile_binary_op,
       'addsub': self.compile_binary_op,
       'mul': self.compile_binary_op,
       'divmod': self.compile_binary_op,
       'pow': self.compile_binary_op,
       'listop': self.compile_binary_op,
       'projection': self.compile_binary_op,
       'constructor': self.compile_func_call,
       'varName': self.compile_var_name,
       'funcCall': self.compile_func_call,
       'match': self.compile_match,
       'unaryMinus': self.compile_unary_minus,
       'literal': self.compile_literal,
       'type': self.compile_type,
     }
     if exptype in dispatch:
         dispatch[exptype](tree, code)
     else:
         msg = i18n.i18n('Unknown expression: %s') % (exptype,)
         area = position.ProgramAreaNear(tree)
         raise GbsCompileException(msg, area)
示例#20
0
 def parse_error(self, top, _previous_token, token):
     "Raises a ParserException describing a parse error."
     if is_nonterminal(top):
         follow = self._followups(top)
     else:
         follow = [Token.type_description(top)]
     if len(follow) == 1:
         msg = i18n.i18n('Found: %s\nExpected: %s') % (token, follow[0])
     else:
         msg = ''
         msg += i18n.i18n('\n'.join([
                             'Found: %s',
                             'Expected one of the following tokens:'])) % (
                  token,)
         msg += '\n' + utils.indent('\n'.join(follow))
     raise ParserException(msg, position.ProgramAreaNear(token))
示例#21
0
 def check(self, tree):
     # Check semantics
     self.api.log(i18n.i18n('Performing semantic checks.'))
     self.lint(tree, strictness=self.options.lint_mode, allow_recursion=self.options.allow_recursion)
     # Check liveness
     if self.options.check_liveness:
         self.check_live_variables(tree)
示例#22
0
def prelude_for_file(filename):
    prelude_basename = i18n.i18n('Prelude') + '.gbs'
    prelude_filename = os.path.join(os.path.dirname(filename), prelude_basename)
    if os.path.exists(prelude_filename) and os.path.basename(filename) != prelude_basename:
        return prelude_filename
    else:
        return None
示例#23
0
 def infer_expression(self, tree):
     "Infer types for an expression."
     exptype = tree.children[0]
     dispatch = {
       'or': self.infer_bool_bool_bool_binary_op,
       'and': self.infer_bool_bool_bool_binary_op,
       'not': self.infer_bool_bool_unary_op,
       'relop': self.infer_a_a_bool_binary_op,
       'addsub': self.infer_int_int_int_binary_op,
       'mul': self.infer_int_int_int_binary_op,
       'divmod': self.infer_int_int_int_binary_op,
       'pow': self.infer_int_int_int_binary_op,
       'listop': self.infer_list_list_list_binary_op,
       'projection': self.infer_projection,
       'constructor': self.infer_constructor,
       'varName': self.infer_var_name,
       'funcCall': self.infer_func_call,
       'match': self.infer_match,
       'unaryMinus': self.infer_a_a_unary_op,
       'literal': self.infer_literal,
       'type': self.infer_type,
     }
     if exptype in dispatch:
         return dispatch[exptype](tree)
     else:
         msg = i18n.i18n('Unknown expression: %s') % (exptype,)
         area = position.ProgramAreaNear(tree)
         self.error(GbsTypeInferenceException(msg, area))
示例#24
0
 def check_unused_assignVarName(self, tree, var=None):
   if var is None:
     var = tree.children[1].children[1]
   if var.value not in tree.live_out:
     msg = i18n.i18n('Variable "%s" defined but not used') % (var.value,)
     area = position.ProgramAreaNear(tree)
     raise GbsUnusedVarException(msg, area)
示例#25
0
 def check_function_definition(self, tree):
     prfn, name, params, body, typeDecl = tree.children
     if body.children == []:
         name = name.value
         area = position.ProgramAreaNear(tree)
         msg = i18n.i18n('function body of "%s" cannot be empty') % (name,)
         raise GbsLintException(msg, area)
     elif not self._body_has_return(body):
         name = name.value
         area = position.ProgramAreaNear(body.children[-1])
         msg = i18n.i18n('function "%s" should have a return') % (name,)
         raise GbsLintException(msg, area)
     return_clause = body.children[-1]
     if self._return_is_empty(return_clause):
         name = name.value
         area = position.ProgramAreaNear(body.children[-1])
         raise GbsLintException(i18n.i18n('return from function "%s" must return something') % (name,), area)
示例#26
0
 def run_object_code(self, compiled_program, initial_board):
     # Make runnable
     runnable = self.make_runnable(compiled_program)
     # Run
     self.api.log(i18n.i18n('Starting program execution.'))
     rtn_vars, final_board = runnable.run(initial_board.clone(), self.api)
     gbs_run = GobstonesRun().initialize(None, compiled_program, initial_board, final_board.value, runnable, rtn_vars)
     return gbs_run
示例#27
0
 def backtrace(self, msg):
     def describe(ar, indent_):
         loc = ar.routine.nearby_elems.get(ar.ip, self.program.tree).pos_begin.file_row()
         return '%s%s %s %s' % ('    ' * indent_, ar.routine.prfn, ar.routine.name, loc)
     cs = self.callstack + [self.ar]
     res = ''
     res += msg + '\n\n'
     res += i18n.i18n('At:') + '\n'
     res += indent('\n'.join([
                          describe(x, y)
                          for x, y in zip(cs, range(0, len(cs)))
                        ])) + '\n'
     bindings = [(k, v) for k, v in seq_sorted(self.ar.bindings.items())
                        if k[0] != '_']
     if len(bindings) > 0:
         res += i18n.i18n('Locals:') + '\n'
         res += indent('\n'.join(['%s: %s' % (k, v) for k, v in bindings]))
     return res
示例#28
0
 def constructor_except(real_type, expected_type):
     area = position.ProgramAreaNear(tree)
     msg = i18n.i18n(
               'constructor "%s" is receiving: %s\n' +
               'But should receive: %s'
           ) % (
               expected_type.name, real_type.fields_repr(), expected_type.fields_repr()
           )
     self.error(GbsTypeInferenceException(msg, area))
示例#29
0
 def compile(self, filename, program_text):
     gbs_run = self.parse(filename, program_text)
     tree = gbs_run.tree
     # Check semantics, liveness and types
     self.check(tree)
     # Compile program
     self.api.log(i18n.i18n('Compiling.'))
     gbs_run.compiled_program = self.compile_program(tree)
     return gbs_run
示例#30
0
 def _check_excluded_types(self, tree, type, excluded_types):
     for excluded_type in excluded_types:
         try:
             gbs_type.unify(type, excluded_type)
             area = position.ProgramAreaNear(tree)
             msg = i18n.i18n('Expression can\'t have type: %s') % (excluded_type,)
             self.error(GbsTypeInferenceException(msg, area))
         except gbs_type.UnificationFailedException as exception:
             pass