Esempio n. 1
0
 def visit(self, node: VariableNode, scope: Scope):
     try:
         typex = scope.find_local(node.lex).type
         name = self.to_var_name(node.lex)
         return name, get_type(typex, self.current_type)
     except:
         var_info = scope.find_attribute(node.lex)
         local_var = self.register_local(var_info.name)
         self.register_instruction(
             cil.GetAttribNode('self', var_info.name,
                               self.current_type.name, local_var,
                               var_info.type.name))
         return local_var, get_type(var_info.type, self.current_type)
    def visit(self, memberCallNode, scope):
        typex = self.currentType
        method = self._get_method(typex, memberCallNode.id,
                                  (memberCallNode.line, memberCallNode.col))
        if not isinstance(method, MethodError):
            # check the args
            argTypes = [self.visit(arg, scope) for arg in memberCallNode.args]

            if len(argTypes) > len(method.param_types):
                errorText = f'Method {method.name} called with wrong number of arguments.'
                self.errors.append(
                    SemanticError(errorText, memberCallNode.line,
                                  memberCallNode.col))
            elif len(argTypes) < len(method.param_types):
                for arg, argInfo in zip(method.param_names[len(argTypes):],
                                        memberCallNode.args[len(argTypes):]):
                    errorText = f'Method {method.name} called with wrong number of arguments.'
                    self.errors.append(SemanticError(errorText, *argInfo.pos))

            for argType, paramType, paramName in zip(argTypes,
                                                     method.param_types,
                                                     method.param_names):
                if not argType.conforms_to(paramType):
                    errorText = f'In call of method {method.name}, type {argType.name} of parameter {paramName} does not conform to declared type {paramType.name}.'
                    self.errors.append(
                        TypexError(errorText, memberCallNode.line,
                                   memberCallNode.col))

        memberCallNode.static_type = typex
        memberCallNode.computed_type = get_type(method.return_type, typex)
        return memberCallNode.computed_type
Esempio n. 3
0
    def visit(self, node: VarDeclarationNode, scope: Scope):
        var_info = scope.find_variable(node.id)
        vtype = get_type(var_info.type, self.current_type)
        local_var = self.register_local(var_info.name)

        value, typex = self.visit(node.expr, scope)
        if vtype.name == 'Object' and typex.name in ['String', 'Int', 'Bool']:
            self.register_instruction(cil.BoxingNode(local_var, typex.name))
        else:
            self.register_instruction(cil.AssignNode(local_var, value))
        return local_var, vtype
    def visit(self, assignNode, scope):
        varInfo = self.find_variable(scope, assignNode.id)
        varType = get_type(varInfo.type, self.currentType)
        typex = self.visit(assignNode.expr, scope)

        if not typex.conforms_to(varType):
            errorText = f'Inferred type {typex.name} of initialization of {assignNode.id} does not conform to identifier\'s declared type {varType.name}.'
            self.errors.append(
                TypexError(errorText, assignNode.line, assignNode.col))

        assignNode.computed_type = typex
        return typex
    def visit(self, newNode, scope):
        try:
            typex = self.context.get_type(newNode.id,
                                          (newNode.line, newNode.col))
        except:
            typex = ErrorType()
            errorText = f'\'new\' used with undefined class {newNode.id}.'
            self.errors.append(TypexError(errorText, newNode.line,
                                          newNode.col))

        typex = get_type(typex, self.currentType)
        newNode.computed_type = typex
        return typex
