コード例 #1
0
    def __init__(self, user_class: UserClass):
        self_var = Variable(user_class)
        args = {'self': self_var}
        base_init = None
        if len(user_class.bases) == 1:
            # TODO: change when class inheritance with multiple bases is implemented
            # use update to keep the original order
            base_init = user_class.bases[0].constructor_method()
            args.update(base_init.args)
            # but change the self type
            args['self'] = self_var

        Method.__init__(self, args=args, return_type=user_class)
        IdentifiedSymbol.__init__(self, identifier=constants.INIT_METHOD_ID)

        self.defined_by_entry = False
        self.is_init = True
        self.origin_class = user_class
        # __init__ method behave like class methods
        from boa3.model.builtin.builtin import Builtin
        self.decorators.append(Builtin.ClassMethodDecorator)

        if base_init is not None:
            origin = self.origin if self.origin else self
            base_init.add_call_origin(origin)
コード例 #2
0
ファイル: codegenerator.py プロジェクト: EdgeDLT/neo3-boa
    def initialize_static_fields(self):
        """
        Converts the signature of the method

        :return: whether there are static fields to be initialized
        """
        if self.initialized_static_fields:
            return False

        num_static_fields = len(self._globals)
        if num_static_fields > 0:
            init_data = bytearray([num_static_fields])
            self.__insert1(OpcodeInfo.INITSSLOT, init_data)

            from boa3.constants import INITIALIZE_METHOD_ID
            if INITIALIZE_METHOD_ID in self.symbol_table:
                from boa3.helpers import get_auxiliary_name
                method = self.symbol_table.pop(INITIALIZE_METHOD_ID)
                new_id = get_auxiliary_name(INITIALIZE_METHOD_ID, method)
                self.symbol_table[new_id] = method

            init_method = Method(is_public=True)
            init_method.init_bytecode = self.last_code
            self.symbol_table[INITIALIZE_METHOD_ID] = init_method

        return num_static_fields > 0
コード例 #3
0
ファイル: codegenerator.py プロジェクト: EdgeDLT/neo3-boa
    def convert_begin_method(self, method: Method):
        """
        Converts the signature of the method

        :param method: method that is being converted
        """
        num_args: int = len(method.args)
        num_vars: int = len(method.locals)

        method.init_address = VMCodeMapping.instance().bytecode_size
        if num_args > 0 or num_vars > 0:
            init_data = bytearray([num_vars, num_args])
            self.__insert1(OpcodeInfo.INITSLOT, init_data)
            method.init_bytecode = self.last_code
        self._current_method = method
コード例 #4
0
 def _get_method_debug_info(self, method_id: str,
                            method: Method) -> Dict[str, Any]:
     from boa3.compiler.codegenerator.vmcodemapping import VMCodeMapping
     return {
         "id":
         str(id(method)),
         "name":
         ',{0}'.format(method_id),  # TODO: include module name
         "range":
         '{0}-{1}'.format(method.start_address, method.end_address),
         "params": [
             '{0},{1}'.format(name, var.type.abi_type)
             for name, var in method.args.items()
         ],
         "return":
         method.return_type.abi_type,
         "variables": [
             '{0},{1}'.format(name, var.type.abi_type)
             for name, var in method.locals.items()
         ],
         "sequence-points": [
             '{0}[{1}]{2}:{3}-{4}:{5}'.format(
                 VMCodeMapping.instance().get_start_address(
                     instruction.code),
                 self._get_method_origin_index(method),
                 instruction.start_line, instruction.start_col,
                 instruction.end_line, instruction.end_col)
             for instruction in method.debug_map()
         ]
     }
