Esempio n. 1
0
    def visit(self, node, scope):
        # Evaluate object
        obj_type = self.visit(node.obj, scope)

        # Check object type conforms to cast type
        cast_type = obj_type
        if node.type is not None:
            try:
                cast_type = self.context.get_type(node.type)
                if isinstance(cast_type, AutoType):
                    raise SemanticError(
                        'AUTO_TYPE can\'t be the type on this type of dispatch'
                    )
                if isinstance(cast_type, SelfType):
                    cast_type = SelfType(self.current_type)
            except SemanticError as ex:
                cast_type = ErrorType()
                self.errors.append(ex.text)
        if not self.check_conformance(obj_type, cast_type):
            self.errors.append(INCOMPATIBLE_TYPES %
                               (obj_type.name, cast_type.name))

        # if the obj that is calling the function is autotype, let it pass
        if isinstance(cast_type, AutoType):
            return cast_type

        if isinstance(cast_type, SelfType):
            cast_type = self.current_type

        # Check this function is defined for cast_type
        try:
            method = cast_type.get_method(node.id)
            if not len(node.args) == len(method.param_types):
                self.errors.append(INVALID_OPERATION %
                                   (method.name, cast_type.name))
                return ErrorType()
            for i, arg in enumerate(node.args):
                computed_type = self.visit(arg, scope)
                if not self.check_conformance(computed_type,
                                              method.param_types[i]):
                    self.errors.append(
                        INCOMPATIBLE_TYPES %
                        (computed_type.name, method.param_types[i].name))

            # check self_type
            rtype = method.return_type
            if isinstance(rtype, SelfType):
                rtype = obj_type

            return rtype

        except SemanticError as ex:
            self.errors.append(ex.text)
            return ErrorType()
Esempio n. 2
0
    def visit(self, node):
        ## Building param-names and param-types of the method
        param_names = []
        param_types = []
        node.index = []
        for param in node.params:
            n, t = param
            node.index.append(None)

            # Checking param name can't be self
            if n == "self":
                self.errors.append(SELF_IS_READONLY)

            while True:
                if n in param_names:
                    n = f'1{n}'
                else:
                    param_names.append(n)
                    break

            try:
                t = self.context.get_type(t)
                if isinstance(t, SelfType):
                    t = SelfType(self.current_type)
                elif isinstance(t, AutoType):
                    node.index[-1] = self.manager.assign_id(self.obj_type)
            except SemanticError as ex:
                self.errors.append(ex.text)
                t = ErrorType()
            param_types.append(t)

        # Checking return type
        try:
            rtype = self.context.get_type(node.type)
            if isinstance(rtype, SelfType):
                rtype = SelfType(self.current_type)
        except SemanticError as ex:
            self.errors.append(ex.text)
            rtype = ErrorType()

        node.idx = self.manager.assign_id(self.obj_type) if isinstance(
            rtype, AutoType) else None

        # Defining the method in the current type. There can not be another method with the same name.
        try:
            self.current_type.define_method(node.id, param_names, param_types,
                                            rtype, node.index, node.idx)
        except SemanticError as ex:
            self.errors.append(ex.text)
Esempio n. 3
0
    def visit(self, node):
        # Checking attribute type
        try:
            attr_type = self.context.get_type(node.type)
            if isinstance(attr_type, SelfType):
                attr_type = SelfType(self.current_type)
        except SemanticError as ex:
            self.errors.append(ex.text)
            attr_type = ErrorType()

        node.idx = self.manager.assign_id(self.obj_type) if isinstance(
            attr_type, AutoType) else None

        #Checking attribute can't be named self
        if node.id == "self":
            self.errors.append(SELF_IS_READONLY)

        # Checking attribute name. No other attribute can have the same name
        flag = False
        try:
            self.current_type.define_attribute(node.id, attr_type, node.idx)
            flag = True
        except SemanticError as ex:
            self.errors.append(ex.text)

        while not flag:
            node.id = f'1{node.id}'
            try:
                self.current_type.define_attribute(node.id, attr_type,
                                                   node.idx)
                flag = True
            except SemanticError:
                pass
    def visit(self, node):
        self.context = Context()
        self.context.types["Object"] = ObjectType()
        self.context.types["Int"] = IntType()
        self.context.types["String"] = StringType()
        self.context.types["Bool"] = BoolType()
        self.context.types["AUTO_TYPE"] = AutoType()
        self.context.types["SELF_TYPE"] = SelfType()
        self.context.types["IO"] = IOType()

        object_type = self.context.get_type("Object")
        for typex in self.context.types.values():
            if typex == object_type:
                continue
            typex.set_parent(object_type)

        for declaration in node.declarations:
            self.visit(declaration)

        copy_visitor = CopyVisitor()
        newAst = copy_visitor.visit(node)
        newAst.context = self.context

        # Reset state
        self.context = None
        self.errors = None

        return newAst
Esempio n. 5
0
    def define_built_in_types(self):
        objectx = ObjectType()
        iox = IOType()
        intx = IntType()
        stringx = StringType()
        boolx = BoolType()
        self_type = SelfType()
        autotype = AutoType()

        # Object Methods
        objectx.define_method('abort', [], [], objectx, [])
        objectx.define_method('type_name', [], [], stringx, [])
        objectx.define_method('copy', [], [], self_type, [])

        # IO Methods
        iox.define_method('out_string', ['x'], [stringx], self_type, [None])
        iox.define_method('out_int', ['x'], [intx], self_type, [None])
        iox.define_method('in_string', [], [], stringx, [])
        iox.define_method('in_int', [], [], intx, [])

        # String Methods
        stringx.define_method('length', [], [], intx, [])
        stringx.define_method('concat', ['s'], [stringx], stringx, [None])
        stringx.define_method('substr', ['i', 'l'], [intx, intx], stringx,
                              [None])

        # Setting Object as parent
        iox.set_parent(objectx)
        stringx.set_parent(objectx)
        intx.set_parent(objectx)
        boolx.set_parent(objectx)

        built_in_types.extend(
            [objectx, iox, stringx, intx, boolx, self_type, autotype])
