예제 #1
0
 def check_range(self):
     # These violations of the Law of Demeter make me queasy.
     lower_bound = self.ast().range().lower()
     upper_bound = self.ast().range().upper()
     if not lower_bound < upper_bound:
         msg = 'lower bound {} must < upper bound {}'
         raise SemanticError(msg.format(lower_bound, upper_bound))
     return True
예제 #2
0
    def __init__(self, modifs, ret_type, name, params, body, ts, localts=None):
        super(mjMethod, self).__init__()
        self.modifs = modifs
        self.ret_type = ret_type
        self.name = name
        self.params = params
        self.processed_params = []
        self.body = body

        # hack
        self._modifiable = mjModifiable()
        self._modifiable.modifs = self.modifs
        self.isStatic = self._modifiable.isStatic
        self.isPublic = self._modifiable.isPublic
        self.isProtected = self._modifiable.isProtected

        self.ts = localts
        if localts is None:
            self.ts = mjTS(ts)

        self.ts.set_owner(self)

        if not ts is None:
            if not ts.addMethod(self):
                raise SemanticError(self.name.get_line(), self.name.get_col(),
                                    "Redefinicion de metodo.")

        param_offset = 3
        if not self.isStatic():
            param_offset = 4

        param_offset = len(self.params) + param_offset

        for (t, v) in self.params:
            param_offset -= 1
            var = mjVariable(t, v, ts=self.ts)
            var.offset = param_offset
            self.processed_params.append(var)
            if not self.ts.addVar(var):
                raise SemanticError(
                    v.get_line(), v.get_col(),
                    "%s ya esta definido como parametro" % v.get_lexeme())

        self.create_block_ts()
        self.body.set_owning_method(self)
예제 #3
0
 def check_type(self, t):
     if t.get_type() in FIRST_primitive_type:
         return
     if t.get_type() == VOID_TYPE:
         return
     if not self.ts.parent().parent().typeExists(t.get_lexeme()):
         raise SemanticError(
             t.get_line(), t.get_col(),
             "No existe ninguna clase llamada %s" % t.get_lexeme())
예제 #4
0
 def solve_extends(self):
     if not self.ext_name is None:
         (valid, ref) = self.ts.parent().validExtend(self.ext_name)
         # copiamos para mantener los offsets de esta clase en particular
         self.ext_class = ref
         if not valid:
             raise SemanticError(self.ext_name.get_line(),
                                 self.ext_name.get_col(),
                                 "No existe la clase padre")
예제 #5
0
 def check(self):
     self.check_type()
     self.check_modifs()
     for v, i in self.list_ids:
         if not i is None:
             i.check()
             if not i.compatibleWith(self.type):
                 raise SemanticError(v.get_line(), v.get_col(),
                                     "Inicializacion de tipo incompatible")
     return ""
예제 #6
0
 def resolve_names(self, scope):
     if not self.decls:
         raise SemanticError('no "main" function in a program',
                             *self.eof.get_char_info())
     for decl in self.decls:
         scope.add(decl.name, decl)
     if 'main' not in scope.members.keys():
         # todo is it correct to show token pos of last decl name?
         semantic_error3('no "main" function in a program', decl.name)
     for decl in self.decls:
         decl.resolve_names(scope)
예제 #7
0
  def hasMain(self):
    mains = []
    for clstr in self._sections["classes"]:
      cl = self.getType(clstr)
      if "main" in cl.ts._sections["methods"].keys():
        ms = cl.ts._sections["methods"]["main"]
        for m in ms:
          if len(m.params) == 0 and \
             m.isStatic() and \
             m.isPublic():
            mains.append(m)

    if len(mains) == 0:
      raise SemanticError(0,0,
                          "No existe ningun metodo static void main()")

    if len(mains) > 1:
      raise SemanticError(0,0,
                          "Existen mas de un metodo static void main()")

    return mains[0].label
예제 #8
0
    def check(self):
        code = "rmem %d\n" % len(self.args)
        for v, e in self.args:
            if not e is None:
                code += e.check()
                if not e.compatibleWith(self.ref):
                    raise SemanticError(v.get_line(), v.get_col(),
                                        "Inicializacion de tipo incompatible")
            var = mjVariable(self.ref, v, e, self.ts)
            if not self.ts.addVar(var):
                raise SemanticError(v.get_line(), v.get_col(),
                                    "Variable redefinida")
            var.offset = self.offset
            self.offset -= 1
            if not e is None:
                code += "dup\n"
                code += "store %d ; offset a %s \n" % (var.offset,
                                                       var.name.get_lexeme())
                code += "pop\n"

        return code