Esempio n. 6
0
    def visit(self, node: InstantiateNode, scope: Scope):
        instance = self.define_internal_local()
        typex = self.context.get_type(node.lex, node.pos)
        typex = get_type(typex, self.current_type)
        self.register_instruction(cil.AllocateNode(typex.name, instance))

        # calling the constructor to load all attributes
        # Si tiene atributos entonces tendrá constructor (esto se deberia optimizar mas)
        if typex.all_attributes():
            self.register_instruction(
                cil.StaticCallNode(typex.name, typex.name, instance,
                                   [cil.ArgNode(instance)], typex.name))

        return instance, typex
    def visit(self, varDeclarationNode, scope):
        varType = self._get_type(
            varDeclarationNode.type,
            (varDeclarationNode.line, varDeclarationNode.col))
        varType = get_type(varType, self.currentType)

        if varDeclarationNode.expr == None:
            return varType
        else:
            typex = self.visit(varDeclarationNode.expr, scope)
            if not typex.conforms_to(varType):
                errorText = f'Inferred type {typex.name} of initialization of {varDeclarationNode.id} does not conform to identifier\'s declared type {varType.name}.'
                self.errors.append(
                    TypexError(errorText, varDeclarationNode.typeLine,
                               varDeclarationNode.typeCol))
            return typex
    def visit(self, attrDeclarationNode, scope):
        attr = self.currentType.get_attribute(
            attrDeclarationNode.id,
            (attrDeclarationNode.line, attrDeclarationNode.col))
        attrType = get_type(attr.type, self.currentType)
        self.currentIndex = attr.index
        typex = self.visit(attrDeclarationNode.expr, scope)
        self.currentIndex = None

        if not typex.conforms_to(attrType):
            errorText = f'Inferred type {typex.name} of initialization of attribute {attr.name} does not conform to declared type {attrType.name}.'
            self.errors.append(
                TypexError(errorText, attrDeclarationNode.line,
                           attrDeclarationNode.col))
            return ErrorType()

        return typex
    def visit(self, funcDeclarationNode, scope):
        parent = self.currentType.parent
        self.currentMethod = self.currentType.get_method(
            funcDeclarationNode.id,
            (funcDeclarationNode.line, funcDeclarationNode.col))

        method = self.currentMethod
        if parent is not None:
            try:
                oldMethod = parent.get_method(
                    funcDeclarationNode.id,
                    (funcDeclarationNode.line, funcDeclarationNode.col))
                if oldMethod.return_type.name != method.return_type.name:
                    errorText = f'In redefined method {funcDeclarationNode.id}, return type {method.return_type.name} is different from original return type {oldMethod.return_type.name}.'
                    self.errors.append(
                        SemanticError(errorText, funcDeclarationNode.typeLine,
                                      funcDeclarationNode.typeCol))
                if len(method.param_names) != len(oldMethod.param_names):
                    errorText = f'Incompatible number of formal parameters in redefined method {funcDeclarationNode.id}.'
                    self.errors.append(
                        SemanticError(errorText, funcDeclarationNode.line,
                                      funcDeclarationNode.col))
                for (name, ptype, pline,
                     pcol), type1, type2 in zip(funcDeclarationNode.params,
                                                method.param_types,
                                                oldMethod.param_types):
                    if type1.name != type2.name:
                        errorText = f'In redefined method {name}, parameter type {type1.name} is different from original type {type2.name}.'
                        self.errors.append(
                            SemanticError(errorText, pline, pcol))
            except:
                pass

        result = self.visit(funcDeclarationNode.body, scope)
        returnType = get_type(method.return_type, self.currentType)

        if not result.conforms_to(returnType):
            errorText = f'Inferred return type {result.name} of method test does not conform to declared return type {returnType.name}.'
            self.errors.append(
                TypexError(errorText, funcDeclarationNode.typeLine,
                           funcDeclarationNode.typeCol))
Esempio n. 10
0
    def visit(self, arrobaCallNode, scope):
        objType = self.visit(arrobaCallNode.obj, scope)
        typex = self._get_type(
            arrobaCallNode.type,
            (arrobaCallNode.typeLine, arrobaCallNode.typeCol))

        if not objType.conforms_to(typex):
            errorText = f'Expression type {typex.name} does not conform to declared static dispatch type {objType.name}.'
            self.errors.append(
                TypexError(errorText, arrobaCallNode.typeLine,
                           arrobaCallNode.typeCol))
            return ErrorType()

        method = self._get_method(typex, arrobaCallNode.id,
                                  (arrobaCallNode.line, arrobaCallNode.col))
        if not isinstance(method, MethodError):
            # check the args
            argTypes = [self.visit(arg, scope) for arg in arrobaCallNode.args]

            if len(argTypes) > len(method.param_types):
                errorText = f'Method {method.name} called with wrong number of arguments.'
                self.errors.append(
                    SemanticError(errorText, arrobaCallNode.line,
                                  arrobaCallNode.col))
            elif len(argTypes) < len(method.param_types):
                for arg, argInfo in zip(method.param_names[len(argTypes):],
                                        arrobaCallNode.args[len(argTypes):]):
                    errorText = f'Method {method.name} called with wrong number of arguments.'
                    self.errors.append(SemanticError(errorText, *argInfo.pos))

            for argType, paramType, paramName in zip(argTypes,
                                                     method.param_types,
                                                     method.param_names):
                if not argType.conforms_to(paramType):
                    errorText = f'In call of method {method.name}, type {argType.name} of parameter {paramName} does not conform to declared type {paramType.name}.'
                    self.errors.append(
                        TypexError(errorText, arrobaCallNode.line,
                                   arrobaCallNode.col))

        arrobaCallNode.computed_type = get_type(method.return_type, TypexError)
        return arrobaCallNode.computed_type
Esempio n. 11
0
 def visit(self, idNode, scope):
     varType = self.find_variable(scope, idNode.id).type
     typex = get_type(varType, self.currentType)
     idNode.computed_type = typex
     return typex
Esempio n. 12
0
 def _return_type(self, typex: Type, node):
     meth = typex.get_method(node.id, node.pos)
     return get_type(meth.return_type, self.current_type)