function_signature.py 文件源码

python
阅读 21 收藏 0 点赞 0 评论 0

项目:viper 作者: ethereum 项目源码 文件源码
def from_definition(cls, code, _sigs=None):
        name = code.name
        pos = 0
        # Determine the arguments, expects something of the form def foo(arg1: num, arg2: num ...
        args = []
        for arg in code.args.args:
            typ = arg.annotation
            if not isinstance(arg.arg, str):
                raise VariableDeclarationException("Argument name invalid", arg)
            if not typ:
                raise InvalidTypeException("Argument must have type", arg)
            if not is_varname_valid(arg.arg):
                raise VariableDeclarationException("Argument name invalid or reserved: " + arg.arg, arg)
            if arg.arg in (x.name for x in args):
                raise VariableDeclarationException("Duplicate function argument name: " + arg.arg, arg)
            parsed_type = parse_type(typ, None, _sigs)
            args.append(VariableRecord(arg.arg, pos, parsed_type, False))
            if isinstance(parsed_type, ByteArrayType):
                pos += 32
            else:
                pos += get_size_of_type(parsed_type) * 32

        # Apply decorators
        const, payable, private, public = False, False, False, False
        for dec in code.decorator_list:
            if isinstance(dec, ast.Name) and dec.id == "constant":
                const = True
            elif isinstance(dec, ast.Name) and dec.id == "payable":
                payable = True
            elif isinstance(dec, ast.Name) and dec.id == "private":
                private = True
            elif isinstance(dec, ast.Name) and dec.id == "public":
                public = True
            else:
                raise StructureException("Bad decorator", dec)
        if public and private:
            raise StructureException("Cannot use public and private decorators on the same function", code)
        if not public and not private and not isinstance(code.body[0], ast.Pass):
            raise StructureException("Function visibility must be declared (@public or @private)", code)
        # Determine the return type and whether or not it's constant. Expects something
        # of the form:
        # def foo(): ...
        # def foo() -> num: ...
        # If there is no return type, ie. it's of the form def foo(): ...
        # and NOT def foo() -> type: ..., then it's null
        if not code.returns:
            output_type = None
        elif isinstance(code.returns, (ast.Name, ast.Compare, ast.Subscript, ast.Call, ast.Tuple)):
            output_type = parse_type(code.returns, None, _sigs)
        else:
            raise InvalidTypeException("Output type invalid or unsupported: %r" % parse_type(code.returns, None), code.returns)
        # Output type must be canonicalizable
        if output_type is not None:
            assert isinstance(output_type, TupleType) or canonicalize_type(output_type)
        # Get the canonical function signature
        sig = name + '(' + ','.join([canonicalize_type(parse_type(arg.annotation, None, _sigs)) for arg in code.args.args]) + ')'
        # Take the first 4 bytes of the hash of the sig to get the method ID
        method_id = fourbytes_to_int(sha3(bytes(sig, 'utf-8'))[:4])
        return cls(name, args, output_type, const, payable, private, sig, method_id)
评论列表
文章目录


问题


面经


文章

微信
公众号

扫码关注公众号