def visit(self, node, scope):  # type: ignore
        if node.method_info is not None:
            self.current_method = self.current_type.get_method(
                node.method_info.name)
            method_scope = scope.create_child()

            for pname, ptype in zip(self.current_method.param_names,
                                    self.current_method.param_types):
                try:
                    method_scope.define_variable(pname, ptype)
                except semantic.BaseSemanticError as e:
                    self.errors.append(e.with_pos(node.lineno, node.columnno))

            body = self.visit(node.body, method_scope)

            if (self.current_method.return_type.name == "SELF_TYPE"
                    and not body.type.conforms_to(self.current_type)):
                self.errors.append(
                    errors.IncompatibleTypesError(
                        node.lineno,
                        node.columnno,
                        body.type.name,
                        self.current_type.name,
                    ))

            elif (self.current_method.return_type.name != "SELF_TYPE" and
                  not body.type.conforms_to(self.current_method.return_type)):
                self.errors.append(
                    errors.IncompatibleTypesError(
                        node.lineno,
                        node.columnno,
                        body.type.name,
                        self.current_method.return_type.name,
                    ))

            if self.current_type.parent is not None:
                try:
                    parent_method = self.current_type.parent.get_method(
                        self.current_method.name)
                except semantic.BaseSemanticError as e:
                    parent_method = None

                if parent_method is not None and parent_method != self.current_method:
                    self.errors.append(
                        errors.WrongSignatureError(node.lineno, node.columnno,
                                                   self.current_method.name))

            self.current_method = None
            return type_checked.CoolMethodDeclNode(node.lineno, node.columnno,
                                                   node.method_info, body)
    def visit(self, node, scope):  # type: ignore
        exp = self.visit(node.expr, scope)
        args = [self.visit(arg, scope) for arg in node.args]
        try:
            static_type = self.get_type(node.static_type)
            method = static_type.get_method(node.id)
            if not exp.type.conforms_to(static_type):
                raise semantic.TypeError(
                    f"Expression type {exp.type.name} does not conform to declared static dispatch type {static_type.name}."
                )
        except semantic.BaseSemanticError as e:
            self.errors.append(e.with_pos(node.lineno, node.columnno))
            return type_checked.CoolStaticDispatchNode(
                node.lineno,
                node.columnno,
                exp,
                ErrorType(),
                node.id,
                args,
                ErrorType(),
            )

        if len(args) != len(method.param_names):
            self.errors.append(
                errors.WrongArgsCountError(
                    node.lineno,
                    node.columnno,
                    method.name,
                    len(method.param_names),
                    len(args),
                ))

        for arg, ptype in zip(args, method.param_types):
            if not arg.type.conforms_to(ptype):
                self.errors.append(
                    errors.IncompatibleTypesError(node.lineno, node.columnno,
                                                  arg.type.name, ptype.name))

        # try:
        #     static_type = self.get_type(node.static_type)
        #     if not exp.type.conforms_to(static_type):
        #         self.errors.append(
        #             errors.NotConformsError(
        #                 node.lineno, node.columnno, exp.type, static_type
        #             )
        #         )
        # except semantic.BaseSemanticError as e:
        #     self.errors.append(e.with_pos(node.lineno, node.columnno))

        return type_checked.CoolStaticDispatchNode(
            node.lineno,
            node.columnno,
            exp,
            static_type,
            node.id,
            args,
            method.return_type,
        )
 def visit(self, node, scope):  # type: ignore
     exp = self.visit(node.expr, scope)
     int_type = self.get_type("Int")
     if not exp.type.conforms_to(int_type):
         self.errors.append(
             errors.IncompatibleTypesError(node.lineno, node.columnno,
                                           exp.type.name, int_type.name))
     return type_checked.CoolTildeNode(node.lineno, node.columnno, exp,
                                       int_type)
    def visit(self, node, scope):  # type: ignore
        exp = self.visit(node.expr, scope)
        bool_type = self.get_type("Bool")
        if exp.type != bool_type:
            self.errors.append(
                errors.IncompatibleTypesError(node.lineno, node.columnno,
                                              exp.type.name, bool_type.name))

        return type_checked.CoolNotNode(node.lineno, node.columnno, exp,
                                        bool_type)
    def visit(self, node, scope):  # type: ignore
        if node.body != [] and node.attr_info is not None:
            exp = self.visit(node.body, scope)
            node_type = node.attr_info.type

            if exp.type.name == "SELF_TYPE" and not self.exp_type.conforms_to(
                    node_type):
                self.errors.append(
                    errors.IncompatibleTypesError(node.lineno, node.columnno,
                                                  node_type.name,
                                                  self.exp_type.name))

            elif exp.type.name != "SELF_TYPE" and not exp.type.conforms_to(
                    node_type):
                self.errors.append(
                    errors.IncompatibleTypesError(node.lineno, node.columnno,
                                                  node_type.name,
                                                  exp.type.name))

            return type_built.CoolAttrDeclNode(node.lineno, node.columnno,
                                               node.attr_info, exp)
    def visit(self, node, scope):  # type: ignore
        conditional = self.visit(node.cond, scope)
        body = self.visit(node.body, scope)

        if conditional.type != self.get_type("Bool"):
            self.errors.append(
                errors.IncompatibleTypesError(node.lineno, node.columnno,
                                              conditional.type.name, "Bool"))

        return type_checked.CoolWhileNode(node.lineno, node.columnno,
                                          conditional, body,
                                          self.get_type("Object"))
    def visit(self, node, scope):  # type: ignore
        try:
            typex = self.get_type(node.type)
        except semantic.BaseSemanticError as e:
            typex = ErrorType()
            self.errors.append(e.with_pos(node.lineno, node.columnno))

        if node.expr == []:
            right_type = typex
            right_exp = None
            # decl_list.append(idx, _type, None)
        else:
            right_exp = self.visit(node.expr, scope)
            right_type = right_exp.type
            # decl_list.append(idx, _type, right_exp)

        if typex.name == "SELF_TYPE" and not right_type.conforms_to(
                self.current_type):
            self.errors.append(
                errors.IncompatibleTypesError(
                    node.lineno,
                    node.columnno,
                    right_type.name,
                    self.current_type.name,
                ))

        elif typex.name != "SELF_TYPE" and not right_type.conforms_to(typex):
            self.errors.append(
                errors.IncompatibleTypesError(node.lineno, node.columnno,
                                              right_type.name, typex.name))

        try:
            scope.define_variable(node.id, typex, force=True)
        except semantic.BaseSemanticError as e:
            self.errors.append(e.with_pos(node.lineno, node.columnno))

        return type_checked.CoolLetDeclNode(node.lineno, node.columnno,
                                            node.id, right_type, right_exp)
    def visit(self, node, scope):  # type: ignore
        conditional = self.visit(node.cond, scope)
        then_expr = self.visit(node.then_expr, scope)
        else_expr = self.visit(node.else_expr, scope)
        bool_type = self.get_type("Bool")

        if not conditional.type.conforms_to(bool_type):
            self.errors.append(
                errors.IncompatibleTypesError(node.lineno, node.columnno,
                                              conditional.type.name, "Bool"))

        lca = self.lowest_common_ancestor(then_expr.type, else_expr.type)
        return type_checked.CoolIfThenElseNode(node.lineno, node.columnno,
                                               conditional, then_expr,
                                               else_expr, lca)
    def visit(self, node, scope):  # type: ignore
        if node.id == "self":
            self.errors.append(
                errors.IsReadOnlyError(node.lineno, node.columnno, "self"))

        try:
            var = scope.find_variable(node.id)
            var_type = var.type
        except semantic.BaseSemanticError as e:
            self.errors.append(e.with_pos(node.lineno, node.columnno))
            var_type = ErrorType()

        exp = self.visit(node.expr, scope)
        if not exp.type.conforms_to(var_type):
            self.errors.append(
                errors.IncompatibleTypesError(node.lineno, node.columnno,
                                              exp.type.name, var_type.name))

        return type_checked.CoolAssignNode(node.lineno, node.columnno, node.id,
                                           exp, exp.type)
