Esempio n. 1
0
    def visit_BoolOp(self, bool_op: ast.BoolOp) -> Optional[IType]:
        """
        Verifies if the types of the operands are valid to the boolean operations

        If the operations are valid, changes de Python operator by the Boa operator in the syntax tree

        :param bool_op: the python ast boolean operation node
        :return: the type of the result of the operation if the operation is valid. Otherwise, returns None
        :rtype: IType or None
        """
        lineno: int = bool_op.lineno
        col_offset: int = bool_op.col_offset
        try:
            return_type: IType = None
            bool_operation: IOperation = None
            operator: Operator = self.get_operator(bool_op.op)

            if not isinstance(operator, Operator):
                # the operator is invalid or it was not implemented yet
                self._log_error(
                    CompilerError.UnresolvedReference(lineno, col_offset, type(operator).__name__)
                )

            l_operand = self.visit(bool_op.values[0])
            for index, operand in enumerate(bool_op.values[1:]):
                r_operand = self.visit(operand)

                operation: IOperation = self.get_bin_op(operator, r_operand, l_operand)
                if operation is None:
                    self._log_error(
                        CompilerError.NotSupportedOperation(lineno, col_offset, operator)
                    )
                elif bool_operation is None:
                    return_type = operation.result
                    bool_operation = operation

                lineno = operand.lineno
                col_offset = operand.col_offset
                l_operand = r_operand

            bool_op.op = bool_operation
            return return_type
        except CompilerError.MismatchedTypes as raised_error:
            raised_error.line = lineno
            raised_error.col = col_offset
            # raises the exception with the line/col info
            self._log_error(raised_error)
Esempio n. 2
0
    def visit_Assign(self, assign: ast.Assign):
        """
        Verifies if it is a multiple assignments statement

        :param assign: the python ast variable assignment node
        """
        # multiple assignments
        if isinstance(assign.targets[0], ast.Tuple):
            self._log_error(
                CompilerError.NotSupportedOperation(assign.lineno, assign.col_offset, 'Multiple variable assignments')
            )
        else:
            for target in assign.targets:
                self.validate_type_variable_assign(target, assign.value)

        # continue to walk through the tree
        self.generic_visit(assign)
Esempio n. 3
0
    def visit_Call(self, call: ast.Call):
        """
        Verifies if the number of arguments is correct

        :param call: the python ast function call node
        :return: the result type of the called function
        """
        if isinstance(call.func, ast.Name):
            callable_id: str = call.func.id
            callable_target = self.get_symbol(callable_id)
        else:
            callable_id, callable_target = self.get_callable_and_update_args(call)  # type: str, ISymbol

        callable_target = self.validate_builtin_callable(callable_id, callable_target)
        if not isinstance(callable_target, Callable):
            # the symbol doesn't exists or is not a function
            self._log_error(
                CompilerError.UnresolvedReference(call.func.lineno, call.func.col_offset, callable_id)
            )
        else:
            if callable_target is Builtin.NewEvent:
                return callable_target.return_type
            # TODO: change when kwargs is implemented
            if len(call.keywords) > 0:
                raise NotImplementedError

            if self.validate_callable_arguments(call, callable_target):
                args = [self.get_type(param) for param in call.args]
                if isinstance(callable_target, IBuiltinMethod):
                    # if the arguments are not generic, build the specified method
                    callable_target: IBuiltinMethod = callable_target.build(args)
                    if not callable_target.is_supported:
                        self._log_error(
                            CompilerError.NotSupportedOperation(call.lineno, call.col_offset, callable_id)
                        )
                        return callable_target.return_type

                self.validate_passed_arguments(call, args, callable_id, callable_target)

            self.update_callable_after_validation(call, callable_id, callable_target)
        return self.get_type(callable_target)
Esempio n. 4
0
 def visit_ClassDef(self, node: ast.ClassDef):
     # TODO: refactor when classes defined by the user are implemented
     self._log_error(
         CompilerError.NotSupportedOperation(node.lineno,
                                             node.col_offset,
                                             symbol_id='class'))