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

CityOfZion / neo3-boa / 858f5658-b835-4f01-86b4-3a69cebd0b86

16 Oct 2023 06:23PM UTC coverage: 91.625% (+0.004%) from 91.621%
858f5658-b835-4f01-86b4-3a69cebd0b86

push

circleci

Mirella de Medeiros
Bump version: 1.0.1 → 1.1.0

1 of 1 new or added line in 1 file covered. (100.0%)

19988 of 21815 relevant lines covered (91.63%)

0.92 hits per line

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

82.05
/boa3/internal/model/builtin/classmethod/extendmethod.py
1
from typing import Any, Dict, Optional
1✔
2

3
from boa3.internal.model.builtin.method.builtinmethod import IBuiltinMethod
1✔
4
from boa3.internal.model.expression import IExpression
1✔
5
from boa3.internal.model.type.collection.sequence.mutable.mutablesequencetype import MutableSequenceType
1✔
6
from boa3.internal.model.type.collection.sequence.sequencetype import SequenceType
1✔
7
from boa3.internal.model.variable import Variable
1✔
8
from boa3.internal.neo.vm.opcode.Opcode import Opcode
1✔
9

10

11
class ExtendMethod(IBuiltinMethod):
1✔
12
    def __init__(self, sequence_type: MutableSequenceType = None):
1✔
13
        from boa3.internal.model.type.type import Type
1✔
14
        if not isinstance(sequence_type, MutableSequenceType):
1✔
15
            sequence_type = Type.mutableSequence
1✔
16

17
        self_arg = Variable(sequence_type)
1✔
18
        item_arg = Variable(Type.sequence.build_collection(sequence_type.value_type))
1✔
19

20
        identifier = 'extend'
1✔
21
        args: Dict[str, Variable] = {'self': self_arg, 'item': item_arg}
1✔
22
        super().__init__(identifier, args)
1✔
23

24
    @property
1✔
25
    def _arg_self(self) -> Variable:
1✔
26
        return self.args['self']
×
27

28
    @property
1✔
29
    def _arg_item(self) -> Variable:
1✔
30
        return self.args['item']
1✔
31

32
    def validate_parameters(self, *params: IExpression) -> bool:
1✔
33
        if len(params) != 2:
×
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
        sequence_type: IType = params[0].type
×
40
        iterator_type: IType = params[1].type
×
41

42
        if not isinstance(sequence_type, MutableSequenceType):
×
43
            return False
×
44
        if not isinstance(iterator_type, SequenceType):
×
45
            return False
×
46
        return sequence_type.value_type.is_type_of(iterator_type.value_type)
×
47

48
    @property
1✔
49
    def stores_on_slot(self) -> bool:
1✔
50
        return True
1✔
51

52
    def generate_internal_opcodes(self, code_generator):
1✔
53
        from boa3.internal.model.builtin.builtin import Builtin
1✔
54
        from boa3.internal.model.operation.binaryop import BinaryOp
1✔
55
        from boa3.internal.model.type.type import Type
1✔
56
        from boa3.internal.neo.vm.type.StackItem import StackItemType
1✔
57

58
        expected_values = self._arg_item.type
1✔
59

60
        code_generator.duplicate_stack_item(2)
1✔
61
        code_generator.insert_type_check(StackItemType.Buffer)  # append opcode only works for array
1✔
62
        # if self is bytes
63
        if_bytes = code_generator.convert_begin_if()
1✔
64
        #   result = self + arg     # when it's bytearray, concatenates the value
65
        code_generator.convert_operation(BinaryOp.Concat.build(Type.bytearray, Type.bytearray))
1✔
66

67
        # else:
68
        else_bytes = code_generator.convert_begin_else(if_bytes, is_internal=True)
1✔
69
        #   while len(item) > 0
70
        code_generator.insert_opcode(Opcode.UNPACK, add_to_stack=[expected_values, Type.int])
1✔
71

72
        begin_while = code_generator.convert_begin_while()
1✔
73
        #       push the array to the top of the stack
74
        code_generator.duplicate_stack_top_item()
1✔
75
        code_generator.insert_opcode(Opcode.INC)
1✔
76
        code_generator.duplicate_stack_item(expected_stack_item=expected_values)
1✔
77

78
        #       get the first value that wasn't appended yet
79
        code_generator.move_stack_item_to_top(3)
1✔
80

81
        #       self.append(item)
82
        code_generator.convert_builtin_method_call(Builtin.SequenceAppend, is_internal=True)
1✔
83

84
        #       update stack control
85
        code_generator.insert_opcode(Opcode.DEC)
1✔
86

87
        while_condition = code_generator.bytecode_size
1✔
88
        code_generator.duplicate_stack_top_item()
1✔
89
        #   while there are items to add
90

91
        code_generator.convert_end_while(begin_while, while_condition, is_internal=True)
1✔
92
        #   clear stack
93
        for _ in self.args:
1✔
94
            code_generator.remove_stack_top_item()
1✔
95

96
        code_generator.convert_end_if(else_bytes, is_internal=True)
1✔
97

98
    def push_self_first(self) -> bool:
1✔
99
        return self.has_self_argument
1✔
100

101
    @property
1✔
102
    def _args_on_stack(self) -> int:
1✔
103
        return len(self.args)
1✔
104

105
    @property
1✔
106
    def _body(self) -> Optional[str]:
1✔
107
        return None
×
108

109
    def build(self, value: Any) -> IBuiltinMethod:
1✔
110
        if type(value) == type(self.args['self'].type):
1✔
111
            return self
1✔
112
        if isinstance(value, MutableSequenceType):
1✔
113
            return ExtendMethod(value)
1✔
114
        return super().build(value)
1✔
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

© 2026 Coveralls, Inc