Пример #10
0
    def visit(self, node, scope):  # type: ignore

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

        args = [self.visit(arg, scope) for arg in node.args]

        if exp.type.name == "AUTO_TYPE":
            return type_checked.CoolDispatchNode(node.lineno, node.columnno,
                                                 exp, node.id, args, exp.type)

        try:
            method = exp.type.get_method(node.id)
        except semantic.BaseSemanticError as e:
            self.errors.append(e.with_pos(node.lineno, node.columnno))
            return type_checked.CoolDispatchNode(node.lineno, node.columnno,
                                                 exp, node.id, args,
                                                 ErrorType())

        if len(args) != len(method.param_names):
            self.errors.append(
                errors.WrongArgsCountError(
                    node.lineno,
                    node.columnno,
                    method.name,
                    len(method.param_names),
                    len(args),
                ))

        for arg, ptype in zip(args, method.param_types):
            args.append(arg)
            if not arg.type.conforms_to(ptype):
                self.errors.append(
                    errors.IncompatibleTypesError(node.lineno, node.columnno,
                                                  arg.type.name, ptype.name))

        if method.return_type.name == "SELF_TYPE":
            return type_checked.CoolDispatchNode(node.lineno, node.columnno,
                                                 exp, node.id, args, exp.type)

        return type_checked.CoolDispatchNode(node.lineno, node.columnno, exp,
                                             node.id, args, method.return_type)