From b48a7d4b976c3471a287a735bd4c6db443856e41 Mon Sep 17 00:00:00 2001 From: Tristan Menzel Date: Fri, 22 Nov 2024 11:07:01 -0800 Subject: [PATCH 1/3] fix: Identify WTuples by name when treating them as structs in an ABI method --- examples/sizes.txt | 3 +- src/puya/ir/main.py | 12 +- test_cases/struct_by_name/contract.py | 39 + .../out/DemoContract.approval.teal | 151 ++++ .../out/DemoContract.arc32.json | 107 +++ .../out/DemoContract.arc56.json | 162 ++++ .../out/DemoContract.clear.teal | 5 + .../out/DemoContract.destructured.ir | 79 ++ .../struct_by_name/out/DemoContract.ssa.ir | 106 +++ .../out/DemoContract.ssa.opt_pass_1.ir | 81 ++ .../out/DemoContract.ssa.opt_pass_2.ir | 79 ++ .../struct_by_name/out/client_DemoContract.py | 37 + test_cases/struct_by_name/out/module.awst | 35 + .../out_O2/DemoContract.approval.teal | 110 +++ .../out_O2/DemoContract.clear.teal | 5 + .../out_O2/DemoContract.destructured.ir | 79 ++ .../DemoContract.approval.teal | 193 +++++ .../out_unoptimized/DemoContract.clear.teal | 5 + .../DemoContract.destructured.ir | 102 +++ test_cases/struct_by_name/puya.log | 815 ++++++++++++++++++ 20 files changed, 2197 insertions(+), 8 deletions(-) create mode 100644 test_cases/struct_by_name/contract.py create mode 100644 test_cases/struct_by_name/out/DemoContract.approval.teal create mode 100644 test_cases/struct_by_name/out/DemoContract.arc32.json create mode 100644 test_cases/struct_by_name/out/DemoContract.arc56.json create mode 100644 test_cases/struct_by_name/out/DemoContract.clear.teal create mode 100644 test_cases/struct_by_name/out/DemoContract.destructured.ir create mode 100644 test_cases/struct_by_name/out/DemoContract.ssa.ir create mode 100644 test_cases/struct_by_name/out/DemoContract.ssa.opt_pass_1.ir create mode 100644 test_cases/struct_by_name/out/DemoContract.ssa.opt_pass_2.ir create mode 100644 test_cases/struct_by_name/out/client_DemoContract.py create mode 100644 test_cases/struct_by_name/out/module.awst create mode 100644 test_cases/struct_by_name/out_O2/DemoContract.approval.teal create mode 100644 test_cases/struct_by_name/out_O2/DemoContract.clear.teal create mode 100644 test_cases/struct_by_name/out_O2/DemoContract.destructured.ir create mode 100644 test_cases/struct_by_name/out_unoptimized/DemoContract.approval.teal create mode 100644 test_cases/struct_by_name/out_unoptimized/DemoContract.clear.teal create mode 100644 test_cases/struct_by_name/out_unoptimized/DemoContract.destructured.ir create mode 100644 test_cases/struct_by_name/puya.log diff --git a/examples/sizes.txt b/examples/sizes.txt index 8b47810865..6b4cadd5eb 100644 --- a/examples/sizes.txt +++ b/examples/sizes.txt @@ -112,6 +112,7 @@ state_totals 65 32 - | 32 16 - stress_tests/BruteForceRotationSearch 228 163 - | 152 106 - string_ops 156 154 - | 58 55 - + struct_by_name/Demo 205 161 - | 115 83 - struct_in_box/Example 242 206 - | 127 99 - stubs/BigUInt 192 121 - | 126 73 - stubs/Bytes 944 279 - | 606 153 - @@ -134,4 +135,4 @@ unssa/UnSSA 432 368 - | 241 204 - voting/VotingRoundApp 1580 1475 - | 727 644 - with_reentrancy/WithReentrancy 245 234 - | 126 117 - - Total 70231 54641 54582 | 33265 22305 22261 \ No newline at end of file + Total 70436 54802 54743 | 33380 22388 22344 \ No newline at end of file diff --git a/src/puya/ir/main.py b/src/puya/ir/main.py index 11c03902a3..56466162f6 100644 --- a/src/puya/ir/main.py +++ b/src/puya/ir/main.py @@ -573,20 +573,18 @@ def _wtypes_to_structs( Will recursively include any structs referenced in fields """ structs = list(structs) - struct_results = dict[wtypes.ARC4Struct | wtypes.WTuple, ARC4Struct]() + struct_results = dict[str, ARC4Struct]() while structs: struct = structs.pop() - if struct in struct_results: + if struct.name in struct_results: continue structs.extend( wtype for wtype in struct.fields.values() - if isinstance(wtype, wtypes.ARC4Struct) and wtype not in struct_results + if isinstance(wtype, wtypes.ARC4Struct) and wtype.name not in struct_results ) - struct_results[struct] = _wtype_to_struct(struct) - return { - wtype.name: struct_results[wtype] for wtype in sorted(struct_results, key=lambda s: s.name) - } + struct_results[struct.name] = _wtype_to_struct(struct) + return dict(sorted(struct_results.items(), key=lambda item: item[0])) def _wtype_to_struct(struct: wtypes.ARC4Struct | wtypes.WTuple) -> ARC4Struct: diff --git a/test_cases/struct_by_name/contract.py b/test_cases/struct_by_name/contract.py new file mode 100644 index 0000000000..39c8772de3 --- /dev/null +++ b/test_cases/struct_by_name/contract.py @@ -0,0 +1,39 @@ +import typing + +from algopy import ARC4Contract, arc4 + + +class StructOne(typing.NamedTuple): + x: arc4.UInt8 + y: arc4.UInt8 + + +class StructTwo(typing.NamedTuple): + x: arc4.UInt8 + y: arc4.UInt8 + + +class DemoContract(ARC4Contract): + """ + Verify that even though named tuples with different names but the same structure should be + considered 'comparable' in the type system, they should be output separately when being + interpreted as an arc4 Struct in an abi method + """ + + @arc4.abimethod() + def get_one(self) -> StructOne: + return StructOne( + x=arc4.UInt8(1), + y=arc4.UInt8(1), + ) + + @arc4.abimethod() + def get_two(self) -> StructTwo: + return StructTwo( + x=arc4.UInt8(1), + y=arc4.UInt8(1), + ) + + @arc4.abimethod() + def compare(self) -> bool: + return self.get_one() == self.get_two() diff --git a/test_cases/struct_by_name/out/DemoContract.approval.teal b/test_cases/struct_by_name/out/DemoContract.approval.teal new file mode 100644 index 0000000000..3cb930abcf --- /dev/null +++ b/test_cases/struct_by_name/out/DemoContract.approval.teal @@ -0,0 +1,151 @@ +#pragma version 10 + +test_cases.struct_by_name.contract.DemoContract.approval_program: + intcblock 1 0 + bytecblock 0x151f7c75 0x01 + callsub __puya_arc4_router__ + return + + +// test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__() -> uint64: +__puya_arc4_router__: + // struct_by_name/contract.py:16 + // class DemoContract(ARC4Contract): + proto 0 1 + txn NumAppArgs + bz __puya_arc4_router___bare_routing@7 + pushbytess 0x3d694b70 0x7fb34e8a 0x46dadea3 // method "get_one()(uint8,uint8)", method "get_two()(uint8,uint8)", method "compare()bool" + txna ApplicationArgs 0 + match __puya_arc4_router___get_one_route@2 __puya_arc4_router___get_two_route@3 __puya_arc4_router___compare_route@4 + intc_1 // 0 + retsub + +__puya_arc4_router___get_one_route@2: + // struct_by_name/contract.py:23 + // @arc4.abimethod() + txn OnCompletion + ! + assert // OnCompletion is not NoOp + txn ApplicationID + assert // can only call when not creating + callsub get_one + concat + bytec_0 // 0x151f7c75 + swap + concat + log + intc_0 // 1 + retsub + +__puya_arc4_router___get_two_route@3: + // struct_by_name/contract.py:30 + // @arc4.abimethod() + txn OnCompletion + ! + assert // OnCompletion is not NoOp + txn ApplicationID + assert // can only call when not creating + callsub get_two + concat + bytec_0 // 0x151f7c75 + swap + concat + log + intc_0 // 1 + retsub + +__puya_arc4_router___compare_route@4: + // struct_by_name/contract.py:37 + // @arc4.abimethod() + txn OnCompletion + ! + assert // OnCompletion is not NoOp + txn ApplicationID + assert // can only call when not creating + callsub compare + pushbytes 0x00 + intc_1 // 0 + uncover 2 + setbit + bytec_0 // 0x151f7c75 + swap + concat + log + intc_0 // 1 + retsub + +__puya_arc4_router___bare_routing@7: + // struct_by_name/contract.py:16 + // class DemoContract(ARC4Contract): + txn OnCompletion + bnz __puya_arc4_router___after_if_else@11 + txn ApplicationID + ! + assert // can only call when creating + intc_0 // 1 + retsub + +__puya_arc4_router___after_if_else@11: + // struct_by_name/contract.py:16 + // class DemoContract(ARC4Contract): + intc_1 // 0 + retsub + + +// test_cases.struct_by_name.contract.DemoContract.get_one() -> bytes, bytes: +get_one: + // struct_by_name/contract.py:23-24 + // @arc4.abimethod() + // def get_one(self) -> StructOne: + proto 0 2 + // struct_by_name/contract.py:26 + // x=arc4.UInt8(1), + bytec_1 // 0x01 + // struct_by_name/contract.py:27 + // y=arc4.UInt8(1), + dup + // struct_by_name/contract.py:25-28 + // return StructOne( + // x=arc4.UInt8(1), + // y=arc4.UInt8(1), + // ) + retsub + + +// test_cases.struct_by_name.contract.DemoContract.get_two() -> bytes, bytes: +get_two: + // struct_by_name/contract.py:30-31 + // @arc4.abimethod() + // def get_two(self) -> StructTwo: + proto 0 2 + // struct_by_name/contract.py:33 + // x=arc4.UInt8(1), + bytec_1 // 0x01 + // struct_by_name/contract.py:34 + // y=arc4.UInt8(1), + dup + // struct_by_name/contract.py:32-35 + // return StructTwo( + // x=arc4.UInt8(1), + // y=arc4.UInt8(1), + // ) + retsub + + +// test_cases.struct_by_name.contract.DemoContract.compare() -> uint64: +compare: + // struct_by_name/contract.py:37-38 + // @arc4.abimethod() + // def compare(self) -> bool: + proto 0 1 + // struct_by_name/contract.py:39 + // return self.get_one() == self.get_two() + callsub get_one + callsub get_two + uncover 3 + uncover 2 + b== + cover 2 + b== + && + retsub diff --git a/test_cases/struct_by_name/out/DemoContract.arc32.json b/test_cases/struct_by_name/out/DemoContract.arc32.json new file mode 100644 index 0000000000..b11118a0a3 --- /dev/null +++ b/test_cases/struct_by_name/out/DemoContract.arc32.json @@ -0,0 +1,107 @@ +{ + "hints": { + "get_one()(uint8,uint8)": { + "call_config": { + "no_op": "CALL" + }, + "structs": { + "output": { + "name": "StructOne", + "elements": [ + [ + "x", + "uint8" + ], + [ + "y", + "uint8" + ] + ] + } + } + }, + "get_two()(uint8,uint8)": { + "call_config": { + "no_op": "CALL" + }, + "structs": { + "output": { + "name": "StructTwo", + "elements": [ + [ + "x", + "uint8" + ], + [ + "y", + "uint8" + ] + ] + } + } + }, + "compare()bool": { + "call_config": { + "no_op": "CALL" + } + } + }, + "source": { + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgp0ZXN0X2Nhc2VzLnN0cnVjdF9ieV9uYW1lLmNvbnRyYWN0LkRlbW9Db250cmFjdC5hcHByb3ZhbF9wcm9ncmFtOgogICAgaW50Y2Jsb2NrIDEgMAogICAgYnl0ZWNibG9jayAweDE1MWY3Yzc1IDB4MDEKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHRlc3RfY2FzZXMuc3RydWN0X2J5X25hbWUuY29udHJhY3QuRGVtb0NvbnRyYWN0Ll9fcHV5YV9hcmM0X3JvdXRlcl9fKCkgLT4gdWludDY0OgpfX3B1eWFfYXJjNF9yb3V0ZXJfXzoKICAgIC8vIHN0cnVjdF9ieV9uYW1lL2NvbnRyYWN0LnB5OjE2CiAgICAvLyBjbGFzcyBEZW1vQ29udHJhY3QoQVJDNENvbnRyYWN0KToKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A3CiAgICBwdXNoYnl0ZXNzIDB4M2Q2OTRiNzAgMHg3ZmIzNGU4YSAweDQ2ZGFkZWEzIC8vIG1ldGhvZCAiZ2V0X29uZSgpKHVpbnQ4LHVpbnQ4KSIsIG1ldGhvZCAiZ2V0X3R3bygpKHVpbnQ4LHVpbnQ4KSIsIG1ldGhvZCAiY29tcGFyZSgpYm9vbCIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2dldF9vbmVfcm91dGVAMiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19nZXRfdHdvX3JvdXRlQDMgX19wdXlhX2FyYzRfcm91dGVyX19fY29tcGFyZV9yb3V0ZUA0CiAgICBpbnRjXzEgLy8gMAogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19nZXRfb25lX3JvdXRlQDI6CiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weToyMwogICAgLy8gQGFyYzQuYWJpbWV0aG9kKCkKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgbm90IE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gY2FuIG9ubHkgY2FsbCB3aGVuIG5vdCBjcmVhdGluZwogICAgY2FsbHN1YiBnZXRfb25lCiAgICBjb25jYXQKICAgIGJ5dGVjXzAgLy8gMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludGNfMCAvLyAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2dldF90d29fcm91dGVAMzoKICAgIC8vIHN0cnVjdF9ieV9uYW1lL2NvbnRyYWN0LnB5OjMwCiAgICAvLyBAYXJjNC5hYmltZXRob2QoKQogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBub3QgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBjYW4gb25seSBjYWxsIHdoZW4gbm90IGNyZWF0aW5nCiAgICBjYWxsc3ViIGdldF90d28KICAgIGNvbmNhdAogICAgYnl0ZWNfMCAvLyAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50Y18wIC8vIDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fY29tcGFyZV9yb3V0ZUA0OgogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MzcKICAgIC8vIEBhcmM0LmFiaW1ldGhvZCgpCiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIG5vdCBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGNhbiBvbmx5IGNhbGwgd2hlbiBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgY29tcGFyZQogICAgcHVzaGJ5dGVzIDB4MDAKICAgIGludGNfMSAvLyAwCiAgICB1bmNvdmVyIDIKICAgIHNldGJpdAogICAgYnl0ZWNfMCAvLyAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50Y18wIC8vIDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDc6CiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weToxNgogICAgLy8gY2xhc3MgRGVtb0NvbnRyYWN0KEFSQzRDb250cmFjdCk6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMQogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBjYW4gb25seSBjYWxsIHdoZW4gY3JlYXRpbmcKICAgIGludGNfMCAvLyAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTE6CiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weToxNgogICAgLy8gY2xhc3MgRGVtb0NvbnRyYWN0KEFSQzRDb250cmFjdCk6CiAgICBpbnRjXzEgLy8gMAogICAgcmV0c3ViCgoKLy8gdGVzdF9jYXNlcy5zdHJ1Y3RfYnlfbmFtZS5jb250cmFjdC5EZW1vQ29udHJhY3QuZ2V0X29uZSgpIC0+IGJ5dGVzLCBieXRlczoKZ2V0X29uZToKICAgIC8vIHN0cnVjdF9ieV9uYW1lL2NvbnRyYWN0LnB5OjIzLTI0CiAgICAvLyBAYXJjNC5hYmltZXRob2QoKQogICAgLy8gZGVmIGdldF9vbmUoc2VsZikgLT4gU3RydWN0T25lOgogICAgcHJvdG8gMCAyCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weToyNgogICAgLy8geD1hcmM0LlVJbnQ4KDEpLAogICAgYnl0ZWNfMSAvLyAweDAxCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weToyNwogICAgLy8geT1hcmM0LlVJbnQ4KDEpLAogICAgZHVwCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weToyNS0yOAogICAgLy8gcmV0dXJuIFN0cnVjdE9uZSgKICAgIC8vICAgICB4PWFyYzQuVUludDgoMSksCiAgICAvLyAgICAgeT1hcmM0LlVJbnQ4KDEpLAogICAgLy8gKQogICAgcmV0c3ViCgoKLy8gdGVzdF9jYXNlcy5zdHJ1Y3RfYnlfbmFtZS5jb250cmFjdC5EZW1vQ29udHJhY3QuZ2V0X3R3bygpIC0+IGJ5dGVzLCBieXRlczoKZ2V0X3R3bzoKICAgIC8vIHN0cnVjdF9ieV9uYW1lL2NvbnRyYWN0LnB5OjMwLTMxCiAgICAvLyBAYXJjNC5hYmltZXRob2QoKQogICAgLy8gZGVmIGdldF90d28oc2VsZikgLT4gU3RydWN0VHdvOgogICAgcHJvdG8gMCAyCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weTozMwogICAgLy8geD1hcmM0LlVJbnQ4KDEpLAogICAgYnl0ZWNfMSAvLyAweDAxCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weTozNAogICAgLy8geT1hcmM0LlVJbnQ4KDEpLAogICAgZHVwCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weTozMi0zNQogICAgLy8gcmV0dXJuIFN0cnVjdFR3bygKICAgIC8vICAgICB4PWFyYzQuVUludDgoMSksCiAgICAvLyAgICAgeT1hcmM0LlVJbnQ4KDEpLAogICAgLy8gKQogICAgcmV0c3ViCgoKLy8gdGVzdF9jYXNlcy5zdHJ1Y3RfYnlfbmFtZS5jb250cmFjdC5EZW1vQ29udHJhY3QuY29tcGFyZSgpIC0+IHVpbnQ2NDoKY29tcGFyZToKICAgIC8vIHN0cnVjdF9ieV9uYW1lL2NvbnRyYWN0LnB5OjM3LTM4CiAgICAvLyBAYXJjNC5hYmltZXRob2QoKQogICAgLy8gZGVmIGNvbXBhcmUoc2VsZikgLT4gYm9vbDoKICAgIHByb3RvIDAgMQogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MzkKICAgIC8vIHJldHVybiBzZWxmLmdldF9vbmUoKSA9PSBzZWxmLmdldF90d28oKQogICAgY2FsbHN1YiBnZXRfb25lCiAgICBjYWxsc3ViIGdldF90d28KICAgIHVuY292ZXIgMwogICAgdW5jb3ZlciAyCiAgICBiPT0KICAgIGNvdmVyIDIKICAgIGI9PQogICAgJiYKICAgIHJldHN1Ygo=", + "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgp0ZXN0X2Nhc2VzLnN0cnVjdF9ieV9uYW1lLmNvbnRyYWN0LkRlbW9Db250cmFjdC5jbGVhcl9zdGF0ZV9wcm9ncmFtOgogICAgcHVzaGludCAxIC8vIDEKICAgIHJldHVybgo=" + }, + "state": { + "global": { + "num_byte_slices": 0, + "num_uints": 0 + }, + "local": { + "num_byte_slices": 0, + "num_uints": 0 + } + }, + "schema": { + "global": { + "declared": {}, + "reserved": {} + }, + "local": { + "declared": {}, + "reserved": {} + } + }, + "contract": { + "name": "DemoContract", + "desc": "\n Verify that even though named tuples with different names, but the same structure should be\n considered 'comparable' in the type system, they should be output separately when being\n interpreted as an arc4 Struct in an abi method\n ", + "methods": [ + { + "name": "get_one", + "args": [], + "readonly": false, + "returns": { + "type": "(uint8,uint8)" + } + }, + { + "name": "get_two", + "args": [], + "readonly": false, + "returns": { + "type": "(uint8,uint8)" + } + }, + { + "name": "compare", + "args": [], + "readonly": false, + "returns": { + "type": "bool" + } + } + ], + "networks": {} + }, + "bare_call_config": { + "no_op": "CREATE" + } +} \ No newline at end of file diff --git a/test_cases/struct_by_name/out/DemoContract.arc56.json b/test_cases/struct_by_name/out/DemoContract.arc56.json new file mode 100644 index 0000000000..535863467d --- /dev/null +++ b/test_cases/struct_by_name/out/DemoContract.arc56.json @@ -0,0 +1,162 @@ +{ + "name": "DemoContract", + "structs": { + "StructOne": [ + { + "name": "x", + "type": "uint8" + }, + { + "name": "y", + "type": "uint8" + } + ], + "StructTwo": [ + { + "name": "x", + "type": "uint8" + }, + { + "name": "y", + "type": "uint8" + } + ] + }, + "methods": [ + { + "name": "get_one", + "args": [], + "returns": { + "type": "(uint8,uint8)", + "struct": "StructOne" + }, + "actions": { + "create": [], + "call": [ + "NoOp" + ] + }, + "readonly": false, + "events": [], + "recommendations": {} + }, + { + "name": "get_two", + "args": [], + "returns": { + "type": "(uint8,uint8)", + "struct": "StructTwo" + }, + "actions": { + "create": [], + "call": [ + "NoOp" + ] + }, + "readonly": false, + "events": [], + "recommendations": {} + }, + { + "name": "compare", + "args": [], + "returns": { + "type": "bool" + }, + "actions": { + "create": [], + "call": [ + "NoOp" + ] + }, + "readonly": false, + "events": [], + "recommendations": {} + } + ], + "arcs": [ + 22, + 28 + ], + "desc": "\n Verify that even though named tuples with different names, but the same structure should be\n considered 'comparable' in the type system, they should be output separately when being\n interpreted as an arc4 Struct in an abi method\n ", + "networks": {}, + "state": { + "schema": { + "global": { + "ints": 0, + "bytes": 0 + }, + "local": { + "ints": 0, + "bytes": 0 + } + }, + "keys": { + "global": {}, + "local": {}, + "box": {} + }, + "maps": { + "global": {}, + "local": {}, + "box": {} + } + }, + "bareActions": { + "create": [ + "NoOp" + ], + "call": [] + }, + "sourceInfo": { + "approval": { + "sourceInfo": [ + { + "pc": [ + 59, + 76, + 93 + ], + "errorMessage": "OnCompletion is not NoOp" + }, + { + "pc": [ + 121 + ], + "errorMessage": "can only call when creating" + }, + { + "pc": [ + 62, + 79, + 96 + ], + "errorMessage": "can only call when not creating" + } + ], + "pcOffsetMethod": "none" + }, + "clear": { + "sourceInfo": [], + "pcOffsetMethod": "none" + } + }, + "source": { + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgp0ZXN0X2Nhc2VzLnN0cnVjdF9ieV9uYW1lLmNvbnRyYWN0LkRlbW9Db250cmFjdC5hcHByb3ZhbF9wcm9ncmFtOgogICAgaW50Y2Jsb2NrIDEgMAogICAgYnl0ZWNibG9jayAweDE1MWY3Yzc1IDB4MDEKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHRlc3RfY2FzZXMuc3RydWN0X2J5X25hbWUuY29udHJhY3QuRGVtb0NvbnRyYWN0Ll9fcHV5YV9hcmM0X3JvdXRlcl9fKCkgLT4gdWludDY0OgpfX3B1eWFfYXJjNF9yb3V0ZXJfXzoKICAgIC8vIHN0cnVjdF9ieV9uYW1lL2NvbnRyYWN0LnB5OjE2CiAgICAvLyBjbGFzcyBEZW1vQ29udHJhY3QoQVJDNENvbnRyYWN0KToKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A3CiAgICBwdXNoYnl0ZXNzIDB4M2Q2OTRiNzAgMHg3ZmIzNGU4YSAweDQ2ZGFkZWEzIC8vIG1ldGhvZCAiZ2V0X29uZSgpKHVpbnQ4LHVpbnQ4KSIsIG1ldGhvZCAiZ2V0X3R3bygpKHVpbnQ4LHVpbnQ4KSIsIG1ldGhvZCAiY29tcGFyZSgpYm9vbCIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2dldF9vbmVfcm91dGVAMiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19nZXRfdHdvX3JvdXRlQDMgX19wdXlhX2FyYzRfcm91dGVyX19fY29tcGFyZV9yb3V0ZUA0CiAgICBpbnRjXzEgLy8gMAogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19nZXRfb25lX3JvdXRlQDI6CiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weToyMwogICAgLy8gQGFyYzQuYWJpbWV0aG9kKCkKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgbm90IE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gY2FuIG9ubHkgY2FsbCB3aGVuIG5vdCBjcmVhdGluZwogICAgY2FsbHN1YiBnZXRfb25lCiAgICBjb25jYXQKICAgIGJ5dGVjXzAgLy8gMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludGNfMCAvLyAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2dldF90d29fcm91dGVAMzoKICAgIC8vIHN0cnVjdF9ieV9uYW1lL2NvbnRyYWN0LnB5OjMwCiAgICAvLyBAYXJjNC5hYmltZXRob2QoKQogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBub3QgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBjYW4gb25seSBjYWxsIHdoZW4gbm90IGNyZWF0aW5nCiAgICBjYWxsc3ViIGdldF90d28KICAgIGNvbmNhdAogICAgYnl0ZWNfMCAvLyAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50Y18wIC8vIDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fY29tcGFyZV9yb3V0ZUA0OgogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MzcKICAgIC8vIEBhcmM0LmFiaW1ldGhvZCgpCiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIG5vdCBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGNhbiBvbmx5IGNhbGwgd2hlbiBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgY29tcGFyZQogICAgcHVzaGJ5dGVzIDB4MDAKICAgIGludGNfMSAvLyAwCiAgICB1bmNvdmVyIDIKICAgIHNldGJpdAogICAgYnl0ZWNfMCAvLyAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50Y18wIC8vIDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDc6CiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weToxNgogICAgLy8gY2xhc3MgRGVtb0NvbnRyYWN0KEFSQzRDb250cmFjdCk6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMQogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBjYW4gb25seSBjYWxsIHdoZW4gY3JlYXRpbmcKICAgIGludGNfMCAvLyAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTE6CiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weToxNgogICAgLy8gY2xhc3MgRGVtb0NvbnRyYWN0KEFSQzRDb250cmFjdCk6CiAgICBpbnRjXzEgLy8gMAogICAgcmV0c3ViCgoKLy8gdGVzdF9jYXNlcy5zdHJ1Y3RfYnlfbmFtZS5jb250cmFjdC5EZW1vQ29udHJhY3QuZ2V0X29uZSgpIC0+IGJ5dGVzLCBieXRlczoKZ2V0X29uZToKICAgIC8vIHN0cnVjdF9ieV9uYW1lL2NvbnRyYWN0LnB5OjIzLTI0CiAgICAvLyBAYXJjNC5hYmltZXRob2QoKQogICAgLy8gZGVmIGdldF9vbmUoc2VsZikgLT4gU3RydWN0T25lOgogICAgcHJvdG8gMCAyCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weToyNgogICAgLy8geD1hcmM0LlVJbnQ4KDEpLAogICAgYnl0ZWNfMSAvLyAweDAxCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weToyNwogICAgLy8geT1hcmM0LlVJbnQ4KDEpLAogICAgZHVwCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weToyNS0yOAogICAgLy8gcmV0dXJuIFN0cnVjdE9uZSgKICAgIC8vICAgICB4PWFyYzQuVUludDgoMSksCiAgICAvLyAgICAgeT1hcmM0LlVJbnQ4KDEpLAogICAgLy8gKQogICAgcmV0c3ViCgoKLy8gdGVzdF9jYXNlcy5zdHJ1Y3RfYnlfbmFtZS5jb250cmFjdC5EZW1vQ29udHJhY3QuZ2V0X3R3bygpIC0+IGJ5dGVzLCBieXRlczoKZ2V0X3R3bzoKICAgIC8vIHN0cnVjdF9ieV9uYW1lL2NvbnRyYWN0LnB5OjMwLTMxCiAgICAvLyBAYXJjNC5hYmltZXRob2QoKQogICAgLy8gZGVmIGdldF90d28oc2VsZikgLT4gU3RydWN0VHdvOgogICAgcHJvdG8gMCAyCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weTozMwogICAgLy8geD1hcmM0LlVJbnQ4KDEpLAogICAgYnl0ZWNfMSAvLyAweDAxCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weTozNAogICAgLy8geT1hcmM0LlVJbnQ4KDEpLAogICAgZHVwCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weTozMi0zNQogICAgLy8gcmV0dXJuIFN0cnVjdFR3bygKICAgIC8vICAgICB4PWFyYzQuVUludDgoMSksCiAgICAvLyAgICAgeT1hcmM0LlVJbnQ4KDEpLAogICAgLy8gKQogICAgcmV0c3ViCgoKLy8gdGVzdF9jYXNlcy5zdHJ1Y3RfYnlfbmFtZS5jb250cmFjdC5EZW1vQ29udHJhY3QuY29tcGFyZSgpIC0+IHVpbnQ2NDoKY29tcGFyZToKICAgIC8vIHN0cnVjdF9ieV9uYW1lL2NvbnRyYWN0LnB5OjM3LTM4CiAgICAvLyBAYXJjNC5hYmltZXRob2QoKQogICAgLy8gZGVmIGNvbXBhcmUoc2VsZikgLT4gYm9vbDoKICAgIHByb3RvIDAgMQogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MzkKICAgIC8vIHJldHVybiBzZWxmLmdldF9vbmUoKSA9PSBzZWxmLmdldF90d28oKQogICAgY2FsbHN1YiBnZXRfb25lCiAgICBjYWxsc3ViIGdldF90d28KICAgIHVuY292ZXIgMwogICAgdW5jb3ZlciAyCiAgICBiPT0KICAgIGNvdmVyIDIKICAgIGI9PQogICAgJiYKICAgIHJldHN1Ygo=", + "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgp0ZXN0X2Nhc2VzLnN0cnVjdF9ieV9uYW1lLmNvbnRyYWN0LkRlbW9Db250cmFjdC5jbGVhcl9zdGF0ZV9wcm9ncmFtOgogICAgcHVzaGludCAxIC8vIDEKICAgIHJldHVybgo=" + }, + "byteCode": { + "approval": "CiACAQAmAgQVH3x1AQGIAAFDigABMRtBAFeCAwQ9aUtwBH+zTooERtreozYaAI4DAAIAEwAkI4kxGRREMRhEiAA8UChMULAiiTEZFEQxGESIADFQKExQsCKJMRkURDEYRIgAJoABACNPAlQoTFCwIokxGUAABjEYFEQiiSOJigACKUmJigACKUmJigABiP/uiP/xTwNPAqhOAqgQiQ==", + "clear": "CoEBQw==" + }, + "compilerInfo": { + "compiler": "puya", + "compilerVersion": { + "major": 99, + "minor": 99, + "patch": 99 + } + }, + "events": [], + "templateVariables": {} +} \ No newline at end of file diff --git a/test_cases/struct_by_name/out/DemoContract.clear.teal b/test_cases/struct_by_name/out/DemoContract.clear.teal new file mode 100644 index 0000000000..41c3a3f9e2 --- /dev/null +++ b/test_cases/struct_by_name/out/DemoContract.clear.teal @@ -0,0 +1,5 @@ +#pragma version 10 + +test_cases.struct_by_name.contract.DemoContract.clear_state_program: + pushint 1 // 1 + return diff --git a/test_cases/struct_by_name/out/DemoContract.destructured.ir b/test_cases/struct_by_name/out/DemoContract.destructured.ir new file mode 100644 index 0000000000..a4772be1c5 --- /dev/null +++ b/test_cases/struct_by_name/out/DemoContract.destructured.ir @@ -0,0 +1,79 @@ +contract test_cases.struct_by_name.contract.DemoContract: + program approval: + subroutine algopy.arc4.ARC4Contract.approval_program() -> bool: + block@0: // L1 + let tmp%0#0: bool = test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__() + return tmp%0#0 + + subroutine test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__() -> bool: + block@0: // L16 + let tmp%0#0: uint64 = (txn NumAppArgs) + goto tmp%0#0 ? block@1 : block@7 + block@1: // abi_routing_L16 + let tmp%2#0: bytes = (txna ApplicationArgs 0) + switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "compare()bool" => block@4, * => return 0u} + block@2: // get_one_route_L23 + let tmp%3#0: uint64 = (txn OnCompletion) + let tmp%4#0: bool = (! tmp%3#0) + (assert tmp%4#0) // OnCompletion is not NoOp + let tmp%5#0: uint64 = (txn ApplicationID) + (assert tmp%5#0) // can only call when not creating + let (elements_to_encode%0#0: bytes, elements_to_encode%1#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_one() + let encoded_tuple_buffer%2#0: bytes = (concat elements_to_encode%0#0 elements_to_encode%1#0) + let tmp%7#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%2#0) + (log tmp%7#0) + return 1u + block@3: // get_two_route_L30 + let tmp%8#0: uint64 = (txn OnCompletion) + let tmp%9#0: bool = (! tmp%8#0) + (assert tmp%9#0) // OnCompletion is not NoOp + let tmp%10#0: uint64 = (txn ApplicationID) + (assert tmp%10#0) // can only call when not creating + let (elements_to_encode%2#0: bytes, elements_to_encode%3#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_two() + let encoded_tuple_buffer%5#0: bytes = (concat elements_to_encode%2#0 elements_to_encode%3#0) + let tmp%12#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%5#0) + (log tmp%12#0) + return 1u + block@4: // compare_route_L37 + let tmp%13#0: uint64 = (txn OnCompletion) + let tmp%14#0: bool = (! tmp%13#0) + (assert tmp%14#0) // OnCompletion is not NoOp + let tmp%15#0: uint64 = (txn ApplicationID) + (assert tmp%15#0) // can only call when not creating + let to_encode%0#0: bool = test_cases.struct_by_name.contract.DemoContract.compare() + let encoded_bool%0#0: bytes = (setbit 0x00 0u to_encode%0#0) + let tmp%17#0: bytes = (concat 0x151f7c75 encoded_bool%0#0) + (log tmp%17#0) + return 1u + block@7: // bare_routing_L16 + let tmp%18#0: uint64 = (txn OnCompletion) + goto tmp%18#0 ? block@11 : block@8 + block@8: // __algopy_default_create_L1 + let tmp%19#0: uint64 = (txn ApplicationID) + let tmp%20#0: bool = (! tmp%19#0) + (assert tmp%20#0) // can only call when creating + return 1u + block@11: // after_if_else_L16 + return 0u + + subroutine test_cases.struct_by_name.contract.DemoContract.get_one() -> : + block@0: // L23 + return 0x01 0x01 + + subroutine test_cases.struct_by_name.contract.DemoContract.get_two() -> : + block@0: // L30 + return 0x01 0x01 + + subroutine test_cases.struct_by_name.contract.DemoContract.compare() -> bool: + block@0: // L37 + let (awst_tmp%0#0: bytes, awst_tmp%1#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_one() + let (awst_tmp%2#0: bytes, awst_tmp%3#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_two() + let tmp%0#0: bool = (b== awst_tmp%0#0 awst_tmp%2#0) + let tmp%1#0: bool = (b== awst_tmp%1#0 awst_tmp%3#0) + let tmp%2#0: bool = (&& tmp%0#0 tmp%1#0) + return tmp%2#0 + + program clear-state: + subroutine algopy.arc4.ARC4Contract.clear_state_program() -> bool: + block@0: // L1 + return 1u \ No newline at end of file diff --git a/test_cases/struct_by_name/out/DemoContract.ssa.ir b/test_cases/struct_by_name/out/DemoContract.ssa.ir new file mode 100644 index 0000000000..489dd83640 --- /dev/null +++ b/test_cases/struct_by_name/out/DemoContract.ssa.ir @@ -0,0 +1,106 @@ +contract test_cases.struct_by_name.contract.DemoContract: + program approval: + subroutine algopy.arc4.ARC4Contract.approval_program() -> bool: + block@0: // L1 + let tmp%0#0: bool = test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__() + return tmp%0#0 + + subroutine test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__() -> bool: + block@0: // L16 + let tmp%0#0: uint64 = (txn NumAppArgs) + let tmp%1#0: bool = (!= tmp%0#0 0u) + goto tmp%1#0 ? block@1 : block@7 + block@1: // abi_routing_L16 + let tmp%2#0: bytes = (txna ApplicationArgs 0) + switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "compare()bool" => block@4, * => block@5} + block@2: // get_one_route_L23 + let tmp%3#0: uint64 = (txn OnCompletion) + let tmp%4#0: bool = (== tmp%3#0 NoOp) + (assert tmp%4#0) // OnCompletion is not NoOp + let tmp%5#0: uint64 = (txn ApplicationID) + let tmp%6#0: bool = (!= tmp%5#0 0u) + (assert tmp%6#0) // can only call when not creating + let (elements_to_encode%0#0: bytes, elements_to_encode%1#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_one() + let current_tail_offset%0#0: uint64 = 2u + let encoded_tuple_buffer%0#0: bytes = 0x + let encoded_tuple_buffer%1#0: bytes = (concat encoded_tuple_buffer%0#0 elements_to_encode%0#0) + let encoded_tuple_buffer%2#0: bytes = (concat encoded_tuple_buffer%1#0 elements_to_encode%1#0) + let tmp%7#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%2#0) + (log tmp%7#0) + return 1u + block@3: // get_two_route_L30 + let tmp%8#0: uint64 = (txn OnCompletion) + let tmp%9#0: bool = (== tmp%8#0 NoOp) + (assert tmp%9#0) // OnCompletion is not NoOp + let tmp%10#0: uint64 = (txn ApplicationID) + let tmp%11#0: bool = (!= tmp%10#0 0u) + (assert tmp%11#0) // can only call when not creating + let (elements_to_encode%2#0: bytes, elements_to_encode%3#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_two() + let current_tail_offset%1#0: uint64 = 2u + let encoded_tuple_buffer%3#0: bytes = 0x + let encoded_tuple_buffer%4#0: bytes = (concat encoded_tuple_buffer%3#0 elements_to_encode%2#0) + let encoded_tuple_buffer%5#0: bytes = (concat encoded_tuple_buffer%4#0 elements_to_encode%3#0) + let tmp%12#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%5#0) + (log tmp%12#0) + return 1u + block@4: // compare_route_L37 + let tmp%13#0: uint64 = (txn OnCompletion) + let tmp%14#0: bool = (== tmp%13#0 NoOp) + (assert tmp%14#0) // OnCompletion is not NoOp + let tmp%15#0: uint64 = (txn ApplicationID) + let tmp%16#0: bool = (!= tmp%15#0 0u) + (assert tmp%16#0) // can only call when not creating + let to_encode%0#0: bool = test_cases.struct_by_name.contract.DemoContract.compare() + let encoded_bool%0#0: bytes = (setbit 0x00 0u to_encode%0#0) + let tmp%17#0: bytes = (concat 0x151f7c75 encoded_bool%0#0) + (log tmp%17#0) + return 1u + block@5: // switch_case_default_L16 + goto block@6 + block@6: // switch_case_next_L16 + goto block@11 + block@7: // bare_routing_L16 + let tmp%18#0: uint64 = (txn OnCompletion) + switch tmp%18#0 {0u => block@8, * => block@9} + block@8: // __algopy_default_create_L1 + let tmp%19#0: uint64 = (txn ApplicationID) + let tmp%20#0: bool = (== tmp%19#0 0u) + (assert tmp%20#0) // can only call when creating + test_cases.struct_by_name.contract.DemoContract.__algopy_default_create() + return 1u + block@9: // switch_case_default_L16 + goto block@10 + block@10: // switch_case_next_L16 + goto block@11 + block@11: // after_if_else_L16 + return 0u + + subroutine test_cases.struct_by_name.contract.DemoContract.get_one() -> : + block@0: // L23 + return 0x01 0x01 + + subroutine test_cases.struct_by_name.contract.DemoContract.get_two() -> : + block@0: // L30 + return 0x01 0x01 + + subroutine test_cases.struct_by_name.contract.DemoContract.compare() -> bool: + block@0: // L37 + let (awst_tmp%0#0: bytes, awst_tmp%1#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_one() + let reinterpret_biguint%0#0: biguint = awst_tmp%0#0 + let (awst_tmp%2#0: bytes, awst_tmp%3#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_two() + let reinterpret_biguint%1#0: biguint = awst_tmp%2#0 + let tmp%0#0: bool = (b== reinterpret_biguint%0#0 reinterpret_biguint%1#0) + let reinterpret_biguint%2#0: biguint = awst_tmp%1#0 + let reinterpret_biguint%3#0: biguint = awst_tmp%3#0 + let tmp%1#0: bool = (b== reinterpret_biguint%2#0 reinterpret_biguint%3#0) + let tmp%2#0: bool = (&& tmp%0#0 tmp%1#0) + return tmp%2#0 + + subroutine test_cases.struct_by_name.contract.DemoContract.__algopy_default_create() -> void: + block@0: // L1 + return + + program clear-state: + subroutine algopy.arc4.ARC4Contract.clear_state_program() -> bool: + block@0: // L1 + return 1u \ No newline at end of file diff --git a/test_cases/struct_by_name/out/DemoContract.ssa.opt_pass_1.ir b/test_cases/struct_by_name/out/DemoContract.ssa.opt_pass_1.ir new file mode 100644 index 0000000000..3b7507b34a --- /dev/null +++ b/test_cases/struct_by_name/out/DemoContract.ssa.opt_pass_1.ir @@ -0,0 +1,81 @@ +contract test_cases.struct_by_name.contract.DemoContract: + program approval: + subroutine algopy.arc4.ARC4Contract.approval_program() -> bool: + block@0: // L1 + let tmp%0#0: bool = test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__() + return tmp%0#0 + + subroutine test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__() -> bool: + block@0: // L16 + let tmp%0#0: uint64 = (txn NumAppArgs) + goto tmp%0#0 ? block@1 : block@7 + block@1: // abi_routing_L16 + let tmp%2#0: bytes = (txna ApplicationArgs 0) + switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "compare()bool" => block@4, * => return 0u} + block@2: // get_one_route_L23 + let tmp%3#0: uint64 = (txn OnCompletion) + let tmp%4#0: bool = (! tmp%3#0) + (assert tmp%4#0) // OnCompletion is not NoOp + let tmp%5#0: uint64 = (txn ApplicationID) + (assert tmp%5#0) // can only call when not creating + let (elements_to_encode%0#0: bytes, elements_to_encode%1#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_one() + let encoded_tuple_buffer%1#0: bytes = elements_to_encode%0#0 + let encoded_tuple_buffer%2#0: bytes = (concat encoded_tuple_buffer%1#0 elements_to_encode%1#0) + let tmp%7#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%2#0) + (log tmp%7#0) + return 1u + block@3: // get_two_route_L30 + let tmp%8#0: uint64 = (txn OnCompletion) + let tmp%9#0: bool = (! tmp%8#0) + (assert tmp%9#0) // OnCompletion is not NoOp + let tmp%10#0: uint64 = (txn ApplicationID) + (assert tmp%10#0) // can only call when not creating + let (elements_to_encode%2#0: bytes, elements_to_encode%3#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_two() + let encoded_tuple_buffer%4#0: bytes = elements_to_encode%2#0 + let encoded_tuple_buffer%5#0: bytes = (concat encoded_tuple_buffer%4#0 elements_to_encode%3#0) + let tmp%12#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%5#0) + (log tmp%12#0) + return 1u + block@4: // compare_route_L37 + let tmp%13#0: uint64 = (txn OnCompletion) + let tmp%14#0: bool = (! tmp%13#0) + (assert tmp%14#0) // OnCompletion is not NoOp + let tmp%15#0: uint64 = (txn ApplicationID) + (assert tmp%15#0) // can only call when not creating + let to_encode%0#0: bool = test_cases.struct_by_name.contract.DemoContract.compare() + let encoded_bool%0#0: bytes = (setbit 0x00 0u to_encode%0#0) + let tmp%17#0: bytes = (concat 0x151f7c75 encoded_bool%0#0) + (log tmp%17#0) + return 1u + block@7: // bare_routing_L16 + let tmp%18#0: uint64 = (txn OnCompletion) + goto tmp%18#0 ? block@11 : block@8 + block@8: // __algopy_default_create_L1 + let tmp%19#0: uint64 = (txn ApplicationID) + let tmp%20#0: bool = (! tmp%19#0) + (assert tmp%20#0) // can only call when creating + return 1u + block@11: // after_if_else_L16 + return 0u + + subroutine test_cases.struct_by_name.contract.DemoContract.get_one() -> : + block@0: // L23 + return 0x01 0x01 + + subroutine test_cases.struct_by_name.contract.DemoContract.get_two() -> : + block@0: // L30 + return 0x01 0x01 + + subroutine test_cases.struct_by_name.contract.DemoContract.compare() -> bool: + block@0: // L37 + let (awst_tmp%0#0: bytes, awst_tmp%1#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_one() + let (awst_tmp%2#0: bytes, awst_tmp%3#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_two() + let tmp%0#0: bool = (b== awst_tmp%0#0 awst_tmp%2#0) + let tmp%1#0: bool = (b== awst_tmp%1#0 awst_tmp%3#0) + let tmp%2#0: bool = (&& tmp%0#0 tmp%1#0) + return tmp%2#0 + + program clear-state: + subroutine algopy.arc4.ARC4Contract.clear_state_program() -> bool: + block@0: // L1 + return 1u \ No newline at end of file diff --git a/test_cases/struct_by_name/out/DemoContract.ssa.opt_pass_2.ir b/test_cases/struct_by_name/out/DemoContract.ssa.opt_pass_2.ir new file mode 100644 index 0000000000..a4772be1c5 --- /dev/null +++ b/test_cases/struct_by_name/out/DemoContract.ssa.opt_pass_2.ir @@ -0,0 +1,79 @@ +contract test_cases.struct_by_name.contract.DemoContract: + program approval: + subroutine algopy.arc4.ARC4Contract.approval_program() -> bool: + block@0: // L1 + let tmp%0#0: bool = test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__() + return tmp%0#0 + + subroutine test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__() -> bool: + block@0: // L16 + let tmp%0#0: uint64 = (txn NumAppArgs) + goto tmp%0#0 ? block@1 : block@7 + block@1: // abi_routing_L16 + let tmp%2#0: bytes = (txna ApplicationArgs 0) + switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "compare()bool" => block@4, * => return 0u} + block@2: // get_one_route_L23 + let tmp%3#0: uint64 = (txn OnCompletion) + let tmp%4#0: bool = (! tmp%3#0) + (assert tmp%4#0) // OnCompletion is not NoOp + let tmp%5#0: uint64 = (txn ApplicationID) + (assert tmp%5#0) // can only call when not creating + let (elements_to_encode%0#0: bytes, elements_to_encode%1#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_one() + let encoded_tuple_buffer%2#0: bytes = (concat elements_to_encode%0#0 elements_to_encode%1#0) + let tmp%7#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%2#0) + (log tmp%7#0) + return 1u + block@3: // get_two_route_L30 + let tmp%8#0: uint64 = (txn OnCompletion) + let tmp%9#0: bool = (! tmp%8#0) + (assert tmp%9#0) // OnCompletion is not NoOp + let tmp%10#0: uint64 = (txn ApplicationID) + (assert tmp%10#0) // can only call when not creating + let (elements_to_encode%2#0: bytes, elements_to_encode%3#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_two() + let encoded_tuple_buffer%5#0: bytes = (concat elements_to_encode%2#0 elements_to_encode%3#0) + let tmp%12#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%5#0) + (log tmp%12#0) + return 1u + block@4: // compare_route_L37 + let tmp%13#0: uint64 = (txn OnCompletion) + let tmp%14#0: bool = (! tmp%13#0) + (assert tmp%14#0) // OnCompletion is not NoOp + let tmp%15#0: uint64 = (txn ApplicationID) + (assert tmp%15#0) // can only call when not creating + let to_encode%0#0: bool = test_cases.struct_by_name.contract.DemoContract.compare() + let encoded_bool%0#0: bytes = (setbit 0x00 0u to_encode%0#0) + let tmp%17#0: bytes = (concat 0x151f7c75 encoded_bool%0#0) + (log tmp%17#0) + return 1u + block@7: // bare_routing_L16 + let tmp%18#0: uint64 = (txn OnCompletion) + goto tmp%18#0 ? block@11 : block@8 + block@8: // __algopy_default_create_L1 + let tmp%19#0: uint64 = (txn ApplicationID) + let tmp%20#0: bool = (! tmp%19#0) + (assert tmp%20#0) // can only call when creating + return 1u + block@11: // after_if_else_L16 + return 0u + + subroutine test_cases.struct_by_name.contract.DemoContract.get_one() -> : + block@0: // L23 + return 0x01 0x01 + + subroutine test_cases.struct_by_name.contract.DemoContract.get_two() -> : + block@0: // L30 + return 0x01 0x01 + + subroutine test_cases.struct_by_name.contract.DemoContract.compare() -> bool: + block@0: // L37 + let (awst_tmp%0#0: bytes, awst_tmp%1#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_one() + let (awst_tmp%2#0: bytes, awst_tmp%3#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_two() + let tmp%0#0: bool = (b== awst_tmp%0#0 awst_tmp%2#0) + let tmp%1#0: bool = (b== awst_tmp%1#0 awst_tmp%3#0) + let tmp%2#0: bool = (&& tmp%0#0 tmp%1#0) + return tmp%2#0 + + program clear-state: + subroutine algopy.arc4.ARC4Contract.clear_state_program() -> bool: + block@0: // L1 + return 1u \ No newline at end of file diff --git a/test_cases/struct_by_name/out/client_DemoContract.py b/test_cases/struct_by_name/out/client_DemoContract.py new file mode 100644 index 0000000000..ab778eb0eb --- /dev/null +++ b/test_cases/struct_by_name/out/client_DemoContract.py @@ -0,0 +1,37 @@ +# This file is auto-generated, do not modify +# flake8: noqa +# fmt: off +import typing + +import algopy + +class StructOne(algopy.arc4.Struct): + x: algopy.arc4.UIntN[typing.Literal[8]] + y: algopy.arc4.UIntN[typing.Literal[8]] + +class StructTwo(algopy.arc4.Struct): + x: algopy.arc4.UIntN[typing.Literal[8]] + y: algopy.arc4.UIntN[typing.Literal[8]] + +class DemoContract(algopy.arc4.ARC4Client, typing.Protocol): + """ + + Verify that even though named tuples with different names, but the same structure should be + considered 'comparable' in the type system, they should be output separately when being + interpreted as an arc4 Struct in an abi method + + """ + @algopy.arc4.abimethod + def get_one( + self, + ) -> StructOne: ... + + @algopy.arc4.abimethod + def get_two( + self, + ) -> StructTwo: ... + + @algopy.arc4.abimethod + def compare( + self, + ) -> algopy.arc4.Bool: ... diff --git a/test_cases/struct_by_name/out/module.awst b/test_cases/struct_by_name/out/module.awst new file mode 100644 index 0000000000..32e324a2cf --- /dev/null +++ b/test_cases/struct_by_name/out/module.awst @@ -0,0 +1,35 @@ +contract DemoContract +{ + method_resolution_order: ( + algopy.arc4.ARC4Contract, + ) + + subroutine algopy.arc4.ARC4Contract.approval_program(): bool + { + return arc4_router() + } + + subroutine algopy.arc4.ARC4Contract.clear_state_program(): bool + { + return true + } + + abimethod test_cases.struct_by_name.contract.DemoContract.get_one(): test_cases.struct_by_name.contract.StructOne + { + return (1_arc4u8, 1_arc4u8) + } + + abimethod test_cases.struct_by_name.contract.DemoContract.get_two(): test_cases.struct_by_name.contract.StructTwo + { + return (1_arc4u8, 1_arc4u8) + } + + abimethod test_cases.struct_by_name.contract.DemoContract.compare(): bool + { + return &&(reinterpret_cast(SINGLE_EVAL(id=0, source=this::get_one())[0]) == reinterpret_cast(SINGLE_EVAL(id=1, source=this::get_two())[0]), reinterpret_cast(SINGLE_EVAL(id=0)[1]) == reinterpret_cast(SINGLE_EVAL(id=1)[1])) + } + + baremethod test_cases.struct_by_name.contract.DemoContract.__algopy_default_create(): void + { + } +} \ No newline at end of file diff --git a/test_cases/struct_by_name/out_O2/DemoContract.approval.teal b/test_cases/struct_by_name/out_O2/DemoContract.approval.teal new file mode 100644 index 0000000000..9766b64bc2 --- /dev/null +++ b/test_cases/struct_by_name/out_O2/DemoContract.approval.teal @@ -0,0 +1,110 @@ +#pragma version 10 + +test_cases.struct_by_name.contract.DemoContract.approval_program: + intcblock 1 0 + bytecblock 0x151f7c75 0x01 + callsub __puya_arc4_router__ + return + + +// test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__() -> uint64: +__puya_arc4_router__: + proto 0 1 + txn NumAppArgs + bz __puya_arc4_router___bare_routing@7 + pushbytess 0x3d694b70 0x7fb34e8a 0x46dadea3 // method "get_one()(uint8,uint8)", method "get_two()(uint8,uint8)", method "compare()bool" + txna ApplicationArgs 0 + match __puya_arc4_router___get_one_route@2 __puya_arc4_router___get_two_route@3 __puya_arc4_router___compare_route@4 + intc_1 // 0 + retsub + +__puya_arc4_router___get_one_route@2: + txn OnCompletion + ! + assert // OnCompletion is not NoOp + txn ApplicationID + assert // can only call when not creating + callsub get_one + concat + bytec_0 // 0x151f7c75 + swap + concat + log + intc_0 // 1 + retsub + +__puya_arc4_router___get_two_route@3: + txn OnCompletion + ! + assert // OnCompletion is not NoOp + txn ApplicationID + assert // can only call when not creating + callsub get_two + concat + bytec_0 // 0x151f7c75 + swap + concat + log + intc_0 // 1 + retsub + +__puya_arc4_router___compare_route@4: + txn OnCompletion + ! + assert // OnCompletion is not NoOp + txn ApplicationID + assert // can only call when not creating + callsub compare + pushbytes 0x00 + intc_1 // 0 + uncover 2 + setbit + bytec_0 // 0x151f7c75 + swap + concat + log + intc_0 // 1 + retsub + +__puya_arc4_router___bare_routing@7: + txn OnCompletion + bnz __puya_arc4_router___after_if_else@11 + txn ApplicationID + ! + assert // can only call when creating + intc_0 // 1 + retsub + +__puya_arc4_router___after_if_else@11: + intc_1 // 0 + retsub + + +// test_cases.struct_by_name.contract.DemoContract.get_one() -> bytes, bytes: +get_one: + proto 0 2 + bytec_1 // 0x01 + dup + retsub + + +// test_cases.struct_by_name.contract.DemoContract.get_two() -> bytes, bytes: +get_two: + proto 0 2 + bytec_1 // 0x01 + dup + retsub + + +// test_cases.struct_by_name.contract.DemoContract.compare() -> uint64: +compare: + proto 0 1 + callsub get_one + callsub get_two + uncover 3 + uncover 2 + b== + cover 2 + b== + && + retsub diff --git a/test_cases/struct_by_name/out_O2/DemoContract.clear.teal b/test_cases/struct_by_name/out_O2/DemoContract.clear.teal new file mode 100644 index 0000000000..41c3a3f9e2 --- /dev/null +++ b/test_cases/struct_by_name/out_O2/DemoContract.clear.teal @@ -0,0 +1,5 @@ +#pragma version 10 + +test_cases.struct_by_name.contract.DemoContract.clear_state_program: + pushint 1 // 1 + return diff --git a/test_cases/struct_by_name/out_O2/DemoContract.destructured.ir b/test_cases/struct_by_name/out_O2/DemoContract.destructured.ir new file mode 100644 index 0000000000..a4772be1c5 --- /dev/null +++ b/test_cases/struct_by_name/out_O2/DemoContract.destructured.ir @@ -0,0 +1,79 @@ +contract test_cases.struct_by_name.contract.DemoContract: + program approval: + subroutine algopy.arc4.ARC4Contract.approval_program() -> bool: + block@0: // L1 + let tmp%0#0: bool = test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__() + return tmp%0#0 + + subroutine test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__() -> bool: + block@0: // L16 + let tmp%0#0: uint64 = (txn NumAppArgs) + goto tmp%0#0 ? block@1 : block@7 + block@1: // abi_routing_L16 + let tmp%2#0: bytes = (txna ApplicationArgs 0) + switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "compare()bool" => block@4, * => return 0u} + block@2: // get_one_route_L23 + let tmp%3#0: uint64 = (txn OnCompletion) + let tmp%4#0: bool = (! tmp%3#0) + (assert tmp%4#0) // OnCompletion is not NoOp + let tmp%5#0: uint64 = (txn ApplicationID) + (assert tmp%5#0) // can only call when not creating + let (elements_to_encode%0#0: bytes, elements_to_encode%1#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_one() + let encoded_tuple_buffer%2#0: bytes = (concat elements_to_encode%0#0 elements_to_encode%1#0) + let tmp%7#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%2#0) + (log tmp%7#0) + return 1u + block@3: // get_two_route_L30 + let tmp%8#0: uint64 = (txn OnCompletion) + let tmp%9#0: bool = (! tmp%8#0) + (assert tmp%9#0) // OnCompletion is not NoOp + let tmp%10#0: uint64 = (txn ApplicationID) + (assert tmp%10#0) // can only call when not creating + let (elements_to_encode%2#0: bytes, elements_to_encode%3#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_two() + let encoded_tuple_buffer%5#0: bytes = (concat elements_to_encode%2#0 elements_to_encode%3#0) + let tmp%12#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%5#0) + (log tmp%12#0) + return 1u + block@4: // compare_route_L37 + let tmp%13#0: uint64 = (txn OnCompletion) + let tmp%14#0: bool = (! tmp%13#0) + (assert tmp%14#0) // OnCompletion is not NoOp + let tmp%15#0: uint64 = (txn ApplicationID) + (assert tmp%15#0) // can only call when not creating + let to_encode%0#0: bool = test_cases.struct_by_name.contract.DemoContract.compare() + let encoded_bool%0#0: bytes = (setbit 0x00 0u to_encode%0#0) + let tmp%17#0: bytes = (concat 0x151f7c75 encoded_bool%0#0) + (log tmp%17#0) + return 1u + block@7: // bare_routing_L16 + let tmp%18#0: uint64 = (txn OnCompletion) + goto tmp%18#0 ? block@11 : block@8 + block@8: // __algopy_default_create_L1 + let tmp%19#0: uint64 = (txn ApplicationID) + let tmp%20#0: bool = (! tmp%19#0) + (assert tmp%20#0) // can only call when creating + return 1u + block@11: // after_if_else_L16 + return 0u + + subroutine test_cases.struct_by_name.contract.DemoContract.get_one() -> : + block@0: // L23 + return 0x01 0x01 + + subroutine test_cases.struct_by_name.contract.DemoContract.get_two() -> : + block@0: // L30 + return 0x01 0x01 + + subroutine test_cases.struct_by_name.contract.DemoContract.compare() -> bool: + block@0: // L37 + let (awst_tmp%0#0: bytes, awst_tmp%1#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_one() + let (awst_tmp%2#0: bytes, awst_tmp%3#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_two() + let tmp%0#0: bool = (b== awst_tmp%0#0 awst_tmp%2#0) + let tmp%1#0: bool = (b== awst_tmp%1#0 awst_tmp%3#0) + let tmp%2#0: bool = (&& tmp%0#0 tmp%1#0) + return tmp%2#0 + + program clear-state: + subroutine algopy.arc4.ARC4Contract.clear_state_program() -> bool: + block@0: // L1 + return 1u \ No newline at end of file diff --git a/test_cases/struct_by_name/out_unoptimized/DemoContract.approval.teal b/test_cases/struct_by_name/out_unoptimized/DemoContract.approval.teal new file mode 100644 index 0000000000..2e7db4630f --- /dev/null +++ b/test_cases/struct_by_name/out_unoptimized/DemoContract.approval.teal @@ -0,0 +1,193 @@ +#pragma version 10 + +test_cases.struct_by_name.contract.DemoContract.approval_program: + intcblock 0 1 + bytecblock 0x151f7c75 0x 0x01 + callsub __puya_arc4_router__ + return + + +// test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__() -> uint64: +__puya_arc4_router__: + // struct_by_name/contract.py:16 + // class DemoContract(ARC4Contract): + proto 0 1 + txn NumAppArgs + intc_0 // 0 + != + bz __puya_arc4_router___bare_routing@7 + txna ApplicationArgs 0 + pushbytes 0x3d694b70 // method "get_one()(uint8,uint8)" + pushbytes 0x7fb34e8a // method "get_two()(uint8,uint8)" + pushbytes 0x46dadea3 // method "compare()bool" + uncover 3 + match __puya_arc4_router___get_one_route@2 __puya_arc4_router___get_two_route@3 __puya_arc4_router___compare_route@4 + b __puya_arc4_router___switch_case_default@5 + +__puya_arc4_router___get_one_route@2: + // struct_by_name/contract.py:23 + // @arc4.abimethod() + txn OnCompletion + intc_0 // NoOp + == + assert // OnCompletion is not NoOp + txn ApplicationID + intc_0 // 0 + != + assert // can only call when not creating + callsub get_one + swap + bytec_1 // 0x + swap + concat + swap + concat + bytec_0 // 0x151f7c75 + swap + concat + log + intc_1 // 1 + retsub + +__puya_arc4_router___get_two_route@3: + // struct_by_name/contract.py:30 + // @arc4.abimethod() + txn OnCompletion + intc_0 // NoOp + == + assert // OnCompletion is not NoOp + txn ApplicationID + intc_0 // 0 + != + assert // can only call when not creating + callsub get_two + swap + bytec_1 // 0x + swap + concat + swap + concat + bytec_0 // 0x151f7c75 + swap + concat + log + intc_1 // 1 + retsub + +__puya_arc4_router___compare_route@4: + // struct_by_name/contract.py:37 + // @arc4.abimethod() + txn OnCompletion + intc_0 // NoOp + == + assert // OnCompletion is not NoOp + txn ApplicationID + intc_0 // 0 + != + assert // can only call when not creating + callsub compare + pushbytes 0x00 + intc_0 // 0 + uncover 2 + setbit + bytec_0 // 0x151f7c75 + swap + concat + log + intc_1 // 1 + retsub + +__puya_arc4_router___switch_case_default@5: + b __puya_arc4_router___after_if_else@11 + +__puya_arc4_router___bare_routing@7: + // struct_by_name/contract.py:16 + // class DemoContract(ARC4Contract): + txn OnCompletion + intc_0 // 0 + swap + match __puya_arc4_router_____algopy_default_create@8 + b __puya_arc4_router___switch_case_default@9 + +__puya_arc4_router_____algopy_default_create@8: + txn ApplicationID + intc_0 // 0 + == + assert // can only call when creating + callsub __algopy_default_create + intc_1 // 1 + retsub + +__puya_arc4_router___switch_case_default@9: + +__puya_arc4_router___after_if_else@11: + // struct_by_name/contract.py:16 + // class DemoContract(ARC4Contract): + intc_0 // 0 + retsub + + +// test_cases.struct_by_name.contract.DemoContract.get_one() -> bytes, bytes: +get_one: + // struct_by_name/contract.py:23-24 + // @arc4.abimethod() + // def get_one(self) -> StructOne: + proto 0 2 + // struct_by_name/contract.py:26 + // x=arc4.UInt8(1), + bytec_2 // 0x01 + // struct_by_name/contract.py:27 + // y=arc4.UInt8(1), + dup + // struct_by_name/contract.py:25-28 + // return StructOne( + // x=arc4.UInt8(1), + // y=arc4.UInt8(1), + // ) + retsub + + +// test_cases.struct_by_name.contract.DemoContract.get_two() -> bytes, bytes: +get_two: + // struct_by_name/contract.py:30-31 + // @arc4.abimethod() + // def get_two(self) -> StructTwo: + proto 0 2 + // struct_by_name/contract.py:33 + // x=arc4.UInt8(1), + bytec_2 // 0x01 + // struct_by_name/contract.py:34 + // y=arc4.UInt8(1), + dup + // struct_by_name/contract.py:32-35 + // return StructTwo( + // x=arc4.UInt8(1), + // y=arc4.UInt8(1), + // ) + retsub + + +// test_cases.struct_by_name.contract.DemoContract.compare() -> uint64: +compare: + // struct_by_name/contract.py:37-38 + // @arc4.abimethod() + // def compare(self) -> bool: + proto 0 1 + // struct_by_name/contract.py:39 + // return self.get_one() == self.get_two() + callsub get_one + swap + callsub get_two + cover 2 + b== + uncover 2 + uncover 2 + b== + && + retsub + + +// test_cases.struct_by_name.contract.DemoContract.__algopy_default_create() -> void: +__algopy_default_create: + proto 0 0 + retsub diff --git a/test_cases/struct_by_name/out_unoptimized/DemoContract.clear.teal b/test_cases/struct_by_name/out_unoptimized/DemoContract.clear.teal new file mode 100644 index 0000000000..41c3a3f9e2 --- /dev/null +++ b/test_cases/struct_by_name/out_unoptimized/DemoContract.clear.teal @@ -0,0 +1,5 @@ +#pragma version 10 + +test_cases.struct_by_name.contract.DemoContract.clear_state_program: + pushint 1 // 1 + return diff --git a/test_cases/struct_by_name/out_unoptimized/DemoContract.destructured.ir b/test_cases/struct_by_name/out_unoptimized/DemoContract.destructured.ir new file mode 100644 index 0000000000..53748840fe --- /dev/null +++ b/test_cases/struct_by_name/out_unoptimized/DemoContract.destructured.ir @@ -0,0 +1,102 @@ +contract test_cases.struct_by_name.contract.DemoContract: + program approval: + subroutine algopy.arc4.ARC4Contract.approval_program() -> bool: + block@0: // L1 + let tmp%0#0: bool = test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__() + return tmp%0#0 + + subroutine test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__() -> bool: + block@0: // L16 + let tmp%0#0: uint64 = (txn NumAppArgs) + let tmp%1#0: bool = (!= tmp%0#0 0u) + goto tmp%1#0 ? block@1 : block@7 + block@1: // abi_routing_L16 + let tmp%2#0: bytes = (txna ApplicationArgs 0) + switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "compare()bool" => block@4, * => block@5} + block@2: // get_one_route_L23 + let tmp%3#0: uint64 = (txn OnCompletion) + let tmp%4#0: bool = (== tmp%3#0 NoOp) + (assert tmp%4#0) // OnCompletion is not NoOp + let tmp%5#0: uint64 = (txn ApplicationID) + let tmp%6#0: bool = (!= tmp%5#0 0u) + (assert tmp%6#0) // can only call when not creating + let (elements_to_encode%0#0: bytes, elements_to_encode%1#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_one() + let encoded_tuple_buffer%1#0: bytes = (concat 0x elements_to_encode%0#0) + let encoded_tuple_buffer%2#0: bytes = (concat encoded_tuple_buffer%1#0 elements_to_encode%1#0) + let tmp%7#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%2#0) + (log tmp%7#0) + return 1u + block@3: // get_two_route_L30 + let tmp%8#0: uint64 = (txn OnCompletion) + let tmp%9#0: bool = (== tmp%8#0 NoOp) + (assert tmp%9#0) // OnCompletion is not NoOp + let tmp%10#0: uint64 = (txn ApplicationID) + let tmp%11#0: bool = (!= tmp%10#0 0u) + (assert tmp%11#0) // can only call when not creating + let (elements_to_encode%2#0: bytes, elements_to_encode%3#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_two() + let encoded_tuple_buffer%4#0: bytes = (concat 0x elements_to_encode%2#0) + let encoded_tuple_buffer%5#0: bytes = (concat encoded_tuple_buffer%4#0 elements_to_encode%3#0) + let tmp%12#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%5#0) + (log tmp%12#0) + return 1u + block@4: // compare_route_L37 + let tmp%13#0: uint64 = (txn OnCompletion) + let tmp%14#0: bool = (== tmp%13#0 NoOp) + (assert tmp%14#0) // OnCompletion is not NoOp + let tmp%15#0: uint64 = (txn ApplicationID) + let tmp%16#0: bool = (!= tmp%15#0 0u) + (assert tmp%16#0) // can only call when not creating + let to_encode%0#0: bool = test_cases.struct_by_name.contract.DemoContract.compare() + let encoded_bool%0#0: bytes = (setbit 0x00 0u to_encode%0#0) + let tmp%17#0: bytes = (concat 0x151f7c75 encoded_bool%0#0) + (log tmp%17#0) + return 1u + block@5: // switch_case_default_L16 + goto block@6 + block@6: // switch_case_next_L16 + goto block@11 + block@7: // bare_routing_L16 + let tmp%18#0: uint64 = (txn OnCompletion) + switch tmp%18#0 {0u => block@8, * => block@9} + block@8: // __algopy_default_create_L1 + let tmp%19#0: uint64 = (txn ApplicationID) + let tmp%20#0: bool = (== tmp%19#0 0u) + (assert tmp%20#0) // can only call when creating + test_cases.struct_by_name.contract.DemoContract.__algopy_default_create() + return 1u + block@9: // switch_case_default_L16 + goto block@10 + block@10: // switch_case_next_L16 + goto block@11 + block@11: // after_if_else_L16 + return 0u + + subroutine test_cases.struct_by_name.contract.DemoContract.get_one() -> : + block@0: // L23 + return 0x01 0x01 + + subroutine test_cases.struct_by_name.contract.DemoContract.get_two() -> : + block@0: // L30 + return 0x01 0x01 + + subroutine test_cases.struct_by_name.contract.DemoContract.compare() -> bool: + block@0: // L37 + let (awst_tmp%0#0: bytes, awst_tmp%1#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_one() + let reinterpret_biguint%0#0: biguint = awst_tmp%0#0 + let (awst_tmp%2#0: bytes, awst_tmp%3#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_two() + let reinterpret_biguint%1#0: biguint = awst_tmp%2#0 + let tmp%0#0: bool = (b== reinterpret_biguint%0#0 reinterpret_biguint%1#0) + let reinterpret_biguint%2#0: biguint = awst_tmp%1#0 + let reinterpret_biguint%3#0: biguint = awst_tmp%3#0 + let tmp%1#0: bool = (b== reinterpret_biguint%2#0 reinterpret_biguint%3#0) + let tmp%2#0: bool = (&& tmp%0#0 tmp%1#0) + return tmp%2#0 + + subroutine test_cases.struct_by_name.contract.DemoContract.__algopy_default_create() -> void: + block@0: // L1 + return + + program clear-state: + subroutine algopy.arc4.ARC4Contract.clear_state_program() -> bool: + block@0: // L1 + return 1u \ No newline at end of file diff --git a/test_cases/struct_by_name/puya.log b/test_cases/struct_by_name/puya.log new file mode 100644 index 0000000000..64af4f262d --- /dev/null +++ b/test_cases/struct_by_name/puya.log @@ -0,0 +1,815 @@ +debug: PuyaPyOptions(output_teal=True, output_source_map=True, output_arc32=True, output_arc56=True, output_ssa_ir=True, output_optimization_ir=True, output_destructured_ir=True, output_memory_ir=True, output_bytecode=True, debug_level=1, optimization_level=1, target_avm_version=10, cli_template_definitions={}, template_vars_prefix='TMPL_', locals_coalescing_strategy=, paths=['struct_by_name'], output_awst=True, output_awst_json=False, output_client=True, log_level=) +info: Found python prefix: /.venv +info: writing struct_by_name/out/module.awst +debug: Sealing block@0: // L12 +debug: Terminated block@0: // L12 +debug: Looking for 'required_budget_with_buffer' in an unsealed block creating an incomplete Phi: block@1: // while_top_L20 +debug: Created Phi assignment: let required_budget_with_buffer#1: uint64 = undefined while trying to resolve 'required_budget_with_buffer' in block@1: // while_top_L20 +debug: Terminated block@1: // while_top_L20 +debug: Sealing block@2: // while_body_L21 +debug: Looking for 'fee_source' in an unsealed block creating an incomplete Phi: block@1: // while_top_L20 +debug: Created Phi assignment: let fee_source#1: uint64 = undefined while trying to resolve 'fee_source' in block@1: // while_top_L20 +debug: Terminated block@2: // while_body_L21 +debug: Sealing block@3: // switch_case_0_L28 +debug: Terminated block@3: // switch_case_0_L28 +debug: Sealing block@4: // switch_case_1_L30 +debug: Terminated block@4: // switch_case_1_L30 +debug: Sealing block@5: // switch_case_default_L26 +debug: Terminated block@5: // switch_case_default_L26 +debug: Sealing block@6: // switch_case_next_L26 +debug: Terminated block@6: // switch_case_next_L26 +debug: Sealing block@1: // while_top_L20 +debug: Added required_budget_with_buffer#0 to Phi node: let required_budget_with_buffer#1: uint64 = φ(required_budget_with_buffer#0 <- block@0) in block@0: // L12 +debug: Created Phi assignment: let required_budget_with_buffer#2: uint64 = undefined while trying to resolve 'required_budget_with_buffer' in block@6: // switch_case_next_L26 +debug: Added required_budget_with_buffer#1 to Phi node: let required_budget_with_buffer#2: uint64 = φ(required_budget_with_buffer#1 <- block@3) in block@3: // switch_case_0_L28 +debug: Added required_budget_with_buffer#1 to Phi node: let required_budget_with_buffer#2: uint64 = φ(required_budget_with_buffer#1 <- block@3, required_budget_with_buffer#1 <- block@4) in block@4: // switch_case_1_L30 +debug: Added required_budget_with_buffer#1 to Phi node: let required_budget_with_buffer#2: uint64 = φ(required_budget_with_buffer#1 <- block@3, required_budget_with_buffer#1 <- block@4, required_budget_with_buffer#1 <- block@5) in block@5: // switch_case_default_L26 +debug: Replacing trivial Phi node: let required_budget_with_buffer#2: uint64 = φ(required_budget_with_buffer#1 <- block@3, required_budget_with_buffer#1 <- block@4, required_budget_with_buffer#1 <- block@5) (required_budget_with_buffer#2) with required_budget_with_buffer#1 +debug: Deleting Phi assignment: let required_budget_with_buffer#2: uint64 = φ(required_budget_with_buffer#1 <- block@3, required_budget_with_buffer#1 <- block@4, required_budget_with_buffer#1 <- block@5) +debug: Replaced trivial Phi node: let required_budget_with_buffer#2: uint64 = φ(required_budget_with_buffer#1 <- block@3, required_budget_with_buffer#1 <- block@4, required_budget_with_buffer#1 <- block@5) (required_budget_with_buffer#2) with required_budget_with_buffer#1 in current definition for 1 blocks +debug: Added required_budget_with_buffer#1 to Phi node: let required_budget_with_buffer#1: uint64 = φ(required_budget_with_buffer#0 <- block@0, required_budget_with_buffer#1 <- block@6) in block@6: // switch_case_next_L26 +debug: Replacing trivial Phi node: let required_budget_with_buffer#1: uint64 = φ(required_budget_with_buffer#0 <- block@0, required_budget_with_buffer#1 <- block@6) (required_budget_with_buffer#1) with required_budget_with_buffer#0 +debug: Deleting Phi assignment: let required_budget_with_buffer#1: uint64 = φ(required_budget_with_buffer#0 <- block@0, required_budget_with_buffer#1 <- block@6) +debug: Replaced trivial Phi node: let required_budget_with_buffer#1: uint64 = φ(required_budget_with_buffer#0 <- block@0, required_budget_with_buffer#1 <- block@6) (required_budget_with_buffer#1) with required_budget_with_buffer#0 in current definition for 6 blocks +debug: Added fee_source#0 to Phi node: let fee_source#1: uint64 = φ(fee_source#0 <- block@0) in block@0: // L12 +debug: Created Phi assignment: let fee_source#2: uint64 = undefined while trying to resolve 'fee_source' in block@6: // switch_case_next_L26 +debug: Added fee_source#1 to Phi node: let fee_source#2: uint64 = φ(fee_source#1 <- block@3) in block@3: // switch_case_0_L28 +debug: Added fee_source#1 to Phi node: let fee_source#2: uint64 = φ(fee_source#1 <- block@3, fee_source#1 <- block@4) in block@4: // switch_case_1_L30 +debug: Added fee_source#1 to Phi node: let fee_source#2: uint64 = φ(fee_source#1 <- block@3, fee_source#1 <- block@4, fee_source#1 <- block@5) in block@5: // switch_case_default_L26 +debug: Replacing trivial Phi node: let fee_source#2: uint64 = φ(fee_source#1 <- block@3, fee_source#1 <- block@4, fee_source#1 <- block@5) (fee_source#2) with fee_source#1 +debug: Deleting Phi assignment: let fee_source#2: uint64 = φ(fee_source#1 <- block@3, fee_source#1 <- block@4, fee_source#1 <- block@5) +debug: Replaced trivial Phi node: let fee_source#2: uint64 = φ(fee_source#1 <- block@3, fee_source#1 <- block@4, fee_source#1 <- block@5) (fee_source#2) with fee_source#1 in current definition for 1 blocks +debug: Added fee_source#1 to Phi node: let fee_source#1: uint64 = φ(fee_source#0 <- block@0, fee_source#1 <- block@6) in block@6: // switch_case_next_L26 +debug: Replacing trivial Phi node: let fee_source#1: uint64 = φ(fee_source#0 <- block@0, fee_source#1 <- block@6) (fee_source#1) with fee_source#0 +debug: Deleting Phi assignment: let fee_source#1: uint64 = φ(fee_source#0 <- block@0, fee_source#1 <- block@6) +debug: Replaced trivial Phi node: let fee_source#1: uint64 = φ(fee_source#0 <- block@0, fee_source#1 <- block@6) (fee_source#1) with fee_source#0 in current definition for 6 blocks +debug: Sealing block@7: // after_while_L20 +debug: Terminated block@7: // after_while_L20 +debug: Sealing block@0: // L4 +debug: Terminated block@0: // L4 +debug: Looking for 'start' in an unsealed block creating an incomplete Phi: block@1: // while_top_L11 +debug: Created Phi assignment: let start#1: uint64 = undefined while trying to resolve 'start' in block@1: // while_top_L11 +debug: Looking for 'item' in an unsealed block creating an incomplete Phi: block@1: // while_top_L11 +debug: Created Phi assignment: let item#1: bytes = undefined while trying to resolve 'item' in block@1: // while_top_L11 +debug: Looking for 'sequence' in an unsealed block creating an incomplete Phi: block@1: // while_top_L11 +debug: Created Phi assignment: let sequence#1: bytes = undefined while trying to resolve 'sequence' in block@1: // while_top_L11 +debug: Terminated block@1: // while_top_L11 +debug: Sealing block@2: // while_body_L12 +debug: Terminated block@2: // while_body_L12 +debug: Sealing block@3: // if_body_L13 +debug: Terminated block@3: // if_body_L13 +debug: Sealing block@4: // after_if_else_L12 +debug: Terminated block@4: // after_if_else_L12 +debug: Sealing block@1: // while_top_L11 +debug: Added start#0 to Phi node: let start#1: uint64 = φ(start#0 <- block@0) in block@0: // L4 +debug: Added start#2 to Phi node: let start#1: uint64 = φ(start#0 <- block@0, start#2 <- block@4) in block@4: // after_if_else_L12 +debug: Added item#0 to Phi node: let item#1: bytes = φ(item#0 <- block@0) in block@0: // L4 +debug: Added item#1 to Phi node: let item#1: bytes = φ(item#0 <- block@0, item#1 <- block@4) in block@4: // after_if_else_L12 +debug: Replacing trivial Phi node: let item#1: bytes = φ(item#0 <- block@0, item#1 <- block@4) (item#1) with item#0 +debug: Deleting Phi assignment: let item#1: bytes = φ(item#0 <- block@0, item#1 <- block@4) +debug: Replaced trivial Phi node: let item#1: bytes = φ(item#0 <- block@0, item#1 <- block@4) (item#1) with item#0 in current definition for 3 blocks +debug: Added sequence#0 to Phi node: let sequence#1: bytes = φ(sequence#0 <- block@0) in block@0: // L4 +debug: Added sequence#1 to Phi node: let sequence#1: bytes = φ(sequence#0 <- block@0, sequence#1 <- block@4) in block@4: // after_if_else_L12 +debug: Replacing trivial Phi node: let sequence#1: bytes = φ(sequence#0 <- block@0, sequence#1 <- block@4) (sequence#1) with sequence#0 +debug: Deleting Phi assignment: let sequence#1: bytes = φ(sequence#0 <- block@0, sequence#1 <- block@4) +debug: Replaced trivial Phi node: let sequence#1: bytes = φ(sequence#0 <- block@0, sequence#1 <- block@4) (sequence#1) with sequence#0 in current definition for 3 blocks +debug: Sealing block@5: // after_while_L11 +debug: Terminated block@5: // after_while_L11 +debug: Sealing block@0: // L25 +debug: Terminated block@0: // L25 +debug: Sealing block@0: // L44 +debug: Terminated block@0: // L44 +debug: Sealing block@0: // L62 +debug: Terminated block@0: // L62 +debug: Sealing block@0: // L92 +debug: Terminated block@0: // L92 +debug: Looking for 'head_offset' in an unsealed block creating an incomplete Phi: block@1: // for_header_L110 +debug: Created Phi assignment: let head_offset#1: uint64 = undefined while trying to resolve 'head_offset' in block@1: // for_header_L110 +debug: Terminated block@1: // for_header_L110 +debug: Sealing block@2: // for_body_L111 +debug: Looking for 'head_and_tail' in an unsealed block creating an incomplete Phi: block@1: // for_header_L110 +debug: Created Phi assignment: let head_and_tail#1: bytes = undefined while trying to resolve 'head_and_tail' in block@1: // for_header_L110 +debug: Looking for 'new_head' in an unsealed block creating an incomplete Phi: block@1: // for_header_L110 +debug: Created Phi assignment: let new_head#1: bytes = undefined while trying to resolve 'new_head' in block@1: // for_header_L110 +debug: Terminated block@2: // for_body_L111 +debug: Sealing block@3: // for_footer_L110 +debug: Terminated block@3: // for_footer_L110 +debug: Sealing block@1: // for_header_L110 +debug: Added head_offset#0 to Phi node: let head_offset#1: uint64 = φ(head_offset#0 <- block@0) in block@0: // L92 +debug: Added head_offset#2 to Phi node: let head_offset#1: uint64 = φ(head_offset#0 <- block@0, head_offset#2 <- block@3) in block@3: // for_footer_L110 +debug: Added head_and_tail#0 to Phi node: let head_and_tail#1: bytes = φ(head_and_tail#0 <- block@0) in block@0: // L92 +debug: Added head_and_tail#1 to Phi node: let head_and_tail#1: bytes = φ(head_and_tail#0 <- block@0, head_and_tail#1 <- block@3) in block@3: // for_footer_L110 +debug: Replacing trivial Phi node: let head_and_tail#1: bytes = φ(head_and_tail#0 <- block@0, head_and_tail#1 <- block@3) (head_and_tail#1) with head_and_tail#0 +debug: Deleting Phi assignment: let head_and_tail#1: bytes = φ(head_and_tail#0 <- block@0, head_and_tail#1 <- block@3) +debug: Replaced trivial Phi node: let head_and_tail#1: bytes = φ(head_and_tail#0 <- block@0, head_and_tail#1 <- block@3) (head_and_tail#1) with head_and_tail#0 in current definition for 3 blocks +debug: Added new_head#0 to Phi node: let new_head#1: bytes = φ(new_head#0 <- block@0) in block@0: // L92 +debug: Added new_head#2 to Phi node: let new_head#1: bytes = φ(new_head#0 <- block@0, new_head#2 <- block@3) in block@3: // for_footer_L110 +debug: Sealing block@4: // after_for_L110 +debug: Created Phi assignment: let length_minus_1#1: uint64 = undefined while trying to resolve 'length_minus_1' in block@1: // for_header_L110 +debug: Added length_minus_1#0 to Phi node: let length_minus_1#1: uint64 = φ(length_minus_1#0 <- block@0) in block@0: // L92 +debug: Added length_minus_1#1 to Phi node: let length_minus_1#1: uint64 = φ(length_minus_1#0 <- block@0, length_minus_1#1 <- block@3) in block@3: // for_footer_L110 +debug: Replacing trivial Phi node: let length_minus_1#1: uint64 = φ(length_minus_1#0 <- block@0, length_minus_1#1 <- block@3) (length_minus_1#1) with length_minus_1#0 +debug: Deleting Phi assignment: let length_minus_1#1: uint64 = φ(length_minus_1#0 <- block@0, length_minus_1#1 <- block@3) +debug: Replaced trivial Phi node: let length_minus_1#1: uint64 = φ(length_minus_1#0 <- block@0, length_minus_1#1 <- block@3) (length_minus_1#1) with length_minus_1#0 in current definition for 3 blocks +debug: Created Phi assignment: let popped_header_offset#1: uint64 = undefined while trying to resolve 'popped_header_offset' in block@1: // for_header_L110 +debug: Added popped_header_offset#0 to Phi node: let popped_header_offset#1: uint64 = φ(popped_header_offset#0 <- block@0) in block@0: // L92 +debug: Added popped_header_offset#1 to Phi node: let popped_header_offset#1: uint64 = φ(popped_header_offset#0 <- block@0, popped_header_offset#1 <- block@3) in block@3: // for_footer_L110 +debug: Replacing trivial Phi node: let popped_header_offset#1: uint64 = φ(popped_header_offset#0 <- block@0, popped_header_offset#1 <- block@3) (popped_header_offset#1) with popped_header_offset#0 +debug: Deleting Phi assignment: let popped_header_offset#1: uint64 = φ(popped_header_offset#0 <- block@0, popped_header_offset#1 <- block@3) +debug: Replaced trivial Phi node: let popped_header_offset#1: uint64 = φ(popped_header_offset#0 <- block@0, popped_header_offset#1 <- block@3) (popped_header_offset#1) with popped_header_offset#0 in current definition for 3 blocks +debug: Created Phi assignment: let popped_offset#1: uint64 = undefined while trying to resolve 'popped_offset' in block@1: // for_header_L110 +debug: Added popped_offset#0 to Phi node: let popped_offset#1: uint64 = φ(popped_offset#0 <- block@0) in block@0: // L92 +debug: Added popped_offset#1 to Phi node: let popped_offset#1: uint64 = φ(popped_offset#0 <- block@0, popped_offset#1 <- block@3) in block@3: // for_footer_L110 +debug: Replacing trivial Phi node: let popped_offset#1: uint64 = φ(popped_offset#0 <- block@0, popped_offset#1 <- block@3) (popped_offset#1) with popped_offset#0 +debug: Deleting Phi assignment: let popped_offset#1: uint64 = φ(popped_offset#0 <- block@0, popped_offset#1 <- block@3) +debug: Replaced trivial Phi node: let popped_offset#1: uint64 = φ(popped_offset#0 <- block@0, popped_offset#1 <- block@3) (popped_offset#1) with popped_offset#0 in current definition for 3 blocks +debug: Created Phi assignment: let popped#1: bytes = undefined while trying to resolve 'popped' in block@1: // for_header_L110 +debug: Added popped#0 to Phi node: let popped#1: bytes = φ(popped#0 <- block@0) in block@0: // L92 +debug: Added popped#1 to Phi node: let popped#1: bytes = φ(popped#0 <- block@0, popped#1 <- block@3) in block@3: // for_footer_L110 +debug: Replacing trivial Phi node: let popped#1: bytes = φ(popped#0 <- block@0, popped#1 <- block@3) (popped#1) with popped#0 +debug: Deleting Phi assignment: let popped#1: bytes = φ(popped#0 <- block@0, popped#1 <- block@3) +debug: Replaced trivial Phi node: let popped#1: bytes = φ(popped#0 <- block@0, popped#1 <- block@3) (popped#1) with popped#0 in current definition for 3 blocks +debug: Terminated block@4: // after_for_L110 +debug: Sealing block@0: // L124 +debug: Terminated block@0: // L124 +debug: Sealing block@1: // if_body_L147 +debug: Terminated block@1: // if_body_L147 +debug: Sealing block@2: // after_if_else_L146 +debug: Created Phi assignment: let array_length#1: uint64 = undefined while trying to resolve 'array_length' in block@2: // after_if_else_L146 +debug: Added array_length#0 to Phi node: let array_length#1: uint64 = φ(array_length#0 <- block@0) in block@0: // L124 +debug: Added array_length#0 to Phi node: let array_length#1: uint64 = φ(array_length#0 <- block@0, array_length#0 <- block@1) in block@1: // if_body_L147 +debug: Replacing trivial Phi node: let array_length#1: uint64 = φ(array_length#0 <- block@0, array_length#0 <- block@1) (array_length#1) with array_length#0 +debug: Deleting Phi assignment: let array_length#1: uint64 = φ(array_length#0 <- block@0, array_length#0 <- block@1) +debug: Replaced trivial Phi node: let array_length#1: uint64 = φ(array_length#0 <- block@0, array_length#0 <- block@1) (array_length#1) with array_length#0 in current definition for 1 blocks +debug: Created Phi assignment: let is_packed#1: bool = undefined while trying to resolve 'is_packed' in block@2: // after_if_else_L146 +debug: Added is_packed#0 to Phi node: let is_packed#1: bool = φ(is_packed#0 <- block@0) in block@0: // L124 +debug: Added is_packed#0 to Phi node: let is_packed#1: bool = φ(is_packed#0 <- block@0, is_packed#0 <- block@1) in block@1: // if_body_L147 +debug: Replacing trivial Phi node: let is_packed#1: bool = φ(is_packed#0 <- block@0, is_packed#0 <- block@1) (is_packed#1) with is_packed#0 +debug: Deleting Phi assignment: let is_packed#1: bool = φ(is_packed#0 <- block@0, is_packed#0 <- block@1) +debug: Replaced trivial Phi node: let is_packed#1: bool = φ(is_packed#0 <- block@0, is_packed#0 <- block@1) (is_packed#1) with is_packed#0 in current definition for 1 blocks +debug: Created Phi assignment: let new_items_count#1: uint64 = undefined while trying to resolve 'new_items_count' in block@2: // after_if_else_L146 +debug: Added new_items_count#0 to Phi node: let new_items_count#1: uint64 = φ(new_items_count#0 <- block@0) in block@0: // L124 +debug: Added new_items_count#0 to Phi node: let new_items_count#1: uint64 = φ(new_items_count#0 <- block@0, new_items_count#0 <- block@1) in block@1: // if_body_L147 +debug: Replacing trivial Phi node: let new_items_count#1: uint64 = φ(new_items_count#0 <- block@0, new_items_count#0 <- block@1) (new_items_count#1) with new_items_count#0 +debug: Deleting Phi assignment: let new_items_count#1: uint64 = φ(new_items_count#0 <- block@0, new_items_count#0 <- block@1) +debug: Replaced trivial Phi node: let new_items_count#1: uint64 = φ(new_items_count#0 <- block@0, new_items_count#0 <- block@1) (new_items_count#1) with new_items_count#0 in current definition for 1 blocks +debug: Terminated block@2: // after_if_else_L146 +debug: Looking for 'i' in an unsealed block creating an incomplete Phi: block@3: // for_header_L150 +debug: Created Phi assignment: let i#1: uint64 = undefined while trying to resolve 'i' in block@3: // for_header_L150 +debug: Terminated block@3: // for_header_L150 +debug: Sealing block@4: // for_body_L151 +debug: Looking for 'result' in an unsealed block creating an incomplete Phi: block@3: // for_header_L150 +debug: Created Phi assignment: let result#2: bytes = undefined while trying to resolve 'result' in block@3: // for_header_L150 +debug: Looking for 'write_offset' in an unsealed block creating an incomplete Phi: block@3: // for_header_L150 +debug: Created Phi assignment: let write_offset#1: uint64 = undefined while trying to resolve 'write_offset' in block@3: // for_header_L150 +debug: Looking for 'new_items_bytes' in an unsealed block creating an incomplete Phi: block@3: // for_header_L150 +debug: Created Phi assignment: let new_items_bytes#1: bytes = undefined while trying to resolve 'new_items_bytes' in block@3: // for_header_L150 +debug: Terminated block@4: // for_body_L151 +debug: Sealing block@5: // for_footer_L150 +debug: Terminated block@5: // for_footer_L150 +debug: Sealing block@3: // for_header_L150 +debug: Added i#0 to Phi node: let i#1: uint64 = φ(i#0 <- block@2) in block@2: // after_if_else_L146 +debug: Added i#2 to Phi node: let i#1: uint64 = φ(i#0 <- block@2, i#2 <- block@5) in block@5: // for_footer_L150 +debug: Created Phi assignment: let result#4: bytes = undefined while trying to resolve 'result' in block@2: // after_if_else_L146 +debug: Added result#0 to Phi node: let result#4: bytes = φ(result#0 <- block@0) in block@0: // L124 +debug: Added result#1 to Phi node: let result#4: bytes = φ(result#0 <- block@0, result#1 <- block@1) in block@1: // if_body_L147 +debug: Added result#4 to Phi node: let result#2: bytes = φ(result#4 <- block@2) in block@2: // after_if_else_L146 +debug: Added result#3 to Phi node: let result#2: bytes = φ(result#4 <- block@2, result#3 <- block@5) in block@5: // for_footer_L150 +debug: Added write_offset#0 to Phi node: let write_offset#1: uint64 = φ(write_offset#0 <- block@2) in block@2: // after_if_else_L146 +debug: Added write_offset#2 to Phi node: let write_offset#1: uint64 = φ(write_offset#0 <- block@2, write_offset#2 <- block@5) in block@5: // for_footer_L150 +debug: Created Phi assignment: let new_items_bytes#2: bytes = undefined while trying to resolve 'new_items_bytes' in block@2: // after_if_else_L146 +debug: Added new_items_bytes#0 to Phi node: let new_items_bytes#2: bytes = φ(new_items_bytes#0 <- block@0) in block@0: // L124 +debug: Added new_items_bytes#0 to Phi node: let new_items_bytes#2: bytes = φ(new_items_bytes#0 <- block@0, new_items_bytes#0 <- block@1) in block@1: // if_body_L147 +debug: Replacing trivial Phi node: let new_items_bytes#2: bytes = φ(new_items_bytes#0 <- block@0, new_items_bytes#0 <- block@1) (new_items_bytes#2) with new_items_bytes#0 +debug: Deleting Phi assignment: let new_items_bytes#2: bytes = φ(new_items_bytes#0 <- block@0, new_items_bytes#0 <- block@1) +debug: Replaced trivial Phi node: let new_items_bytes#2: bytes = φ(new_items_bytes#0 <- block@0, new_items_bytes#0 <- block@1) (new_items_bytes#2) with new_items_bytes#0 in current definition for 1 blocks +debug: Added new_items_bytes#0 to Phi node: let new_items_bytes#1: bytes = φ(new_items_bytes#0 <- block@2) in block@2: // after_if_else_L146 +debug: Added new_items_bytes#1 to Phi node: let new_items_bytes#1: bytes = φ(new_items_bytes#0 <- block@2, new_items_bytes#1 <- block@5) in block@5: // for_footer_L150 +debug: Replacing trivial Phi node: let new_items_bytes#1: bytes = φ(new_items_bytes#0 <- block@2, new_items_bytes#1 <- block@5) (new_items_bytes#1) with new_items_bytes#0 +debug: Deleting Phi assignment: let new_items_bytes#1: bytes = φ(new_items_bytes#0 <- block@2, new_items_bytes#1 <- block@5) +debug: Replaced trivial Phi node: let new_items_bytes#1: bytes = φ(new_items_bytes#0 <- block@2, new_items_bytes#1 <- block@5) (new_items_bytes#1) with new_items_bytes#0 in current definition for 3 blocks +debug: Sealing block@6: // after_for_L150 +debug: Terminated block@6: // after_for_L150 +debug: Sealing block@0: // L157 +debug: Terminated block@0: // L157 +debug: Sealing block@0: // L189 +debug: Terminated block@0: // L189 +debug: Looking for 'head_offset' in an unsealed block creating an incomplete Phi: block@1: // for_header_L199 +debug: Created Phi assignment: let head_offset#1: uint64 = undefined while trying to resolve 'head_offset' in block@1: // for_header_L199 +debug: Terminated block@1: // for_header_L199 +debug: Sealing block@2: // for_body_L200 +debug: Looking for 'array_head_and_tail' in an unsealed block creating an incomplete Phi: block@1: // for_header_L199 +debug: Created Phi assignment: let array_head_and_tail#1: bytes = undefined while trying to resolve 'array_head_and_tail' in block@1: // for_header_L199 +debug: Looking for 'new_head' in an unsealed block creating an incomplete Phi: block@1: // for_header_L199 +debug: Created Phi assignment: let new_head#1: bytes = undefined while trying to resolve 'new_head' in block@1: // for_header_L199 +debug: Looking for 'item_offset_adjustment' in an unsealed block creating an incomplete Phi: block@1: // for_header_L199 +debug: Created Phi assignment: let item_offset_adjustment#1: uint64 = undefined while trying to resolve 'item_offset_adjustment' in block@1: // for_header_L199 +debug: Terminated block@2: // for_body_L200 +debug: Sealing block@3: // for_footer_L199 +debug: Terminated block@3: // for_footer_L199 +debug: Sealing block@1: // for_header_L199 +debug: Added head_offset#0 to Phi node: let head_offset#1: uint64 = φ(head_offset#0 <- block@0) in block@0: // L189 +debug: Added head_offset#2 to Phi node: let head_offset#1: uint64 = φ(head_offset#0 <- block@0, head_offset#2 <- block@3) in block@3: // for_footer_L199 +debug: Added array_head_and_tail#0 to Phi node: let array_head_and_tail#1: bytes = φ(array_head_and_tail#0 <- block@0) in block@0: // L189 +debug: Added array_head_and_tail#1 to Phi node: let array_head_and_tail#1: bytes = φ(array_head_and_tail#0 <- block@0, array_head_and_tail#1 <- block@3) in block@3: // for_footer_L199 +debug: Replacing trivial Phi node: let array_head_and_tail#1: bytes = φ(array_head_and_tail#0 <- block@0, array_head_and_tail#1 <- block@3) (array_head_and_tail#1) with array_head_and_tail#0 +debug: Deleting Phi assignment: let array_head_and_tail#1: bytes = φ(array_head_and_tail#0 <- block@0, array_head_and_tail#1 <- block@3) +debug: Replaced trivial Phi node: let array_head_and_tail#1: bytes = φ(array_head_and_tail#0 <- block@0, array_head_and_tail#1 <- block@3) (array_head_and_tail#1) with array_head_and_tail#0 in current definition for 3 blocks +debug: Added new_head#0 to Phi node: let new_head#1: bytes = φ(new_head#0 <- block@0) in block@0: // L189 +debug: Added new_head#2 to Phi node: let new_head#1: bytes = φ(new_head#0 <- block@0, new_head#2 <- block@3) in block@3: // for_footer_L199 +debug: Added item_offset_adjustment#0 to Phi node: let item_offset_adjustment#1: uint64 = φ(item_offset_adjustment#0 <- block@0) in block@0: // L189 +debug: Added item_offset_adjustment#1 to Phi node: let item_offset_adjustment#1: uint64 = φ(item_offset_adjustment#0 <- block@0, item_offset_adjustment#1 <- block@3) in block@3: // for_footer_L199 +debug: Replacing trivial Phi node: let item_offset_adjustment#1: uint64 = φ(item_offset_adjustment#0 <- block@0, item_offset_adjustment#1 <- block@3) (item_offset_adjustment#1) with item_offset_adjustment#0 +debug: Deleting Phi assignment: let item_offset_adjustment#1: uint64 = φ(item_offset_adjustment#0 <- block@0, item_offset_adjustment#1 <- block@3) +debug: Replaced trivial Phi node: let item_offset_adjustment#1: uint64 = φ(item_offset_adjustment#0 <- block@0, item_offset_adjustment#1 <- block@3) (item_offset_adjustment#1) with item_offset_adjustment#0 in current definition for 3 blocks +debug: Sealing block@4: // after_for_L199 +debug: Created Phi assignment: let new_items_count#1: uint64 = undefined while trying to resolve 'new_items_count' in block@1: // for_header_L199 +debug: Added new_items_count#0 to Phi node: let new_items_count#1: uint64 = φ(new_items_count#0 <- block@0) in block@0: // L189 +debug: Added new_items_count#1 to Phi node: let new_items_count#1: uint64 = φ(new_items_count#0 <- block@0, new_items_count#1 <- block@3) in block@3: // for_footer_L199 +debug: Replacing trivial Phi node: let new_items_count#1: uint64 = φ(new_items_count#0 <- block@0, new_items_count#1 <- block@3) (new_items_count#1) with new_items_count#0 +debug: Deleting Phi assignment: let new_items_count#1: uint64 = φ(new_items_count#0 <- block@0, new_items_count#1 <- block@3) +debug: Replaced trivial Phi node: let new_items_count#1: uint64 = φ(new_items_count#0 <- block@0, new_items_count#1 <- block@3) (new_items_count#1) with new_items_count#0 in current definition for 3 blocks +debug: Terminated block@4: // after_for_L199 +debug: Looking for 'head_offset' in an unsealed block creating an incomplete Phi: block@5: // for_header_L204 +debug: Created Phi assignment: let head_offset#4: uint64 = undefined while trying to resolve 'head_offset' in block@5: // for_header_L204 +debug: Terminated block@5: // for_header_L204 +debug: Sealing block@6: // for_body_L205 +debug: Looking for 'new_head_and_tail' in an unsealed block creating an incomplete Phi: block@5: // for_header_L204 +debug: Created Phi assignment: let new_head_and_tail#1: bytes = undefined while trying to resolve 'new_head_and_tail' in block@5: // for_header_L204 +debug: Looking for 'new_head' in an unsealed block creating an incomplete Phi: block@5: // for_header_L204 +debug: Created Phi assignment: let new_head#3: bytes = undefined while trying to resolve 'new_head' in block@5: // for_header_L204 +debug: Looking for 'item_offset_adjustment' in an unsealed block creating an incomplete Phi: block@5: // for_header_L204 +debug: Created Phi assignment: let item_offset_adjustment#3: uint64 = undefined while trying to resolve 'item_offset_adjustment' in block@5: // for_header_L204 +debug: Terminated block@6: // for_body_L205 +debug: Sealing block@7: // for_footer_L204 +debug: Terminated block@7: // for_footer_L204 +debug: Sealing block@5: // for_header_L204 +debug: Added head_offset#3 to Phi node: let head_offset#4: uint64 = φ(head_offset#3 <- block@4) in block@4: // after_for_L199 +debug: Added head_offset#5 to Phi node: let head_offset#4: uint64 = φ(head_offset#3 <- block@4, head_offset#5 <- block@7) in block@7: // for_footer_L204 +debug: Created Phi assignment: let new_head_and_tail#2: bytes = undefined while trying to resolve 'new_head_and_tail' in block@1: // for_header_L199 +debug: Added new_head_and_tail#0 to Phi node: let new_head_and_tail#2: bytes = φ(new_head_and_tail#0 <- block@0) in block@0: // L189 +debug: Added new_head_and_tail#2 to Phi node: let new_head_and_tail#2: bytes = φ(new_head_and_tail#0 <- block@0, new_head_and_tail#2 <- block@3) in block@3: // for_footer_L199 +debug: Replacing trivial Phi node: let new_head_and_tail#2: bytes = φ(new_head_and_tail#0 <- block@0, new_head_and_tail#2 <- block@3) (new_head_and_tail#2) with new_head_and_tail#0 +debug: Deleting Phi assignment: let new_head_and_tail#2: bytes = φ(new_head_and_tail#0 <- block@0, new_head_and_tail#2 <- block@3) +debug: Replaced trivial Phi node: let new_head_and_tail#2: bytes = φ(new_head_and_tail#0 <- block@0, new_head_and_tail#2 <- block@3) (new_head_and_tail#2) with new_head_and_tail#0 in current definition for 3 blocks +debug: Added new_head_and_tail#0 to Phi node: let new_head_and_tail#1: bytes = φ(new_head_and_tail#0 <- block@4) in block@4: // after_for_L199 +debug: Added new_head_and_tail#1 to Phi node: let new_head_and_tail#1: bytes = φ(new_head_and_tail#0 <- block@4, new_head_and_tail#1 <- block@7) in block@7: // for_footer_L204 +debug: Replacing trivial Phi node: let new_head_and_tail#1: bytes = φ(new_head_and_tail#0 <- block@4, new_head_and_tail#1 <- block@7) (new_head_and_tail#1) with new_head_and_tail#0 +debug: Deleting Phi assignment: let new_head_and_tail#1: bytes = φ(new_head_and_tail#0 <- block@4, new_head_and_tail#1 <- block@7) +debug: Replaced trivial Phi node: let new_head_and_tail#1: bytes = φ(new_head_and_tail#0 <- block@4, new_head_and_tail#1 <- block@7) (new_head_and_tail#1) with new_head_and_tail#0 in current definition for 3 blocks +debug: Added new_head#1 to Phi node: let new_head#3: bytes = φ(new_head#1 <- block@4) in block@4: // after_for_L199 +debug: Added new_head#4 to Phi node: let new_head#3: bytes = φ(new_head#1 <- block@4, new_head#4 <- block@7) in block@7: // for_footer_L204 +debug: Added item_offset_adjustment#2 to Phi node: let item_offset_adjustment#3: uint64 = φ(item_offset_adjustment#2 <- block@4) in block@4: // after_for_L199 +debug: Added item_offset_adjustment#3 to Phi node: let item_offset_adjustment#3: uint64 = φ(item_offset_adjustment#2 <- block@4, item_offset_adjustment#3 <- block@7) in block@7: // for_footer_L204 +debug: Replacing trivial Phi node: let item_offset_adjustment#3: uint64 = φ(item_offset_adjustment#2 <- block@4, item_offset_adjustment#3 <- block@7) (item_offset_adjustment#3) with item_offset_adjustment#2 +debug: Deleting Phi assignment: let item_offset_adjustment#3: uint64 = φ(item_offset_adjustment#2 <- block@4, item_offset_adjustment#3 <- block@7) +debug: Replaced trivial Phi node: let item_offset_adjustment#3: uint64 = φ(item_offset_adjustment#2 <- block@4, item_offset_adjustment#3 <- block@7) (item_offset_adjustment#3) with item_offset_adjustment#2 in current definition for 3 blocks +debug: Sealing block@8: // after_for_L204 +debug: Created Phi assignment: let array_items_count#1: uint64 = undefined while trying to resolve 'array_items_count' in block@5: // for_header_L204 +debug: Created Phi assignment: let array_items_count#2: uint64 = undefined while trying to resolve 'array_items_count' in block@1: // for_header_L199 +debug: Added array_items_count#0 to Phi node: let array_items_count#2: uint64 = φ(array_items_count#0 <- block@0) in block@0: // L189 +debug: Added array_items_count#2 to Phi node: let array_items_count#2: uint64 = φ(array_items_count#0 <- block@0, array_items_count#2 <- block@3) in block@3: // for_footer_L199 +debug: Replacing trivial Phi node: let array_items_count#2: uint64 = φ(array_items_count#0 <- block@0, array_items_count#2 <- block@3) (array_items_count#2) with array_items_count#0 +debug: Deleting Phi assignment: let array_items_count#2: uint64 = φ(array_items_count#0 <- block@0, array_items_count#2 <- block@3) +debug: Replaced trivial Phi node: let array_items_count#2: uint64 = φ(array_items_count#0 <- block@0, array_items_count#2 <- block@3) (array_items_count#2) with array_items_count#0 in current definition for 3 blocks +debug: Added array_items_count#0 to Phi node: let array_items_count#1: uint64 = φ(array_items_count#0 <- block@4) in block@4: // after_for_L199 +debug: Added array_items_count#1 to Phi node: let array_items_count#1: uint64 = φ(array_items_count#0 <- block@4, array_items_count#1 <- block@7) in block@7: // for_footer_L204 +debug: Replacing trivial Phi node: let array_items_count#1: uint64 = φ(array_items_count#0 <- block@4, array_items_count#1 <- block@7) (array_items_count#1) with array_items_count#0 +debug: Deleting Phi assignment: let array_items_count#1: uint64 = φ(array_items_count#0 <- block@4, array_items_count#1 <- block@7) +debug: Replaced trivial Phi node: let array_items_count#1: uint64 = φ(array_items_count#0 <- block@4, array_items_count#1 <- block@7) (array_items_count#1) with array_items_count#0 in current definition for 3 blocks +debug: Created Phi assignment: let new_items_count#2: uint64 = undefined while trying to resolve 'new_items_count' in block@5: // for_header_L204 +debug: Added new_items_count#0 to Phi node: let new_items_count#2: uint64 = φ(new_items_count#0 <- block@4) in block@4: // after_for_L199 +debug: Added new_items_count#2 to Phi node: let new_items_count#2: uint64 = φ(new_items_count#0 <- block@4, new_items_count#2 <- block@7) in block@7: // for_footer_L204 +debug: Replacing trivial Phi node: let new_items_count#2: uint64 = φ(new_items_count#0 <- block@4, new_items_count#2 <- block@7) (new_items_count#2) with new_items_count#0 +debug: Deleting Phi assignment: let new_items_count#2: uint64 = φ(new_items_count#0 <- block@4, new_items_count#2 <- block@7) +debug: Replaced trivial Phi node: let new_items_count#2: uint64 = φ(new_items_count#0 <- block@4, new_items_count#2 <- block@7) (new_items_count#2) with new_items_count#0 in current definition for 3 blocks +debug: Created Phi assignment: let array_head_and_tail#2: bytes = undefined while trying to resolve 'array_head_and_tail' in block@5: // for_header_L204 +debug: Added array_head_and_tail#0 to Phi node: let array_head_and_tail#2: bytes = φ(array_head_and_tail#0 <- block@4) in block@4: // after_for_L199 +debug: Added array_head_and_tail#2 to Phi node: let array_head_and_tail#2: bytes = φ(array_head_and_tail#0 <- block@4, array_head_and_tail#2 <- block@7) in block@7: // for_footer_L204 +debug: Replacing trivial Phi node: let array_head_and_tail#2: bytes = φ(array_head_and_tail#0 <- block@4, array_head_and_tail#2 <- block@7) (array_head_and_tail#2) with array_head_and_tail#0 +debug: Deleting Phi assignment: let array_head_and_tail#2: bytes = φ(array_head_and_tail#0 <- block@4, array_head_and_tail#2 <- block@7) +debug: Replaced trivial Phi node: let array_head_and_tail#2: bytes = φ(array_head_and_tail#0 <- block@4, array_head_and_tail#2 <- block@7) (array_head_and_tail#2) with array_head_and_tail#0 in current definition for 3 blocks +debug: Terminated block@8: // after_for_L204 +debug: Sealing block@0: // L217 +debug: Terminated block@0: // L217 +debug: Sealing block@0: // L240 +debug: Terminated block@0: // L240 +debug: Sealing block@0: // L252 +debug: Terminated block@0: // L252 +debug: Looking for 'head_offset' in an unsealed block creating an incomplete Phi: block@1: // for_header_L269 +debug: Created Phi assignment: let head_offset#1: uint64 = undefined while trying to resolve 'head_offset' in block@1: // for_header_L269 +debug: Terminated block@1: // for_header_L269 +debug: Sealing block@2: // for_body_L270 +debug: Looking for 'new_head_and_tail' in an unsealed block creating an incomplete Phi: block@1: // for_header_L269 +debug: Created Phi assignment: let new_head_and_tail#1: bytes = undefined while trying to resolve 'new_head_and_tail' in block@1: // for_header_L269 +debug: Looking for 'new_item_length' in an unsealed block creating an incomplete Phi: block@1: // for_header_L269 +debug: Created Phi assignment: let new_item_length#1: uint64 = undefined while trying to resolve 'new_item_length' in block@1: // for_header_L269 +debug: Looking for 'original_item_length' in an unsealed block creating an incomplete Phi: block@1: // for_header_L269 +debug: Created Phi assignment: let original_item_length#1: uint64 = undefined while trying to resolve 'original_item_length' in block@1: // for_header_L269 +debug: Terminated block@2: // for_body_L270 +debug: Sealing block@3: // for_footer_L269 +debug: Terminated block@3: // for_footer_L269 +debug: Sealing block@1: // for_header_L269 +debug: Added head_offset#0 to Phi node: let head_offset#1: uint64 = φ(head_offset#0 <- block@0) in block@0: // L252 +debug: Added head_offset#2 to Phi node: let head_offset#1: uint64 = φ(head_offset#0 <- block@0, head_offset#2 <- block@3) in block@3: // for_footer_L269 +debug: Added new_head_and_tail#0 to Phi node: let new_head_and_tail#1: bytes = φ(new_head_and_tail#0 <- block@0) in block@0: // L252 +debug: Added new_head_and_tail#2 to Phi node: let new_head_and_tail#1: bytes = φ(new_head_and_tail#0 <- block@0, new_head_and_tail#2 <- block@3) in block@3: // for_footer_L269 +debug: Added new_item_length#0 to Phi node: let new_item_length#1: uint64 = φ(new_item_length#0 <- block@0) in block@0: // L252 +debug: Added new_item_length#1 to Phi node: let new_item_length#1: uint64 = φ(new_item_length#0 <- block@0, new_item_length#1 <- block@3) in block@3: // for_footer_L269 +debug: Replacing trivial Phi node: let new_item_length#1: uint64 = φ(new_item_length#0 <- block@0, new_item_length#1 <- block@3) (new_item_length#1) with new_item_length#0 +debug: Deleting Phi assignment: let new_item_length#1: uint64 = φ(new_item_length#0 <- block@0, new_item_length#1 <- block@3) +debug: Replaced trivial Phi node: let new_item_length#1: uint64 = φ(new_item_length#0 <- block@0, new_item_length#1 <- block@3) (new_item_length#1) with new_item_length#0 in current definition for 3 blocks +debug: Added original_item_length#0 to Phi node: let original_item_length#1: uint64 = φ(original_item_length#0 <- block@0) in block@0: // L252 +debug: Added original_item_length#1 to Phi node: let original_item_length#1: uint64 = φ(original_item_length#0 <- block@0, original_item_length#1 <- block@3) in block@3: // for_footer_L269 +debug: Replacing trivial Phi node: let original_item_length#1: uint64 = φ(original_item_length#0 <- block@0, original_item_length#1 <- block@3) (original_item_length#1) with original_item_length#0 +debug: Deleting Phi assignment: let original_item_length#1: uint64 = φ(original_item_length#0 <- block@0, original_item_length#1 <- block@3) +debug: Replaced trivial Phi node: let original_item_length#1: uint64 = φ(original_item_length#0 <- block@0, original_item_length#1 <- block@3) (original_item_length#1) with original_item_length#0 in current definition for 3 blocks +debug: Sealing block@4: // after_for_L269 +debug: Terminated block@4: // after_for_L269 +debug: Sealing block@0: // L278 +debug: Terminated block@0: // L278 +debug: Sealing block@0: // L306 +debug: Terminated block@0: // L306 +debug: Looking for 'head_offset' in an unsealed block creating an incomplete Phi: block@1: // for_header_L327 +debug: Created Phi assignment: let head_offset#1: uint64 = undefined while trying to resolve 'head_offset' in block@1: // for_header_L327 +debug: Terminated block@1: // for_header_L327 +debug: Sealing block@2: // for_body_L328 +debug: Looking for 'tail_offset' in an unsealed block creating an incomplete Phi: block@1: // for_header_L327 +debug: Created Phi assignment: let tail_offset#1: uint64 = undefined while trying to resolve 'tail_offset' in block@1: // for_header_L327 +debug: Looking for 'array_head_and_tail' in an unsealed block creating an incomplete Phi: block@1: // for_header_L327 +debug: Created Phi assignment: let array_head_and_tail#1: bytes = undefined while trying to resolve 'array_head_and_tail' in block@1: // for_header_L327 +debug: Terminated block@2: // for_body_L328 +debug: Sealing block@3: // for_footer_L327 +debug: Terminated block@3: // for_footer_L327 +debug: Sealing block@1: // for_header_L327 +debug: Added head_offset#0 to Phi node: let head_offset#1: uint64 = φ(head_offset#0 <- block@0) in block@0: // L306 +debug: Added head_offset#3 to Phi node: let head_offset#1: uint64 = φ(head_offset#0 <- block@0, head_offset#3 <- block@3) in block@3: // for_footer_L327 +debug: Added tail_offset#0 to Phi node: let tail_offset#1: uint64 = φ(tail_offset#0 <- block@0) in block@0: // L306 +debug: Added tail_offset#2 to Phi node: let tail_offset#1: uint64 = φ(tail_offset#0 <- block@0, tail_offset#2 <- block@3) in block@3: // for_footer_L327 +debug: Added array_head_and_tail#0 to Phi node: let array_head_and_tail#1: bytes = φ(array_head_and_tail#0 <- block@0) in block@0: // L306 +debug: Added array_head_and_tail#2 to Phi node: let array_head_and_tail#1: bytes = φ(array_head_and_tail#0 <- block@0, array_head_and_tail#2 <- block@3) in block@3: // for_footer_L327 +debug: Sealing block@4: // after_for_L327 +debug: Terminated block@4: // after_for_L327 +debug: Sealing block@0: // L16 +debug: Terminated block@0: // L16 +debug: Sealing block@1: // abi_routing_L16 +debug: Terminated block@1: // abi_routing_L16 +debug: Sealing block@2: // get_one_route_L23 +debug: Terminated block@2: // get_one_route_L23 +debug: Sealing block@3: // get_two_route_L30 +debug: Terminated block@3: // get_two_route_L30 +debug: Sealing block@4: // compare_route_L37 +debug: Terminated block@4: // compare_route_L37 +debug: Sealing block@5: // switch_case_default_L16 +debug: Terminated block@5: // switch_case_default_L16 +debug: Sealing block@6: // switch_case_next_L16 +debug: Terminated block@6: // switch_case_next_L16 +debug: Sealing block@7: // bare_routing_L16 +debug: Terminated block@7: // bare_routing_L16 +debug: Sealing block@8: // __algopy_default_create_L1 +debug: Terminated block@8: // __algopy_default_create_L1 +debug: Sealing block@9: // switch_case_default_L16 +debug: Terminated block@9: // switch_case_default_L16 +debug: Sealing block@10: // switch_case_next_L16 +debug: Terminated block@10: // switch_case_next_L16 +debug: Sealing block@11: // after_if_else_L16 +debug: Terminated block@11: // after_if_else_L16 +debug: Sealing block@0: // L23 +debug: Terminated block@0: // L23 +debug: Sealing block@0: // L30 +debug: Terminated block@0: // L30 +debug: Sealing block@0: // L37 +debug: Terminated block@0: // L37 +debug: Sealing block@0: // L1 +debug: Terminated block@0: // L1 +debug: Sealing block@0: // L1 +debug: Terminated block@0: // L1 +debug: Sealing block@0: // L1 +debug: Terminated block@0: // L1 +debug: Output IR to struct_by_name/out/DemoContract.ssa.ir +info: optimizing test_cases.struct_by_name.contract.DemoContract at level 1 +debug: Begin optimization pass 1/100 +debug: Optimizing subroutine algopy.arc4.ARC4Contract.approval_program +debug: Splitting parallel copies prior to optimization +debug: Optimizer: Constant Replacer +debug: Optimizer: Copy Propagation +debug: Optimizer: Intrinsic Simplifier +debug: Optimizer: Remove Unused Variables +debug: Optimizer: Remove Unused Ops +debug: Optimizer: Inner Txn Field Replacer +debug: Optimizer: Replace Compiled References +debug: Optimizer: Simplify Control Ops +debug: Optimizer: Remove Linear Jump +debug: Optimizer: Remove Empty Blocks +debug: Optimizer: Remove Unreachable Blocks +debug: Optimizer: Repeated Expression Elimination +debug: Optimizer: Remove Calls To No Op Subroutines +debug: Optimizing subroutine test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__ +debug: Splitting parallel copies prior to optimization +debug: Optimizer: Constant Replacer +debug: Optimizer: Copy Propagation +debug: Optimizer: Intrinsic Simplifier +debug: Simplified (== tmp%3#0 NoOp) to (! tmp%3#0) +debug: Simplified (concat 0x elements_to_encode%0#0) to elements_to_encode%0#0 +debug: Simplified (== tmp%8#0 NoOp) to (! tmp%8#0) +debug: Simplified (concat 0x elements_to_encode%2#0) to elements_to_encode%2#0 +debug: Simplified (== tmp%13#0 NoOp) to (! tmp%13#0) +debug: Simplified (== tmp%19#0 0u) to (! tmp%19#0) +debug: Optimizer: Remove Unused Variables +debug: Removing unused variable tmp%1#0 +debug: Removing unused variable tmp%6#0 +debug: Removing unused variable current_tail_offset%0#0 +debug: Removing unused variable encoded_tuple_buffer%0#0 +debug: Removing unused variable tmp%11#0 +debug: Removing unused variable current_tail_offset%1#0 +debug: Removing unused variable encoded_tuple_buffer%3#0 +debug: Removing unused variable tmp%16#0 +debug: Optimizer: Remove Unused Ops +debug: Optimizer: Inner Txn Field Replacer +debug: Optimizer: Replace Compiled References +debug: Optimizer: Simplify Control Ops +debug: inlining the default target of a switch/goto nth +debug: adding block@1: // abi_routing_L16 as a predecessor of block@6: // switch_case_next_L16 due to inlining of block@5: // switch_case_default_L16 +debug: simplified terminator of block@1: // abi_routing_L16 from switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "compare()bool" => block@4, * => block@5} to switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "compare()bool" => block@4, * => block@6} +debug: simplifying a switch with constants into goto nth +debug: simplified terminator of block@7: // bare_routing_L16 from switch tmp%18#0 {0u => block@8, * => block@9} to goto_nth [block@8][tmp%18#0] else goto block@9 +debug: inlining the default target of a switch/goto nth +debug: adding block@1: // abi_routing_L16 as a predecessor of block@11: // after_if_else_L16 due to inlining of block@6: // switch_case_next_L16 +debug: simplified terminator of block@1: // abi_routing_L16 from switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "compare()bool" => block@4, * => block@6} to switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "compare()bool" => block@4, * => block@11} +debug: simplifying a goto nth with two targets into a conditional branch +debug: simplified terminator of block@7: // bare_routing_L16 from goto_nth [block@8][tmp%18#0] else goto block@9 to goto tmp%18#0 ? block@9 : block@8 +debug: inlining the default target of a switch/goto nth +debug: simplified terminator of block@1: // abi_routing_L16 from switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "compare()bool" => block@4, * => block@11} to switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "compare()bool" => block@4, * => return 0u} +debug: Optimizer: Remove Linear Jump +debug: Replaced predecessor block@6: // switch_case_next_L16 with block@5: // switch_case_default_L16 in block@11: // after_if_else_L16 +debug: Merged linear block@6: // switch_case_next_L16 into block@5: // switch_case_default_L16 +debug: Replaced predecessor block@10: // switch_case_next_L16 with block@9: // switch_case_default_L16 in block@11: // after_if_else_L16 +debug: Merged linear block@10: // switch_case_next_L16 into block@9: // switch_case_default_L16 +debug: Optimizer: Remove Empty Blocks +debug: Removed empty block: block@5: // switch_case_default_L16 +debug: Removed empty block: block@9: // switch_case_default_L16 +debug: Optimizer: Remove Unreachable Blocks +debug: Optimizer: Repeated Expression Elimination +debug: Optimizer: Remove Calls To No Op Subroutines +debug: Optimizing subroutine test_cases.struct_by_name.contract.DemoContract.get_one +debug: Splitting parallel copies prior to optimization +debug: Optimizer: Constant Replacer +debug: Optimizer: Copy Propagation +debug: Optimizer: Intrinsic Simplifier +debug: Optimizer: Remove Unused Variables +debug: Optimizer: Remove Unused Ops +debug: Optimizer: Inner Txn Field Replacer +debug: Optimizer: Replace Compiled References +debug: Optimizer: Simplify Control Ops +debug: Optimizer: Remove Linear Jump +debug: Optimizer: Remove Empty Blocks +debug: Optimizer: Remove Unreachable Blocks +debug: Optimizer: Repeated Expression Elimination +debug: Optimizer: Remove Calls To No Op Subroutines +debug: Optimizing subroutine test_cases.struct_by_name.contract.DemoContract.get_two +debug: Splitting parallel copies prior to optimization +debug: Optimizer: Constant Replacer +debug: Optimizer: Copy Propagation +debug: Optimizer: Intrinsic Simplifier +debug: Optimizer: Remove Unused Variables +debug: Optimizer: Remove Unused Ops +debug: Optimizer: Inner Txn Field Replacer +debug: Optimizer: Replace Compiled References +debug: Optimizer: Simplify Control Ops +debug: Optimizer: Remove Linear Jump +debug: Optimizer: Remove Empty Blocks +debug: Optimizer: Remove Unreachable Blocks +debug: Optimizer: Repeated Expression Elimination +debug: Optimizer: Remove Calls To No Op Subroutines +debug: Optimizing subroutine test_cases.struct_by_name.contract.DemoContract.compare +debug: Splitting parallel copies prior to optimization +debug: Optimizer: Constant Replacer +debug: Optimizer: Copy Propagation +debug: Found equivalence set: awst_tmp%0#0, reinterpret_biguint%0#0 +debug: Replacing {reinterpret_biguint%0#0} with awst_tmp%0#0 made 1 modifications +debug: Found equivalence set: awst_tmp%2#0, reinterpret_biguint%1#0 +debug: Replacing {reinterpret_biguint%1#0} with awst_tmp%2#0 made 1 modifications +debug: Found equivalence set: awst_tmp%1#0, reinterpret_biguint%2#0 +debug: Replacing {reinterpret_biguint%2#0} with awst_tmp%1#0 made 1 modifications +debug: Found equivalence set: awst_tmp%3#0, reinterpret_biguint%3#0 +debug: Replacing {reinterpret_biguint%3#0} with awst_tmp%3#0 made 1 modifications +debug: Optimizer: Intrinsic Simplifier +debug: Optimizer: Remove Unused Variables +debug: Optimizer: Remove Unused Ops +debug: Optimizer: Inner Txn Field Replacer +debug: Optimizer: Replace Compiled References +debug: Optimizer: Simplify Control Ops +debug: Optimizer: Remove Linear Jump +debug: Optimizer: Remove Empty Blocks +debug: Optimizer: Remove Unreachable Blocks +debug: Optimizer: Repeated Expression Elimination +debug: Optimizer: Remove Calls To No Op Subroutines +debug: Optimizing subroutine test_cases.struct_by_name.contract.DemoContract.__algopy_default_create +debug: Splitting parallel copies prior to optimization +debug: Optimizer: Constant Replacer +debug: Optimizer: Copy Propagation +debug: Optimizer: Intrinsic Simplifier +debug: Optimizer: Remove Unused Variables +debug: Optimizer: Remove Unused Ops +debug: Optimizer: Inner Txn Field Replacer +debug: Optimizer: Replace Compiled References +debug: Optimizer: Simplify Control Ops +debug: Optimizer: Remove Linear Jump +debug: Optimizer: Remove Empty Blocks +debug: Optimizer: Remove Unreachable Blocks +debug: Optimizer: Repeated Expression Elimination +debug: Optimizer: Remove Calls To No Op Subroutines +debug: Optimizing subroutine algopy.arc4.ARC4Contract.clear_state_program +debug: Splitting parallel copies prior to optimization +debug: Optimizer: Constant Replacer +debug: Optimizer: Copy Propagation +debug: Optimizer: Intrinsic Simplifier +debug: Optimizer: Remove Unused Variables +debug: Optimizer: Remove Unused Ops +debug: Optimizer: Inner Txn Field Replacer +debug: Optimizer: Replace Compiled References +debug: Optimizer: Simplify Control Ops +debug: Optimizer: Remove Linear Jump +debug: Optimizer: Remove Empty Blocks +debug: Optimizer: Remove Unreachable Blocks +debug: Optimizer: Repeated Expression Elimination +debug: Optimizer: Remove Calls To No Op Subroutines +debug: Output IR to struct_by_name/out/DemoContract.ssa.opt_pass_1.ir +debug: Begin optimization pass 2/100 +debug: Optimizing subroutine algopy.arc4.ARC4Contract.approval_program +debug: Optimizer: Constant Replacer +debug: Optimizer: Copy Propagation +debug: Optimizer: Intrinsic Simplifier +debug: Optimizer: Remove Unused Variables +debug: Optimizer: Remove Unused Ops +debug: Optimizer: Inner Txn Field Replacer +debug: Optimizer: Replace Compiled References +debug: Optimizer: Simplify Control Ops +debug: Optimizer: Remove Linear Jump +debug: Optimizer: Remove Empty Blocks +debug: Optimizer: Remove Unreachable Blocks +debug: Optimizer: Repeated Expression Elimination +debug: Optimizer: Remove Calls To No Op Subroutines +debug: Optimizing subroutine test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__ +debug: Optimizer: Constant Replacer +debug: Optimizer: Copy Propagation +debug: Found equivalence set: elements_to_encode%0#0, encoded_tuple_buffer%1#0 +debug: Replacing {encoded_tuple_buffer%1#0} with elements_to_encode%0#0 made 1 modifications +debug: Found equivalence set: elements_to_encode%2#0, encoded_tuple_buffer%4#0 +debug: Replacing {encoded_tuple_buffer%4#0} with elements_to_encode%2#0 made 1 modifications +debug: Optimizer: Intrinsic Simplifier +debug: Optimizer: Remove Unused Variables +debug: Optimizer: Remove Unused Ops +debug: Optimizer: Inner Txn Field Replacer +debug: Optimizer: Replace Compiled References +debug: Optimizer: Simplify Control Ops +debug: Optimizer: Remove Linear Jump +debug: Optimizer: Remove Empty Blocks +debug: Optimizer: Remove Unreachable Blocks +debug: Optimizer: Repeated Expression Elimination +debug: Optimizer: Remove Calls To No Op Subroutines +debug: Optimizing subroutine test_cases.struct_by_name.contract.DemoContract.get_one +debug: Optimizer: Constant Replacer +debug: Optimizer: Copy Propagation +debug: Optimizer: Intrinsic Simplifier +debug: Optimizer: Remove Unused Variables +debug: Optimizer: Remove Unused Ops +debug: Optimizer: Inner Txn Field Replacer +debug: Optimizer: Replace Compiled References +debug: Optimizer: Simplify Control Ops +debug: Optimizer: Remove Linear Jump +debug: Optimizer: Remove Empty Blocks +debug: Optimizer: Remove Unreachable Blocks +debug: Optimizer: Repeated Expression Elimination +debug: Optimizer: Remove Calls To No Op Subroutines +debug: Optimizing subroutine test_cases.struct_by_name.contract.DemoContract.get_two +debug: Optimizer: Constant Replacer +debug: Optimizer: Copy Propagation +debug: Optimizer: Intrinsic Simplifier +debug: Optimizer: Remove Unused Variables +debug: Optimizer: Remove Unused Ops +debug: Optimizer: Inner Txn Field Replacer +debug: Optimizer: Replace Compiled References +debug: Optimizer: Simplify Control Ops +debug: Optimizer: Remove Linear Jump +debug: Optimizer: Remove Empty Blocks +debug: Optimizer: Remove Unreachable Blocks +debug: Optimizer: Repeated Expression Elimination +debug: Optimizer: Remove Calls To No Op Subroutines +debug: Optimizing subroutine test_cases.struct_by_name.contract.DemoContract.compare +debug: Optimizer: Constant Replacer +debug: Optimizer: Copy Propagation +debug: Optimizer: Intrinsic Simplifier +debug: Optimizer: Remove Unused Variables +debug: Optimizer: Remove Unused Ops +debug: Optimizer: Inner Txn Field Replacer +debug: Optimizer: Replace Compiled References +debug: Optimizer: Simplify Control Ops +debug: Optimizer: Remove Linear Jump +debug: Optimizer: Remove Empty Blocks +debug: Optimizer: Remove Unreachable Blocks +debug: Optimizer: Repeated Expression Elimination +debug: Optimizer: Remove Calls To No Op Subroutines +debug: Optimizing subroutine algopy.arc4.ARC4Contract.clear_state_program +debug: Optimizer: Constant Replacer +debug: Optimizer: Copy Propagation +debug: Optimizer: Intrinsic Simplifier +debug: Optimizer: Remove Unused Variables +debug: Optimizer: Remove Unused Ops +debug: Optimizer: Inner Txn Field Replacer +debug: Optimizer: Replace Compiled References +debug: Optimizer: Simplify Control Ops +debug: Optimizer: Remove Linear Jump +debug: Optimizer: Remove Empty Blocks +debug: Optimizer: Remove Unreachable Blocks +debug: Optimizer: Repeated Expression Elimination +debug: Optimizer: Remove Calls To No Op Subroutines +debug: Output IR to struct_by_name/out/DemoContract.ssa.opt_pass_2.ir +debug: Begin optimization pass 3/100 +debug: Optimizing subroutine algopy.arc4.ARC4Contract.approval_program +debug: Optimizer: Constant Replacer +debug: Optimizer: Copy Propagation +debug: Optimizer: Intrinsic Simplifier +debug: Optimizer: Remove Unused Variables +debug: Optimizer: Remove Unused Ops +debug: Optimizer: Inner Txn Field Replacer +debug: Optimizer: Replace Compiled References +debug: Optimizer: Simplify Control Ops +debug: Optimizer: Remove Linear Jump +debug: Optimizer: Remove Empty Blocks +debug: Optimizer: Remove Unreachable Blocks +debug: Optimizer: Repeated Expression Elimination +debug: Optimizer: Remove Calls To No Op Subroutines +debug: Optimizing subroutine test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__ +debug: Optimizer: Constant Replacer +debug: Optimizer: Copy Propagation +debug: Optimizer: Intrinsic Simplifier +debug: Optimizer: Remove Unused Variables +debug: Optimizer: Remove Unused Ops +debug: Optimizer: Inner Txn Field Replacer +debug: Optimizer: Replace Compiled References +debug: Optimizer: Simplify Control Ops +debug: Optimizer: Remove Linear Jump +debug: Optimizer: Remove Empty Blocks +debug: Optimizer: Remove Unreachable Blocks +debug: Optimizer: Repeated Expression Elimination +debug: Optimizer: Remove Calls To No Op Subroutines +debug: Optimizing subroutine test_cases.struct_by_name.contract.DemoContract.get_one +debug: Optimizer: Constant Replacer +debug: Optimizer: Copy Propagation +debug: Optimizer: Intrinsic Simplifier +debug: Optimizer: Remove Unused Variables +debug: Optimizer: Remove Unused Ops +debug: Optimizer: Inner Txn Field Replacer +debug: Optimizer: Replace Compiled References +debug: Optimizer: Simplify Control Ops +debug: Optimizer: Remove Linear Jump +debug: Optimizer: Remove Empty Blocks +debug: Optimizer: Remove Unreachable Blocks +debug: Optimizer: Repeated Expression Elimination +debug: Optimizer: Remove Calls To No Op Subroutines +debug: Optimizing subroutine test_cases.struct_by_name.contract.DemoContract.get_two +debug: Optimizer: Constant Replacer +debug: Optimizer: Copy Propagation +debug: Optimizer: Intrinsic Simplifier +debug: Optimizer: Remove Unused Variables +debug: Optimizer: Remove Unused Ops +debug: Optimizer: Inner Txn Field Replacer +debug: Optimizer: Replace Compiled References +debug: Optimizer: Simplify Control Ops +debug: Optimizer: Remove Linear Jump +debug: Optimizer: Remove Empty Blocks +debug: Optimizer: Remove Unreachable Blocks +debug: Optimizer: Repeated Expression Elimination +debug: Optimizer: Remove Calls To No Op Subroutines +debug: Optimizing subroutine test_cases.struct_by_name.contract.DemoContract.compare +debug: Optimizer: Constant Replacer +debug: Optimizer: Copy Propagation +debug: Optimizer: Intrinsic Simplifier +debug: Optimizer: Remove Unused Variables +debug: Optimizer: Remove Unused Ops +debug: Optimizer: Inner Txn Field Replacer +debug: Optimizer: Replace Compiled References +debug: Optimizer: Simplify Control Ops +debug: Optimizer: Remove Linear Jump +debug: Optimizer: Remove Empty Blocks +debug: Optimizer: Remove Unreachable Blocks +debug: Optimizer: Repeated Expression Elimination +debug: Optimizer: Remove Calls To No Op Subroutines +debug: Optimizing subroutine algopy.arc4.ARC4Contract.clear_state_program +debug: Optimizer: Constant Replacer +debug: Optimizer: Copy Propagation +debug: Optimizer: Intrinsic Simplifier +debug: Optimizer: Remove Unused Variables +debug: Optimizer: Remove Unused Ops +debug: Optimizer: Inner Txn Field Replacer +debug: Optimizer: Replace Compiled References +debug: Optimizer: Simplify Control Ops +debug: Optimizer: Remove Linear Jump +debug: Optimizer: Remove Empty Blocks +debug: Optimizer: Remove Unreachable Blocks +debug: Optimizer: Repeated Expression Elimination +debug: Optimizer: Remove Calls To No Op Subroutines +debug: No optimizations performed in pass 3, ending loop +debug: Removing Phis from algopy.arc4.ARC4Contract.approval_program +debug: Removing Phis from test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__ +debug: Removing Phis from test_cases.struct_by_name.contract.DemoContract.get_one +debug: Removing Phis from test_cases.struct_by_name.contract.DemoContract.get_two +debug: Removing Phis from test_cases.struct_by_name.contract.DemoContract.compare +debug: Removing Phis from algopy.arc4.ARC4Contract.clear_state_program +debug: Coalescing local variables in algopy.arc4.ARC4Contract.approval_program using strategy RootOperandGrouping +debug: Coalescing resulted in 0 replacement/s +debug: Coalescing local variables in test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__ using strategy RootOperandGrouping +debug: Coalescing resulted in 0 replacement/s +debug: Coalescing local variables in test_cases.struct_by_name.contract.DemoContract.get_one using strategy RootOperandGrouping +debug: Coalescing resulted in 0 replacement/s +debug: Coalescing local variables in test_cases.struct_by_name.contract.DemoContract.get_two using strategy RootOperandGrouping +debug: Coalescing resulted in 0 replacement/s +debug: Coalescing local variables in test_cases.struct_by_name.contract.DemoContract.compare using strategy RootOperandGrouping +debug: Coalescing resulted in 0 replacement/s +debug: Coalescing local variables in algopy.arc4.ARC4Contract.clear_state_program using strategy RootOperandGrouping +debug: Coalescing resulted in 0 replacement/s +debug: Sequentializing parallel copies in algopy.arc4.ARC4Contract.approval_program +debug: Sequentializing parallel copies in test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__ +debug: Sequentializing parallel copies in test_cases.struct_by_name.contract.DemoContract.get_one +debug: Sequentializing parallel copies in test_cases.struct_by_name.contract.DemoContract.get_two +debug: Sequentializing parallel copies in test_cases.struct_by_name.contract.DemoContract.compare +debug: Sequentializing parallel copies in algopy.arc4.ARC4Contract.clear_state_program +debug: Performing post-SSA optimizations +debug: Output IR to struct_by_name/out/DemoContract.destructured.ir +debug: Inserted main_block@0.ops[1]: 'l-store-copy tmp%0#0 0' +debug: Replaced main_block@0.ops[3]: 'v-load tmp%0#0' with 'l-load tmp%0#0' +debug: Inserted __puya_arc4_router___block@0.ops[1]: 'l-store-copy tmp%0#0 0' +debug: Replaced __puya_arc4_router___block@0.ops[3]: 'v-load tmp%0#0' with 'l-load tmp%0#0' +debug: Inserted __puya_arc4_router___abi_routing@1.ops[1]: 'l-store-copy tmp%2#0 0' +debug: Replaced __puya_arc4_router___abi_routing@1.ops[6]: 'v-load tmp%2#0' with 'l-load tmp%2#0' +debug: Inserted __puya_arc4_router___get_one_route@2.ops[1]: 'l-store-copy tmp%3#0 0' +debug: Replaced __puya_arc4_router___get_one_route@2.ops[3]: 'v-load tmp%3#0' with 'l-load tmp%3#0' +debug: Inserted __puya_arc4_router___get_one_route@2.ops[5]: 'l-store-copy tmp%4#0 0' +debug: Replaced __puya_arc4_router___get_one_route@2.ops[7]: 'v-load tmp%4#0' with 'l-load tmp%4#0' +debug: Inserted __puya_arc4_router___get_one_route@2.ops[10]: 'l-store-copy tmp%5#0 0' +debug: Replaced __puya_arc4_router___get_one_route@2.ops[12]: 'v-load tmp%5#0' with 'l-load tmp%5#0' +debug: Inserted __puya_arc4_router___get_one_route@2.ops[16]: 'l-store-copy elements_to_encode%0#0 0' +debug: Replaced __puya_arc4_router___get_one_route@2.ops[18]: 'v-load elements_to_encode%0#0' with 'l-load elements_to_encode%0#0' +debug: Inserted __puya_arc4_router___get_one_route@2.ops[25]: 'l-store-copy tmp%7#0 0' +debug: Replaced __puya_arc4_router___get_one_route@2.ops[27]: 'v-load tmp%7#0' with 'l-load tmp%7#0' +debug: Inserted __puya_arc4_router___get_one_route@2.ops[21]: 'l-store-copy encoded_tuple_buffer%2#0 0' +debug: Replaced __puya_arc4_router___get_one_route@2.ops[24]: 'v-load encoded_tuple_buffer%2#0' with 'l-load encoded_tuple_buffer%2#0' +debug: Inserted __puya_arc4_router___get_one_route@2.ops[15]: 'l-store-copy elements_to_encode%1#0 1' +debug: Replaced __puya_arc4_router___get_one_route@2.ops[20]: 'v-load elements_to_encode%1#0' with 'l-load elements_to_encode%1#0' +debug: Inserted __puya_arc4_router___get_two_route@3.ops[1]: 'l-store-copy tmp%8#0 0' +debug: Replaced __puya_arc4_router___get_two_route@3.ops[3]: 'v-load tmp%8#0' with 'l-load tmp%8#0' +debug: Inserted __puya_arc4_router___get_two_route@3.ops[5]: 'l-store-copy tmp%9#0 0' +debug: Replaced __puya_arc4_router___get_two_route@3.ops[7]: 'v-load tmp%9#0' with 'l-load tmp%9#0' +debug: Inserted __puya_arc4_router___get_two_route@3.ops[10]: 'l-store-copy tmp%10#0 0' +debug: Replaced __puya_arc4_router___get_two_route@3.ops[12]: 'v-load tmp%10#0' with 'l-load tmp%10#0' +debug: Inserted __puya_arc4_router___get_two_route@3.ops[16]: 'l-store-copy elements_to_encode%2#0 0' +debug: Replaced __puya_arc4_router___get_two_route@3.ops[18]: 'v-load elements_to_encode%2#0' with 'l-load elements_to_encode%2#0' +debug: Inserted __puya_arc4_router___get_two_route@3.ops[25]: 'l-store-copy tmp%12#0 0' +debug: Replaced __puya_arc4_router___get_two_route@3.ops[27]: 'v-load tmp%12#0' with 'l-load tmp%12#0' +debug: Inserted __puya_arc4_router___get_two_route@3.ops[21]: 'l-store-copy encoded_tuple_buffer%5#0 0' +debug: Replaced __puya_arc4_router___get_two_route@3.ops[24]: 'v-load encoded_tuple_buffer%5#0' with 'l-load encoded_tuple_buffer%5#0' +debug: Inserted __puya_arc4_router___get_two_route@3.ops[15]: 'l-store-copy elements_to_encode%3#0 1' +debug: Replaced __puya_arc4_router___get_two_route@3.ops[20]: 'v-load elements_to_encode%3#0' with 'l-load elements_to_encode%3#0' +debug: Inserted __puya_arc4_router___compare_route@4.ops[1]: 'l-store-copy tmp%13#0 0' +debug: Replaced __puya_arc4_router___compare_route@4.ops[3]: 'v-load tmp%13#0' with 'l-load tmp%13#0' +debug: Inserted __puya_arc4_router___compare_route@4.ops[5]: 'l-store-copy tmp%14#0 0' +debug: Replaced __puya_arc4_router___compare_route@4.ops[7]: 'v-load tmp%14#0' with 'l-load tmp%14#0' +debug: Inserted __puya_arc4_router___compare_route@4.ops[10]: 'l-store-copy tmp%15#0 0' +debug: Replaced __puya_arc4_router___compare_route@4.ops[12]: 'v-load tmp%15#0' with 'l-load tmp%15#0' +debug: Inserted __puya_arc4_router___compare_route@4.ops[24]: 'l-store-copy tmp%17#0 0' +debug: Replaced __puya_arc4_router___compare_route@4.ops[26]: 'v-load tmp%17#0' with 'l-load tmp%17#0' +debug: Inserted __puya_arc4_router___compare_route@4.ops[20]: 'l-store-copy encoded_bool%0#0 0' +debug: Replaced __puya_arc4_router___compare_route@4.ops[23]: 'v-load encoded_bool%0#0' with 'l-load encoded_bool%0#0' +debug: Inserted __puya_arc4_router___compare_route@4.ops[15]: 'l-store-copy to_encode%0#0 0' +debug: Replaced __puya_arc4_router___compare_route@4.ops[19]: 'v-load to_encode%0#0' with 'l-load to_encode%0#0' +debug: Inserted __puya_arc4_router___bare_routing@7.ops[1]: 'l-store-copy tmp%18#0 0' +debug: Replaced __puya_arc4_router___bare_routing@7.ops[3]: 'v-load tmp%18#0' with 'l-load tmp%18#0' +debug: Inserted __puya_arc4_router_____algopy_default_create@8.ops[1]: 'l-store-copy tmp%19#0 0' +debug: Replaced __puya_arc4_router_____algopy_default_create@8.ops[3]: 'v-load tmp%19#0' with 'l-load tmp%19#0' +debug: Inserted __puya_arc4_router_____algopy_default_create@8.ops[5]: 'l-store-copy tmp%20#0 0' +debug: Replaced __puya_arc4_router_____algopy_default_create@8.ops[7]: 'v-load tmp%20#0' with 'l-load tmp%20#0' +debug: Inserted compare_block@0.ops[17]: 'l-store-copy tmp%2#0 0' +debug: Replaced compare_block@0.ops[19]: 'v-load tmp%2#0' with 'l-load tmp%2#0' +debug: Inserted compare_block@0.ops[5]: 'l-store-copy awst_tmp%2#0 0' +debug: Replaced compare_block@0.ops[8]: 'v-load awst_tmp%2#0' with 'l-load awst_tmp%2#0' +debug: Inserted compare_block@0.ops[14]: 'l-store-copy tmp%1#0 0' +debug: Replaced compare_block@0.ops[17]: 'v-load tmp%1#0' with 'l-load tmp%1#0' +debug: Inserted compare_block@0.ops[2]: 'l-store-copy awst_tmp%0#0 0' +debug: Replaced compare_block@0.ops[8]: 'v-load awst_tmp%0#0' with 'l-load awst_tmp%0#0' +debug: Inserted compare_block@0.ops[11]: 'l-store-copy tmp%0#0 0' +debug: Replaced compare_block@0.ops[18]: 'v-load tmp%0#0' with 'l-load tmp%0#0' +debug: Inserted compare_block@0.ops[5]: 'l-store-copy awst_tmp%3#0 2' +debug: Replaced compare_block@0.ops[15]: 'v-load awst_tmp%3#0' with 'l-load awst_tmp%3#0' +debug: Inserted compare_block@0.ops[1]: 'l-store-copy awst_tmp%1#0 1' +debug: Replaced compare_block@0.ops[15]: 'v-load awst_tmp%1#0' with 'l-load awst_tmp%1#0' +debug: Found 3 edge set/s for test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__ +info: Writing struct_by_name/out/DemoContract.arc32.json +info: Writing struct_by_name/out/DemoContract.arc56.json +info: Writing struct_by_name/out/DemoContract.approval.teal +info: Writing struct_by_name/out/DemoContract.clear.teal +info: Writing struct_by_name/out/DemoContract.approval.bin +info: Writing struct_by_name/out/DemoContract.clear.bin +info: Writing struct_by_name/out/DemoContract.approval.puya.map +info: Writing struct_by_name/out/DemoContract.clear.puya.map +info: writing struct_by_name/out/client_DemoContract.py \ No newline at end of file From c6dae281a429e1127de6ac9fc6477d0d0b08ebc0 Mon Sep 17 00:00:00 2001 From: Daniel McGregor Date: Mon, 25 Nov 2024 10:47:23 +0800 Subject: [PATCH 2/3] fix: correctly handle name collisions with structs in ARC-56 --- examples/sizes.txt | 4 +- src/puya/arc56.py | 10 +- src/puyapy/awst_build/arc4_client_gen.py | 15 +- test_cases/struct_by_name/contract.py | 11 +- test_cases/struct_by_name/mod.py | 8 + .../out/DemoContract.approval.teal | 104 ++++++-- .../out/DemoContract.arc32.json | 32 ++- .../out/DemoContract.arc56.json | 49 +++- .../out/DemoContract.destructured.ir | 72 ++++-- .../struct_by_name/out/DemoContract.ssa.ir | 95 ++++--- .../out/DemoContract.ssa.opt_pass_1.ir | 74 ++++-- .../out/DemoContract.ssa.opt_pass_2.ir | 73 ++++-- .../struct_by_name/out/client_DemoContract.py | 11 +- test_cases/struct_by_name/out/module.awst | 7 +- .../out_O2/DemoContract.approval.teal | 54 +++- .../out_O2/DemoContract.destructured.ir | 72 ++++-- .../DemoContract.approval.teal | 126 +++++++--- .../DemoContract.destructured.ir | 92 ++++--- test_cases/struct_by_name/puya.log | 238 +++++++++++++----- 19 files changed, 857 insertions(+), 290 deletions(-) create mode 100644 test_cases/struct_by_name/mod.py diff --git a/examples/sizes.txt b/examples/sizes.txt index 6b4cadd5eb..e729e821d6 100644 --- a/examples/sizes.txt +++ b/examples/sizes.txt @@ -112,7 +112,7 @@ state_totals 65 32 - | 32 16 - stress_tests/BruteForceRotationSearch 228 163 - | 152 106 - string_ops 156 154 - | 58 55 - - struct_by_name/Demo 205 161 - | 115 83 - + struct_by_name/Demo 271 217 - | 155 113 - struct_in_box/Example 242 206 - | 127 99 - stubs/BigUInt 192 121 - | 126 73 - stubs/Bytes 944 279 - | 606 153 - @@ -135,4 +135,4 @@ unssa/UnSSA 432 368 - | 241 204 - voting/VotingRoundApp 1580 1475 - | 727 644 - with_reentrancy/WithReentrancy 245 234 - | 126 117 - - Total 70436 54802 54743 | 33380 22388 22344 \ No newline at end of file + Total 70502 54858 54799 | 33420 22418 22374 \ No newline at end of file diff --git a/src/puya/arc56.py b/src/puya/arc56.py index bdde5a7d16..dc41217c35 100644 --- a/src/puya/arc56.py +++ b/src/puya/arc56.py @@ -181,13 +181,15 @@ def _get_source_info(debug_info: DebugInfo) -> Sequence[models.SourceInfo]: class _StructAliases: def __init__(self, structs: Iterable[ARC4Struct]) -> None: - self.aliases = dict[str, str]() + alias_to_fullname = dict[str, str]() for struct in structs: - self.aliases[struct.fullname] = ( + alias = ( struct.fullname - if struct.name in self.aliases or struct.name in models.AVMType + if struct.name in alias_to_fullname or struct.name in models.AVMType else struct.name ) + alias_to_fullname[alias] = struct.fullname + self.aliases = {v: k for k, v in alias_to_fullname.items()} @typing.overload def resolve(self, struct: str) -> str: ... @@ -203,7 +205,7 @@ def resolve(self, struct: str | None) -> str | None: def _struct_to_event(structs: _StructAliases, struct: ARC4Struct) -> models.Event: return models.Event( - name=struct.name, + name=structs.resolve(struct.name), desc=struct.desc, args=[ models.EventArg( diff --git a/src/puyapy/awst_build/arc4_client_gen.py b/src/puyapy/awst_build/arc4_client_gen.py index e5917bdf7a..683f63361d 100644 --- a/src/puyapy/awst_build/arc4_client_gen.py +++ b/src/puyapy/awst_build/arc4_client_gen.py @@ -1,3 +1,4 @@ +import re import textwrap from collections.abc import Iterable, Sequence from pathlib import Path @@ -18,6 +19,7 @@ _AUTO_GENERATED_COMMENT = "# This file is auto-generated, do not modify" _INDENT = " " * 4 +_NON_ALPHA_NUMERIC = re.compile(r"\W+") def write_arc4_client(contract: arc56.Contract, out_dir: Path) -> None: @@ -42,7 +44,7 @@ def __init__(self, contract: arc56.Contract): self.contract = contract self.python_methods = set[str]() self.struct_to_class = dict[str, str]() - self.reserved_class_names = {contract.name} + self.reserved_class_names = set[str]() self.reserved_method_names = set[str]() self.class_decls = list[str]() @@ -53,6 +55,7 @@ def generate(cls, contract: arc56.Contract) -> str: def _gen(self) -> str: # generate class definitions for any referenced structs in methods # don't generate from self.contract.structs as it may contain other struct definitions + client_class = self._unique_class(self.contract.name) for method in self.contract.methods: for struct in filter(None, (method.returns.struct, *(a.struct for a in method.args))): if struct not in self.struct_to_class and ( @@ -70,7 +73,7 @@ def _gen(self) -> str: "", *self.class_decls, "", - f"class {self.contract.name}(algopy.arc4.ARC4Client, typing.Protocol):", + f"class {client_class}(algopy.arc4.ARC4Client, typing.Protocol):", *_docstring(self.contract.desc), *self._gen_methods(), ) @@ -110,7 +113,7 @@ def _get_client_type(self, typ: str) -> str: return str(arc4_to_pytype(typ, None)) def _unique_class(self, name: str) -> str: - base_name = name + base_name = name = _get_python_safe_name(name) seq = 1 while name in self.reserved_class_names: seq += 1 @@ -120,7 +123,7 @@ def _unique_class(self, name: str) -> str: return name def _unique_method(self, name: str) -> str: - base_name = name + base_name = name = _get_python_safe_name(name) seq = 1 while name in self.reserved_method_names: seq += 1 @@ -218,3 +221,7 @@ def _indent(lines: Iterable[str] | str) -> str: if not isinstance(lines, str): lines = "\n".join(lines) return textwrap.indent(lines, _INDENT) + + +def _get_python_safe_name(name: str) -> str: + return _NON_ALPHA_NUMERIC.sub("_", name) diff --git a/test_cases/struct_by_name/contract.py b/test_cases/struct_by_name/contract.py index 39c8772de3..add2c00ff9 100644 --- a/test_cases/struct_by_name/contract.py +++ b/test_cases/struct_by_name/contract.py @@ -2,6 +2,8 @@ from algopy import ARC4Contract, arc4 +from test_cases.struct_by_name.mod import StructTwo as StructThree + class StructOne(typing.NamedTuple): x: arc4.UInt8 @@ -34,6 +36,13 @@ def get_two(self) -> StructTwo: y=arc4.UInt8(1), ) + @arc4.abimethod() + def get_three(self) -> StructThree: + return StructThree( + x=arc4.UInt8(1), + y=arc4.UInt8(1), + ) + @arc4.abimethod() def compare(self) -> bool: - return self.get_one() == self.get_two() + return self.get_one() == self.get_two() and self.get_two() == self.get_three() diff --git a/test_cases/struct_by_name/mod.py b/test_cases/struct_by_name/mod.py new file mode 100644 index 0000000000..5a38f47c92 --- /dev/null +++ b/test_cases/struct_by_name/mod.py @@ -0,0 +1,8 @@ +import typing + +from algopy import arc4 + + +class StructTwo(typing.NamedTuple): + x: arc4.UInt8 + y: arc4.UInt8 diff --git a/test_cases/struct_by_name/out/DemoContract.approval.teal b/test_cases/struct_by_name/out/DemoContract.approval.teal index 3cb930abcf..d807f4dcdf 100644 --- a/test_cases/struct_by_name/out/DemoContract.approval.teal +++ b/test_cases/struct_by_name/out/DemoContract.approval.teal @@ -9,19 +9,19 @@ test_cases.struct_by_name.contract.DemoContract.approval_program: // test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__() -> uint64: __puya_arc4_router__: - // struct_by_name/contract.py:16 + // struct_by_name/contract.py:18 // class DemoContract(ARC4Contract): proto 0 1 txn NumAppArgs - bz __puya_arc4_router___bare_routing@7 - pushbytess 0x3d694b70 0x7fb34e8a 0x46dadea3 // method "get_one()(uint8,uint8)", method "get_two()(uint8,uint8)", method "compare()bool" + bz __puya_arc4_router___bare_routing@8 + pushbytess 0x3d694b70 0x7fb34e8a 0x8ba7c4c2 0x46dadea3 // method "get_one()(uint8,uint8)", method "get_two()(uint8,uint8)", method "get_three()(uint8,uint8)", method "compare()bool" txna ApplicationArgs 0 - match __puya_arc4_router___get_one_route@2 __puya_arc4_router___get_two_route@3 __puya_arc4_router___compare_route@4 + match __puya_arc4_router___get_one_route@2 __puya_arc4_router___get_two_route@3 __puya_arc4_router___get_three_route@4 __puya_arc4_router___compare_route@5 intc_1 // 0 retsub __puya_arc4_router___get_one_route@2: - // struct_by_name/contract.py:23 + // struct_by_name/contract.py:25 // @arc4.abimethod() txn OnCompletion ! @@ -38,7 +38,7 @@ __puya_arc4_router___get_one_route@2: retsub __puya_arc4_router___get_two_route@3: - // struct_by_name/contract.py:30 + // struct_by_name/contract.py:32 // @arc4.abimethod() txn OnCompletion ! @@ -54,8 +54,25 @@ __puya_arc4_router___get_two_route@3: intc_0 // 1 retsub -__puya_arc4_router___compare_route@4: - // struct_by_name/contract.py:37 +__puya_arc4_router___get_three_route@4: + // struct_by_name/contract.py:39 + // @arc4.abimethod() + txn OnCompletion + ! + assert // OnCompletion is not NoOp + txn ApplicationID + assert // can only call when not creating + callsub get_three + concat + bytec_0 // 0x151f7c75 + swap + concat + log + intc_0 // 1 + retsub + +__puya_arc4_router___compare_route@5: + // struct_by_name/contract.py:46 // @arc4.abimethod() txn OnCompletion ! @@ -74,19 +91,19 @@ __puya_arc4_router___compare_route@4: intc_0 // 1 retsub -__puya_arc4_router___bare_routing@7: - // struct_by_name/contract.py:16 +__puya_arc4_router___bare_routing@8: + // struct_by_name/contract.py:18 // class DemoContract(ARC4Contract): txn OnCompletion - bnz __puya_arc4_router___after_if_else@11 + bnz __puya_arc4_router___after_if_else@12 txn ApplicationID ! assert // can only call when creating intc_0 // 1 retsub -__puya_arc4_router___after_if_else@11: - // struct_by_name/contract.py:16 +__puya_arc4_router___after_if_else@12: + // struct_by_name/contract.py:18 // class DemoContract(ARC4Contract): intc_1 // 0 retsub @@ -94,17 +111,17 @@ __puya_arc4_router___after_if_else@11: // test_cases.struct_by_name.contract.DemoContract.get_one() -> bytes, bytes: get_one: - // struct_by_name/contract.py:23-24 + // struct_by_name/contract.py:25-26 // @arc4.abimethod() // def get_one(self) -> StructOne: proto 0 2 - // struct_by_name/contract.py:26 + // struct_by_name/contract.py:28 // x=arc4.UInt8(1), bytec_1 // 0x01 - // struct_by_name/contract.py:27 + // struct_by_name/contract.py:29 // y=arc4.UInt8(1), dup - // struct_by_name/contract.py:25-28 + // struct_by_name/contract.py:27-30 // return StructOne( // x=arc4.UInt8(1), // y=arc4.UInt8(1), @@ -114,17 +131,17 @@ get_one: // test_cases.struct_by_name.contract.DemoContract.get_two() -> bytes, bytes: get_two: - // struct_by_name/contract.py:30-31 + // struct_by_name/contract.py:32-33 // @arc4.abimethod() // def get_two(self) -> StructTwo: proto 0 2 - // struct_by_name/contract.py:33 + // struct_by_name/contract.py:35 // x=arc4.UInt8(1), bytec_1 // 0x01 - // struct_by_name/contract.py:34 + // struct_by_name/contract.py:36 // y=arc4.UInt8(1), dup - // struct_by_name/contract.py:32-35 + // struct_by_name/contract.py:34-37 // return StructTwo( // x=arc4.UInt8(1), // y=arc4.UInt8(1), @@ -132,14 +149,34 @@ get_two: retsub +// test_cases.struct_by_name.contract.DemoContract.get_three() -> bytes, bytes: +get_three: + // struct_by_name/contract.py:39-40 + // @arc4.abimethod() + // def get_three(self) -> StructThree: + proto 0 2 + // struct_by_name/contract.py:42 + // x=arc4.UInt8(1), + bytec_1 // 0x01 + // struct_by_name/contract.py:43 + // y=arc4.UInt8(1), + dup + // struct_by_name/contract.py:41-44 + // return StructThree( + // x=arc4.UInt8(1), + // y=arc4.UInt8(1), + // ) + retsub + + // test_cases.struct_by_name.contract.DemoContract.compare() -> uint64: compare: - // struct_by_name/contract.py:37-38 + // struct_by_name/contract.py:46-47 // @arc4.abimethod() // def compare(self) -> bool: proto 0 1 - // struct_by_name/contract.py:39 - // return self.get_one() == self.get_two() + // struct_by_name/contract.py:48 + // return self.get_one() == self.get_two() and self.get_two() == self.get_three() callsub get_one callsub get_two uncover 3 @@ -148,4 +185,23 @@ compare: cover 2 b== && + bz compare_bool_false@3 + callsub get_two + callsub get_three + uncover 3 + uncover 2 + b== + cover 2 + b== + && + bz compare_bool_false@3 + intc_0 // 1 + b compare_bool_merge@4 + +compare_bool_false@3: + intc_1 // 0 + +compare_bool_merge@4: + // struct_by_name/contract.py:48 + // return self.get_one() == self.get_two() and self.get_two() == self.get_three() retsub diff --git a/test_cases/struct_by_name/out/DemoContract.arc32.json b/test_cases/struct_by_name/out/DemoContract.arc32.json index b11118a0a3..f10b5b8a20 100644 --- a/test_cases/struct_by_name/out/DemoContract.arc32.json +++ b/test_cases/struct_by_name/out/DemoContract.arc32.json @@ -40,6 +40,26 @@ } } }, + "get_three()(uint8,uint8)": { + "call_config": { + "no_op": "CALL" + }, + "structs": { + "output": { + "name": "StructTwo", + "elements": [ + [ + "x", + "uint8" + ], + [ + "y", + "uint8" + ] + ] + } + } + }, "compare()bool": { "call_config": { "no_op": "CALL" @@ -47,7 +67,7 @@ } }, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgp0ZXN0X2Nhc2VzLnN0cnVjdF9ieV9uYW1lLmNvbnRyYWN0LkRlbW9Db250cmFjdC5hcHByb3ZhbF9wcm9ncmFtOgogICAgaW50Y2Jsb2NrIDEgMAogICAgYnl0ZWNibG9jayAweDE1MWY3Yzc1IDB4MDEKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHRlc3RfY2FzZXMuc3RydWN0X2J5X25hbWUuY29udHJhY3QuRGVtb0NvbnRyYWN0Ll9fcHV5YV9hcmM0X3JvdXRlcl9fKCkgLT4gdWludDY0OgpfX3B1eWFfYXJjNF9yb3V0ZXJfXzoKICAgIC8vIHN0cnVjdF9ieV9uYW1lL2NvbnRyYWN0LnB5OjE2CiAgICAvLyBjbGFzcyBEZW1vQ29udHJhY3QoQVJDNENvbnRyYWN0KToKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A3CiAgICBwdXNoYnl0ZXNzIDB4M2Q2OTRiNzAgMHg3ZmIzNGU4YSAweDQ2ZGFkZWEzIC8vIG1ldGhvZCAiZ2V0X29uZSgpKHVpbnQ4LHVpbnQ4KSIsIG1ldGhvZCAiZ2V0X3R3bygpKHVpbnQ4LHVpbnQ4KSIsIG1ldGhvZCAiY29tcGFyZSgpYm9vbCIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2dldF9vbmVfcm91dGVAMiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19nZXRfdHdvX3JvdXRlQDMgX19wdXlhX2FyYzRfcm91dGVyX19fY29tcGFyZV9yb3V0ZUA0CiAgICBpbnRjXzEgLy8gMAogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19nZXRfb25lX3JvdXRlQDI6CiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weToyMwogICAgLy8gQGFyYzQuYWJpbWV0aG9kKCkKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgbm90IE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gY2FuIG9ubHkgY2FsbCB3aGVuIG5vdCBjcmVhdGluZwogICAgY2FsbHN1YiBnZXRfb25lCiAgICBjb25jYXQKICAgIGJ5dGVjXzAgLy8gMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludGNfMCAvLyAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2dldF90d29fcm91dGVAMzoKICAgIC8vIHN0cnVjdF9ieV9uYW1lL2NvbnRyYWN0LnB5OjMwCiAgICAvLyBAYXJjNC5hYmltZXRob2QoKQogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBub3QgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBjYW4gb25seSBjYWxsIHdoZW4gbm90IGNyZWF0aW5nCiAgICBjYWxsc3ViIGdldF90d28KICAgIGNvbmNhdAogICAgYnl0ZWNfMCAvLyAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50Y18wIC8vIDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fY29tcGFyZV9yb3V0ZUA0OgogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MzcKICAgIC8vIEBhcmM0LmFiaW1ldGhvZCgpCiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIG5vdCBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGNhbiBvbmx5IGNhbGwgd2hlbiBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgY29tcGFyZQogICAgcHVzaGJ5dGVzIDB4MDAKICAgIGludGNfMSAvLyAwCiAgICB1bmNvdmVyIDIKICAgIHNldGJpdAogICAgYnl0ZWNfMCAvLyAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50Y18wIC8vIDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDc6CiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weToxNgogICAgLy8gY2xhc3MgRGVtb0NvbnRyYWN0KEFSQzRDb250cmFjdCk6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMQogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBjYW4gb25seSBjYWxsIHdoZW4gY3JlYXRpbmcKICAgIGludGNfMCAvLyAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTE6CiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weToxNgogICAgLy8gY2xhc3MgRGVtb0NvbnRyYWN0KEFSQzRDb250cmFjdCk6CiAgICBpbnRjXzEgLy8gMAogICAgcmV0c3ViCgoKLy8gdGVzdF9jYXNlcy5zdHJ1Y3RfYnlfbmFtZS5jb250cmFjdC5EZW1vQ29udHJhY3QuZ2V0X29uZSgpIC0+IGJ5dGVzLCBieXRlczoKZ2V0X29uZToKICAgIC8vIHN0cnVjdF9ieV9uYW1lL2NvbnRyYWN0LnB5OjIzLTI0CiAgICAvLyBAYXJjNC5hYmltZXRob2QoKQogICAgLy8gZGVmIGdldF9vbmUoc2VsZikgLT4gU3RydWN0T25lOgogICAgcHJvdG8gMCAyCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weToyNgogICAgLy8geD1hcmM0LlVJbnQ4KDEpLAogICAgYnl0ZWNfMSAvLyAweDAxCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weToyNwogICAgLy8geT1hcmM0LlVJbnQ4KDEpLAogICAgZHVwCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weToyNS0yOAogICAgLy8gcmV0dXJuIFN0cnVjdE9uZSgKICAgIC8vICAgICB4PWFyYzQuVUludDgoMSksCiAgICAvLyAgICAgeT1hcmM0LlVJbnQ4KDEpLAogICAgLy8gKQogICAgcmV0c3ViCgoKLy8gdGVzdF9jYXNlcy5zdHJ1Y3RfYnlfbmFtZS5jb250cmFjdC5EZW1vQ29udHJhY3QuZ2V0X3R3bygpIC0+IGJ5dGVzLCBieXRlczoKZ2V0X3R3bzoKICAgIC8vIHN0cnVjdF9ieV9uYW1lL2NvbnRyYWN0LnB5OjMwLTMxCiAgICAvLyBAYXJjNC5hYmltZXRob2QoKQogICAgLy8gZGVmIGdldF90d28oc2VsZikgLT4gU3RydWN0VHdvOgogICAgcHJvdG8gMCAyCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weTozMwogICAgLy8geD1hcmM0LlVJbnQ4KDEpLAogICAgYnl0ZWNfMSAvLyAweDAxCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weTozNAogICAgLy8geT1hcmM0LlVJbnQ4KDEpLAogICAgZHVwCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weTozMi0zNQogICAgLy8gcmV0dXJuIFN0cnVjdFR3bygKICAgIC8vICAgICB4PWFyYzQuVUludDgoMSksCiAgICAvLyAgICAgeT1hcmM0LlVJbnQ4KDEpLAogICAgLy8gKQogICAgcmV0c3ViCgoKLy8gdGVzdF9jYXNlcy5zdHJ1Y3RfYnlfbmFtZS5jb250cmFjdC5EZW1vQ29udHJhY3QuY29tcGFyZSgpIC0+IHVpbnQ2NDoKY29tcGFyZToKICAgIC8vIHN0cnVjdF9ieV9uYW1lL2NvbnRyYWN0LnB5OjM3LTM4CiAgICAvLyBAYXJjNC5hYmltZXRob2QoKQogICAgLy8gZGVmIGNvbXBhcmUoc2VsZikgLT4gYm9vbDoKICAgIHByb3RvIDAgMQogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MzkKICAgIC8vIHJldHVybiBzZWxmLmdldF9vbmUoKSA9PSBzZWxmLmdldF90d28oKQogICAgY2FsbHN1YiBnZXRfb25lCiAgICBjYWxsc3ViIGdldF90d28KICAgIHVuY292ZXIgMwogICAgdW5jb3ZlciAyCiAgICBiPT0KICAgIGNvdmVyIDIKICAgIGI9PQogICAgJiYKICAgIHJldHN1Ygo=", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgp0ZXN0X2Nhc2VzLnN0cnVjdF9ieV9uYW1lLmNvbnRyYWN0LkRlbW9Db250cmFjdC5hcHByb3ZhbF9wcm9ncmFtOgogICAgaW50Y2Jsb2NrIDEgMAogICAgYnl0ZWNibG9jayAweDE1MWY3Yzc1IDB4MDEKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHRlc3RfY2FzZXMuc3RydWN0X2J5X25hbWUuY29udHJhY3QuRGVtb0NvbnRyYWN0Ll9fcHV5YV9hcmM0X3JvdXRlcl9fKCkgLT4gdWludDY0OgpfX3B1eWFfYXJjNF9yb3V0ZXJfXzoKICAgIC8vIHN0cnVjdF9ieV9uYW1lL2NvbnRyYWN0LnB5OjE4CiAgICAvLyBjbGFzcyBEZW1vQ29udHJhY3QoQVJDNENvbnRyYWN0KToKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A4CiAgICBwdXNoYnl0ZXNzIDB4M2Q2OTRiNzAgMHg3ZmIzNGU4YSAweDhiYTdjNGMyIDB4NDZkYWRlYTMgLy8gbWV0aG9kICJnZXRfb25lKCkodWludDgsdWludDgpIiwgbWV0aG9kICJnZXRfdHdvKCkodWludDgsdWludDgpIiwgbWV0aG9kICJnZXRfdGhyZWUoKSh1aW50OCx1aW50OCkiLCBtZXRob2QgImNvbXBhcmUoKWJvb2wiCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAwCiAgICBtYXRjaCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19nZXRfb25lX3JvdXRlQDIgX19wdXlhX2FyYzRfcm91dGVyX19fZ2V0X3R3b19yb3V0ZUAzIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2dldF90aHJlZV9yb3V0ZUA0IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2NvbXBhcmVfcm91dGVANQogICAgaW50Y18xIC8vIDAKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fZ2V0X29uZV9yb3V0ZUAyOgogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MjUKICAgIC8vIEBhcmM0LmFiaW1ldGhvZCgpCiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIG5vdCBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGNhbiBvbmx5IGNhbGwgd2hlbiBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgZ2V0X29uZQogICAgY29uY2F0CiAgICBieXRlY18wIC8vIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnRjXzAgLy8gMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19nZXRfdHdvX3JvdXRlQDM6CiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weTozMgogICAgLy8gQGFyYzQuYWJpbWV0aG9kKCkKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgbm90IE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gY2FuIG9ubHkgY2FsbCB3aGVuIG5vdCBjcmVhdGluZwogICAgY2FsbHN1YiBnZXRfdHdvCiAgICBjb25jYXQKICAgIGJ5dGVjXzAgLy8gMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludGNfMCAvLyAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2dldF90aHJlZV9yb3V0ZUA0OgogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MzkKICAgIC8vIEBhcmM0LmFiaW1ldGhvZCgpCiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIG5vdCBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGNhbiBvbmx5IGNhbGwgd2hlbiBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgZ2V0X3RocmVlCiAgICBjb25jYXQKICAgIGJ5dGVjXzAgLy8gMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludGNfMCAvLyAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2NvbXBhcmVfcm91dGVANToKICAgIC8vIHN0cnVjdF9ieV9uYW1lL2NvbnRyYWN0LnB5OjQ2CiAgICAvLyBAYXJjNC5hYmltZXRob2QoKQogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBub3QgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBjYW4gb25seSBjYWxsIHdoZW4gbm90IGNyZWF0aW5nCiAgICBjYWxsc3ViIGNvbXBhcmUKICAgIHB1c2hieXRlcyAweDAwCiAgICBpbnRjXzEgLy8gMAogICAgdW5jb3ZlciAyCiAgICBzZXRiaXQKICAgIGJ5dGVjXzAgLy8gMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludGNfMCAvLyAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A4OgogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MTgKICAgIC8vIGNsYXNzIERlbW9Db250cmFjdChBUkM0Q29udHJhY3QpOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgYm56IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTIKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gY2FuIG9ubHkgY2FsbCB3aGVuIGNyZWF0aW5nCiAgICBpbnRjXzAgLy8gMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEyOgogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MTgKICAgIC8vIGNsYXNzIERlbW9Db250cmFjdChBUkM0Q29udHJhY3QpOgogICAgaW50Y18xIC8vIDAKICAgIHJldHN1YgoKCi8vIHRlc3RfY2FzZXMuc3RydWN0X2J5X25hbWUuY29udHJhY3QuRGVtb0NvbnRyYWN0LmdldF9vbmUoKSAtPiBieXRlcywgYnl0ZXM6CmdldF9vbmU6CiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weToyNS0yNgogICAgLy8gQGFyYzQuYWJpbWV0aG9kKCkKICAgIC8vIGRlZiBnZXRfb25lKHNlbGYpIC0+IFN0cnVjdE9uZToKICAgIHByb3RvIDAgMgogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MjgKICAgIC8vIHg9YXJjNC5VSW50OCgxKSwKICAgIGJ5dGVjXzEgLy8gMHgwMQogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MjkKICAgIC8vIHk9YXJjNC5VSW50OCgxKSwKICAgIGR1cAogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MjctMzAKICAgIC8vIHJldHVybiBTdHJ1Y3RPbmUoCiAgICAvLyAgICAgeD1hcmM0LlVJbnQ4KDEpLAogICAgLy8gICAgIHk9YXJjNC5VSW50OCgxKSwKICAgIC8vICkKICAgIHJldHN1YgoKCi8vIHRlc3RfY2FzZXMuc3RydWN0X2J5X25hbWUuY29udHJhY3QuRGVtb0NvbnRyYWN0LmdldF90d28oKSAtPiBieXRlcywgYnl0ZXM6CmdldF90d286CiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weTozMi0zMwogICAgLy8gQGFyYzQuYWJpbWV0aG9kKCkKICAgIC8vIGRlZiBnZXRfdHdvKHNlbGYpIC0+IFN0cnVjdFR3bzoKICAgIHByb3RvIDAgMgogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MzUKICAgIC8vIHg9YXJjNC5VSW50OCgxKSwKICAgIGJ5dGVjXzEgLy8gMHgwMQogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MzYKICAgIC8vIHk9YXJjNC5VSW50OCgxKSwKICAgIGR1cAogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MzQtMzcKICAgIC8vIHJldHVybiBTdHJ1Y3RUd28oCiAgICAvLyAgICAgeD1hcmM0LlVJbnQ4KDEpLAogICAgLy8gICAgIHk9YXJjNC5VSW50OCgxKSwKICAgIC8vICkKICAgIHJldHN1YgoKCi8vIHRlc3RfY2FzZXMuc3RydWN0X2J5X25hbWUuY29udHJhY3QuRGVtb0NvbnRyYWN0LmdldF90aHJlZSgpIC0+IGJ5dGVzLCBieXRlczoKZ2V0X3RocmVlOgogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MzktNDAKICAgIC8vIEBhcmM0LmFiaW1ldGhvZCgpCiAgICAvLyBkZWYgZ2V0X3RocmVlKHNlbGYpIC0+IFN0cnVjdFRocmVlOgogICAgcHJvdG8gMCAyCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weTo0MgogICAgLy8geD1hcmM0LlVJbnQ4KDEpLAogICAgYnl0ZWNfMSAvLyAweDAxCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weTo0MwogICAgLy8geT1hcmM0LlVJbnQ4KDEpLAogICAgZHVwCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weTo0MS00NAogICAgLy8gcmV0dXJuIFN0cnVjdFRocmVlKAogICAgLy8gICAgIHg9YXJjNC5VSW50OCgxKSwKICAgIC8vICAgICB5PWFyYzQuVUludDgoMSksCiAgICAvLyApCiAgICByZXRzdWIKCgovLyB0ZXN0X2Nhc2VzLnN0cnVjdF9ieV9uYW1lLmNvbnRyYWN0LkRlbW9Db250cmFjdC5jb21wYXJlKCkgLT4gdWludDY0Ogpjb21wYXJlOgogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6NDYtNDcKICAgIC8vIEBhcmM0LmFiaW1ldGhvZCgpCiAgICAvLyBkZWYgY29tcGFyZShzZWxmKSAtPiBib29sOgogICAgcHJvdG8gMCAxCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weTo0OAogICAgLy8gcmV0dXJuIHNlbGYuZ2V0X29uZSgpID09IHNlbGYuZ2V0X3R3bygpIGFuZCBzZWxmLmdldF90d28oKSA9PSBzZWxmLmdldF90aHJlZSgpCiAgICBjYWxsc3ViIGdldF9vbmUKICAgIGNhbGxzdWIgZ2V0X3R3bwogICAgdW5jb3ZlciAzCiAgICB1bmNvdmVyIDIKICAgIGI9PQogICAgY292ZXIgMgogICAgYj09CiAgICAmJgogICAgYnogY29tcGFyZV9ib29sX2ZhbHNlQDMKICAgIGNhbGxzdWIgZ2V0X3R3bwogICAgY2FsbHN1YiBnZXRfdGhyZWUKICAgIHVuY292ZXIgMwogICAgdW5jb3ZlciAyCiAgICBiPT0KICAgIGNvdmVyIDIKICAgIGI9PQogICAgJiYKICAgIGJ6IGNvbXBhcmVfYm9vbF9mYWxzZUAzCiAgICBpbnRjXzAgLy8gMQogICAgYiBjb21wYXJlX2Jvb2xfbWVyZ2VANAoKY29tcGFyZV9ib29sX2ZhbHNlQDM6CiAgICBpbnRjXzEgLy8gMAoKY29tcGFyZV9ib29sX21lcmdlQDQ6CiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weTo0OAogICAgLy8gcmV0dXJuIHNlbGYuZ2V0X29uZSgpID09IHNlbGYuZ2V0X3R3bygpIGFuZCBzZWxmLmdldF90d28oKSA9PSBzZWxmLmdldF90aHJlZSgpCiAgICByZXRzdWIK", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgp0ZXN0X2Nhc2VzLnN0cnVjdF9ieV9uYW1lLmNvbnRyYWN0LkRlbW9Db250cmFjdC5jbGVhcl9zdGF0ZV9wcm9ncmFtOgogICAgcHVzaGludCAxIC8vIDEKICAgIHJldHVybgo=" }, "state": { @@ -72,7 +92,7 @@ }, "contract": { "name": "DemoContract", - "desc": "\n Verify that even though named tuples with different names, but the same structure should be\n considered 'comparable' in the type system, they should be output separately when being\n interpreted as an arc4 Struct in an abi method\n ", + "desc": "\n Verify that even though named tuples with different names but the same structure should be\n considered 'comparable' in the type system, they should be output separately when being\n interpreted as an arc4 Struct in an abi method\n ", "methods": [ { "name": "get_one", @@ -90,6 +110,14 @@ "type": "(uint8,uint8)" } }, + { + "name": "get_three", + "args": [], + "readonly": false, + "returns": { + "type": "(uint8,uint8)" + } + }, { "name": "compare", "args": [], diff --git a/test_cases/struct_by_name/out/DemoContract.arc56.json b/test_cases/struct_by_name/out/DemoContract.arc56.json index 535863467d..ad56f19e05 100644 --- a/test_cases/struct_by_name/out/DemoContract.arc56.json +++ b/test_cases/struct_by_name/out/DemoContract.arc56.json @@ -20,6 +20,16 @@ "name": "y", "type": "uint8" } + ], + "test_cases.struct_by_name.mod.StructTwo": [ + { + "name": "x", + "type": "uint8" + }, + { + "name": "y", + "type": "uint8" + } ] }, "methods": [ @@ -57,6 +67,23 @@ "events": [], "recommendations": {} }, + { + "name": "get_three", + "args": [], + "returns": { + "type": "(uint8,uint8)", + "struct": "test_cases.struct_by_name.mod.StructTwo" + }, + "actions": { + "create": [], + "call": [ + "NoOp" + ] + }, + "readonly": false, + "events": [], + "recommendations": {} + }, { "name": "compare", "args": [], @@ -78,7 +105,7 @@ 22, 28 ], - "desc": "\n Verify that even though named tuples with different names, but the same structure should be\n considered 'comparable' in the type system, they should be output separately when being\n interpreted as an arc4 Struct in an abi method\n ", + "desc": "\n Verify that even though named tuples with different names but the same structure should be\n considered 'comparable' in the type system, they should be output separately when being\n interpreted as an arc4 Struct in an abi method\n ", "networks": {}, "state": { "schema": { @@ -113,23 +140,25 @@ "sourceInfo": [ { "pc": [ - 59, - 76, - 93 + 66, + 83, + 100, + 117 ], "errorMessage": "OnCompletion is not NoOp" }, { "pc": [ - 121 + 145 ], "errorMessage": "can only call when creating" }, { "pc": [ - 62, - 79, - 96 + 69, + 86, + 103, + 120 ], "errorMessage": "can only call when not creating" } @@ -142,11 +171,11 @@ } }, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgp0ZXN0X2Nhc2VzLnN0cnVjdF9ieV9uYW1lLmNvbnRyYWN0LkRlbW9Db250cmFjdC5hcHByb3ZhbF9wcm9ncmFtOgogICAgaW50Y2Jsb2NrIDEgMAogICAgYnl0ZWNibG9jayAweDE1MWY3Yzc1IDB4MDEKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHRlc3RfY2FzZXMuc3RydWN0X2J5X25hbWUuY29udHJhY3QuRGVtb0NvbnRyYWN0Ll9fcHV5YV9hcmM0X3JvdXRlcl9fKCkgLT4gdWludDY0OgpfX3B1eWFfYXJjNF9yb3V0ZXJfXzoKICAgIC8vIHN0cnVjdF9ieV9uYW1lL2NvbnRyYWN0LnB5OjE2CiAgICAvLyBjbGFzcyBEZW1vQ29udHJhY3QoQVJDNENvbnRyYWN0KToKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A3CiAgICBwdXNoYnl0ZXNzIDB4M2Q2OTRiNzAgMHg3ZmIzNGU4YSAweDQ2ZGFkZWEzIC8vIG1ldGhvZCAiZ2V0X29uZSgpKHVpbnQ4LHVpbnQ4KSIsIG1ldGhvZCAiZ2V0X3R3bygpKHVpbnQ4LHVpbnQ4KSIsIG1ldGhvZCAiY29tcGFyZSgpYm9vbCIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2dldF9vbmVfcm91dGVAMiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19nZXRfdHdvX3JvdXRlQDMgX19wdXlhX2FyYzRfcm91dGVyX19fY29tcGFyZV9yb3V0ZUA0CiAgICBpbnRjXzEgLy8gMAogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19nZXRfb25lX3JvdXRlQDI6CiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weToyMwogICAgLy8gQGFyYzQuYWJpbWV0aG9kKCkKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgbm90IE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gY2FuIG9ubHkgY2FsbCB3aGVuIG5vdCBjcmVhdGluZwogICAgY2FsbHN1YiBnZXRfb25lCiAgICBjb25jYXQKICAgIGJ5dGVjXzAgLy8gMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludGNfMCAvLyAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2dldF90d29fcm91dGVAMzoKICAgIC8vIHN0cnVjdF9ieV9uYW1lL2NvbnRyYWN0LnB5OjMwCiAgICAvLyBAYXJjNC5hYmltZXRob2QoKQogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBub3QgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBjYW4gb25seSBjYWxsIHdoZW4gbm90IGNyZWF0aW5nCiAgICBjYWxsc3ViIGdldF90d28KICAgIGNvbmNhdAogICAgYnl0ZWNfMCAvLyAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50Y18wIC8vIDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fY29tcGFyZV9yb3V0ZUA0OgogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MzcKICAgIC8vIEBhcmM0LmFiaW1ldGhvZCgpCiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIG5vdCBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGNhbiBvbmx5IGNhbGwgd2hlbiBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgY29tcGFyZQogICAgcHVzaGJ5dGVzIDB4MDAKICAgIGludGNfMSAvLyAwCiAgICB1bmNvdmVyIDIKICAgIHNldGJpdAogICAgYnl0ZWNfMCAvLyAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50Y18wIC8vIDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDc6CiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weToxNgogICAgLy8gY2xhc3MgRGVtb0NvbnRyYWN0KEFSQzRDb250cmFjdCk6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMQogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBjYW4gb25seSBjYWxsIHdoZW4gY3JlYXRpbmcKICAgIGludGNfMCAvLyAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTE6CiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weToxNgogICAgLy8gY2xhc3MgRGVtb0NvbnRyYWN0KEFSQzRDb250cmFjdCk6CiAgICBpbnRjXzEgLy8gMAogICAgcmV0c3ViCgoKLy8gdGVzdF9jYXNlcy5zdHJ1Y3RfYnlfbmFtZS5jb250cmFjdC5EZW1vQ29udHJhY3QuZ2V0X29uZSgpIC0+IGJ5dGVzLCBieXRlczoKZ2V0X29uZToKICAgIC8vIHN0cnVjdF9ieV9uYW1lL2NvbnRyYWN0LnB5OjIzLTI0CiAgICAvLyBAYXJjNC5hYmltZXRob2QoKQogICAgLy8gZGVmIGdldF9vbmUoc2VsZikgLT4gU3RydWN0T25lOgogICAgcHJvdG8gMCAyCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weToyNgogICAgLy8geD1hcmM0LlVJbnQ4KDEpLAogICAgYnl0ZWNfMSAvLyAweDAxCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weToyNwogICAgLy8geT1hcmM0LlVJbnQ4KDEpLAogICAgZHVwCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weToyNS0yOAogICAgLy8gcmV0dXJuIFN0cnVjdE9uZSgKICAgIC8vICAgICB4PWFyYzQuVUludDgoMSksCiAgICAvLyAgICAgeT1hcmM0LlVJbnQ4KDEpLAogICAgLy8gKQogICAgcmV0c3ViCgoKLy8gdGVzdF9jYXNlcy5zdHJ1Y3RfYnlfbmFtZS5jb250cmFjdC5EZW1vQ29udHJhY3QuZ2V0X3R3bygpIC0+IGJ5dGVzLCBieXRlczoKZ2V0X3R3bzoKICAgIC8vIHN0cnVjdF9ieV9uYW1lL2NvbnRyYWN0LnB5OjMwLTMxCiAgICAvLyBAYXJjNC5hYmltZXRob2QoKQogICAgLy8gZGVmIGdldF90d28oc2VsZikgLT4gU3RydWN0VHdvOgogICAgcHJvdG8gMCAyCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weTozMwogICAgLy8geD1hcmM0LlVJbnQ4KDEpLAogICAgYnl0ZWNfMSAvLyAweDAxCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weTozNAogICAgLy8geT1hcmM0LlVJbnQ4KDEpLAogICAgZHVwCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weTozMi0zNQogICAgLy8gcmV0dXJuIFN0cnVjdFR3bygKICAgIC8vICAgICB4PWFyYzQuVUludDgoMSksCiAgICAvLyAgICAgeT1hcmM0LlVJbnQ4KDEpLAogICAgLy8gKQogICAgcmV0c3ViCgoKLy8gdGVzdF9jYXNlcy5zdHJ1Y3RfYnlfbmFtZS5jb250cmFjdC5EZW1vQ29udHJhY3QuY29tcGFyZSgpIC0+IHVpbnQ2NDoKY29tcGFyZToKICAgIC8vIHN0cnVjdF9ieV9uYW1lL2NvbnRyYWN0LnB5OjM3LTM4CiAgICAvLyBAYXJjNC5hYmltZXRob2QoKQogICAgLy8gZGVmIGNvbXBhcmUoc2VsZikgLT4gYm9vbDoKICAgIHByb3RvIDAgMQogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MzkKICAgIC8vIHJldHVybiBzZWxmLmdldF9vbmUoKSA9PSBzZWxmLmdldF90d28oKQogICAgY2FsbHN1YiBnZXRfb25lCiAgICBjYWxsc3ViIGdldF90d28KICAgIHVuY292ZXIgMwogICAgdW5jb3ZlciAyCiAgICBiPT0KICAgIGNvdmVyIDIKICAgIGI9PQogICAgJiYKICAgIHJldHN1Ygo=", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgp0ZXN0X2Nhc2VzLnN0cnVjdF9ieV9uYW1lLmNvbnRyYWN0LkRlbW9Db250cmFjdC5hcHByb3ZhbF9wcm9ncmFtOgogICAgaW50Y2Jsb2NrIDEgMAogICAgYnl0ZWNibG9jayAweDE1MWY3Yzc1IDB4MDEKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHRlc3RfY2FzZXMuc3RydWN0X2J5X25hbWUuY29udHJhY3QuRGVtb0NvbnRyYWN0Ll9fcHV5YV9hcmM0X3JvdXRlcl9fKCkgLT4gdWludDY0OgpfX3B1eWFfYXJjNF9yb3V0ZXJfXzoKICAgIC8vIHN0cnVjdF9ieV9uYW1lL2NvbnRyYWN0LnB5OjE4CiAgICAvLyBjbGFzcyBEZW1vQ29udHJhY3QoQVJDNENvbnRyYWN0KToKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A4CiAgICBwdXNoYnl0ZXNzIDB4M2Q2OTRiNzAgMHg3ZmIzNGU4YSAweDhiYTdjNGMyIDB4NDZkYWRlYTMgLy8gbWV0aG9kICJnZXRfb25lKCkodWludDgsdWludDgpIiwgbWV0aG9kICJnZXRfdHdvKCkodWludDgsdWludDgpIiwgbWV0aG9kICJnZXRfdGhyZWUoKSh1aW50OCx1aW50OCkiLCBtZXRob2QgImNvbXBhcmUoKWJvb2wiCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAwCiAgICBtYXRjaCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19nZXRfb25lX3JvdXRlQDIgX19wdXlhX2FyYzRfcm91dGVyX19fZ2V0X3R3b19yb3V0ZUAzIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2dldF90aHJlZV9yb3V0ZUA0IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2NvbXBhcmVfcm91dGVANQogICAgaW50Y18xIC8vIDAKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fZ2V0X29uZV9yb3V0ZUAyOgogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MjUKICAgIC8vIEBhcmM0LmFiaW1ldGhvZCgpCiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIG5vdCBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGNhbiBvbmx5IGNhbGwgd2hlbiBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgZ2V0X29uZQogICAgY29uY2F0CiAgICBieXRlY18wIC8vIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnRjXzAgLy8gMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19nZXRfdHdvX3JvdXRlQDM6CiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weTozMgogICAgLy8gQGFyYzQuYWJpbWV0aG9kKCkKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgbm90IE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gY2FuIG9ubHkgY2FsbCB3aGVuIG5vdCBjcmVhdGluZwogICAgY2FsbHN1YiBnZXRfdHdvCiAgICBjb25jYXQKICAgIGJ5dGVjXzAgLy8gMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludGNfMCAvLyAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2dldF90aHJlZV9yb3V0ZUA0OgogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MzkKICAgIC8vIEBhcmM0LmFiaW1ldGhvZCgpCiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIG5vdCBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGNhbiBvbmx5IGNhbGwgd2hlbiBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgZ2V0X3RocmVlCiAgICBjb25jYXQKICAgIGJ5dGVjXzAgLy8gMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludGNfMCAvLyAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2NvbXBhcmVfcm91dGVANToKICAgIC8vIHN0cnVjdF9ieV9uYW1lL2NvbnRyYWN0LnB5OjQ2CiAgICAvLyBAYXJjNC5hYmltZXRob2QoKQogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBub3QgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBjYW4gb25seSBjYWxsIHdoZW4gbm90IGNyZWF0aW5nCiAgICBjYWxsc3ViIGNvbXBhcmUKICAgIHB1c2hieXRlcyAweDAwCiAgICBpbnRjXzEgLy8gMAogICAgdW5jb3ZlciAyCiAgICBzZXRiaXQKICAgIGJ5dGVjXzAgLy8gMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludGNfMCAvLyAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A4OgogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MTgKICAgIC8vIGNsYXNzIERlbW9Db250cmFjdChBUkM0Q29udHJhY3QpOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgYm56IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTIKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gY2FuIG9ubHkgY2FsbCB3aGVuIGNyZWF0aW5nCiAgICBpbnRjXzAgLy8gMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEyOgogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MTgKICAgIC8vIGNsYXNzIERlbW9Db250cmFjdChBUkM0Q29udHJhY3QpOgogICAgaW50Y18xIC8vIDAKICAgIHJldHN1YgoKCi8vIHRlc3RfY2FzZXMuc3RydWN0X2J5X25hbWUuY29udHJhY3QuRGVtb0NvbnRyYWN0LmdldF9vbmUoKSAtPiBieXRlcywgYnl0ZXM6CmdldF9vbmU6CiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weToyNS0yNgogICAgLy8gQGFyYzQuYWJpbWV0aG9kKCkKICAgIC8vIGRlZiBnZXRfb25lKHNlbGYpIC0+IFN0cnVjdE9uZToKICAgIHByb3RvIDAgMgogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MjgKICAgIC8vIHg9YXJjNC5VSW50OCgxKSwKICAgIGJ5dGVjXzEgLy8gMHgwMQogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MjkKICAgIC8vIHk9YXJjNC5VSW50OCgxKSwKICAgIGR1cAogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MjctMzAKICAgIC8vIHJldHVybiBTdHJ1Y3RPbmUoCiAgICAvLyAgICAgeD1hcmM0LlVJbnQ4KDEpLAogICAgLy8gICAgIHk9YXJjNC5VSW50OCgxKSwKICAgIC8vICkKICAgIHJldHN1YgoKCi8vIHRlc3RfY2FzZXMuc3RydWN0X2J5X25hbWUuY29udHJhY3QuRGVtb0NvbnRyYWN0LmdldF90d28oKSAtPiBieXRlcywgYnl0ZXM6CmdldF90d286CiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weTozMi0zMwogICAgLy8gQGFyYzQuYWJpbWV0aG9kKCkKICAgIC8vIGRlZiBnZXRfdHdvKHNlbGYpIC0+IFN0cnVjdFR3bzoKICAgIHByb3RvIDAgMgogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MzUKICAgIC8vIHg9YXJjNC5VSW50OCgxKSwKICAgIGJ5dGVjXzEgLy8gMHgwMQogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MzYKICAgIC8vIHk9YXJjNC5VSW50OCgxKSwKICAgIGR1cAogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MzQtMzcKICAgIC8vIHJldHVybiBTdHJ1Y3RUd28oCiAgICAvLyAgICAgeD1hcmM0LlVJbnQ4KDEpLAogICAgLy8gICAgIHk9YXJjNC5VSW50OCgxKSwKICAgIC8vICkKICAgIHJldHN1YgoKCi8vIHRlc3RfY2FzZXMuc3RydWN0X2J5X25hbWUuY29udHJhY3QuRGVtb0NvbnRyYWN0LmdldF90aHJlZSgpIC0+IGJ5dGVzLCBieXRlczoKZ2V0X3RocmVlOgogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6MzktNDAKICAgIC8vIEBhcmM0LmFiaW1ldGhvZCgpCiAgICAvLyBkZWYgZ2V0X3RocmVlKHNlbGYpIC0+IFN0cnVjdFRocmVlOgogICAgcHJvdG8gMCAyCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weTo0MgogICAgLy8geD1hcmM0LlVJbnQ4KDEpLAogICAgYnl0ZWNfMSAvLyAweDAxCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weTo0MwogICAgLy8geT1hcmM0LlVJbnQ4KDEpLAogICAgZHVwCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weTo0MS00NAogICAgLy8gcmV0dXJuIFN0cnVjdFRocmVlKAogICAgLy8gICAgIHg9YXJjNC5VSW50OCgxKSwKICAgIC8vICAgICB5PWFyYzQuVUludDgoMSksCiAgICAvLyApCiAgICByZXRzdWIKCgovLyB0ZXN0X2Nhc2VzLnN0cnVjdF9ieV9uYW1lLmNvbnRyYWN0LkRlbW9Db250cmFjdC5jb21wYXJlKCkgLT4gdWludDY0Ogpjb21wYXJlOgogICAgLy8gc3RydWN0X2J5X25hbWUvY29udHJhY3QucHk6NDYtNDcKICAgIC8vIEBhcmM0LmFiaW1ldGhvZCgpCiAgICAvLyBkZWYgY29tcGFyZShzZWxmKSAtPiBib29sOgogICAgcHJvdG8gMCAxCiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weTo0OAogICAgLy8gcmV0dXJuIHNlbGYuZ2V0X29uZSgpID09IHNlbGYuZ2V0X3R3bygpIGFuZCBzZWxmLmdldF90d28oKSA9PSBzZWxmLmdldF90aHJlZSgpCiAgICBjYWxsc3ViIGdldF9vbmUKICAgIGNhbGxzdWIgZ2V0X3R3bwogICAgdW5jb3ZlciAzCiAgICB1bmNvdmVyIDIKICAgIGI9PQogICAgY292ZXIgMgogICAgYj09CiAgICAmJgogICAgYnogY29tcGFyZV9ib29sX2ZhbHNlQDMKICAgIGNhbGxzdWIgZ2V0X3R3bwogICAgY2FsbHN1YiBnZXRfdGhyZWUKICAgIHVuY292ZXIgMwogICAgdW5jb3ZlciAyCiAgICBiPT0KICAgIGNvdmVyIDIKICAgIGI9PQogICAgJiYKICAgIGJ6IGNvbXBhcmVfYm9vbF9mYWxzZUAzCiAgICBpbnRjXzAgLy8gMQogICAgYiBjb21wYXJlX2Jvb2xfbWVyZ2VANAoKY29tcGFyZV9ib29sX2ZhbHNlQDM6CiAgICBpbnRjXzEgLy8gMAoKY29tcGFyZV9ib29sX21lcmdlQDQ6CiAgICAvLyBzdHJ1Y3RfYnlfbmFtZS9jb250cmFjdC5weTo0OAogICAgLy8gcmV0dXJuIHNlbGYuZ2V0X29uZSgpID09IHNlbGYuZ2V0X3R3bygpIGFuZCBzZWxmLmdldF90d28oKSA9PSBzZWxmLmdldF90aHJlZSgpCiAgICByZXRzdWIK", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgp0ZXN0X2Nhc2VzLnN0cnVjdF9ieV9uYW1lLmNvbnRyYWN0LkRlbW9Db250cmFjdC5jbGVhcl9zdGF0ZV9wcm9ncmFtOgogICAgcHVzaGludCAxIC8vIDEKICAgIHJldHVybgo=" }, "byteCode": { - "approval": "CiACAQAmAgQVH3x1AQGIAAFDigABMRtBAFeCAwQ9aUtwBH+zTooERtreozYaAI4DAAIAEwAkI4kxGRREMRhEiAA8UChMULAiiTEZFEQxGESIADFQKExQsCKJMRkURDEYRIgAJoABACNPAlQoTFCwIokxGUAABjEYFEQiiSOJigACKUmJigACKUmJigABiP/uiP/xTwNPAqhOAqgQiQ==", + "approval": "CiACAQAmAgQVH3x1AQGIAAFDigABMRtBAG+CBAQ9aUtwBH+zTooEi6fEwgRG2t6jNhoAjgQAAgATACQANSOJMRkURDEYRIgATVAoTFCwIokxGRREMRhEiABCUChMULAiiTEZFEQxGESIADdQKExQsCKJMRkURDEYRIgALIABACNPAlQoTFCwIokxGUAABjEYFEQiiSOJigACKUmJigACKUmJigACKUmJigABiP/oiP/rTwNPAqhOAqgQQQAWiP/ciP/fTwNPAqhOAqgQQQAEIkIAASOJ", "clear": "CoEBQw==" }, "compilerInfo": { diff --git a/test_cases/struct_by_name/out/DemoContract.destructured.ir b/test_cases/struct_by_name/out/DemoContract.destructured.ir index a4772be1c5..d577859cc2 100644 --- a/test_cases/struct_by_name/out/DemoContract.destructured.ir +++ b/test_cases/struct_by_name/out/DemoContract.destructured.ir @@ -6,13 +6,13 @@ contract test_cases.struct_by_name.contract.DemoContract: return tmp%0#0 subroutine test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__() -> bool: - block@0: // L16 + block@0: // L18 let tmp%0#0: uint64 = (txn NumAppArgs) - goto tmp%0#0 ? block@1 : block@7 - block@1: // abi_routing_L16 + goto tmp%0#0 ? block@1 : block@8 + block@1: // abi_routing_L18 let tmp%2#0: bytes = (txna ApplicationArgs 0) - switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "compare()bool" => block@4, * => return 0u} - block@2: // get_one_route_L23 + switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "get_three()(uint8,uint8)" => block@4, method "compare()bool" => block@5, * => return 0u} + block@2: // get_one_route_L25 let tmp%3#0: uint64 = (txn OnCompletion) let tmp%4#0: bool = (! tmp%3#0) (assert tmp%4#0) // OnCompletion is not NoOp @@ -23,7 +23,7 @@ contract test_cases.struct_by_name.contract.DemoContract: let tmp%7#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%2#0) (log tmp%7#0) return 1u - block@3: // get_two_route_L30 + block@3: // get_two_route_L32 let tmp%8#0: uint64 = (txn OnCompletion) let tmp%9#0: bool = (! tmp%8#0) (assert tmp%9#0) // OnCompletion is not NoOp @@ -34,44 +34,74 @@ contract test_cases.struct_by_name.contract.DemoContract: let tmp%12#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%5#0) (log tmp%12#0) return 1u - block@4: // compare_route_L37 + block@4: // get_three_route_L39 let tmp%13#0: uint64 = (txn OnCompletion) let tmp%14#0: bool = (! tmp%13#0) (assert tmp%14#0) // OnCompletion is not NoOp let tmp%15#0: uint64 = (txn ApplicationID) (assert tmp%15#0) // can only call when not creating - let to_encode%0#0: bool = test_cases.struct_by_name.contract.DemoContract.compare() - let encoded_bool%0#0: bytes = (setbit 0x00 0u to_encode%0#0) - let tmp%17#0: bytes = (concat 0x151f7c75 encoded_bool%0#0) + let (elements_to_encode%4#0: bytes, elements_to_encode%5#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_three() + let encoded_tuple_buffer%8#0: bytes = (concat elements_to_encode%4#0 elements_to_encode%5#0) + let tmp%17#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%8#0) (log tmp%17#0) return 1u - block@7: // bare_routing_L16 + block@5: // compare_route_L46 let tmp%18#0: uint64 = (txn OnCompletion) - goto tmp%18#0 ? block@11 : block@8 - block@8: // __algopy_default_create_L1 - let tmp%19#0: uint64 = (txn ApplicationID) - let tmp%20#0: bool = (! tmp%19#0) - (assert tmp%20#0) // can only call when creating + let tmp%19#0: bool = (! tmp%18#0) + (assert tmp%19#0) // OnCompletion is not NoOp + let tmp%20#0: uint64 = (txn ApplicationID) + (assert tmp%20#0) // can only call when not creating + let to_encode%0#0: bool = test_cases.struct_by_name.contract.DemoContract.compare() + let encoded_bool%0#0: bytes = (setbit 0x00 0u to_encode%0#0) + let tmp%22#0: bytes = (concat 0x151f7c75 encoded_bool%0#0) + (log tmp%22#0) return 1u - block@11: // after_if_else_L16 + block@8: // bare_routing_L18 + let tmp%23#0: uint64 = (txn OnCompletion) + goto tmp%23#0 ? block@12 : block@9 + block@9: // __algopy_default_create_L1 + let tmp%24#0: uint64 = (txn ApplicationID) + let tmp%25#0: bool = (! tmp%24#0) + (assert tmp%25#0) // can only call when creating + return 1u + block@12: // after_if_else_L18 return 0u subroutine test_cases.struct_by_name.contract.DemoContract.get_one() -> : - block@0: // L23 + block@0: // L25 return 0x01 0x01 subroutine test_cases.struct_by_name.contract.DemoContract.get_two() -> : - block@0: // L30 + block@0: // L32 + return 0x01 0x01 + + subroutine test_cases.struct_by_name.contract.DemoContract.get_three() -> : + block@0: // L39 return 0x01 0x01 subroutine test_cases.struct_by_name.contract.DemoContract.compare() -> bool: - block@0: // L37 + block@0: // L46 let (awst_tmp%0#0: bytes, awst_tmp%1#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_one() let (awst_tmp%2#0: bytes, awst_tmp%3#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_two() let tmp%0#0: bool = (b== awst_tmp%0#0 awst_tmp%2#0) let tmp%1#0: bool = (b== awst_tmp%1#0 awst_tmp%3#0) let tmp%2#0: bool = (&& tmp%0#0 tmp%1#0) - return tmp%2#0 + goto tmp%2#0 ? block@1 : block@3 + block@1: // and_contd_L48 + let (awst_tmp%4#0: bytes, awst_tmp%5#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_two() + let (awst_tmp%6#0: bytes, awst_tmp%7#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_three() + let tmp%3#0: bool = (b== awst_tmp%4#0 awst_tmp%6#0) + let tmp%4#0: bool = (b== awst_tmp%5#0 awst_tmp%7#0) + let tmp%5#0: bool = (&& tmp%3#0 tmp%4#0) + goto tmp%5#0 ? block@2 : block@3 + block@2: // bool_true_L48 + let and_result%0#0: bool = 1u + goto block@4 + block@3: // bool_false_L48 + let and_result%0#0: bool = 0u + goto block@4 + block@4: // bool_merge_L48 + return and_result%0#0 program clear-state: subroutine algopy.arc4.ARC4Contract.clear_state_program() -> bool: diff --git a/test_cases/struct_by_name/out/DemoContract.ssa.ir b/test_cases/struct_by_name/out/DemoContract.ssa.ir index 489dd83640..bc2901d6a2 100644 --- a/test_cases/struct_by_name/out/DemoContract.ssa.ir +++ b/test_cases/struct_by_name/out/DemoContract.ssa.ir @@ -6,14 +6,14 @@ contract test_cases.struct_by_name.contract.DemoContract: return tmp%0#0 subroutine test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__() -> bool: - block@0: // L16 + block@0: // L18 let tmp%0#0: uint64 = (txn NumAppArgs) let tmp%1#0: bool = (!= tmp%0#0 0u) - goto tmp%1#0 ? block@1 : block@7 - block@1: // abi_routing_L16 + goto tmp%1#0 ? block@1 : block@8 + block@1: // abi_routing_L18 let tmp%2#0: bytes = (txna ApplicationArgs 0) - switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "compare()bool" => block@4, * => block@5} - block@2: // get_one_route_L23 + switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "get_three()(uint8,uint8)" => block@4, method "compare()bool" => block@5, * => block@6} + block@2: // get_one_route_L25 let tmp%3#0: uint64 = (txn OnCompletion) let tmp%4#0: bool = (== tmp%3#0 NoOp) (assert tmp%4#0) // OnCompletion is not NoOp @@ -28,7 +28,7 @@ contract test_cases.struct_by_name.contract.DemoContract: let tmp%7#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%2#0) (log tmp%7#0) return 1u - block@3: // get_two_route_L30 + block@3: // get_two_route_L32 let tmp%8#0: uint64 = (txn OnCompletion) let tmp%9#0: bool = (== tmp%8#0 NoOp) (assert tmp%9#0) // OnCompletion is not NoOp @@ -43,48 +43,67 @@ contract test_cases.struct_by_name.contract.DemoContract: let tmp%12#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%5#0) (log tmp%12#0) return 1u - block@4: // compare_route_L37 + block@4: // get_three_route_L39 let tmp%13#0: uint64 = (txn OnCompletion) let tmp%14#0: bool = (== tmp%13#0 NoOp) (assert tmp%14#0) // OnCompletion is not NoOp let tmp%15#0: uint64 = (txn ApplicationID) let tmp%16#0: bool = (!= tmp%15#0 0u) (assert tmp%16#0) // can only call when not creating - let to_encode%0#0: bool = test_cases.struct_by_name.contract.DemoContract.compare() - let encoded_bool%0#0: bytes = (setbit 0x00 0u to_encode%0#0) - let tmp%17#0: bytes = (concat 0x151f7c75 encoded_bool%0#0) + let (elements_to_encode%4#0: bytes, elements_to_encode%5#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_three() + let current_tail_offset%2#0: uint64 = 2u + let encoded_tuple_buffer%6#0: bytes = 0x + let encoded_tuple_buffer%7#0: bytes = (concat encoded_tuple_buffer%6#0 elements_to_encode%4#0) + let encoded_tuple_buffer%8#0: bytes = (concat encoded_tuple_buffer%7#0 elements_to_encode%5#0) + let tmp%17#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%8#0) (log tmp%17#0) return 1u - block@5: // switch_case_default_L16 - goto block@6 - block@6: // switch_case_next_L16 - goto block@11 - block@7: // bare_routing_L16 + block@5: // compare_route_L46 let tmp%18#0: uint64 = (txn OnCompletion) - switch tmp%18#0 {0u => block@8, * => block@9} - block@8: // __algopy_default_create_L1 - let tmp%19#0: uint64 = (txn ApplicationID) - let tmp%20#0: bool = (== tmp%19#0 0u) - (assert tmp%20#0) // can only call when creating + let tmp%19#0: bool = (== tmp%18#0 NoOp) + (assert tmp%19#0) // OnCompletion is not NoOp + let tmp%20#0: uint64 = (txn ApplicationID) + let tmp%21#0: bool = (!= tmp%20#0 0u) + (assert tmp%21#0) // can only call when not creating + let to_encode%0#0: bool = test_cases.struct_by_name.contract.DemoContract.compare() + let encoded_bool%0#0: bytes = (setbit 0x00 0u to_encode%0#0) + let tmp%22#0: bytes = (concat 0x151f7c75 encoded_bool%0#0) + (log tmp%22#0) + return 1u + block@6: // switch_case_default_L18 + goto block@7 + block@7: // switch_case_next_L18 + goto block@12 + block@8: // bare_routing_L18 + let tmp%23#0: uint64 = (txn OnCompletion) + switch tmp%23#0 {0u => block@9, * => block@10} + block@9: // __algopy_default_create_L1 + let tmp%24#0: uint64 = (txn ApplicationID) + let tmp%25#0: bool = (== tmp%24#0 0u) + (assert tmp%25#0) // can only call when creating test_cases.struct_by_name.contract.DemoContract.__algopy_default_create() return 1u - block@9: // switch_case_default_L16 - goto block@10 - block@10: // switch_case_next_L16 + block@10: // switch_case_default_L18 goto block@11 - block@11: // after_if_else_L16 + block@11: // switch_case_next_L18 + goto block@12 + block@12: // after_if_else_L18 return 0u subroutine test_cases.struct_by_name.contract.DemoContract.get_one() -> : - block@0: // L23 + block@0: // L25 return 0x01 0x01 subroutine test_cases.struct_by_name.contract.DemoContract.get_two() -> : - block@0: // L30 + block@0: // L32 + return 0x01 0x01 + + subroutine test_cases.struct_by_name.contract.DemoContract.get_three() -> : + block@0: // L39 return 0x01 0x01 subroutine test_cases.struct_by_name.contract.DemoContract.compare() -> bool: - block@0: // L37 + block@0: // L46 let (awst_tmp%0#0: bytes, awst_tmp%1#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_one() let reinterpret_biguint%0#0: biguint = awst_tmp%0#0 let (awst_tmp%2#0: bytes, awst_tmp%3#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_two() @@ -94,7 +113,27 @@ contract test_cases.struct_by_name.contract.DemoContract: let reinterpret_biguint%3#0: biguint = awst_tmp%3#0 let tmp%1#0: bool = (b== reinterpret_biguint%2#0 reinterpret_biguint%3#0) let tmp%2#0: bool = (&& tmp%0#0 tmp%1#0) - return tmp%2#0 + goto tmp%2#0 ? block@1 : block@3 + block@1: // and_contd_L48 + let (awst_tmp%4#0: bytes, awst_tmp%5#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_two() + let reinterpret_biguint%4#0: biguint = awst_tmp%4#0 + let (awst_tmp%6#0: bytes, awst_tmp%7#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_three() + let reinterpret_biguint%5#0: biguint = awst_tmp%6#0 + let tmp%3#0: bool = (b== reinterpret_biguint%4#0 reinterpret_biguint%5#0) + let reinterpret_biguint%6#0: biguint = awst_tmp%5#0 + let reinterpret_biguint%7#0: biguint = awst_tmp%7#0 + let tmp%4#0: bool = (b== reinterpret_biguint%6#0 reinterpret_biguint%7#0) + let tmp%5#0: bool = (&& tmp%3#0 tmp%4#0) + goto tmp%5#0 ? block@2 : block@3 + block@2: // bool_true_L48 + let and_result%0#0: bool = 1u + goto block@4 + block@3: // bool_false_L48 + let and_result%0#1: bool = 0u + goto block@4 + block@4: // bool_merge_L48 + let and_result%0#2: bool = φ(and_result%0#0 <- block@2, and_result%0#1 <- block@3) + return and_result%0#2 subroutine test_cases.struct_by_name.contract.DemoContract.__algopy_default_create() -> void: block@0: // L1 diff --git a/test_cases/struct_by_name/out/DemoContract.ssa.opt_pass_1.ir b/test_cases/struct_by_name/out/DemoContract.ssa.opt_pass_1.ir index 3b7507b34a..1373bd840b 100644 --- a/test_cases/struct_by_name/out/DemoContract.ssa.opt_pass_1.ir +++ b/test_cases/struct_by_name/out/DemoContract.ssa.opt_pass_1.ir @@ -6,13 +6,13 @@ contract test_cases.struct_by_name.contract.DemoContract: return tmp%0#0 subroutine test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__() -> bool: - block@0: // L16 + block@0: // L18 let tmp%0#0: uint64 = (txn NumAppArgs) - goto tmp%0#0 ? block@1 : block@7 - block@1: // abi_routing_L16 + goto tmp%0#0 ? block@1 : block@8 + block@1: // abi_routing_L18 let tmp%2#0: bytes = (txna ApplicationArgs 0) - switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "compare()bool" => block@4, * => return 0u} - block@2: // get_one_route_L23 + switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "get_three()(uint8,uint8)" => block@4, method "compare()bool" => block@5, * => return 0u} + block@2: // get_one_route_L25 let tmp%3#0: uint64 = (txn OnCompletion) let tmp%4#0: bool = (! tmp%3#0) (assert tmp%4#0) // OnCompletion is not NoOp @@ -24,7 +24,7 @@ contract test_cases.struct_by_name.contract.DemoContract: let tmp%7#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%2#0) (log tmp%7#0) return 1u - block@3: // get_two_route_L30 + block@3: // get_two_route_L32 let tmp%8#0: uint64 = (txn OnCompletion) let tmp%9#0: bool = (! tmp%8#0) (assert tmp%9#0) // OnCompletion is not NoOp @@ -36,44 +36,76 @@ contract test_cases.struct_by_name.contract.DemoContract: let tmp%12#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%5#0) (log tmp%12#0) return 1u - block@4: // compare_route_L37 + block@4: // get_three_route_L39 let tmp%13#0: uint64 = (txn OnCompletion) let tmp%14#0: bool = (! tmp%13#0) (assert tmp%14#0) // OnCompletion is not NoOp let tmp%15#0: uint64 = (txn ApplicationID) (assert tmp%15#0) // can only call when not creating - let to_encode%0#0: bool = test_cases.struct_by_name.contract.DemoContract.compare() - let encoded_bool%0#0: bytes = (setbit 0x00 0u to_encode%0#0) - let tmp%17#0: bytes = (concat 0x151f7c75 encoded_bool%0#0) + let (elements_to_encode%4#0: bytes, elements_to_encode%5#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_three() + let encoded_tuple_buffer%7#0: bytes = elements_to_encode%4#0 + let encoded_tuple_buffer%8#0: bytes = (concat encoded_tuple_buffer%7#0 elements_to_encode%5#0) + let tmp%17#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%8#0) (log tmp%17#0) return 1u - block@7: // bare_routing_L16 + block@5: // compare_route_L46 let tmp%18#0: uint64 = (txn OnCompletion) - goto tmp%18#0 ? block@11 : block@8 - block@8: // __algopy_default_create_L1 - let tmp%19#0: uint64 = (txn ApplicationID) - let tmp%20#0: bool = (! tmp%19#0) - (assert tmp%20#0) // can only call when creating + let tmp%19#0: bool = (! tmp%18#0) + (assert tmp%19#0) // OnCompletion is not NoOp + let tmp%20#0: uint64 = (txn ApplicationID) + (assert tmp%20#0) // can only call when not creating + let to_encode%0#0: bool = test_cases.struct_by_name.contract.DemoContract.compare() + let encoded_bool%0#0: bytes = (setbit 0x00 0u to_encode%0#0) + let tmp%22#0: bytes = (concat 0x151f7c75 encoded_bool%0#0) + (log tmp%22#0) return 1u - block@11: // after_if_else_L16 + block@8: // bare_routing_L18 + let tmp%23#0: uint64 = (txn OnCompletion) + goto tmp%23#0 ? block@12 : block@9 + block@9: // __algopy_default_create_L1 + let tmp%24#0: uint64 = (txn ApplicationID) + let tmp%25#0: bool = (! tmp%24#0) + (assert tmp%25#0) // can only call when creating + return 1u + block@12: // after_if_else_L18 return 0u subroutine test_cases.struct_by_name.contract.DemoContract.get_one() -> : - block@0: // L23 + block@0: // L25 return 0x01 0x01 subroutine test_cases.struct_by_name.contract.DemoContract.get_two() -> : - block@0: // L30 + block@0: // L32 + return 0x01 0x01 + + subroutine test_cases.struct_by_name.contract.DemoContract.get_three() -> : + block@0: // L39 return 0x01 0x01 subroutine test_cases.struct_by_name.contract.DemoContract.compare() -> bool: - block@0: // L37 + block@0: // L46 let (awst_tmp%0#0: bytes, awst_tmp%1#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_one() let (awst_tmp%2#0: bytes, awst_tmp%3#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_two() let tmp%0#0: bool = (b== awst_tmp%0#0 awst_tmp%2#0) let tmp%1#0: bool = (b== awst_tmp%1#0 awst_tmp%3#0) let tmp%2#0: bool = (&& tmp%0#0 tmp%1#0) - return tmp%2#0 + goto tmp%2#0 ? block@1 : block@3 + block@1: // and_contd_L48 + let (awst_tmp%4#0: bytes, awst_tmp%5#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_two() + let (awst_tmp%6#0: bytes, awst_tmp%7#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_three() + let tmp%3#0: bool = (b== awst_tmp%4#0 awst_tmp%6#0) + let tmp%4#0: bool = (b== awst_tmp%5#0 awst_tmp%7#0) + let tmp%5#0: bool = (&& tmp%3#0 tmp%4#0) + goto tmp%5#0 ? block@2 : block@3 + block@2: // bool_true_L48 + let and_result%0#0: bool = 1u + goto block@4 + block@3: // bool_false_L48 + let and_result%0#1: bool = 0u + goto block@4 + block@4: // bool_merge_L48 + let and_result%0#2: bool = φ(and_result%0#0 <- block@2, and_result%0#1 <- block@3) + return and_result%0#2 program clear-state: subroutine algopy.arc4.ARC4Contract.clear_state_program() -> bool: diff --git a/test_cases/struct_by_name/out/DemoContract.ssa.opt_pass_2.ir b/test_cases/struct_by_name/out/DemoContract.ssa.opt_pass_2.ir index a4772be1c5..aa1086996b 100644 --- a/test_cases/struct_by_name/out/DemoContract.ssa.opt_pass_2.ir +++ b/test_cases/struct_by_name/out/DemoContract.ssa.opt_pass_2.ir @@ -6,13 +6,13 @@ contract test_cases.struct_by_name.contract.DemoContract: return tmp%0#0 subroutine test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__() -> bool: - block@0: // L16 + block@0: // L18 let tmp%0#0: uint64 = (txn NumAppArgs) - goto tmp%0#0 ? block@1 : block@7 - block@1: // abi_routing_L16 + goto tmp%0#0 ? block@1 : block@8 + block@1: // abi_routing_L18 let tmp%2#0: bytes = (txna ApplicationArgs 0) - switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "compare()bool" => block@4, * => return 0u} - block@2: // get_one_route_L23 + switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "get_three()(uint8,uint8)" => block@4, method "compare()bool" => block@5, * => return 0u} + block@2: // get_one_route_L25 let tmp%3#0: uint64 = (txn OnCompletion) let tmp%4#0: bool = (! tmp%3#0) (assert tmp%4#0) // OnCompletion is not NoOp @@ -23,7 +23,7 @@ contract test_cases.struct_by_name.contract.DemoContract: let tmp%7#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%2#0) (log tmp%7#0) return 1u - block@3: // get_two_route_L30 + block@3: // get_two_route_L32 let tmp%8#0: uint64 = (txn OnCompletion) let tmp%9#0: bool = (! tmp%8#0) (assert tmp%9#0) // OnCompletion is not NoOp @@ -34,44 +34,75 @@ contract test_cases.struct_by_name.contract.DemoContract: let tmp%12#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%5#0) (log tmp%12#0) return 1u - block@4: // compare_route_L37 + block@4: // get_three_route_L39 let tmp%13#0: uint64 = (txn OnCompletion) let tmp%14#0: bool = (! tmp%13#0) (assert tmp%14#0) // OnCompletion is not NoOp let tmp%15#0: uint64 = (txn ApplicationID) (assert tmp%15#0) // can only call when not creating - let to_encode%0#0: bool = test_cases.struct_by_name.contract.DemoContract.compare() - let encoded_bool%0#0: bytes = (setbit 0x00 0u to_encode%0#0) - let tmp%17#0: bytes = (concat 0x151f7c75 encoded_bool%0#0) + let (elements_to_encode%4#0: bytes, elements_to_encode%5#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_three() + let encoded_tuple_buffer%8#0: bytes = (concat elements_to_encode%4#0 elements_to_encode%5#0) + let tmp%17#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%8#0) (log tmp%17#0) return 1u - block@7: // bare_routing_L16 + block@5: // compare_route_L46 let tmp%18#0: uint64 = (txn OnCompletion) - goto tmp%18#0 ? block@11 : block@8 - block@8: // __algopy_default_create_L1 - let tmp%19#0: uint64 = (txn ApplicationID) - let tmp%20#0: bool = (! tmp%19#0) - (assert tmp%20#0) // can only call when creating + let tmp%19#0: bool = (! tmp%18#0) + (assert tmp%19#0) // OnCompletion is not NoOp + let tmp%20#0: uint64 = (txn ApplicationID) + (assert tmp%20#0) // can only call when not creating + let to_encode%0#0: bool = test_cases.struct_by_name.contract.DemoContract.compare() + let encoded_bool%0#0: bytes = (setbit 0x00 0u to_encode%0#0) + let tmp%22#0: bytes = (concat 0x151f7c75 encoded_bool%0#0) + (log tmp%22#0) return 1u - block@11: // after_if_else_L16 + block@8: // bare_routing_L18 + let tmp%23#0: uint64 = (txn OnCompletion) + goto tmp%23#0 ? block@12 : block@9 + block@9: // __algopy_default_create_L1 + let tmp%24#0: uint64 = (txn ApplicationID) + let tmp%25#0: bool = (! tmp%24#0) + (assert tmp%25#0) // can only call when creating + return 1u + block@12: // after_if_else_L18 return 0u subroutine test_cases.struct_by_name.contract.DemoContract.get_one() -> : - block@0: // L23 + block@0: // L25 return 0x01 0x01 subroutine test_cases.struct_by_name.contract.DemoContract.get_two() -> : - block@0: // L30 + block@0: // L32 + return 0x01 0x01 + + subroutine test_cases.struct_by_name.contract.DemoContract.get_three() -> : + block@0: // L39 return 0x01 0x01 subroutine test_cases.struct_by_name.contract.DemoContract.compare() -> bool: - block@0: // L37 + block@0: // L46 let (awst_tmp%0#0: bytes, awst_tmp%1#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_one() let (awst_tmp%2#0: bytes, awst_tmp%3#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_two() let tmp%0#0: bool = (b== awst_tmp%0#0 awst_tmp%2#0) let tmp%1#0: bool = (b== awst_tmp%1#0 awst_tmp%3#0) let tmp%2#0: bool = (&& tmp%0#0 tmp%1#0) - return tmp%2#0 + goto tmp%2#0 ? block@1 : block@3 + block@1: // and_contd_L48 + let (awst_tmp%4#0: bytes, awst_tmp%5#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_two() + let (awst_tmp%6#0: bytes, awst_tmp%7#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_three() + let tmp%3#0: bool = (b== awst_tmp%4#0 awst_tmp%6#0) + let tmp%4#0: bool = (b== awst_tmp%5#0 awst_tmp%7#0) + let tmp%5#0: bool = (&& tmp%3#0 tmp%4#0) + goto tmp%5#0 ? block@2 : block@3 + block@2: // bool_true_L48 + let and_result%0#0: bool = 1u + goto block@4 + block@3: // bool_false_L48 + let and_result%0#1: bool = 0u + goto block@4 + block@4: // bool_merge_L48 + let and_result%0#2: bool = φ(and_result%0#0 <- block@2, and_result%0#1 <- block@3) + return and_result%0#2 program clear-state: subroutine algopy.arc4.ARC4Contract.clear_state_program() -> bool: diff --git a/test_cases/struct_by_name/out/client_DemoContract.py b/test_cases/struct_by_name/out/client_DemoContract.py index ab778eb0eb..9644b856a6 100644 --- a/test_cases/struct_by_name/out/client_DemoContract.py +++ b/test_cases/struct_by_name/out/client_DemoContract.py @@ -13,10 +13,14 @@ class StructTwo(algopy.arc4.Struct): x: algopy.arc4.UIntN[typing.Literal[8]] y: algopy.arc4.UIntN[typing.Literal[8]] +class test_cases_struct_by_name_mod_StructTwo(algopy.arc4.Struct): + x: algopy.arc4.UIntN[typing.Literal[8]] + y: algopy.arc4.UIntN[typing.Literal[8]] + class DemoContract(algopy.arc4.ARC4Client, typing.Protocol): """ - Verify that even though named tuples with different names, but the same structure should be + Verify that even though named tuples with different names but the same structure should be considered 'comparable' in the type system, they should be output separately when being interpreted as an arc4 Struct in an abi method @@ -31,6 +35,11 @@ def get_two( self, ) -> StructTwo: ... + @algopy.arc4.abimethod + def get_three( + self, + ) -> test_cases_struct_by_name_mod_StructTwo: ... + @algopy.arc4.abimethod def compare( self, diff --git a/test_cases/struct_by_name/out/module.awst b/test_cases/struct_by_name/out/module.awst index 32e324a2cf..5b54962f89 100644 --- a/test_cases/struct_by_name/out/module.awst +++ b/test_cases/struct_by_name/out/module.awst @@ -24,9 +24,14 @@ contract DemoContract return (1_arc4u8, 1_arc4u8) } + abimethod test_cases.struct_by_name.contract.DemoContract.get_three(): test_cases.struct_by_name.mod.StructTwo + { + return (1_arc4u8, 1_arc4u8) + } + abimethod test_cases.struct_by_name.contract.DemoContract.compare(): bool { - return &&(reinterpret_cast(SINGLE_EVAL(id=0, source=this::get_one())[0]) == reinterpret_cast(SINGLE_EVAL(id=1, source=this::get_two())[0]), reinterpret_cast(SINGLE_EVAL(id=0)[1]) == reinterpret_cast(SINGLE_EVAL(id=1)[1])) + return &&(reinterpret_cast(SINGLE_EVAL(id=0, source=this::get_one())[0]) == reinterpret_cast(SINGLE_EVAL(id=1, source=this::get_two())[0]), reinterpret_cast(SINGLE_EVAL(id=0)[1]) == reinterpret_cast(SINGLE_EVAL(id=1)[1])) and &&(reinterpret_cast(SINGLE_EVAL(id=2, source=this::get_two())[0]) == reinterpret_cast(SINGLE_EVAL(id=3, source=this::get_three())[0]), reinterpret_cast(SINGLE_EVAL(id=2)[1]) == reinterpret_cast(SINGLE_EVAL(id=3)[1])) } baremethod test_cases.struct_by_name.contract.DemoContract.__algopy_default_create(): void diff --git a/test_cases/struct_by_name/out_O2/DemoContract.approval.teal b/test_cases/struct_by_name/out_O2/DemoContract.approval.teal index 9766b64bc2..f4559f012e 100644 --- a/test_cases/struct_by_name/out_O2/DemoContract.approval.teal +++ b/test_cases/struct_by_name/out_O2/DemoContract.approval.teal @@ -11,10 +11,10 @@ test_cases.struct_by_name.contract.DemoContract.approval_program: __puya_arc4_router__: proto 0 1 txn NumAppArgs - bz __puya_arc4_router___bare_routing@7 - pushbytess 0x3d694b70 0x7fb34e8a 0x46dadea3 // method "get_one()(uint8,uint8)", method "get_two()(uint8,uint8)", method "compare()bool" + bz __puya_arc4_router___bare_routing@8 + pushbytess 0x3d694b70 0x7fb34e8a 0x8ba7c4c2 0x46dadea3 // method "get_one()(uint8,uint8)", method "get_two()(uint8,uint8)", method "get_three()(uint8,uint8)", method "compare()bool" txna ApplicationArgs 0 - match __puya_arc4_router___get_one_route@2 __puya_arc4_router___get_two_route@3 __puya_arc4_router___compare_route@4 + match __puya_arc4_router___get_one_route@2 __puya_arc4_router___get_two_route@3 __puya_arc4_router___get_three_route@4 __puya_arc4_router___compare_route@5 intc_1 // 0 retsub @@ -48,7 +48,22 @@ __puya_arc4_router___get_two_route@3: intc_0 // 1 retsub -__puya_arc4_router___compare_route@4: +__puya_arc4_router___get_three_route@4: + txn OnCompletion + ! + assert // OnCompletion is not NoOp + txn ApplicationID + assert // can only call when not creating + callsub get_three + concat + bytec_0 // 0x151f7c75 + swap + concat + log + intc_0 // 1 + retsub + +__puya_arc4_router___compare_route@5: txn OnCompletion ! assert // OnCompletion is not NoOp @@ -66,16 +81,16 @@ __puya_arc4_router___compare_route@4: intc_0 // 1 retsub -__puya_arc4_router___bare_routing@7: +__puya_arc4_router___bare_routing@8: txn OnCompletion - bnz __puya_arc4_router___after_if_else@11 + bnz __puya_arc4_router___after_if_else@12 txn ApplicationID ! assert // can only call when creating intc_0 // 1 retsub -__puya_arc4_router___after_if_else@11: +__puya_arc4_router___after_if_else@12: intc_1 // 0 retsub @@ -96,6 +111,14 @@ get_two: retsub +// test_cases.struct_by_name.contract.DemoContract.get_three() -> bytes, bytes: +get_three: + proto 0 2 + bytec_1 // 0x01 + dup + retsub + + // test_cases.struct_by_name.contract.DemoContract.compare() -> uint64: compare: proto 0 1 @@ -107,4 +130,21 @@ compare: cover 2 b== && + bz compare_bool_false@3 + callsub get_two + callsub get_three + uncover 3 + uncover 2 + b== + cover 2 + b== + && + bz compare_bool_false@3 + intc_0 // 1 + b compare_bool_merge@4 + +compare_bool_false@3: + intc_1 // 0 + +compare_bool_merge@4: retsub diff --git a/test_cases/struct_by_name/out_O2/DemoContract.destructured.ir b/test_cases/struct_by_name/out_O2/DemoContract.destructured.ir index a4772be1c5..d577859cc2 100644 --- a/test_cases/struct_by_name/out_O2/DemoContract.destructured.ir +++ b/test_cases/struct_by_name/out_O2/DemoContract.destructured.ir @@ -6,13 +6,13 @@ contract test_cases.struct_by_name.contract.DemoContract: return tmp%0#0 subroutine test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__() -> bool: - block@0: // L16 + block@0: // L18 let tmp%0#0: uint64 = (txn NumAppArgs) - goto tmp%0#0 ? block@1 : block@7 - block@1: // abi_routing_L16 + goto tmp%0#0 ? block@1 : block@8 + block@1: // abi_routing_L18 let tmp%2#0: bytes = (txna ApplicationArgs 0) - switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "compare()bool" => block@4, * => return 0u} - block@2: // get_one_route_L23 + switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "get_three()(uint8,uint8)" => block@4, method "compare()bool" => block@5, * => return 0u} + block@2: // get_one_route_L25 let tmp%3#0: uint64 = (txn OnCompletion) let tmp%4#0: bool = (! tmp%3#0) (assert tmp%4#0) // OnCompletion is not NoOp @@ -23,7 +23,7 @@ contract test_cases.struct_by_name.contract.DemoContract: let tmp%7#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%2#0) (log tmp%7#0) return 1u - block@3: // get_two_route_L30 + block@3: // get_two_route_L32 let tmp%8#0: uint64 = (txn OnCompletion) let tmp%9#0: bool = (! tmp%8#0) (assert tmp%9#0) // OnCompletion is not NoOp @@ -34,44 +34,74 @@ contract test_cases.struct_by_name.contract.DemoContract: let tmp%12#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%5#0) (log tmp%12#0) return 1u - block@4: // compare_route_L37 + block@4: // get_three_route_L39 let tmp%13#0: uint64 = (txn OnCompletion) let tmp%14#0: bool = (! tmp%13#0) (assert tmp%14#0) // OnCompletion is not NoOp let tmp%15#0: uint64 = (txn ApplicationID) (assert tmp%15#0) // can only call when not creating - let to_encode%0#0: bool = test_cases.struct_by_name.contract.DemoContract.compare() - let encoded_bool%0#0: bytes = (setbit 0x00 0u to_encode%0#0) - let tmp%17#0: bytes = (concat 0x151f7c75 encoded_bool%0#0) + let (elements_to_encode%4#0: bytes, elements_to_encode%5#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_three() + let encoded_tuple_buffer%8#0: bytes = (concat elements_to_encode%4#0 elements_to_encode%5#0) + let tmp%17#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%8#0) (log tmp%17#0) return 1u - block@7: // bare_routing_L16 + block@5: // compare_route_L46 let tmp%18#0: uint64 = (txn OnCompletion) - goto tmp%18#0 ? block@11 : block@8 - block@8: // __algopy_default_create_L1 - let tmp%19#0: uint64 = (txn ApplicationID) - let tmp%20#0: bool = (! tmp%19#0) - (assert tmp%20#0) // can only call when creating + let tmp%19#0: bool = (! tmp%18#0) + (assert tmp%19#0) // OnCompletion is not NoOp + let tmp%20#0: uint64 = (txn ApplicationID) + (assert tmp%20#0) // can only call when not creating + let to_encode%0#0: bool = test_cases.struct_by_name.contract.DemoContract.compare() + let encoded_bool%0#0: bytes = (setbit 0x00 0u to_encode%0#0) + let tmp%22#0: bytes = (concat 0x151f7c75 encoded_bool%0#0) + (log tmp%22#0) return 1u - block@11: // after_if_else_L16 + block@8: // bare_routing_L18 + let tmp%23#0: uint64 = (txn OnCompletion) + goto tmp%23#0 ? block@12 : block@9 + block@9: // __algopy_default_create_L1 + let tmp%24#0: uint64 = (txn ApplicationID) + let tmp%25#0: bool = (! tmp%24#0) + (assert tmp%25#0) // can only call when creating + return 1u + block@12: // after_if_else_L18 return 0u subroutine test_cases.struct_by_name.contract.DemoContract.get_one() -> : - block@0: // L23 + block@0: // L25 return 0x01 0x01 subroutine test_cases.struct_by_name.contract.DemoContract.get_two() -> : - block@0: // L30 + block@0: // L32 + return 0x01 0x01 + + subroutine test_cases.struct_by_name.contract.DemoContract.get_three() -> : + block@0: // L39 return 0x01 0x01 subroutine test_cases.struct_by_name.contract.DemoContract.compare() -> bool: - block@0: // L37 + block@0: // L46 let (awst_tmp%0#0: bytes, awst_tmp%1#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_one() let (awst_tmp%2#0: bytes, awst_tmp%3#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_two() let tmp%0#0: bool = (b== awst_tmp%0#0 awst_tmp%2#0) let tmp%1#0: bool = (b== awst_tmp%1#0 awst_tmp%3#0) let tmp%2#0: bool = (&& tmp%0#0 tmp%1#0) - return tmp%2#0 + goto tmp%2#0 ? block@1 : block@3 + block@1: // and_contd_L48 + let (awst_tmp%4#0: bytes, awst_tmp%5#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_two() + let (awst_tmp%6#0: bytes, awst_tmp%7#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_three() + let tmp%3#0: bool = (b== awst_tmp%4#0 awst_tmp%6#0) + let tmp%4#0: bool = (b== awst_tmp%5#0 awst_tmp%7#0) + let tmp%5#0: bool = (&& tmp%3#0 tmp%4#0) + goto tmp%5#0 ? block@2 : block@3 + block@2: // bool_true_L48 + let and_result%0#0: bool = 1u + goto block@4 + block@3: // bool_false_L48 + let and_result%0#0: bool = 0u + goto block@4 + block@4: // bool_merge_L48 + return and_result%0#0 program clear-state: subroutine algopy.arc4.ARC4Contract.clear_state_program() -> bool: diff --git a/test_cases/struct_by_name/out_unoptimized/DemoContract.approval.teal b/test_cases/struct_by_name/out_unoptimized/DemoContract.approval.teal index 2e7db4630f..428e64a75c 100644 --- a/test_cases/struct_by_name/out_unoptimized/DemoContract.approval.teal +++ b/test_cases/struct_by_name/out_unoptimized/DemoContract.approval.teal @@ -9,23 +9,24 @@ test_cases.struct_by_name.contract.DemoContract.approval_program: // test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__() -> uint64: __puya_arc4_router__: - // struct_by_name/contract.py:16 + // struct_by_name/contract.py:18 // class DemoContract(ARC4Contract): proto 0 1 txn NumAppArgs intc_0 // 0 != - bz __puya_arc4_router___bare_routing@7 + bz __puya_arc4_router___bare_routing@8 txna ApplicationArgs 0 pushbytes 0x3d694b70 // method "get_one()(uint8,uint8)" pushbytes 0x7fb34e8a // method "get_two()(uint8,uint8)" + pushbytes 0x8ba7c4c2 // method "get_three()(uint8,uint8)" pushbytes 0x46dadea3 // method "compare()bool" - uncover 3 - match __puya_arc4_router___get_one_route@2 __puya_arc4_router___get_two_route@3 __puya_arc4_router___compare_route@4 - b __puya_arc4_router___switch_case_default@5 + uncover 4 + match __puya_arc4_router___get_one_route@2 __puya_arc4_router___get_two_route@3 __puya_arc4_router___get_three_route@4 __puya_arc4_router___compare_route@5 + b __puya_arc4_router___switch_case_default@6 __puya_arc4_router___get_one_route@2: - // struct_by_name/contract.py:23 + // struct_by_name/contract.py:25 // @arc4.abimethod() txn OnCompletion intc_0 // NoOp @@ -50,7 +51,7 @@ __puya_arc4_router___get_one_route@2: retsub __puya_arc4_router___get_two_route@3: - // struct_by_name/contract.py:30 + // struct_by_name/contract.py:32 // @arc4.abimethod() txn OnCompletion intc_0 // NoOp @@ -74,8 +75,33 @@ __puya_arc4_router___get_two_route@3: intc_1 // 1 retsub -__puya_arc4_router___compare_route@4: - // struct_by_name/contract.py:37 +__puya_arc4_router___get_three_route@4: + // struct_by_name/contract.py:39 + // @arc4.abimethod() + txn OnCompletion + intc_0 // NoOp + == + assert // OnCompletion is not NoOp + txn ApplicationID + intc_0 // 0 + != + assert // can only call when not creating + callsub get_three + swap + bytec_1 // 0x + swap + concat + swap + concat + bytec_0 // 0x151f7c75 + swap + concat + log + intc_1 // 1 + retsub + +__puya_arc4_router___compare_route@5: + // struct_by_name/contract.py:46 // @arc4.abimethod() txn OnCompletion intc_0 // NoOp @@ -97,19 +123,19 @@ __puya_arc4_router___compare_route@4: intc_1 // 1 retsub -__puya_arc4_router___switch_case_default@5: - b __puya_arc4_router___after_if_else@11 +__puya_arc4_router___switch_case_default@6: + b __puya_arc4_router___after_if_else@12 -__puya_arc4_router___bare_routing@7: - // struct_by_name/contract.py:16 +__puya_arc4_router___bare_routing@8: + // struct_by_name/contract.py:18 // class DemoContract(ARC4Contract): txn OnCompletion intc_0 // 0 swap - match __puya_arc4_router_____algopy_default_create@8 - b __puya_arc4_router___switch_case_default@9 + match __puya_arc4_router_____algopy_default_create@9 + b __puya_arc4_router___switch_case_default@10 -__puya_arc4_router_____algopy_default_create@8: +__puya_arc4_router_____algopy_default_create@9: txn ApplicationID intc_0 // 0 == @@ -118,10 +144,10 @@ __puya_arc4_router_____algopy_default_create@8: intc_1 // 1 retsub -__puya_arc4_router___switch_case_default@9: +__puya_arc4_router___switch_case_default@10: -__puya_arc4_router___after_if_else@11: - // struct_by_name/contract.py:16 +__puya_arc4_router___after_if_else@12: + // struct_by_name/contract.py:18 // class DemoContract(ARC4Contract): intc_0 // 0 retsub @@ -129,17 +155,17 @@ __puya_arc4_router___after_if_else@11: // test_cases.struct_by_name.contract.DemoContract.get_one() -> bytes, bytes: get_one: - // struct_by_name/contract.py:23-24 + // struct_by_name/contract.py:25-26 // @arc4.abimethod() // def get_one(self) -> StructOne: proto 0 2 - // struct_by_name/contract.py:26 + // struct_by_name/contract.py:28 // x=arc4.UInt8(1), bytec_2 // 0x01 - // struct_by_name/contract.py:27 + // struct_by_name/contract.py:29 // y=arc4.UInt8(1), dup - // struct_by_name/contract.py:25-28 + // struct_by_name/contract.py:27-30 // return StructOne( // x=arc4.UInt8(1), // y=arc4.UInt8(1), @@ -149,17 +175,17 @@ get_one: // test_cases.struct_by_name.contract.DemoContract.get_two() -> bytes, bytes: get_two: - // struct_by_name/contract.py:30-31 + // struct_by_name/contract.py:32-33 // @arc4.abimethod() // def get_two(self) -> StructTwo: proto 0 2 - // struct_by_name/contract.py:33 + // struct_by_name/contract.py:35 // x=arc4.UInt8(1), bytec_2 // 0x01 - // struct_by_name/contract.py:34 + // struct_by_name/contract.py:36 // y=arc4.UInt8(1), dup - // struct_by_name/contract.py:32-35 + // struct_by_name/contract.py:34-37 // return StructTwo( // x=arc4.UInt8(1), // y=arc4.UInt8(1), @@ -167,14 +193,34 @@ get_two: retsub +// test_cases.struct_by_name.contract.DemoContract.get_three() -> bytes, bytes: +get_three: + // struct_by_name/contract.py:39-40 + // @arc4.abimethod() + // def get_three(self) -> StructThree: + proto 0 2 + // struct_by_name/contract.py:42 + // x=arc4.UInt8(1), + bytec_2 // 0x01 + // struct_by_name/contract.py:43 + // y=arc4.UInt8(1), + dup + // struct_by_name/contract.py:41-44 + // return StructThree( + // x=arc4.UInt8(1), + // y=arc4.UInt8(1), + // ) + retsub + + // test_cases.struct_by_name.contract.DemoContract.compare() -> uint64: compare: - // struct_by_name/contract.py:37-38 + // struct_by_name/contract.py:46-47 // @arc4.abimethod() // def compare(self) -> bool: proto 0 1 - // struct_by_name/contract.py:39 - // return self.get_one() == self.get_two() + // struct_by_name/contract.py:48 + // return self.get_one() == self.get_two() and self.get_two() == self.get_three() callsub get_one swap callsub get_two @@ -184,6 +230,26 @@ compare: uncover 2 b== && + bz compare_bool_false@3 + callsub get_two + swap + callsub get_three + cover 2 + b== + uncover 2 + uncover 2 + b== + && + bz compare_bool_false@3 + intc_1 // 1 + b compare_bool_merge@4 + +compare_bool_false@3: + intc_0 // 0 + +compare_bool_merge@4: + // struct_by_name/contract.py:48 + // return self.get_one() == self.get_two() and self.get_two() == self.get_three() retsub diff --git a/test_cases/struct_by_name/out_unoptimized/DemoContract.destructured.ir b/test_cases/struct_by_name/out_unoptimized/DemoContract.destructured.ir index 53748840fe..b282675536 100644 --- a/test_cases/struct_by_name/out_unoptimized/DemoContract.destructured.ir +++ b/test_cases/struct_by_name/out_unoptimized/DemoContract.destructured.ir @@ -6,14 +6,14 @@ contract test_cases.struct_by_name.contract.DemoContract: return tmp%0#0 subroutine test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__() -> bool: - block@0: // L16 + block@0: // L18 let tmp%0#0: uint64 = (txn NumAppArgs) let tmp%1#0: bool = (!= tmp%0#0 0u) - goto tmp%1#0 ? block@1 : block@7 - block@1: // abi_routing_L16 + goto tmp%1#0 ? block@1 : block@8 + block@1: // abi_routing_L18 let tmp%2#0: bytes = (txna ApplicationArgs 0) - switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "compare()bool" => block@4, * => block@5} - block@2: // get_one_route_L23 + switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "get_three()(uint8,uint8)" => block@4, method "compare()bool" => block@5, * => block@6} + block@2: // get_one_route_L25 let tmp%3#0: uint64 = (txn OnCompletion) let tmp%4#0: bool = (== tmp%3#0 NoOp) (assert tmp%4#0) // OnCompletion is not NoOp @@ -26,7 +26,7 @@ contract test_cases.struct_by_name.contract.DemoContract: let tmp%7#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%2#0) (log tmp%7#0) return 1u - block@3: // get_two_route_L30 + block@3: // get_two_route_L32 let tmp%8#0: uint64 = (txn OnCompletion) let tmp%9#0: bool = (== tmp%8#0 NoOp) (assert tmp%9#0) // OnCompletion is not NoOp @@ -39,48 +39,65 @@ contract test_cases.struct_by_name.contract.DemoContract: let tmp%12#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%5#0) (log tmp%12#0) return 1u - block@4: // compare_route_L37 + block@4: // get_three_route_L39 let tmp%13#0: uint64 = (txn OnCompletion) let tmp%14#0: bool = (== tmp%13#0 NoOp) (assert tmp%14#0) // OnCompletion is not NoOp let tmp%15#0: uint64 = (txn ApplicationID) let tmp%16#0: bool = (!= tmp%15#0 0u) (assert tmp%16#0) // can only call when not creating - let to_encode%0#0: bool = test_cases.struct_by_name.contract.DemoContract.compare() - let encoded_bool%0#0: bytes = (setbit 0x00 0u to_encode%0#0) - let tmp%17#0: bytes = (concat 0x151f7c75 encoded_bool%0#0) + let (elements_to_encode%4#0: bytes, elements_to_encode%5#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_three() + let encoded_tuple_buffer%7#0: bytes = (concat 0x elements_to_encode%4#0) + let encoded_tuple_buffer%8#0: bytes = (concat encoded_tuple_buffer%7#0 elements_to_encode%5#0) + let tmp%17#0: bytes = (concat 0x151f7c75 encoded_tuple_buffer%8#0) (log tmp%17#0) return 1u - block@5: // switch_case_default_L16 - goto block@6 - block@6: // switch_case_next_L16 - goto block@11 - block@7: // bare_routing_L16 + block@5: // compare_route_L46 let tmp%18#0: uint64 = (txn OnCompletion) - switch tmp%18#0 {0u => block@8, * => block@9} - block@8: // __algopy_default_create_L1 - let tmp%19#0: uint64 = (txn ApplicationID) - let tmp%20#0: bool = (== tmp%19#0 0u) - (assert tmp%20#0) // can only call when creating + let tmp%19#0: bool = (== tmp%18#0 NoOp) + (assert tmp%19#0) // OnCompletion is not NoOp + let tmp%20#0: uint64 = (txn ApplicationID) + let tmp%21#0: bool = (!= tmp%20#0 0u) + (assert tmp%21#0) // can only call when not creating + let to_encode%0#0: bool = test_cases.struct_by_name.contract.DemoContract.compare() + let encoded_bool%0#0: bytes = (setbit 0x00 0u to_encode%0#0) + let tmp%22#0: bytes = (concat 0x151f7c75 encoded_bool%0#0) + (log tmp%22#0) + return 1u + block@6: // switch_case_default_L18 + goto block@7 + block@7: // switch_case_next_L18 + goto block@12 + block@8: // bare_routing_L18 + let tmp%23#0: uint64 = (txn OnCompletion) + switch tmp%23#0 {0u => block@9, * => block@10} + block@9: // __algopy_default_create_L1 + let tmp%24#0: uint64 = (txn ApplicationID) + let tmp%25#0: bool = (== tmp%24#0 0u) + (assert tmp%25#0) // can only call when creating test_cases.struct_by_name.contract.DemoContract.__algopy_default_create() return 1u - block@9: // switch_case_default_L16 - goto block@10 - block@10: // switch_case_next_L16 + block@10: // switch_case_default_L18 goto block@11 - block@11: // after_if_else_L16 + block@11: // switch_case_next_L18 + goto block@12 + block@12: // after_if_else_L18 return 0u subroutine test_cases.struct_by_name.contract.DemoContract.get_one() -> : - block@0: // L23 + block@0: // L25 return 0x01 0x01 subroutine test_cases.struct_by_name.contract.DemoContract.get_two() -> : - block@0: // L30 + block@0: // L32 + return 0x01 0x01 + + subroutine test_cases.struct_by_name.contract.DemoContract.get_three() -> : + block@0: // L39 return 0x01 0x01 subroutine test_cases.struct_by_name.contract.DemoContract.compare() -> bool: - block@0: // L37 + block@0: // L46 let (awst_tmp%0#0: bytes, awst_tmp%1#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_one() let reinterpret_biguint%0#0: biguint = awst_tmp%0#0 let (awst_tmp%2#0: bytes, awst_tmp%3#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_two() @@ -90,7 +107,26 @@ contract test_cases.struct_by_name.contract.DemoContract: let reinterpret_biguint%3#0: biguint = awst_tmp%3#0 let tmp%1#0: bool = (b== reinterpret_biguint%2#0 reinterpret_biguint%3#0) let tmp%2#0: bool = (&& tmp%0#0 tmp%1#0) - return tmp%2#0 + goto tmp%2#0 ? block@1 : block@3 + block@1: // and_contd_L48 + let (awst_tmp%4#0: bytes, awst_tmp%5#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_two() + let reinterpret_biguint%4#0: biguint = awst_tmp%4#0 + let (awst_tmp%6#0: bytes, awst_tmp%7#0: bytes) = test_cases.struct_by_name.contract.DemoContract.get_three() + let reinterpret_biguint%5#0: biguint = awst_tmp%6#0 + let tmp%3#0: bool = (b== reinterpret_biguint%4#0 reinterpret_biguint%5#0) + let reinterpret_biguint%6#0: biguint = awst_tmp%5#0 + let reinterpret_biguint%7#0: biguint = awst_tmp%7#0 + let tmp%4#0: bool = (b== reinterpret_biguint%6#0 reinterpret_biguint%7#0) + let tmp%5#0: bool = (&& tmp%3#0 tmp%4#0) + goto tmp%5#0 ? block@2 : block@3 + block@2: // bool_true_L48 + let and_result%0#0: bool = 1u + goto block@4 + block@3: // bool_false_L48 + let and_result%0#0: bool = 0u + goto block@4 + block@4: // bool_merge_L48 + return and_result%0#0 subroutine test_cases.struct_by_name.contract.DemoContract.__algopy_default_create() -> void: block@0: // L1 diff --git a/test_cases/struct_by_name/puya.log b/test_cases/struct_by_name/puya.log index 64af4f262d..4ef0a136cd 100644 --- a/test_cases/struct_by_name/puya.log +++ b/test_cases/struct_by_name/puya.log @@ -350,36 +350,51 @@ debug: Added array_head_and_tail#0 to Phi node: let array_head_and_tail#1: bytes debug: Added array_head_and_tail#2 to Phi node: let array_head_and_tail#1: bytes = φ(array_head_and_tail#0 <- block@0, array_head_and_tail#2 <- block@3) in block@3: // for_footer_L327 debug: Sealing block@4: // after_for_L327 debug: Terminated block@4: // after_for_L327 -debug: Sealing block@0: // L16 -debug: Terminated block@0: // L16 -debug: Sealing block@1: // abi_routing_L16 -debug: Terminated block@1: // abi_routing_L16 -debug: Sealing block@2: // get_one_route_L23 -debug: Terminated block@2: // get_one_route_L23 -debug: Sealing block@3: // get_two_route_L30 -debug: Terminated block@3: // get_two_route_L30 -debug: Sealing block@4: // compare_route_L37 -debug: Terminated block@4: // compare_route_L37 -debug: Sealing block@5: // switch_case_default_L16 -debug: Terminated block@5: // switch_case_default_L16 -debug: Sealing block@6: // switch_case_next_L16 -debug: Terminated block@6: // switch_case_next_L16 -debug: Sealing block@7: // bare_routing_L16 -debug: Terminated block@7: // bare_routing_L16 -debug: Sealing block@8: // __algopy_default_create_L1 -debug: Terminated block@8: // __algopy_default_create_L1 -debug: Sealing block@9: // switch_case_default_L16 -debug: Terminated block@9: // switch_case_default_L16 -debug: Sealing block@10: // switch_case_next_L16 -debug: Terminated block@10: // switch_case_next_L16 -debug: Sealing block@11: // after_if_else_L16 -debug: Terminated block@11: // after_if_else_L16 -debug: Sealing block@0: // L23 -debug: Terminated block@0: // L23 -debug: Sealing block@0: // L30 -debug: Terminated block@0: // L30 -debug: Sealing block@0: // L37 -debug: Terminated block@0: // L37 +debug: Sealing block@0: // L18 +debug: Terminated block@0: // L18 +debug: Sealing block@1: // abi_routing_L18 +debug: Terminated block@1: // abi_routing_L18 +debug: Sealing block@2: // get_one_route_L25 +debug: Terminated block@2: // get_one_route_L25 +debug: Sealing block@3: // get_two_route_L32 +debug: Terminated block@3: // get_two_route_L32 +debug: Sealing block@4: // get_three_route_L39 +debug: Terminated block@4: // get_three_route_L39 +debug: Sealing block@5: // compare_route_L46 +debug: Terminated block@5: // compare_route_L46 +debug: Sealing block@6: // switch_case_default_L18 +debug: Terminated block@6: // switch_case_default_L18 +debug: Sealing block@7: // switch_case_next_L18 +debug: Terminated block@7: // switch_case_next_L18 +debug: Sealing block@8: // bare_routing_L18 +debug: Terminated block@8: // bare_routing_L18 +debug: Sealing block@9: // __algopy_default_create_L1 +debug: Terminated block@9: // __algopy_default_create_L1 +debug: Sealing block@10: // switch_case_default_L18 +debug: Terminated block@10: // switch_case_default_L18 +debug: Sealing block@11: // switch_case_next_L18 +debug: Terminated block@11: // switch_case_next_L18 +debug: Sealing block@12: // after_if_else_L18 +debug: Terminated block@12: // after_if_else_L18 +debug: Sealing block@0: // L25 +debug: Terminated block@0: // L25 +debug: Sealing block@0: // L32 +debug: Terminated block@0: // L32 +debug: Sealing block@0: // L39 +debug: Terminated block@0: // L39 +debug: Sealing block@0: // L46 +debug: Terminated block@0: // L46 +debug: Sealing block@1: // and_contd_L48 +debug: Terminated block@1: // and_contd_L48 +debug: Sealing block@2: // bool_true_L48 +debug: Terminated block@2: // bool_true_L48 +debug: Sealing block@3: // bool_false_L48 +debug: Terminated block@3: // bool_false_L48 +debug: Sealing block@4: // bool_merge_L48 +debug: Created Phi assignment: let and_result%0#2: bool = undefined while trying to resolve 'and_result%0' in block@4: // bool_merge_L48 +debug: Added and_result%0#0 to Phi node: let and_result%0#2: bool = φ(and_result%0#0 <- block@2) in block@2: // bool_true_L48 +debug: Added and_result%0#1 to Phi node: let and_result%0#2: bool = φ(and_result%0#0 <- block@2, and_result%0#1 <- block@3) in block@3: // bool_false_L48 +debug: Terminated block@4: // bool_merge_L48 debug: Sealing block@0: // L1 debug: Terminated block@0: // L1 debug: Sealing block@0: // L1 @@ -414,7 +429,9 @@ debug: Simplified (concat 0x elements_to_encode%0#0) to elements_to_encode%0#0 debug: Simplified (== tmp%8#0 NoOp) to (! tmp%8#0) debug: Simplified (concat 0x elements_to_encode%2#0) to elements_to_encode%2#0 debug: Simplified (== tmp%13#0 NoOp) to (! tmp%13#0) -debug: Simplified (== tmp%19#0 0u) to (! tmp%19#0) +debug: Simplified (concat 0x elements_to_encode%4#0) to elements_to_encode%4#0 +debug: Simplified (== tmp%18#0 NoOp) to (! tmp%18#0) +debug: Simplified (== tmp%24#0 0u) to (! tmp%24#0) debug: Optimizer: Remove Unused Variables debug: Removing unused variable tmp%1#0 debug: Removing unused variable tmp%6#0 @@ -424,30 +441,33 @@ debug: Removing unused variable tmp%11#0 debug: Removing unused variable current_tail_offset%1#0 debug: Removing unused variable encoded_tuple_buffer%3#0 debug: Removing unused variable tmp%16#0 +debug: Removing unused variable current_tail_offset%2#0 +debug: Removing unused variable encoded_tuple_buffer%6#0 +debug: Removing unused variable tmp%21#0 debug: Optimizer: Remove Unused Ops debug: Optimizer: Inner Txn Field Replacer debug: Optimizer: Replace Compiled References debug: Optimizer: Simplify Control Ops debug: inlining the default target of a switch/goto nth -debug: adding block@1: // abi_routing_L16 as a predecessor of block@6: // switch_case_next_L16 due to inlining of block@5: // switch_case_default_L16 -debug: simplified terminator of block@1: // abi_routing_L16 from switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "compare()bool" => block@4, * => block@5} to switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "compare()bool" => block@4, * => block@6} +debug: adding block@1: // abi_routing_L18 as a predecessor of block@7: // switch_case_next_L18 due to inlining of block@6: // switch_case_default_L18 +debug: simplified terminator of block@1: // abi_routing_L18 from switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "get_three()(uint8,uint8)" => block@4, method "compare()bool" => block@5, * => block@6} to switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "get_three()(uint8,uint8)" => block@4, method "compare()bool" => block@5, * => block@7} debug: simplifying a switch with constants into goto nth -debug: simplified terminator of block@7: // bare_routing_L16 from switch tmp%18#0 {0u => block@8, * => block@9} to goto_nth [block@8][tmp%18#0] else goto block@9 +debug: simplified terminator of block@8: // bare_routing_L18 from switch tmp%23#0 {0u => block@9, * => block@10} to goto_nth [block@9][tmp%23#0] else goto block@10 debug: inlining the default target of a switch/goto nth -debug: adding block@1: // abi_routing_L16 as a predecessor of block@11: // after_if_else_L16 due to inlining of block@6: // switch_case_next_L16 -debug: simplified terminator of block@1: // abi_routing_L16 from switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "compare()bool" => block@4, * => block@6} to switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "compare()bool" => block@4, * => block@11} +debug: adding block@1: // abi_routing_L18 as a predecessor of block@12: // after_if_else_L18 due to inlining of block@7: // switch_case_next_L18 +debug: simplified terminator of block@1: // abi_routing_L18 from switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "get_three()(uint8,uint8)" => block@4, method "compare()bool" => block@5, * => block@7} to switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "get_three()(uint8,uint8)" => block@4, method "compare()bool" => block@5, * => block@12} debug: simplifying a goto nth with two targets into a conditional branch -debug: simplified terminator of block@7: // bare_routing_L16 from goto_nth [block@8][tmp%18#0] else goto block@9 to goto tmp%18#0 ? block@9 : block@8 +debug: simplified terminator of block@8: // bare_routing_L18 from goto_nth [block@9][tmp%23#0] else goto block@10 to goto tmp%23#0 ? block@10 : block@9 debug: inlining the default target of a switch/goto nth -debug: simplified terminator of block@1: // abi_routing_L16 from switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "compare()bool" => block@4, * => block@11} to switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "compare()bool" => block@4, * => return 0u} +debug: simplified terminator of block@1: // abi_routing_L18 from switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "get_three()(uint8,uint8)" => block@4, method "compare()bool" => block@5, * => block@12} to switch tmp%2#0 {method "get_one()(uint8,uint8)" => block@2, method "get_two()(uint8,uint8)" => block@3, method "get_three()(uint8,uint8)" => block@4, method "compare()bool" => block@5, * => return 0u} debug: Optimizer: Remove Linear Jump -debug: Replaced predecessor block@6: // switch_case_next_L16 with block@5: // switch_case_default_L16 in block@11: // after_if_else_L16 -debug: Merged linear block@6: // switch_case_next_L16 into block@5: // switch_case_default_L16 -debug: Replaced predecessor block@10: // switch_case_next_L16 with block@9: // switch_case_default_L16 in block@11: // after_if_else_L16 -debug: Merged linear block@10: // switch_case_next_L16 into block@9: // switch_case_default_L16 +debug: Replaced predecessor block@7: // switch_case_next_L18 with block@6: // switch_case_default_L18 in block@12: // after_if_else_L18 +debug: Merged linear block@7: // switch_case_next_L18 into block@6: // switch_case_default_L18 +debug: Replaced predecessor block@11: // switch_case_next_L18 with block@10: // switch_case_default_L18 in block@12: // after_if_else_L18 +debug: Merged linear block@11: // switch_case_next_L18 into block@10: // switch_case_default_L18 debug: Optimizer: Remove Empty Blocks -debug: Removed empty block: block@5: // switch_case_default_L16 -debug: Removed empty block: block@9: // switch_case_default_L16 +debug: Removed empty block: block@6: // switch_case_default_L18 +debug: Removed empty block: block@10: // switch_case_default_L18 debug: Optimizer: Remove Unreachable Blocks debug: Optimizer: Repeated Expression Elimination debug: Optimizer: Remove Calls To No Op Subroutines @@ -481,6 +501,21 @@ debug: Optimizer: Remove Empty Blocks debug: Optimizer: Remove Unreachable Blocks debug: Optimizer: Repeated Expression Elimination debug: Optimizer: Remove Calls To No Op Subroutines +debug: Optimizing subroutine test_cases.struct_by_name.contract.DemoContract.get_three +debug: Splitting parallel copies prior to optimization +debug: Optimizer: Constant Replacer +debug: Optimizer: Copy Propagation +debug: Optimizer: Intrinsic Simplifier +debug: Optimizer: Remove Unused Variables +debug: Optimizer: Remove Unused Ops +debug: Optimizer: Inner Txn Field Replacer +debug: Optimizer: Replace Compiled References +debug: Optimizer: Simplify Control Ops +debug: Optimizer: Remove Linear Jump +debug: Optimizer: Remove Empty Blocks +debug: Optimizer: Remove Unreachable Blocks +debug: Optimizer: Repeated Expression Elimination +debug: Optimizer: Remove Calls To No Op Subroutines debug: Optimizing subroutine test_cases.struct_by_name.contract.DemoContract.compare debug: Splitting parallel copies prior to optimization debug: Optimizer: Constant Replacer @@ -493,6 +528,14 @@ debug: Found equivalence set: awst_tmp%1#0, reinterpret_biguint%2#0 debug: Replacing {reinterpret_biguint%2#0} with awst_tmp%1#0 made 1 modifications debug: Found equivalence set: awst_tmp%3#0, reinterpret_biguint%3#0 debug: Replacing {reinterpret_biguint%3#0} with awst_tmp%3#0 made 1 modifications +debug: Found equivalence set: awst_tmp%4#0, reinterpret_biguint%4#0 +debug: Replacing {reinterpret_biguint%4#0} with awst_tmp%4#0 made 1 modifications +debug: Found equivalence set: awst_tmp%6#0, reinterpret_biguint%5#0 +debug: Replacing {reinterpret_biguint%5#0} with awst_tmp%6#0 made 1 modifications +debug: Found equivalence set: awst_tmp%5#0, reinterpret_biguint%6#0 +debug: Replacing {reinterpret_biguint%6#0} with awst_tmp%5#0 made 1 modifications +debug: Found equivalence set: awst_tmp%7#0, reinterpret_biguint%7#0 +debug: Replacing {reinterpret_biguint%7#0} with awst_tmp%7#0 made 1 modifications debug: Optimizer: Intrinsic Simplifier debug: Optimizer: Remove Unused Variables debug: Optimizer: Remove Unused Ops @@ -557,6 +600,8 @@ debug: Found equivalence set: elements_to_encode%0#0, encoded_tuple_buffer%1#0 debug: Replacing {encoded_tuple_buffer%1#0} with elements_to_encode%0#0 made 1 modifications debug: Found equivalence set: elements_to_encode%2#0, encoded_tuple_buffer%4#0 debug: Replacing {encoded_tuple_buffer%4#0} with elements_to_encode%2#0 made 1 modifications +debug: Found equivalence set: elements_to_encode%4#0, encoded_tuple_buffer%7#0 +debug: Replacing {encoded_tuple_buffer%7#0} with elements_to_encode%4#0 made 1 modifications debug: Optimizer: Intrinsic Simplifier debug: Optimizer: Remove Unused Variables debug: Optimizer: Remove Unused Ops @@ -596,6 +641,20 @@ debug: Optimizer: Remove Empty Blocks debug: Optimizer: Remove Unreachable Blocks debug: Optimizer: Repeated Expression Elimination debug: Optimizer: Remove Calls To No Op Subroutines +debug: Optimizing subroutine test_cases.struct_by_name.contract.DemoContract.get_three +debug: Optimizer: Constant Replacer +debug: Optimizer: Copy Propagation +debug: Optimizer: Intrinsic Simplifier +debug: Optimizer: Remove Unused Variables +debug: Optimizer: Remove Unused Ops +debug: Optimizer: Inner Txn Field Replacer +debug: Optimizer: Replace Compiled References +debug: Optimizer: Simplify Control Ops +debug: Optimizer: Remove Linear Jump +debug: Optimizer: Remove Empty Blocks +debug: Optimizer: Remove Unreachable Blocks +debug: Optimizer: Repeated Expression Elimination +debug: Optimizer: Remove Calls To No Op Subroutines debug: Optimizing subroutine test_cases.struct_by_name.contract.DemoContract.compare debug: Optimizer: Constant Replacer debug: Optimizer: Copy Propagation @@ -682,6 +741,20 @@ debug: Optimizer: Remove Empty Blocks debug: Optimizer: Remove Unreachable Blocks debug: Optimizer: Repeated Expression Elimination debug: Optimizer: Remove Calls To No Op Subroutines +debug: Optimizing subroutine test_cases.struct_by_name.contract.DemoContract.get_three +debug: Optimizer: Constant Replacer +debug: Optimizer: Copy Propagation +debug: Optimizer: Intrinsic Simplifier +debug: Optimizer: Remove Unused Variables +debug: Optimizer: Remove Unused Ops +debug: Optimizer: Inner Txn Field Replacer +debug: Optimizer: Replace Compiled References +debug: Optimizer: Simplify Control Ops +debug: Optimizer: Remove Linear Jump +debug: Optimizer: Remove Empty Blocks +debug: Optimizer: Remove Unreachable Blocks +debug: Optimizer: Repeated Expression Elimination +debug: Optimizer: Remove Calls To No Op Subroutines debug: Optimizing subroutine test_cases.struct_by_name.contract.DemoContract.compare debug: Optimizer: Constant Replacer debug: Optimizer: Copy Propagation @@ -715,6 +788,7 @@ debug: Removing Phis from algopy.arc4.ARC4Contract.approval_program debug: Removing Phis from test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__ debug: Removing Phis from test_cases.struct_by_name.contract.DemoContract.get_one debug: Removing Phis from test_cases.struct_by_name.contract.DemoContract.get_two +debug: Removing Phis from test_cases.struct_by_name.contract.DemoContract.get_three debug: Removing Phis from test_cases.struct_by_name.contract.DemoContract.compare debug: Removing Phis from algopy.arc4.ARC4Contract.clear_state_program debug: Coalescing local variables in algopy.arc4.ARC4Contract.approval_program using strategy RootOperandGrouping @@ -725,14 +799,18 @@ debug: Coalescing local variables in test_cases.struct_by_name.contract.DemoCont debug: Coalescing resulted in 0 replacement/s debug: Coalescing local variables in test_cases.struct_by_name.contract.DemoContract.get_two using strategy RootOperandGrouping debug: Coalescing resulted in 0 replacement/s -debug: Coalescing local variables in test_cases.struct_by_name.contract.DemoContract.compare using strategy RootOperandGrouping +debug: Coalescing local variables in test_cases.struct_by_name.contract.DemoContract.get_three using strategy RootOperandGrouping debug: Coalescing resulted in 0 replacement/s +debug: Coalescing local variables in test_cases.struct_by_name.contract.DemoContract.compare using strategy RootOperandGrouping +debug: Coalescing and_result%0#0 with [and_result%0#5, and_result%0#1, and_result%0#2] +debug: Coalescing resulted in 7 replacement/s debug: Coalescing local variables in algopy.arc4.ARC4Contract.clear_state_program using strategy RootOperandGrouping debug: Coalescing resulted in 0 replacement/s debug: Sequentializing parallel copies in algopy.arc4.ARC4Contract.approval_program debug: Sequentializing parallel copies in test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__ debug: Sequentializing parallel copies in test_cases.struct_by_name.contract.DemoContract.get_one debug: Sequentializing parallel copies in test_cases.struct_by_name.contract.DemoContract.get_two +debug: Sequentializing parallel copies in test_cases.struct_by_name.contract.DemoContract.get_three debug: Sequentializing parallel copies in test_cases.struct_by_name.contract.DemoContract.compare debug: Sequentializing parallel copies in algopy.arc4.ARC4Contract.clear_state_program debug: Performing post-SSA optimizations @@ -742,7 +820,7 @@ debug: Replaced main_block@0.ops[3]: 'v-load tmp%0#0' with 'l-load tmp%0#0' debug: Inserted __puya_arc4_router___block@0.ops[1]: 'l-store-copy tmp%0#0 0' debug: Replaced __puya_arc4_router___block@0.ops[3]: 'v-load tmp%0#0' with 'l-load tmp%0#0' debug: Inserted __puya_arc4_router___abi_routing@1.ops[1]: 'l-store-copy tmp%2#0 0' -debug: Replaced __puya_arc4_router___abi_routing@1.ops[6]: 'v-load tmp%2#0' with 'l-load tmp%2#0' +debug: Replaced __puya_arc4_router___abi_routing@1.ops[7]: 'v-load tmp%2#0' with 'l-load tmp%2#0' debug: Inserted __puya_arc4_router___get_one_route@2.ops[1]: 'l-store-copy tmp%3#0 0' debug: Replaced __puya_arc4_router___get_one_route@2.ops[3]: 'v-load tmp%3#0' with 'l-load tmp%3#0' debug: Inserted __puya_arc4_router___get_one_route@2.ops[5]: 'l-store-copy tmp%4#0 0' @@ -771,24 +849,38 @@ debug: Inserted __puya_arc4_router___get_two_route@3.ops[21]: 'l-store-copy enco debug: Replaced __puya_arc4_router___get_two_route@3.ops[24]: 'v-load encoded_tuple_buffer%5#0' with 'l-load encoded_tuple_buffer%5#0' debug: Inserted __puya_arc4_router___get_two_route@3.ops[15]: 'l-store-copy elements_to_encode%3#0 1' debug: Replaced __puya_arc4_router___get_two_route@3.ops[20]: 'v-load elements_to_encode%3#0' with 'l-load elements_to_encode%3#0' -debug: Inserted __puya_arc4_router___compare_route@4.ops[1]: 'l-store-copy tmp%13#0 0' -debug: Replaced __puya_arc4_router___compare_route@4.ops[3]: 'v-load tmp%13#0' with 'l-load tmp%13#0' -debug: Inserted __puya_arc4_router___compare_route@4.ops[5]: 'l-store-copy tmp%14#0 0' -debug: Replaced __puya_arc4_router___compare_route@4.ops[7]: 'v-load tmp%14#0' with 'l-load tmp%14#0' -debug: Inserted __puya_arc4_router___compare_route@4.ops[10]: 'l-store-copy tmp%15#0 0' -debug: Replaced __puya_arc4_router___compare_route@4.ops[12]: 'v-load tmp%15#0' with 'l-load tmp%15#0' -debug: Inserted __puya_arc4_router___compare_route@4.ops[24]: 'l-store-copy tmp%17#0 0' -debug: Replaced __puya_arc4_router___compare_route@4.ops[26]: 'v-load tmp%17#0' with 'l-load tmp%17#0' -debug: Inserted __puya_arc4_router___compare_route@4.ops[20]: 'l-store-copy encoded_bool%0#0 0' -debug: Replaced __puya_arc4_router___compare_route@4.ops[23]: 'v-load encoded_bool%0#0' with 'l-load encoded_bool%0#0' -debug: Inserted __puya_arc4_router___compare_route@4.ops[15]: 'l-store-copy to_encode%0#0 0' -debug: Replaced __puya_arc4_router___compare_route@4.ops[19]: 'v-load to_encode%0#0' with 'l-load to_encode%0#0' -debug: Inserted __puya_arc4_router___bare_routing@7.ops[1]: 'l-store-copy tmp%18#0 0' -debug: Replaced __puya_arc4_router___bare_routing@7.ops[3]: 'v-load tmp%18#0' with 'l-load tmp%18#0' -debug: Inserted __puya_arc4_router_____algopy_default_create@8.ops[1]: 'l-store-copy tmp%19#0 0' -debug: Replaced __puya_arc4_router_____algopy_default_create@8.ops[3]: 'v-load tmp%19#0' with 'l-load tmp%19#0' -debug: Inserted __puya_arc4_router_____algopy_default_create@8.ops[5]: 'l-store-copy tmp%20#0 0' -debug: Replaced __puya_arc4_router_____algopy_default_create@8.ops[7]: 'v-load tmp%20#0' with 'l-load tmp%20#0' +debug: Inserted __puya_arc4_router___get_three_route@4.ops[1]: 'l-store-copy tmp%13#0 0' +debug: Replaced __puya_arc4_router___get_three_route@4.ops[3]: 'v-load tmp%13#0' with 'l-load tmp%13#0' +debug: Inserted __puya_arc4_router___get_three_route@4.ops[5]: 'l-store-copy tmp%14#0 0' +debug: Replaced __puya_arc4_router___get_three_route@4.ops[7]: 'v-load tmp%14#0' with 'l-load tmp%14#0' +debug: Inserted __puya_arc4_router___get_three_route@4.ops[10]: 'l-store-copy tmp%15#0 0' +debug: Replaced __puya_arc4_router___get_three_route@4.ops[12]: 'v-load tmp%15#0' with 'l-load tmp%15#0' +debug: Inserted __puya_arc4_router___get_three_route@4.ops[16]: 'l-store-copy elements_to_encode%4#0 0' +debug: Replaced __puya_arc4_router___get_three_route@4.ops[18]: 'v-load elements_to_encode%4#0' with 'l-load elements_to_encode%4#0' +debug: Inserted __puya_arc4_router___get_three_route@4.ops[25]: 'l-store-copy tmp%17#0 0' +debug: Replaced __puya_arc4_router___get_three_route@4.ops[27]: 'v-load tmp%17#0' with 'l-load tmp%17#0' +debug: Inserted __puya_arc4_router___get_three_route@4.ops[21]: 'l-store-copy encoded_tuple_buffer%8#0 0' +debug: Replaced __puya_arc4_router___get_three_route@4.ops[24]: 'v-load encoded_tuple_buffer%8#0' with 'l-load encoded_tuple_buffer%8#0' +debug: Inserted __puya_arc4_router___get_three_route@4.ops[15]: 'l-store-copy elements_to_encode%5#0 1' +debug: Replaced __puya_arc4_router___get_three_route@4.ops[20]: 'v-load elements_to_encode%5#0' with 'l-load elements_to_encode%5#0' +debug: Inserted __puya_arc4_router___compare_route@5.ops[1]: 'l-store-copy tmp%18#0 0' +debug: Replaced __puya_arc4_router___compare_route@5.ops[3]: 'v-load tmp%18#0' with 'l-load tmp%18#0' +debug: Inserted __puya_arc4_router___compare_route@5.ops[5]: 'l-store-copy tmp%19#0 0' +debug: Replaced __puya_arc4_router___compare_route@5.ops[7]: 'v-load tmp%19#0' with 'l-load tmp%19#0' +debug: Inserted __puya_arc4_router___compare_route@5.ops[10]: 'l-store-copy tmp%20#0 0' +debug: Replaced __puya_arc4_router___compare_route@5.ops[12]: 'v-load tmp%20#0' with 'l-load tmp%20#0' +debug: Inserted __puya_arc4_router___compare_route@5.ops[24]: 'l-store-copy tmp%22#0 0' +debug: Replaced __puya_arc4_router___compare_route@5.ops[26]: 'v-load tmp%22#0' with 'l-load tmp%22#0' +debug: Inserted __puya_arc4_router___compare_route@5.ops[20]: 'l-store-copy encoded_bool%0#0 0' +debug: Replaced __puya_arc4_router___compare_route@5.ops[23]: 'v-load encoded_bool%0#0' with 'l-load encoded_bool%0#0' +debug: Inserted __puya_arc4_router___compare_route@5.ops[15]: 'l-store-copy to_encode%0#0 0' +debug: Replaced __puya_arc4_router___compare_route@5.ops[19]: 'v-load to_encode%0#0' with 'l-load to_encode%0#0' +debug: Inserted __puya_arc4_router___bare_routing@8.ops[1]: 'l-store-copy tmp%23#0 0' +debug: Replaced __puya_arc4_router___bare_routing@8.ops[3]: 'v-load tmp%23#0' with 'l-load tmp%23#0' +debug: Inserted __puya_arc4_router_____algopy_default_create@9.ops[1]: 'l-store-copy tmp%24#0 0' +debug: Replaced __puya_arc4_router_____algopy_default_create@9.ops[3]: 'v-load tmp%24#0' with 'l-load tmp%24#0' +debug: Inserted __puya_arc4_router_____algopy_default_create@9.ops[5]: 'l-store-copy tmp%25#0 0' +debug: Replaced __puya_arc4_router_____algopy_default_create@9.ops[7]: 'v-load tmp%25#0' with 'l-load tmp%25#0' debug: Inserted compare_block@0.ops[17]: 'l-store-copy tmp%2#0 0' debug: Replaced compare_block@0.ops[19]: 'v-load tmp%2#0' with 'l-load tmp%2#0' debug: Inserted compare_block@0.ops[5]: 'l-store-copy awst_tmp%2#0 0' @@ -803,7 +895,25 @@ debug: Inserted compare_block@0.ops[5]: 'l-store-copy awst_tmp%3#0 2' debug: Replaced compare_block@0.ops[15]: 'v-load awst_tmp%3#0' with 'l-load awst_tmp%3#0' debug: Inserted compare_block@0.ops[1]: 'l-store-copy awst_tmp%1#0 1' debug: Replaced compare_block@0.ops[15]: 'v-load awst_tmp%1#0' with 'l-load awst_tmp%1#0' +debug: Inserted compare_and_contd@1.ops[17]: 'l-store-copy tmp%5#0 0' +debug: Replaced compare_and_contd@1.ops[19]: 'v-load tmp%5#0' with 'l-load tmp%5#0' +debug: Inserted compare_and_contd@1.ops[5]: 'l-store-copy awst_tmp%6#0 0' +debug: Replaced compare_and_contd@1.ops[8]: 'v-load awst_tmp%6#0' with 'l-load awst_tmp%6#0' +debug: Inserted compare_and_contd@1.ops[14]: 'l-store-copy tmp%4#0 0' +debug: Replaced compare_and_contd@1.ops[17]: 'v-load tmp%4#0' with 'l-load tmp%4#0' +debug: Inserted compare_and_contd@1.ops[2]: 'l-store-copy awst_tmp%4#0 0' +debug: Replaced compare_and_contd@1.ops[8]: 'v-load awst_tmp%4#0' with 'l-load awst_tmp%4#0' +debug: Inserted compare_and_contd@1.ops[11]: 'l-store-copy tmp%3#0 0' +debug: Replaced compare_and_contd@1.ops[18]: 'v-load tmp%3#0' with 'l-load tmp%3#0' +debug: Inserted compare_and_contd@1.ops[5]: 'l-store-copy awst_tmp%7#0 2' +debug: Replaced compare_and_contd@1.ops[15]: 'v-load awst_tmp%7#0' with 'l-load awst_tmp%7#0' +debug: Inserted compare_and_contd@1.ops[1]: 'l-store-copy awst_tmp%5#0 1' +debug: Replaced compare_and_contd@1.ops[15]: 'v-load awst_tmp%5#0' with 'l-load awst_tmp%5#0' debug: Found 3 edge set/s for test_cases.struct_by_name.contract.DemoContract.__puya_arc4_router__ +debug: Found 2 edge set/s for test_cases.struct_by_name.contract.DemoContract.compare +debug: Allocated 1 variable/s to x-stack: and_result%0#0 +debug: shared x-stack for compare_bool_true@2 -> compare_bool_merge@4: and_result%0#0 +debug: shared x-stack for compare_bool_false@3 -> compare_bool_merge@4: and_result%0#0 info: Writing struct_by_name/out/DemoContract.arc32.json info: Writing struct_by_name/out/DemoContract.arc56.json info: Writing struct_by_name/out/DemoContract.approval.teal From 5d838284e081eac13aeb01f4c7db5938bbb64f4f Mon Sep 17 00:00:00 2001 From: Daniel McGregor Date: Mon, 25 Nov 2024 10:48:20 +0800 Subject: [PATCH 3/3] fix(internal): make ARC4Struct.name produce a name based only on alphanumeric characters only e.g. `A-Za-z0-9_` --- src/puya/models.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/puya/models.py b/src/puya/models.py index 0555f1e195..40faa8069c 100644 --- a/src/puya/models.py +++ b/src/puya/models.py @@ -1,5 +1,6 @@ import abc import enum +import re import typing from collections.abc import Mapping, Sequence @@ -62,7 +63,7 @@ class ARC4Struct: @property def name(self) -> str: - return self.fullname.rsplit(".", maxsplit=1)[-1] + return re.split(r"\W", self.fullname)[-1] @attrs.frozen(kw_only=True)