• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

CityOfZion / neo3-boa / e084b44c-1a5f-4649-92cd-d3ed06099181

05 Mar 2024 05:58PM UTC coverage: 92.023% (-0.08%) from 92.107%
e084b44c-1a5f-4649-92cd-d3ed06099181

push

circleci

Mirella de Medeiros
CU-86drpnc9z - Drop support to Python 3.10

20547 of 22328 relevant lines covered (92.02%)

1.84 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.5
/boa3/internal/model/builtin/classmethod/indexbytesstringmethod.py
1
import ast
2✔
2

3
from boa3.internal.model.builtin.classmethod.indexmethod import IndexMethod
2✔
4
from boa3.internal.model.expression import IExpression
2✔
5
from boa3.internal.model.type.primitive.bytestype import BytesType
2✔
6
from boa3.internal.model.type.primitive.strtype import StrType
2✔
7
from boa3.internal.model.variable import Variable
2✔
8
from boa3.internal.neo.vm.opcode.Opcode import Opcode
2✔
9

10

11
class IndexBytesStringMethod(IndexMethod):
2✔
12

13
    def __init__(self, self_type: StrType | None = None):
2✔
14
        from boa3.internal.model.type.type import Type
2✔
15
        if not isinstance(self_type, (StrType, BytesType)):
2✔
16
            self_type = Type.str
2✔
17

18
        args: dict[str, Variable] = {
2✔
19
            'self': Variable(self_type),
20
            'x': Variable(self_type),
21
            'start': Variable(Type.int),
22
            'end': Variable(Type.optional.build(Type.int)),
23
        }
24

25
        start_default = ast.parse("{0}".format(0)
2✔
26
                                  ).body[0].value
27
        end_default = ast.parse("{0}".format(Type.none.default_value)
2✔
28
                                ).body[0].value
29

30
        super().__init__(args, defaults=[start_default, end_default])
2✔
31

32
    def validate_parameters(self, *params: IExpression) -> bool:
2✔
33
        if 2 <= len(params) <= 4:
×
34
            return False
×
35
        if not all(isinstance(param, IExpression) for param in params):
×
36
            return False
×
37

38
        from boa3.internal.model.type.itype import IType
×
39
        self_type: IType = params[0].type
×
40

41
        if not isinstance(self_type, (StrType, BytesType)):
×
42
            return False
×
43

44
        if not self_type.is_type_of(params[1]):
×
45
            return False
×
46

47
        return True
×
48

49
    @property
2✔
50
    def error_message(self) -> str:
2✔
51
        return 'substring not found' if isinstance(self._arg_self.type, StrType) else 'subsequence of bytes not found'
2✔
52

53
    def generate_internal_opcodes(self, code_generator):
2✔
54
        from boa3.internal.model.builtin.builtin import Builtin
2✔
55
        from boa3.internal.model.operation.binaryop import BinaryOp
2✔
56

57
        # fix possible negative or too big indexes for start and end parameters
58
        code_generator.swap_reverse_stack_items(2)
2✔
59
        code_generator.swap_reverse_stack_items(4)
2✔
60
        code_generator.swap_reverse_stack_items(2)
2✔
61
        code_generator.fix_negative_index()
2✔
62
        code_generator.swap_reverse_stack_items(2)
2✔
63
        code_generator.duplicate_stack_top_item()
2✔
64
        code_generator.insert_type_check(None)
2✔
65
        if_end_is_none = code_generator.convert_begin_if()
2✔
66
        code_generator.change_jump(if_end_is_none, Opcode.JMPIFNOT)
2✔
67
        code_generator.remove_stack_top_item()
2✔
68
        code_generator.duplicate_stack_item(2)
2✔
69
        code_generator.convert_builtin_method_call(Builtin.Len, is_internal=True)
2✔
70
        else_end_is_not_none = code_generator.convert_begin_else(if_end_is_none, is_internal=True)
2✔
71
        code_generator.fix_negative_index()
2✔
72
        code_generator.convert_end_if(else_end_is_not_none, is_internal=True)
2✔
73
        code_generator.swap_reverse_stack_items(2)
2✔
74
        code_generator.fix_index_out_of_range(True)
2✔
75
        code_generator.swap_reverse_stack_items(2)
2✔
76
        code_generator.fix_index_out_of_range(True)
2✔
77
        code_generator.swap_reverse_stack_items(2)
2✔
78

79
        # change order of items on stack
80
        code_generator.duplicate_stack_item(4)
2✔
81
        code_generator.convert_builtin_method_call(Builtin.Len, is_internal=True)
2✔
82
        code_generator.swap_reverse_stack_items(3, rotate=True)
2✔
83
        code_generator.swap_reverse_stack_items(3, rotate=True)
2✔
84

85
        # current_index = start
86
        # while (size < end - current_index):
87
        while_start = code_generator.convert_begin_while()
2✔
88
        code_generator.duplicate_stack_item(4)
2✔
89
        code_generator.duplicate_stack_item(2)
2✔
90
        code_generator.duplicate_stack_item(5)
2✔
91
        code_generator.convert_get_substring(is_internal=True)
2✔
92
        code_generator.duplicate_stack_item(6)
2✔
93
        code_generator.convert_operation(BinaryOp.NumEq, is_internal=True)
2✔
94
        #   if str[index:current_index + size] == substr:
95
        if_was_found = code_generator.convert_begin_if()
2✔
96
        code_generator.change_jump(if_was_found, Opcode.JMPIFNOT)
2✔
97
        #       break
98
        code_generator.convert_loop_break()
2✔
99
        code_generator.convert_end_if(if_was_found)
2✔
100
        #   current_index += 1
101
        code_generator.insert_opcode(Opcode.INC)
2✔
102

103
        condition_address = code_generator.bytecode_size
2✔
104
        code_generator.duplicate_stack_item(2)
2✔
105
        code_generator.duplicate_stack_item(2)
2✔
106
        code_generator.convert_operation(BinaryOp.Sub, is_internal=True)
2✔
107
        code_generator.duplicate_stack_item(4)
2✔
108
        code_generator.convert_operation(BinaryOp.GtE, is_internal=True)
2✔
109
        code_generator.convert_end_while(while_start, condition_address, is_internal=True)
2✔
110

111
        # if current_index + size >= end:
112
        code_generator.duplicate_stack_item(2)
2✔
113
        code_generator.duplicate_stack_item(2)
2✔
114
        code_generator.convert_operation(BinaryOp.Sub, is_internal=True)
2✔
115
        code_generator.duplicate_stack_item(4)
2✔
116
        check_was_found = code_generator.convert_begin_if()
2✔
117
        code_generator.change_jump(check_was_found, Opcode.JMPGE)
2✔
118
        #   raise Exception('substring not found')
119
        code_generator.convert_literal(self.error_message)
2✔
120
        code_generator.convert_raise_exception()
2✔
121
        code_generator.convert_end_if(check_was_found)
2✔
122
        # else:
123
        #   return current_index
124
        for _ in range(1, len(code_generator._stack)):
2✔
125
            code_generator.remove_stack_item(2)
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc