Example #1
0
    def visit(self, node: FuncDeclarationNode):
        args_names = []
        args_types = []
        for name, type_ in node.params:
            if name in args_names:
                error_text = SemanticError.PARAMETER_MULTY_DEFINED % name
                self.errors.append(SemanticError(error_text, *type_.pos))
            args_names.append(name)

            try:
                arg_type = self.context.get_type(type_.value, type_.pos)
            except SemanticError:
                error_text = TypesError.PARAMETER_UNDEFINED % (type_.value,
                                                               type_.value)
                self.errors.append(TypesError(error_text, *type_.pos))
                arg_type = ErrorType()
            args_types.append(arg_type)

        try:
            return_type = self.context.get_type(node.type, node.type_pos)
        except SemanticError as e:
            error_text = TypesError.RETURN_TYPE_UNDEFINED % (node.type,
                                                             node.id)
            self.errors.append(TypesError(error_text, *node.type_pos))
            return_type = ErrorType(node.type_pos)

        try:
            self.current_type.define_method(node.id, args_names, args_types,
                                            return_type, node.pos)
        except SemanticError as e:
            self.errors.append(e)
Example #2
0
    def visit(self, node: ClassDeclarationNode):
        try:
            self.current_type = self.context.get_type(node.id, node.pos)
        except SemanticError as e:
            self.current_type = ErrorType()
            self.errors.append(e)

        if node.parent is not None:
            if node.parent in ['Int', 'Bool', 'String']:
                error_text = SemanticError.INHERIT_ERROR % (node.id,
                                                            node.parent)
                self.errors.append(SemanticError(error_text, *node.parent_pos))
            try:
                parent = self.context.get_type(node.parent, node.parent_pos)
            except SemanticError:
                error_text = TypesError.INHERIT_UNDEFINED % (node.id,
                                                             node.parent)
                self.errors.append(TypesError(error_text, *node.parent_pos))
                parent = None
            try:
                current = parent
                while current is not None:
                    if current.name == self.current_type.name:
                        error_text = SemanticError.CIRCULAR_DEPENDENCY % (
                            self.current_type.name, self.current_type.name)
                        raise SemanticError(error_text, *node.pos)
                    current = current.parent
            except SemanticError as e:
                parent = ErrorType()
                self.errors.append(e)
            self.current_type.set_parent(parent)

        for feature in node.features:
            self.visit(feature)
    def visit(self, node: InstantiateNode, scope: Scope):
        try:
            type_ = self.context.get_type(node.lex, node.pos)
        except SemanticError:
            type_ = ErrorType()
            error_text = TypesError.NEW_UNDEFINED_CLASS % node.lex
            self.errors.append(TypesError(error_text, *node.pos))

        return get_type(type_, self.current_type)
 def visit(self, node: NotNode, scope: Scope):
     ltype = self.visit(node.expr, scope)
     typex = BoolType()
     if ltype != typex:
         error_text = TypesError.UOPERATION_NOT_DEFINED % (
             'not', ltype.name, typex.name)
         self.errors.append(TypesError(error_text, *node.pos))
         return ErrorType()
     return typex
 def visit(self, node: BinaryNotNode, scope: Scope):
     ltype = self.visit(node.expr, scope)
     int_type = IntType()
     if ltype != int_type:
         error_text = TypesError.UOPERATION_NOT_DEFINED % ('~', ltype.name,
                                                           int_type.name)
         self.errors.append(TypesError(error_text, *node.pos))
         return ErrorType()
     return int_type
    def visit(self, node: WhileNode, scope: Scope):
        cond = self.visit(node.cond, scope)

        if cond.name != 'Bool':
            self.errors.append(
                TypesError(TypesError.LOOP_CONDITION_ERROR, *node.pos))

        self.visit(node.expr, scope)
        return ObjectType()
 def visit(self, node: EqualNode, scope: Scope):
     ltype = self.visit(node.left, scope)
     rtype = self.visit(node.right, scope)
     if (ltype == IntType() or rtype == IntType() or ltype == StringType()
             or rtype == StringType() or ltype == BoolType()
             or rtype == BoolType()) and ltype != rtype:
         error_text = TypesError.COMPARISON_ERROR
         self.errors.append(TypesError(error_text, *node.pos))
         return ErrorType()
     else:
         return BoolType()
    def visit(self, node: ConditionalNode, scope: Scope):
        cond = self.visit(node.cond, scope)

        if cond.name != 'Bool':
            error_text = TypesError.PREDICATE_ERROR % ('if', 'Bool')
            self.errors.append(TypesError(error_text, *node.pos))

        true_type = self.visit(node.stm, scope)
        false_type = self.visit(node.else_stm, scope)

        return get_common_basetype([false_type, true_type])
    def visit(self, node: AssignNode, scope: Scope):
        vinfo = self.find_variable(scope, node.id)
        vtype = get_type(vinfo.type, self.current_type)

        typex = self.visit(node.expr, scope)

        if not typex.conforms_to(vtype):
            error_text = TypesError.UNCONFORMS_TYPE % (typex.name, node.id,
                                                       vtype.name)
            self.errors.append(TypesError(error_text, *node.pos))
        return typex
 def binary_operation(self, node, scope, operator):
     ltype = self.visit(node.left, scope)
     rtype = self.visit(node.right, scope)
     int_type = IntType()
     if ltype != int_type or rtype != int_type:
         error_text = TypesError.BOPERATION_NOT_DEFINED % (
             ltype.name, operator, rtype.name)
         self.errors.append(TypesError(error_text, *node.pos))
         return ErrorType()
     if operator == '<' or operator == '<=':
         return BoolType()
     return int_type
    def visit(self, node: VarDeclarationNode, scope: Scope):

        vtype = self._get_type(node.type, node.type_pos)
        vtype = get_type(vtype, self.current_type)

        if node.expr != None:
            typex = self.visit(node.expr, scope)
            if not typex.conforms_to(vtype):
                error_text = TypesError.UNCONFORMS_TYPE % (typex.name, node.id,
                                                           vtype.name)
                self.errors.append(TypesError(error_text, *node.type_pos))
            return typex
        return vtype
    def visit(self, node: AttrDeclarationNode, scope: Scope):
        attr = self.current_type.get_attribute(node.id, node.pos)
        vartype = get_type(attr.type, self.current_type)

        self.current_index = attr.index
        typex = self.visit(node.expr, scope)
        self.current_index = None

        if not typex.conforms_to(vartype):
            error_text = TypesError.ATTR_TYPE_ERROR % (typex.name, attr.name,
                                                       vartype.name)
            self.errors.append(TypesError(error_text, *node.pos))
            return ErrorType()
        return typex
    def visit(self, node: BaseCallNode, scope: Scope):
        obj = self.visit(node.obj, scope)
        typex = self._get_type(node.type, node.type_pos)

        if not obj.conforms_to(typex):
            error_text = TypesError.INCOMPATIBLE_TYPES_DISPATCH % (typex.name,
                                                                   obj.name)
            self.errors.append(TypesError(error_text, *node.type_pos))
            return ErrorType()

        meth = self._get_method(typex, node.id, node.pos)
        if not isinstance(meth, MethodError):
            self._check_args(meth, scope, node.args, node.pos)

        return get_type(meth.return_type, typex)
Example #14
0
    def visit(self, node: AttrDeclarationNode):
        try:
            attr_type = self.context.get_type(node.type, node.pos)
        except SemanticError as e:
            error_text = TypesError.ATTR_TYPE_UNDEFINED % (node.type, node.id)
            attr_type = ErrorType(node.type_pos)
            self.errors.append(TypesError(error_text, *node.type_pos))

        if node.id == 'self':
            self.errors.append(
                SemanticError(SemanticError.SELF_ATTR, *node.pos))

        try:
            self.current_type.define_attribute(node.id, attr_type, node.pos)
        except SemanticError as e:
            self.errors.append(e)
    def _check_args(self, meth: Method, scope: Scope, args, pos):
        arg_types = [self.visit(arg, scope) for arg in args]

        if len(arg_types) > len(meth.param_types):
            error_text = SemanticError.ARGUMENT_ERROR % meth.name
            self.errors.append(SemanticError(error_text, *pos))
        elif len(arg_types) < len(meth.param_types):
            for arg, arg_info in zip(meth.param_names[len(arg_types):],
                                     args[len(arg_types):]):
                error_text = SemanticError.ARGUMENT_ERROR % (meth.name)
                self.errors.append(SemanticError(error_text, *arg_info.pos))

        for atype, ptype, param_name in zip(arg_types, meth.param_types,
                                            meth.param_names):
            if not atype.conforms_to(ptype):
                error_text = TypesError.INCOSISTENT_ARG_TYPE % (
                    meth.name, atype.name, param_name, ptype.name)
                self.errors.append(TypesError(error_text, *pos))
    def visit(self, node: FuncDeclarationNode, scope: Scope):
        parent = self.current_type.parent

        self.current_method = method = self.current_type.get_method(
            node.id, node.pos)
        if parent is not None:
            try:
                old_meth = parent.get_method(node.id, node.pos)
                if old_meth.return_type.name != method.return_type.name:
                    error_text = SemanticError.WRONG_SIGNATURE_RETURN % (
                        node.id, method.return_type.name,
                        old_meth.return_type.name)
                    self.errors.append(
                        SemanticError(error_text, *node.type_pos))
                if len(method.param_names) != len(old_meth.param_names):
                    error_text = SemanticError.WRONG_NUMBER_PARAM % node.id
                    self.errors.append(SemanticError(error_text, *node.pos))
                for (name, param), type1, type2 in zip(node.params,
                                                       method.param_types,
                                                       old_meth.param_types):
                    if type1.name != type2.name:
                        error_text = SemanticError.WRONG_SIGNATURE_PARAMETER % (
                            name, type1.name, type2.name)
                        self.errors.append(
                            SemanticError(error_text, *param.pos))
            except SemanticError:
                pass

        result = self.visit(node.body, scope)

        return_type = get_type(method.return_type, self.current_type)

        if not result.conforms_to(return_type):
            error_text = TypesError.RETURN_TYPE_ERROR % (result.name,
                                                         return_type.name)
            self.errors.append(TypesError(error_text, *node.type_pos))
Example #17
0
 def get_type(self, name: str, pos) -> Type:
     try:
         return self.types[name]
     except KeyError:
         error_text = TypesError.TYPE_NOT_DEFINED % name
         raise TypesError(error_text, *pos)
Example #18
0
 def set_parent(self, parent):
     if type(self.parent) != ObjectType and self.parent is not None:
         error_text = TypesError.PARENT_ALREADY_DEFINED % self.name
         raise TypesError(error_text, *self.pos)
     self.parent = parent