Esempio n. 6
0
    def visit(self, node, scope):
        nscope = scope.create_child()

        node.idx_list = [None] * len(node.id_list)
        for i, item in enumerate(node.id_list):
            idx, typex, expr = item
            # create a new_scope for every variable defined
            new_scope = nscope.create_child()

            if idx == 'self':
                self.errors.append(SELF_IS_READONLY)
                idx = f'1{idx}'
                node.id_list[i] = (idx, typex, expr)

            try:
                typex = self.context.get_type(typex)
                if isinstance(typex, SelfType):
                    typex = SelfType(self.current_type)
            except SemanticError as ex:
                self.errors.append(ex.text)
                typex = ErrorType()

            if isinstance(typex, AutoType):
                node.idx_list[i] = self.manager.assign_id(self.obj_type)

            if expr is not None:
                expr_type = self.visit(expr, new_scope)
                if not self.check_conformance(expr_type, typex):
                    self.errors.append(INCOMPATIBLE_TYPES %
                                       (expr_type.name, typex.name))

            new_scope.define_variable(idx, typex, node.idx_list[i])
            nscope = new_scope

        return self.visit(node.body, nscope)
 def visit(self, node, scope):
     try:
         node_type = self.context.get_type(
             node.lex) if node.lex != "SELF_TYPE" else SelfType()
     except SemanticError as err:
         self.AddError(f"Unable to instantiate:", err.text)
         node_type = ErrorType()
     node.computed_type = node_type
Esempio n. 8
0
    def visit(self, node, scope, types):
        try:
            typex = self.context.get_type(node.lex)
            if isinstance(typex, SelfType):
                typex = SelfType(self.current_type)
        except SemanticError:
            typex = ErrorType()

        return typex, [typex]
Esempio n. 9
0
    def visit(self, node, scope):
        self.current_type = self.context.get_type(node.id)
        scope.define_variable('self', SelfType(self.current_type))
        attributes = self.current_type.all_attributes()
        for values in attributes:
            attr, _ = values
            scope.define_variable(attr.name, attr.type, attr.idx)

        for feature in node.features:
            self.visit(feature, scope.create_child())
Esempio n. 10
0
    def visit(self, node, scope):
        try:
            typex = self.context.get_type(node.lex)
            if isinstance(typex, AutoType):
                raise SemanticError('AUTO_TYPE can\'t be instanciate with new')
            if isinstance(typex, SelfType):
                typex = SelfType(self.current_type)
        except SemanticError as ex:
            self.errors.append(ex.text)
            typex = ErrorType()

        return typex
    def build_default_classes(self):
        Object = self.context.get_type("Object")
        String = self.context.get_type("String")
        Int = self.context.get_type("Int")
        Io = self.context.get_type("IO")
        Bool = self.context.get_type("Bool")

        String.set_parent(Object)
        Int.set_parent(Object)
        Io.set_parent(Object)
        Bool.set_parent(Object)

        Object.define_method("abort", [], [], Object)
        Object.define_method("type_name", [], [], String)
        Object.define_method("copy", [], [], SelfType())

        String.define_method("length", [], [], Int)
        String.define_method("concat", ["s"], [String], String)
        String.define_method("substr", ["i", "l"], [Int, Int], String)

        Io.define_method("out_string", ["x"], [String], SelfType())
        Io.define_method("out_int", ["x"], [Int], SelfType())
        Io.define_method("in_string", [], [], String)
        Io.define_method("in_int", [], [], Int)
    def visit(self, node):
        try:
            attr_type = self.context.get_type(
                node.type) if node.type != "SELF_TYPE" else SelfType()
        except SemanticError as err:
            self.errors.append(err.text)
            attr_type = ErrorType()

        if node.id[0] != node.id[0].lower():
            self.errors.append(
                f"Error in \"{node.id}\". Objects different than types must start with lower case."
            )
        try:
            self.current_type.define_attribute(node.id, attr_type)
        except SemanticError as err:
            self.errors.append(err.text)
Esempio n. 13
0
    def visit(self, node, scope):
        # check expression
        self.visit(node.expr, scope)

        nscope = scope.create_child()

        # check branches
        types = []
        node.branch_idx = []
        for branch in node.branch_list:
            idx, typex, expr = branch

            node.branch_idx.append(None)

            # check idx is not self
            if idx == 'self':
                self.errors.append(SELF_IS_READONLY)

            try:
                var_type = self.context.get_type(typex)
                if isinstance(var_type, SelfType):
                    var_type = SelfType(self.current_type)
            except SemanticError as ex:
                self.errors.append(ex.text)
                var_type = ErrorType()

            # check type is autotype and assign an id in the manager
            if isinstance(var_type, AutoType):
                node.branch_idx[-1] = self.manager.assign_id(self.obj_type)

            new_scope = nscope.create_child()
            new_scope.define_variable(idx, var_type, node.branch_idx[-1])

            computed_type = self.visit(expr, new_scope)
            types.append(computed_type)

        return LCA(types)