예제 #9
0
    def check(self):
        e = self.expr.resolve()
        if mjp.isToken(e):
            if mjp.literalToType(e.get_type()) != BOOLEAN_TYPE:
                raise SemanticError(e.get_line(), e.get_col(),
                                    "La expresion debe ser de tipo boolean")
        elif isVariable(e):
            if e.type.get_type() != BOOLEAN_TYPE:
                raise SemanticError(e.name.get_line(), e.name.get_col(),
                                    "La expresion debe ser de tipo boolean")
        elif isMethod(e):
            if e.is_constructor() or e.ret_type.get_type() != BOOLEAN_TYPE:
                raise SemanticError(self.expr.ref.get_line(),
                                    self.expr.ref.get_col(),
                                    "La expresion debe ser de tipo boolean")
        else:
            raise Exception()

        rand = "".join(
            random.choice(string.letters + string.digits) for i in xrange(10))
        label_true = "if_true_%s" % rand
        label_false = "if_false_%s" % rand
        label_end = "else_false_%s" % rand

        self.expr.label_cc_true = label_true
        self.expr.label_cc_false = label_false
        code = self.expr.check()
        code += "bf %s\n" % label_false
        code += "%s: nop\n" % label_true
        code += self.stat.check()
        code += "jump %s\n" % label_end
        code += "%s: nop\n" % label_false

        if not self.elsestat is None:
            code += self.elsestat.check()

        code += "%s: nop\n" % label_end

        return code
예제 #10
0
    def check(self):
        if self.method.is_constructor():
            if not self.expr is None:
                raise SemanticError(
                    self.ret.get_line(), self.ret.get_col(),
                    "Los return en constructores no deben retornar valores")
            else:
                return ""

        if self.expr is None:
            if self.method.ret_type.get_type() != VOID_TYPE:
                raise SemanticError(
                    self.ret.get_line(), self.ret.get_col(),
                    "La sentencia return debe contener una expresion de tipo %s"
                    % self.method.ret_type.get_lexeme())
        else:
            t = self.expr.resolve()
            #raise Exception("Checkear compatibilidad de herencia tambien!")
            if mjp.isToken(t):
                rt = mjp.literalToType(t.get_type())
                if rt != self.method.ret_type.get_type():
                    raise SemanticError(
                        self.ret.get_line(), self.ret.get_col(),
                        "Se esta retornando %s en un metodo de tipo %s" %
                        (mjp.typeToStr(rt), self.method.ret_type.get_lexeme()))
            else:
                if t.type.get_lexeme() != self.method.ret_type.get_lexeme():
                    raise SemanticError(
                        self.ret.get_line(), self.ret.get_col(),
                        "Se esta retornando %s en un metodo de tipo %s" %
                        (t.type.get_lexeme(),
                         self.method.ret_type.get_lexeme()))

            offset = 3
            if self.method.isStatic():
                offset = 2  # no hay this
            return self.expr.check() + "store %d ; offset a ret_val\n" % (
                offset + len(self.method.params) + 1)
        return ""
예제 #11
0
    def __init__(self, modifs, t, list_ids, ts):
        super(mjClassVariableDecl, self).__init__()
        self.modifs = modifs
        self.type = t
        self.list_ids = list_ids
        self.ts = ts

        for v, i in self.list_ids:
            var = mjClassVariable(self.type, v, i, self.modifs, self.ts)
            if not i is None:
                i.set_ts(ts)
                i.set_var(var)
            if not self.ts.addVar(var):
                raise SemanticError(v.get_line(), v.get_col(),
                                    "Variable redefinida")
 def raise_error(self, message):
     print(SemanticError(message))
예제 #13
0
 def error(self, error_code, token):
     raise SemanticError(error_code=error_code,
                         token=token,
                         message=f"{error_code.value} -> {token}")
예제 #14
0
 def getType(self, v):
   if not v in self._sections["classes"]:
     raise SemanticError(0,0,
                         "No existe ningun tipo llamado %s" % v)
   return self._sections["classes"][v]
예제 #15
0
    def check_type(self, parent):
        if parent.type:
            return parent.type
        core = None
        if isinstance(parent.core, tuple):
            core = parent.core[1]
        else:
            core = parent.core
        if core in self.__rules['rules']:
            if self.__rules['rules'][core]['final']:
                parent.type = self.__rules['rules'][core]['type']
                return parent.type
            else:
                rule = self.__rules['rules'][core]['options'][parent.rule]

                if core == ':declaration':
                    identifier = None
                    type_check = self.check_type(parent.children[rule[0]])
                    if parent.rule == 0:
                        assignment = parent.children[1]
                        identifier = assignment.children[0].core[2]

                    else:
                        identifier = parent.children[1].core[2]

                    if identifier in self.__identifier_table.keys():
                        if not isinstance(self.__identifier_table[identifier],
                                          dict):
                            raise SemanticError(
                                f'Variable \'{identifier}\' already declared.')
                        raise SemanticError(
                            f'Identifier \'{identifier}\' already used in function.'
                        )

                    self.__identifier_table[identifier] = parent.children[
                        rule[0]].core[2]
                    if parent.rule == 0:
                        self.check_type(parent.children[rule[1]])

                    parent.type = type_check
                    if parent.rule == 0:
                        parent.children[1].children[0].type = self.check_type(
                            parent.children[1].children[0])
                    else:
                        parent.children[1].type = self.check_type(
                            parent.children[1])
                elif core == ':assignment':
                    identifier_raw_type = self.check_type(parent.children[0])
                    value_type = self.check_type(parent.children[2])

                    identifier = parent.children[0].core[2]
                    identifier_type = self.__identifier_table[identifier]

                    parent.type = identifier_type
                    if value_type in self.__rules['compatibilities'][
                            identifier_type]:
                        parent.type = value_type
                    else:
                        raise TypeError(
                            f'\'{identifier_type}\' not compatible with \'{value_type}\' on line {parent.children[0].core[0][1]}.'
                        )
                elif core == ':operation':
                    types = []
                    operator = parent.children[1].core[2]

                    if parent.rule == 0:
                        raise SemanticError(
                            'Operations with more than 2 elements are currently not supported.'
                        )

                    for element in rule:
                        node = parent.children[element]
                        types.append(self.check_type(node))

                    initial_type = None

                    if 'FLOAT' in types:
                        if 'CHAR' not in types and 'STRING' not in types:
                            initial_type = 'FLOAT'
                        else:
                            raise TypeError(
                                f'\'CHAR|STRING\' not compatible with \'FLOAT\'.'
                            )
                    elif 'STRING' in types:
                        for element in types:
                            if element != 'STRING':
                                raise TypeError(
                                    f'\'{element}\' not compatible with \'STRING\'.'
                                )
                        initial_type = 'STRING'
                    elif 'CHAR' in types:
                        for element in types:
                            if element != 'CHAR':
                                raise TypeError(
                                    f'\'{element}\' not compatible with \'CHAR\'.'
                                )
                        initial_type = 'CHAR'
                    elif 'INT' in types:
                        for element in types:
                            if element != 'INT':
                                raise TypeError(
                                    f'\'{element}\' not compatible with \'INT\'.'
                                )
                        initial_type = 'INT'
                    else:
                        raise TypeError(f'Type not compatible with operation.')

                    if operator != '+':
                        if operator == '%' and initial_type != 'INT':
                            raise TypeError(
                                f'\'{initial_type}\' not compatible with \'{operator}\' operator.'
                            )
                        if initial_type != 'INT' and initial_type != 'FLOAT':
                            raise TypeError(
                                f'\'{initial_type}\' not compatible with \'{operator}\' operator.'
                            )
                    parent.type = initial_type
                elif core == ':logical_value':
                    value_type = self.check_type(parent.children[rule[0]])
                    if value_type != 'BOOLEAN':
                        raise TypeError(
                            f'\'{value_type}\' not compatible with \'BOOLEAN\'.'
                        )
                    parent.type = value_type
                elif core == ':comparison':
                    types = []
                    operator = parent.children[1].core[2]

                    for element in rule:
                        node = parent.children[element]
                        types.append(self.check_type(node))

                    numeric_operators = ['<=', '>=', '>', '<']
                    if operator in numeric_operators:
                        for element in types:
                            if element not in ['INT', 'FLOAT']:
                                raise TypeError(
                                    f'\'{element}\' not compatible with \'{operator}\' operator.'
                                )

                    parent.type = 'BOOLEAN'
                elif core == ':function':
                    type_node = None
                    identifier_type = 'sokka'
                    type_check = None

                    if rule:
                        type_node = parent.children[rule[0]]

                    if type_node:
                        identifier_type = type_node.core[2]
                        type_check = self.check_type(type_node)

                    identifier = parent.children[1].core[2]

                    if identifier in self.__identifier_table.keys():
                        if isinstance(self.__identifier_table[identifier],
                                      dict):
                            raise SemanticError(
                                f'Function \'{identifier}\' already declared.')
                        raise SemanticError(
                            f'Identifier \'{identifier}\' already used in variable.'
                        )

                    self.__identifier_table[identifier] = dict()
                    self.__identifier_table[identifier][
                        'type'] = identifier_type

                    if parent.rule == 0 or parent.rule == 1:
                        args_node = parent.children[3]
                        args_types = self.check_type(args_node)
                        self.__identifier_table[identifier][
                            'args_types'] = args_types

                    parent.type = type_check
                elif core == ':logical_operation':
                    parent.type = 'BOOLEAN'
                if rule:
                    if len(rule) == 1:
                        if not parent.type:
                            parent.type = self.check_type(
                                parent.children[rule[0]])

                if len(parent.children) > 1:
                    self.check_children(parent)

                return parent.type
        elif core == 'identifier':
            identifier = parent.core[2]
            if identifier in self.__identifier_table.keys():
                if not isinstance(self.__identifier_table[identifier], dict):
                    parent.type = self.__rules['rules'][
                        self.__identifier_table[identifier]]['type']
                    return parent.type
            else:
                raise SemanticError(
                    f'Variable \'{identifier}\' referenced before assignment.')
        elif core == 'type':
            parent.type = self.__rules['rules'][parent.core[2]]['type']
            return parent.type
        elif core == ':args':
            nodes = []
            nodes.append(parent.children[0].children[0].core[2])
            if parent.rule == 0:
                nodes.extend(self.check_type(parent.children[1]))
            return nodes
        elif core == ':argses':
            nodes = []
            nodes.append(parent.children[1].children[0].core[2])
            if parent.rule == 0:
                nodes.extend(self.check_type(parent.children[2]))
            return nodes
        elif core == ':call':
            identifier = parent.children[0].core[2]
            if identifier in self.__identifier_table.keys():
                if isinstance(self.__identifier_table[identifier], dict):
                    if 'args_types' in self.__identifier_table[
                            identifier].keys():
                        expected_args = self.__identifier_table[identifier][
                            'args_types']
                        if parent.rule == 0:
                            args_raw_types = self.check_type(
                                parent.children[2])
                            if len(args_raw_types) != len(expected_args):
                                raise SemanticError(
                                    f'Missing arguments for functions, expected: {str(expected_args)}.'
                                )
                            for i, arg_type in enumerate(args_raw_types):
                                if arg_type not in self.__rules[
                                        'compatibilities'][expected_args[i]]:
                                    raise TypeError(
                                        f'Incompatible arguments in call, expected: {str(expected_args)}.'
                                    )
                        else:
                            raise SemanticError(
                                f'Missing arguments for functions, expected: {str(expected_args)}.'
                            )
                    function_type = self.__identifier_table[identifier]['type']
                    parent.type = self.__rules['rules'][function_type]['type']
                    return parent.type
            raise SemanticError(f'Function \'{identifier}\' not declared.')
        elif core == ':args_call':
            nodes = []
            nodes.append(self.check_type(parent.children[0]))
            if parent.rule == 0:
                nodes.extend(self.check_type(parent.children[1]))
            return nodes
        elif core == ':args_calls':
            nodes = []
            nodes.append(self.check_type(parent.children[1]))
            if parent.rule == 0:
                nodes.extend(self.check_type(parent.children[2]))
            return nodes
        else:
            self.check_children(parent)