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()
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)
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
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])
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
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]
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())
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)
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)