예제 #1
0
def test_get_struct_definition():
    identifier_dict = {
        scope('T'):
        StructDefinition(
            full_name=scope('T'),
            members={
                'a': MemberDefinition(offset=0, cairo_type=TypeFelt()),
                'b': MemberDefinition(offset=1, cairo_type=TypeFelt()),
            },
            size=2,
        ),
        scope('MyConst'):
        ConstDefinition(value=5),
    }

    manager = IdentifierManager.from_dict(identifier_dict)

    struct_def = get_struct_definition(ScopedName.from_string('T'), manager)

    # Convert to a list, to check the order of the elements in the dict.
    assert list(struct_def.members.items()) == [
        ('a', MemberDefinition(offset=0, cairo_type=TypeFelt())),
        ('b', MemberDefinition(offset=1, cairo_type=TypeFelt())),
    ]

    assert struct_def.size == 2

    with pytest.raises(
            DefinitionError,
            match="Expected 'MyConst' to be a struct. Found: 'const'."):
        get_struct_definition(scope('MyConst'), manager)

    with pytest.raises(MissingIdentifierError,
                       match=re.escape("Unknown identifier 'abc'.")):
        get_struct_definition(scope('abc'), manager)
예제 #2
0
def test_type_visitor():
    t = TypeStruct(scope=scope('T'), is_fully_resolved=False)
    t_star = TypePointer(pointee=t)
    t_star2 = TypePointer(pointee=t_star)
    assert simplify_type_system(
        parse_expr('fp + 3 + [ap]')) == (parse_expr('fp + 3 + [ap]'),
                                         TypeFelt())
    assert simplify_type_system(
        parse_expr('cast(fp + 3 + [ap], T*)')) == (parse_expr('fp + 3 + [ap]'),
                                                   t_star)
    # Two casts.
    assert simplify_type_system(
        parse_expr('cast(cast(fp, T*), felt)')) == (parse_expr('fp'),
                                                    TypeFelt())
    # Cast from T to T.
    assert simplify_type_system(
        parse_expr('cast([cast(fp, T*)], T)')) == (parse_expr('[fp]'), t)
    # Dereference.
    assert simplify_type_system(
        parse_expr('[cast(fp, T**)]')) == (parse_expr('[fp]'), t_star)
    assert simplify_type_system(
        parse_expr('[[cast(fp, T**)]]')) == (parse_expr('[[fp]]'), t)
    # Address of.
    assert simplify_type_system(
        parse_expr('&([[cast(fp, T**)]])')) == (parse_expr('[fp]'), t_star)
    assert simplify_type_system(
        parse_expr('&&[[cast(fp, T**)]]')) == (parse_expr('fp'), t_star2)
def test_struct_collector():
    modules = {'module': """
struct S:
    member x : S*
    member y : S*
end
""", '__main__': """
from module import S

func foo{z}(a : S, b) -> (c : S):
    struct T:
        member x : S*
    end
    const X = 5
    return (c=a + X)
end
const Y = 1 + 1
"""}

    scope = ScopedName.from_string

    struct_defs = _collect_struct_definitions(modules)

    expected_def = {
        'module.S': StructDefinition(
            full_name=scope('module.S'),
            members={
                'x': MemberDefinition(offset=0, cairo_type=TypePointer(pointee=TypeStruct(
                    scope=scope('module.S'), is_fully_resolved=True))),
                'y': MemberDefinition(offset=1, cairo_type=TypePointer(pointee=TypeStruct(
                    scope=scope('module.S'), is_fully_resolved=True))),
            }, size=2),
        '__main__.S': AliasDefinition(destination=scope('module.S')),
        '__main__.foo.Args': StructDefinition(
            full_name=scope('__main__.foo.Args'),
            members={
                'a': MemberDefinition(offset=0, cairo_type=TypeStruct(
                    scope=scope('module.S'), is_fully_resolved=True)),
                'b': MemberDefinition(offset=2, cairo_type=TypeFelt()),
            }, size=3),
        '__main__.foo.ImplicitArgs': StructDefinition(
            full_name=scope('__main__.foo.ImplicitArgs'),
            members={'z': MemberDefinition(offset=0, cairo_type=TypeFelt())}, size=1),
        '__main__.foo.Return': StructDefinition(
            full_name=scope('__main__.foo.Return'),
            members={
                'c': MemberDefinition(offset=0, cairo_type=TypeStruct(
                    scope=scope('module.S'), is_fully_resolved=True))
            }, size=2),
        '__main__.foo.T': StructDefinition(
            full_name=scope('__main__.foo.T'),
            members={
                'x': MemberDefinition(offset=0, cairo_type=TypePointer(pointee=TypeStruct(
                    scope=scope('module.S'), is_fully_resolved=True))),
            }, size=1)
    }

    assert struct_defs == expected_def
