def visit(self, node: AttrDeclarationNode, scope: Scope, set_type=None):
        # print('attr declaration')
        if node.id == "self":
            self.errors.append(SEMANTIC_ERROR % (
                node.lineno, node.colno,
                f'"self" is used as attribute name in class "{self.current_type.name}".'
            ))
            if node.val is not None:
                self.visit(node.val, scope)
            return
        var, _ = scope.my_find_var(node.id)
        attr_type = self.context.get_type(node.type)
        if var is not None:
            self.errors.append(ATTR_ALREADY_DEFINED %
                               (node.lineno, node.colno, node.id))
        else:
            scope.define_variable(node.id, attr_type)

        if node.val is not None:
            return_type = self.visit(node.val, scope)
        else:
            return_type = attr_type

        if attr_type.name == BasicTypes.SELF.value:
            attr_type = self.current_type
        if return_type.name == BasicTypes.SELF.value:
            return_type = self.current_type
        if not return_type.conforms_to(attr_type):
            self.errors.append(
                INCOMPATIBLE_TYPES %
                (node.lineno, node.colno, return_type.name, attr_type.name))
    def visit(self, node, scope):
        token = self.visit(node.obj, scope)

        if isinstance(token, VoidPod):
            raise RuntimeException(
                'Reference to an instance of a void object.')

        _o = self.context.get_type('Object')
        _s = self.context.get_type('String')
        _io = self.context.get_type('IO')

        if token.type.conforms_to(_o) and (_o.name,
                                           node.method) in cl_baseline:
            args = (token, ) + tuple(
                self.visit(arg, scope) for arg in node.args) + (self.context, )
            return cl_baseline[_o.name, node.method](*args)

        if token.type.conforms_to(_s) and (_s.name,
                                           node.method) in cl_baseline:
            args = (token, ) + tuple(
                self.visit(arg, scope) for arg in node.args) + (self.context, )
            return cl_baseline[_s.name, node.method](*args)

        if token.type.conforms_to(_io) and (_io.name,
                                            node.method) in cl_baseline:
            args = (token, ) + tuple(
                self.visit(arg, scope) for arg in node.args) + (self.context, )
            return cl_baseline[_io.name, node.method](*args)

        #si es una instantiate.f() meter en el scope hijo todos sus atributos
        _funcCall_scope = Scope()
        #para el caso [email protected]()
        if not node.parent is None:
            parent_t = self.context.get_type(node.parent)
            method = parent_t.get_method(node.method, parent_t, False)
        else:
            method = token.get_method(node.method, self.currentType, False)

        for _id, _t, _arg in zip(method.param_names, method.param_types,
                                 node.args):
            _funcCall_scope.define_variable(_id, _t).token = self.visit(
                _arg, scope)

        _funcCall_scope.define_variable('self', token.type).token = token

        self.stack.append(self.currentPod)
        self.currentPod = token

        result = self.visit(method.expr, _funcCall_scope)

        self.currentPod = self.stack.pop()
        return result