コード例 #5
0
    def visit_FunctionDef(self, function: ast.FunctionDef):
        """
        Visitor of the function node

        Includes the method in the scope of its module

        :param function:
        """
        fun_args = self.visit(function.args)
        fun_rtype_symbol = self.visit(
            function.returns) if function.returns is not None else Type.none

        if fun_rtype_symbol is None:
            # it is a function with None return: Main(a: int) -> None:
            raise NotImplementedError

        if isinstance(fun_rtype_symbol, str):
            symbol = self.get_symbol(function.returns.id)
            fun_rtype_symbol = self.get_type(symbol)

        fun_return: IType = self.get_type(fun_rtype_symbol)
        fun_decorators: List[Method] = self._get_function_decorators(function)

        if Builtin.Metadata in fun_decorators:
            self._read_metadata_object(function)
            return Builtin.Metadata

        method = Method(args=fun_args,
                        defaults=function.args.defaults,
                        return_type=fun_return,
                        origin_node=function,
                        is_public=Builtin.Public in fun_decorators)
        self._current_method = method

        # don't evaluate constant expression - for example: string for documentation
        from boa3.constants import SYS_VERSION_INFO
        if SYS_VERSION_INFO >= (3, 8):
            function.body = [
                stmt for stmt in function.body
                if not (isinstance(stmt, ast.Expr)
                        and isinstance(stmt.value, ast.Constant))
            ]
        else:
            function.body = [
                stmt for stmt in function.body
                if not (isinstance(stmt, ast.Expr) and
                        (hasattr(stmt.value, 'n') or hasattr(stmt.value, 's')))
            ]
        for stmt in function.body:
            self.visit(stmt)

        self.__include_callable(function.name, method)
        self._current_method = None
コード例 #6
0
    def visit_FunctionDef(self, function: ast.FunctionDef):
        """
        Visitor of the function node

        Includes the method in the scope of its module

        :param function:
        """
        fun_args = self.visit(function.args)
        fun_rtype_symbol = self.visit(function.returns) if function.returns is not None else Type.none

        if fun_rtype_symbol is None:
            # it is a function with None return: Main(a: int) -> None:
            raise NotImplementedError

        if isinstance(fun_rtype_symbol, str):
            symbol = self.get_symbol(function.returns.id)
            fun_rtype_symbol = self.get_type(symbol)

        fun_return: IType = self.get_type(fun_rtype_symbol)
        fun_decorators: List[Method] = self._get_function_decorators(function)

        if Builtin.Metadata in fun_decorators:
            self._read_metadata_object(function)
            return Builtin.Metadata

        method = Method(args=fun_args, defaults=function.args.defaults, return_type=fun_return,
                        origin_node=function, is_public=Builtin.Public in fun_decorators)
        self._current_method = method
        self._scope_stack.append(SymbolScope())

        # don't evaluate constant expression - for example: string for documentation
        from boa3.constants import SYS_VERSION_INFO
        if SYS_VERSION_INFO >= (3, 8):
            function.body = [stmt for stmt in function.body
                             if not (isinstance(stmt, ast.Expr) and isinstance(stmt.value, ast.Constant))]
        else:
            function.body = [stmt for stmt in function.body
                             if not (isinstance(stmt, ast.Expr) and
                                     (hasattr(stmt.value, 'n') or hasattr(stmt.value, 's'))
                                     )]
        for stmt in function.body:
            self.visit(stmt)

        self.__include_callable(function.name, method)
        method_scope = self._scope_stack.pop()
        global_scope_symbols = self._scope_stack[0].symbols if len(self._scope_stack) > 0 else {}

        for var_id, var in method_scope.symbols.items():
            if isinstance(var, Variable) and var_id not in self._annotated_variables:
                method.include_variable(var_id, Variable(UndefinedType, var.origin))
            else:
                method.include_symbol(var_id, var)

        self._annotated_variables.clear()
        self._current_method = None
コード例 #7
0
    def _validate_metadata_symbols(self):
        """
        Validates if the symbols match the requirements from the given metadata
        """
        if self._metadata is not None:
            if self._metadata.is_payable:
                """
                Payable smart contracts requires the implementation of a 'verify' function, that must implement the
                following signature:

                ```
                @public
                def verify(*args) -> bool
                ```
                """
                verify_id: str = 'verify'
                if (verify_id
                        not in self.global_symbols  # couldn't find verify
                        or not isinstance(self.global_symbols[verify_id],
                                          Method)  # verify is not a function
                        or self.global_symbols[verify_id].origin is
                        None  # verify is not a user function
                    ):
                    self._log_error(
                        CompilerError.MetadataImplementationMissing(
                            line=self._metadata_node.lineno,
                            col=self._metadata_node.col_offset,
                            symbol_id=verify_id,
                            metadata_attr_id='is_payable'))
                elif (self.global_symbols[verify_id].return_type != Type.bool
                      or not self.global_symbols[verify_id].is_public):
                    actual = self.global_symbols[verify_id]
                    expected = Method(actual.args, Type.bool, True)
                    self._log_error(
                        CompilerError.MetadataIncorrectImplementation(
                            line=actual.origin.lineno,
                            col=actual.origin.col_offset,
                            symbol_id=verify_id,
                            expected_symbol=expected,
                            actual_symbol=actual))