예제 #4
0
def test_reference_rebinding():
    identifier_values = {
        scope('ref'):
        ReferenceDefinition(
            full_name=scope('ref'),
            cairo_type=TypeFelt(),
            references=[],
        )
    }

    reference_manager = ReferenceManager()
    flow_tracking_data = FlowTrackingDataActual(ap_tracking=RegTrackingData())
    consts = get_vm_consts(identifier_values, reference_manager,
                           flow_tracking_data)
    with pytest.raises(FlowTrackingError, match='Reference ref revoked'):
        consts.ref

    flow_tracking_data = flow_tracking_data.add_reference(
        reference_manager=reference_manager,
        name=scope('ref'),
        ref=Reference(
            pc=10,
            value=parse_expr('10'),
            ap_tracking_data=RegTrackingData(group=0, offset=2),
        ),
    )
    consts = get_vm_consts(identifier_values, reference_manager,
                           flow_tracking_data)
    assert consts.ref == 10
예제 #5
0
def test_revoked_reference():
    reference_manager = ReferenceManager()
    ref_id = reference_manager.alloc_id(reference=Reference(
        pc=0,
        value=parse_expr('[ap + 1]'),
        ap_tracking_data=RegTrackingData(group=0, offset=2),
    ))

    identifier_values = {
        scope('x'):
        ReferenceDefinition(full_name=scope('x'),
                            cairo_type=TypeFelt(),
                            references=[]),
    }
    prime = 2**64 + 13
    ap = 100
    fp = 200
    memory = {}

    flow_tracking_data = FlowTrackingDataActual(
        ap_tracking=RegTrackingData(group=1, offset=4),
        reference_ids={scope('x'): ref_id},
    )
    context = VmConstsContext(
        identifiers=IdentifierManager.from_dict(identifier_values),
        evaluator=ExpressionEvaluator(prime, ap, fp, memory).eval,
        reference_manager=reference_manager,
        flow_tracking_data=flow_tracking_data,
        memory=memory,
        pc=0)
    consts = VmConsts(context=context, accessible_scopes=[ScopedName()])

    with pytest.raises(FlowTrackingError, match='Failed to deduce ap.'):
        assert consts.x
def test_type_tuples():
    t = TypeStruct(scope=scope('T'), is_fully_resolved=True)
    t_star = TypePointer(pointee=t)

    # Simple tuple.
    simplify_type_system_test('(fp, [cast(fp, T*)], cast(fp,T*))',
                              '(fp, [fp], fp)',
                              TypeTuple(members=[TypeFelt(), t, t_star], ))

    # Nested.
    simplify_type_system_test(
        '(fp, (), ([cast(fp, T*)],))', '(fp, (), ([fp],))',
        TypeTuple(members=[
            TypeFelt(),
            TypeTuple(members=[]),
            TypeTuple(members=[t])
        ], ))
def test_type_visitor_pointer_arithmetic():
    t = TypeStruct(scope=scope('T'), is_fully_resolved=True)
    t_star = TypePointer(pointee=t)

    simplify_type_system_test('cast(fp, T*) + 3', 'fp + 3', t_star)
    simplify_type_system_test('cast(fp, T*) - 3', 'fp - 3', t_star)
    simplify_type_system_test('cast(fp, T*) - cast(3, T*)', 'fp - 3',
                              TypeFelt())
예제 #8
0
def test_type_visitor_pointer_arithmetic():
    t = TypeStruct(scope=scope('T'), is_fully_resolved=False)
    t_star = TypePointer(pointee=t)
    assert simplify_type_system(parse_expr('cast(fp, T*) + 3')) == (
        parse_expr('fp + 3'), t_star)
    assert simplify_type_system(parse_expr('cast(fp, T*) - 3')) == (
        parse_expr('fp - 3'), t_star)
    assert simplify_type_system(parse_expr('cast(fp, T*) - cast(3, T*)')) == (
        parse_expr('fp - 3'), TypeFelt())
예제 #9
0
def test_type_tuples():
    t = TypeStruct(scope=scope('T'), is_fully_resolved=False)
    t_star = TypePointer(pointee=t)

    # Simple tuple.
    assert simplify_type_system(parse_expr('(fp, [cast(fp, T*)], cast(fp,T*))')) == (
        parse_expr('(fp, [fp], fp)'), TypeTuple(members=[TypeFelt(), t, t_star],)
    )

    # Nested.
    assert simplify_type_system(parse_expr('(fp, (), ([cast(fp, T*)],))')) == (
        parse_expr('(fp, (), ([fp],))'), TypeTuple(
            members=[
                TypeFelt(),
                TypeTuple(members=[]),
                TypeTuple(members=[t])],
        )
    )
def test_type_visitor():
    t = TypeStruct(scope=scope('T'), is_fully_resolved=True)
    t_star = TypePointer(pointee=t)
    t_star2 = TypePointer(pointee=t_star)

    simplify_type_system_test('fp + 3 + [ap]', 'fp + 3 + [ap]', TypeFelt())
    simplify_type_system_test('cast(fp + 3 + [ap], T*)', 'fp + 3 + [ap]',
                              t_star)
    # Two casts.
    simplify_type_system_test('cast(cast(fp, T*), felt)', 'fp', TypeFelt())
    # Cast from T to T.
    simplify_type_system_test('cast([cast(fp, T*)], T)', '[fp]', t)
    # Dereference.
    simplify_type_system_test('[cast(fp, T**)]', '[fp]', t_star)
    simplify_type_system_test('[[cast(fp, T**)]]', '[[fp]]', t)
    # Address of.
    simplify_type_system_test('&([[cast(fp, T**)]])', '[fp]', t_star)
    simplify_type_system_test('&&[[cast(fp, T**)]]', 'fp', t_star2)
    def visit_ExprNeg(self, expr: ExprNeg) -> Tuple[ExprNeg, TypeFelt]:
        inner_expr, inner_type = self.visit(expr.val)
        if not isinstance(inner_type, TypeFelt):
            raise CairoTypeError(
                f"Unary '-' is not supported for type '{inner_type.format()}'.",
                location=expr.location)

        return dataclasses.replace(
            expr, val=inner_expr), TypeFelt(location=expr.location)
 def visit_ExprDeref(self, expr: ExprDeref) -> Tuple[ExprDeref, CairoType]:
     addr_expr, addr_type = self.visit(expr.addr)
     if isinstance(addr_type, TypeFelt):
         return dataclasses.replace(
             expr, addr=addr_expr), TypeFelt(location=expr.location)
     elif isinstance(addr_type, TypePointer):
         return dataclasses.replace(expr, addr=addr_expr), addr_type.pointee
     else:
         raise CairoTypeError(
             f"Cannot dereference type '{addr_type.format()}'.",
             location=expr.location)
예제 #13
0
def test_process_calldata_failure():
    location = dummy_location()
    with pytest.raises(PreprocessorError,
                       match=re.escape('Unsupported argument type felt**.')):
        process_test_calldata(
            members={
                'arg_a':
                MemberDefinition(
                    offset=0, cairo_type=FELT_STAR_STAR, location=location),
                'arg_b':
                MemberDefinition(
                    offset=1, cairo_type=TypeFelt(), location=location),
            })
    with pytest.raises(
            PreprocessorError,
            match='Array argument "arg_a" must be preceeded by a length '
            'argument named "arg_a_len" of type felt.'):
        process_test_calldata(
            members={
                'arg_a':
                MemberDefinition(
                    offset=0, cairo_type=FELT_STAR, location=location),
                'arg_b':
                MemberDefinition(
                    offset=1, cairo_type=TypeFelt(), location=location),
            })
    with pytest.raises(
            PreprocessorError,
            match=re.escape(
                "The 'range_check' builtin must be declared in the '%builtins' directive when using "
                'array arguments in external functions.')):
        process_test_calldata(members={
            'arg_len':
            MemberDefinition(offset=0,
                             cairo_type=TypeFelt(),
                             location=location),
            'arg':
            MemberDefinition(offset=1, cairo_type=FELT_STAR,
                             location=location),
        },
                              has_range_check_builtin=False)
    def process_retdata(
            self, ret_struct_ptr: Expression, ret_struct_type: CairoType,
            struct_def: StructDefinition,
            location: Optional[Location]) -> Tuple[Expression, Expression]:
        """
        Processes the return values and return retdata_size and retdata_ptr.
        """

        # Verify all of the return types are felts.
        for _, member_def in struct_def.members.items():
            cairo_type = member_def.cairo_type
            if not isinstance(cairo_type, TypeFelt):
                raise PreprocessorError(
                    f'Unsupported argument type {cairo_type.format()}.',
                    location=cairo_type.location)

        self.add_reference(
            name=self.current_scope + 'retdata_ptr',
            value=ExprDeref(
                addr=ExprReg(reg=Register.AP),
                location=location,
            ),
            cairo_type=TypePointer(TypeFelt()),
            require_future_definition=False,
            location=location)

        self.visit(CodeElementHint(
            hint=ExprHint(
                hint_code='memory[ap] = segments.add()',
                n_prefix_newlines=0,
                location=location,
            ),
            location=location,
        ))

        # Skip check of hint whitelist as it fails before the workaround below.
        super().visit_CodeElementInstruction(CodeElementInstruction(InstructionAst(
            body=AddApInstruction(ExprConst(1)),
            inc_ap=False,
            location=location)))

        # Remove the references from the last instruction's flow tracking as they are
        # not needed by the hint and they cause the hint whitelist to fail.
        assert len(self.instructions[-1].hints) == 1
        hint, hint_flow_tracking_data = self.instructions[-1].hints[0]
        self.instructions[-1].hints[0] = hint, dataclasses.replace(
            hint_flow_tracking_data, reference_ids={})
        self.visit(CodeElementCompoundAssertEq(
            ExprDeref(
                ExprCast(ExprIdentifier('retdata_ptr'), TypePointer(ret_struct_type))),
            ret_struct_ptr))

        return (ExprConst(struct_def.size), ExprIdentifier('retdata_ptr'))
def test_struct_sorting():
    orig = StructDefinition(full_name=ScopedName.from_string('T'),
                            members={
                                'b':
                                MemberDefinition(offset=1,
                                                 cairo_type=TypeFelt()),
                                'a':
                                MemberDefinition(offset=0,
                                                 cairo_type=TypeFelt()),
                            },
                            size=2)
    members = orig.members

    assert list(members.items()) != sorted(
        members.items(), key=lambda key_value: key_value[1].offset)

    schema = IdentifierDefinitionSchema()
    loaded = schema.load(schema.dump(orig))
    members = loaded.members
    assert list(members.items()) == sorted(
        members.items(), key=lambda key_value: key_value[1].offset)
def test_type_tuples_failures():
    identifier_dict = {
        scope('T'):
        StructDefinition(
            full_name=scope('T'),
            members={
                'x': MemberDefinition(offset=0, cairo_type=TypeFelt()),
                'y': MemberDefinition(offset=1, cairo_type=TypeFelt()),
            },
            size=2,
        ),
    }
    identifiers = IdentifierManager.from_dict(identifier_dict)

    verify_exception('1 + cast((1, 2), T).x',
                     """
file:?:?: Accessing struct members for r-value structs is not supported yet.
1 + cast((1, 2), T).x
    ^***************^
""",
                     identifiers=identifiers)
    def visit_ExprPow(self,
                      expr: ExprOperator) -> Tuple[ExprOperator, CairoType]:
        a_expr, a_type = self.visit(expr.a)
        b_expr, b_type = self.visit(expr.b)

        if not isinstance(a_type, TypeFelt) and isinstance(b_type, TypeFelt):
            raise CairoTypeError(
                f"Operator '**' is not implemented for types "
                f"'{a_type.format()}' and '{b_type.format()}'.",
                location=expr.location)
        return dataclasses.replace(expr, a=a_expr,
                                   b=b_expr), TypeFelt(location=expr.location)
def test_offset_reference_definition_typed_members():
    t = TypeStruct(scope=scope('T'), is_fully_resolved=True)
    s_star = TypePointer(
        pointee=TypeStruct(scope=scope('S'), is_fully_resolved=True))
    reference_manager = ReferenceManager()
    identifiers = {
        scope('T'): ScopeDefinition(),
        scope('T.x'): MemberDefinition(offset=3, cairo_type=s_star),
        scope('T.flt'): MemberDefinition(offset=4, cairo_type=TypeFelt()),
        scope('S'): ScopeDefinition(),
        scope('S.x'): MemberDefinition(offset=10, cairo_type=t),
    }
    main_reference = ReferenceDefinition(full_name=scope('a'), references=[])
    references = {
        scope('a'):
        reference_manager.get_id(
            Reference(
                pc=0,
                value=mark_types_in_expr_resolved(parse_expr('cast(ap, T*)')),
                ap_tracking_data=RegTrackingData(group=0, offset=0),
            )),
    }

    flow_tracking_data = FlowTrackingDataActual(
        ap_tracking=RegTrackingData(group=0, offset=1),
        reference_ids=references,
    )

    # Create OffsetReferenceDefinition instances for expressions of the form "a.<member_path>",
    # such as a.x and a.x.x, and check the result of evaluation those expressions.
    for member_path, expected_result in [
        ('x', 'cast([ap - 1 + 3], S*)'),
        ('x.x', 'cast([[ap - 1 + 3] + 10], T)'),
        ('x.x.x', 'cast([&[[ap - 1 + 3] + 10] + 3], S*)'),
        ('x.x.flt', 'cast([&[[ap - 1 + 3] + 10] + 4], felt)')
    ]:
        definition = OffsetReferenceDefinition(parent=main_reference,
                                               identifier_values=identifiers,
                                               member_path=scope(member_path))
        assert definition.eval(
            reference_manager=reference_manager,
            flow_tracking_data=flow_tracking_data).format() == expected_result

    definition = OffsetReferenceDefinition(parent=main_reference,
                                           identifier_values=identifiers,
                                           member_path=scope('x.x.flt.x'))
    with pytest.raises(
            DefinitionError,
            match='Member access requires a type of the form Struct*.'):
        assert definition.eval(
            reference_manager=reference_manager,
            flow_tracking_data=flow_tracking_data).format() == expected_result
예제 #19
0
    def wrap(self, expr: Expression) -> ExprIdentifier:
        identifier = ExprIdentifier(name=self.context.new_tempvar_name(),
                                    location=expr.location)

        expr = self.translate_ap(expr)
        self.n_vars += 1

        self.code_elements.append(
            CodeElementTemporaryVariable(typed_identifier=TypedIdentifier(
                identifier=identifier,
                expr_type=TypeFelt(location=expr.location)),
                                         expr=expr,
                                         location=expr.location))
        return identifier
def test_resolve_search_result():
    struct_def = StructDefinition(
        full_name=scope('T'),
        members={
            'a': MemberDefinition(offset=0, cairo_type=TypeFelt()),
            'b': MemberDefinition(offset=1, cairo_type=TypeFelt()),
        },
        size=2,
    )

    identifier_dict = {
        struct_def.full_name: struct_def,
    }

    identifier = IdentifierManager.from_dict(identifier_dict)

    with pytest.raises(IdentifierError,
                       match="Unexpected '.' after 'T.a' which is member"):
        resolve_search_result(search_result=IdentifierSearchResult(
            identifier_definition=struct_def,
            canonical_name=struct_def.full_name,
            non_parsed=scope('a.z')),
                              identifiers=identifier)
예제 #21
0
def test_process_calldata_flow():
    location = dummy_location()
    code_elements, expr = process_test_calldata(
        members={
            'a_len':
            MemberDefinition(
                offset=0, cairo_type=TypeFelt(), location=location),
            'a':
            MemberDefinition(offset=1, cairo_type=FELT_STAR,
                             location=location),
            'b':
            MemberDefinition(
                offset=2, cairo_type=TypeFelt(), location=location),
        })

    assert ''.join(
        code_element.format(100) + '\n'
        for code_element in code_elements) == """\
let __calldata_ptr : felt* = cast(calldata_ptr, felt*)
let __calldata_arg_a_len = [__calldata_ptr]
let __calldata_ptr = __calldata_ptr + 1
assert [range_check_ptr] = __calldata_arg_a_len
let range_check_ptr = range_check_ptr + 1
let __calldata_arg_a : felt* = __calldata_ptr
tempvar __calldata_ptr = __calldata_ptr + __calldata_arg_a_len
let __calldata_arg_b = [__calldata_ptr]
let __calldata_ptr = __calldata_ptr + 1
let __calldata_actual_size = __calldata_ptr - cast(calldata_ptr, felt*)
assert calldata_size = __calldata_actual_size
"""

    assert expr.format(
    ) == 'a_len=__calldata_arg_a_len, a=__calldata_arg_a, b=__calldata_arg_b,'

    assert code_elements[0].expr.location.parent_location == (
        location, 'While handling calldata of')
    def visit_ExprOperator(
            self, expr: ExprOperator) -> Tuple[ExprOperator, CairoType]:
        a_expr, a_type = self.visit(expr.a)
        b_expr, b_type = self.visit(expr.b)
        op = expr.op

        result_type: CairoType
        if isinstance(a_type, TypeFelt) and isinstance(b_type, TypeFelt):
            result_type = TypeFelt(location=expr.location)
        elif isinstance(a_type, TypePointer) and isinstance(
                b_type, TypeFelt) and op in ['+', '-']:
            result_type = a_type
        elif isinstance(a_type, TypeFelt) and isinstance(
                b_type, TypePointer) and op == '+':
            result_type = b_type
        elif isinstance(a_type,
                        TypePointer) and a_type == b_type and op == '-':
            result_type = TypeFelt(location=expr.location)
        else:
            raise CairoTypeError(
                f"Operator '{op}' is not implemented for types "
                f"'{a_type.format()}' and '{b_type.format()}'.",
                location=expr.location)
        return dataclasses.replace(expr, a=a_expr, b=b_expr), result_type
예제 #23
0
def test_get_struct_members():
    identifier_dict = {
        scope('T.b'): MemberDefinition(offset=1, cairo_type=TypeFelt()),
        scope('T.a'): MemberDefinition(offset=0, cairo_type=TypeFelt()),
        scope('T.SIZE'): ConstDefinition(value=2),
        scope('S.a'): MemberDefinition(offset=0, cairo_type=TypeFelt()),
        scope('S.c'): MemberDefinition(offset=1, cairo_type=TypeFelt()),
        scope('S.SIZE'): ConstDefinition(value=2),
    }
    manager = IdentifierManager.from_dict(identifier_dict)

    member = get_struct_members(scope('T'), manager)
    # Convert to a list, to check the order of the elements in the dict.
    assert list(member.items()) == [
        ('a', MemberDefinition(offset=0, cairo_type=TypeFelt())),
        ('b', MemberDefinition(offset=1, cairo_type=TypeFelt())),
    ]
예제 #24
0
 def type_felt(self, value, meta):
     return TypeFelt(location=self.meta2loc(meta))
예제 #25
0
import itertools
from typing import Optional

from starkware.cairo.lang.compiler.ast.cairo_types import (CairoType, CastType,
                                                           TypeFelt,
                                                           TypePointer,
                                                           TypeStruct,
                                                           TypeTuple)
from starkware.cairo.lang.compiler.ast.expr import ExprDeref, Expression, ExprTuple
from starkware.cairo.lang.compiler.error_handling import LocationError
from starkware.cairo.lang.compiler.identifier_manager import IdentifierManager
from starkware.cairo.lang.compiler.identifier_utils import get_struct_definition

FELT_STAR = TypePointer(pointee=TypeFelt())


class CairoTypeError(LocationError):
    pass


def check_cast(src_type: CairoType,
               dest_type: CairoType,
               identifier_manager: IdentifierManager,
               expr: Optional[Expression] = None,
               cast_type: CastType = CastType.EXPLICIT) -> bool:
    """
    Returns true if the given expression can be casted from src_type to dest_type
    according to the given 'cast_type'.
    In some cases of cast failure, an exception with more specific details is raised.

    'expr' must be specified (not None) when CastType.EXPLICIT (or above) is used.
예제 #26
0
 def get_type(self) -> CairoType:
     """
     Returns the type of the identifier. If not specified, the default type is felt (TypeFelt).
     """
     return TypeFelt(location=self.location
                     ) if self.expr_type is None else self.expr_type
예제 #27
0
def test_type_tuple():
    typ = parse_type('(felt)')
    assert typ == TypeTuple(members=[TypeFelt()])
    assert typ.format() == '(felt)'
    assert parse_type('( felt, felt* , (felt, T.S,)* )').format(
    ) == '(felt, felt*, (felt, T.S)*)'
 def visit_ExprReg(self, expr: ExprReg) -> Tuple[ExprReg, TypeFelt]:
     return expr, TypeFelt(location=expr.location)
예제 #29
0
def test_references():
    reference_manager = ReferenceManager()
    references = {
        scope('x.ref'):
        reference_manager.get_id(
            Reference(
                pc=0,
                value=parse_expr('[ap + 1]'),
                ap_tracking_data=RegTrackingData(group=0, offset=2),
            )),
        scope('x.ref2'):
        reference_manager.get_id(
            Reference(
                pc=0,
                value=parse_expr('[ap + 1] + 0'),
                ap_tracking_data=RegTrackingData(group=0, offset=2),
            )),
        scope('x.ref3'):
        reference_manager.get_id(
            Reference(
                pc=0,
                value=parse_expr('ap + 1'),
                ap_tracking_data=RegTrackingData(group=0, offset=2),
            )),
        scope('x.typeref'):
        reference_manager.get_id(
            Reference(
                pc=0,
                value=mark_types_in_expr_resolved(
                    parse_expr('cast(ap + 1, a*)')),
                ap_tracking_data=RegTrackingData(group=0, offset=3),
            )),
        scope('x.typeref2'):
        reference_manager.get_id(
            Reference(
                pc=0,
                value=mark_types_in_expr_resolved(
                    parse_expr('cast([ap + 1], a*)')),
                ap_tracking_data=RegTrackingData(group=0, offset=3),
            )),
    }
    identifier_values = {
        scope('x.ref'):
        ReferenceDefinition(full_name=scope('x.ref'), references=[]),
        scope('x.ref2'):
        ReferenceDefinition(full_name=scope('x.ref2'), references=[]),
        scope('x.ref3'):
        ReferenceDefinition(full_name=scope('x.ref3'), references=[]),
        scope('x.typeref'):
        ReferenceDefinition(full_name=scope('x.typeref'), references=[]),
        scope('x.typeref2'):
        ReferenceDefinition(full_name=scope('x.typeref2'), references=[]),
        scope('a.member'):
        MemberDefinition(offset=10, cairo_type=TypeFelt()),
        scope('a.scope0.member'):
        MemberDefinition(offset=2, cairo_type=TypeFelt()),
    }
    prime = 2**64 + 13
    ap = 100
    fp = 200
    memory = {
        (ap - 2) + 1: 1234,
        (ap - 1) + 1: 1000,
        (ap - 1) + 1 + 2: 13,
        (ap - 1) + 1 + 10: 17,
    }

    flow_tracking_data = FlowTrackingDataActual(
        ap_tracking=RegTrackingData(group=0, offset=4),
        reference_ids=references,
    )
    context = VmConstsContext(
        identifiers=IdentifierManager.from_dict(identifier_values),
        evaluator=ExpressionEvaluator(prime, ap, fp, memory).eval,
        reference_manager=reference_manager,
        flow_tracking_data=flow_tracking_data,
        memory=memory,
        pc=0)
    consts = VmConsts(context=context, accessible_scopes=[ScopedName()])

    assert consts.x.ref == memory[(ap - 2) + 1]
    assert consts.x.typeref.address_ == (ap - 1) + 1
    assert consts.x.typeref.member == memory[(ap - 1) + 1 + 10]
    with pytest.raises(
            NotImplementedError,
            match="Expected a member, found 'scope0' which is 'scope'"):
        consts.x.typeref.scope0

    # Test that VmConsts can be used to assign values to references of the form '[...]'.
    memory.clear()

    consts.x.ref = 1234
    assert memory == {(ap - 2) + 1: 1234}

    memory.clear()
    consts.x.typeref.member = 1001
    assert memory == {(ap - 1) + 1 + 10: 1001}

    memory.clear()
    consts.x.typeref2 = 4321
    assert memory == {(ap - 1) + 1: 4321}

    consts.x.typeref2.member = 1
    assert memory == {
        (ap - 1) + 1: 4321,
        4321 + 10: 1,
    }

    with pytest.raises(AssertionError,
                       match='Cannot change the value of a scope definition'):
        consts.x = 1000
    with pytest.raises(
            AssertionError,
            match=
            r'x.ref2 \(= \[ap \+ 1\] \+ 0\) does not reference memory and cannot be assigned.',
    ):
        consts.x.ref2 = 1000
    with pytest.raises(
            AssertionError,
            match=
            r'x.typeref \(= ap \+ 1\) does not reference memory and cannot be assigned.',
    ):
        consts.x.typeref = 1000
예제 #30
0
def test_references():
    reference_manager = ReferenceManager()
    references = {
        scope('x.ref'):
        reference_manager.alloc_id(
            Reference(
                pc=0,
                value=parse_expr('[ap + 1]'),
                ap_tracking_data=RegTrackingData(group=0, offset=2),
            )),
        scope('x.ref2'):
        reference_manager.alloc_id(
            Reference(
                pc=0,
                value=parse_expr('[ap + 1] + 0'),
                ap_tracking_data=RegTrackingData(group=0, offset=2),
            )),
        scope('x.ref3'):
        reference_manager.alloc_id(
            Reference(
                pc=0,
                value=parse_expr('ap + 1'),
                ap_tracking_data=RegTrackingData(group=0, offset=2),
            )),
        scope('x.typeref'):
        reference_manager.alloc_id(
            Reference(
                pc=0,
                value=mark_types_in_expr_resolved(
                    parse_expr('cast(ap + 1, MyStruct*)')),
                ap_tracking_data=RegTrackingData(group=0, offset=3),
            )),
        scope('x.typeref2'):
        reference_manager.alloc_id(
            Reference(
                pc=0,
                value=mark_types_in_expr_resolved(
                    parse_expr('cast([ap + 1], MyStruct*)')),
                ap_tracking_data=RegTrackingData(group=0, offset=3),
            )),
    }
    my_struct_star = TypePointer(
        pointee=TypeStruct(scope=scope('MyStruct'), is_fully_resolved=True))
    identifier_values = {
        scope('x.ref'):
        ReferenceDefinition(full_name=scope('x.ref'),
                            cairo_type=TypeFelt(),
                            references=[]),
        scope('x.ref2'):
        ReferenceDefinition(full_name=scope('x.ref2'),
                            cairo_type=TypeFelt(),
                            references=[]),
        scope('x.ref3'):
        ReferenceDefinition(full_name=scope('x.ref3'),
                            cairo_type=TypeFelt(),
                            references=[]),
        scope('x.typeref'):
        ReferenceDefinition(full_name=scope('x.typeref'),
                            cairo_type=my_struct_star,
                            references=[]),
        scope('x.typeref2'):
        ReferenceDefinition(full_name=scope('x.typeref2'),
                            cairo_type=my_struct_star,
                            references=[]),
        scope('MyStruct'):
        StructDefinition(
            full_name=scope('MyStruct'),
            members={
                'member': MemberDefinition(offset=10, cairo_type=TypeFelt()),
            },
            size=11,
        ),
    }
    prime = 2**64 + 13
    ap = 100
    fp = 200
    memory = {
        (ap - 2) + 1: 1234,
        (ap - 1) + 1: 1000,
        (ap - 1) + 1 + 2: 13,
        (ap - 1) + 1 + 10: 17,
    }

    flow_tracking_data = FlowTrackingDataActual(
        ap_tracking=RegTrackingData(group=0, offset=4),
        reference_ids=references,
    )
    context = VmConstsContext(
        identifiers=IdentifierManager.from_dict(identifier_values),
        evaluator=ExpressionEvaluator(prime, ap, fp, memory).eval,
        reference_manager=reference_manager,
        flow_tracking_data=flow_tracking_data,
        memory=memory,
        pc=0)
    consts = VmConsts(context=context, accessible_scopes=[ScopedName()])

    assert consts.x.ref == memory[(ap - 2) + 1]
    assert consts.x.typeref.address_ == (ap - 1) + 1
    assert consts.x.typeref.member == memory[(ap - 1) + 1 + 10]
    with pytest.raises(IdentifierError,
                       match="'abc' is not a member of 'MyStruct'."):
        consts.x.typeref.abc

    with pytest.raises(IdentifierError,
                       match="'SIZE' is not a member of 'MyStruct'."):
        consts.x.typeref.SIZE

    with pytest.raises(
            AssertionError,
            match='Cannot change the value of a struct definition.'):
        consts.MyStruct = 13

    assert consts.MyStruct.member == 10
    with pytest.raises(AssertionError,
                       match='Cannot change the value of a constant.'):
        consts.MyStruct.member = 13

    assert consts.MyStruct.SIZE == 11
    with pytest.raises(AssertionError,
                       match='Cannot change the value of a constant.'):
        consts.MyStruct.SIZE = 13

    with pytest.raises(IdentifierError,
                       match="'abc' is not a member of 'MyStruct'."):
        consts.MyStruct.abc

    # Test that VmConsts can be used to assign values to references of the form '[...]'.
    memory.clear()

    consts.x.ref = 1234
    assert memory == {(ap - 2) + 1: 1234}

    memory.clear()
    consts.x.typeref.member = 1001
    assert memory == {(ap - 1) + 1 + 10: 1001}

    memory.clear()
    consts.x.typeref2 = 4321
    assert memory == {(ap - 1) + 1: 4321}

    consts.x.typeref2.member = 1
    assert memory == {
        (ap - 1) + 1: 4321,
        4321 + 10: 1,
    }

    with pytest.raises(AssertionError,
                       match='Cannot change the value of a scope definition'):
        consts.x = 1000
    with pytest.raises(
            AssertionError,
            match=
            r'x.ref2 \(= \[ap \+ 1\] \+ 0\) does not reference memory and cannot be assigned.',
    ):
        consts.x.ref2 = 1000
    with pytest.raises(
            AssertionError,
            match=
            r'x.typeref \(= ap \+ 1\) does not reference memory and cannot be assigned.',
    ):
        consts.x.typeref = 1000