From 5bbf6265ac442abf010d5f74993c12b832af10a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Delabrouille?= Date: Thu, 9 Jun 2022 16:16:34 -0400 Subject: [PATCH 1/3] feat(exercise): add exercise register03 --- .patches/registers/registers03.cairo.patch | 15 +++ exercises/registers/registers03.cairo | 101 +++++++++++++++++++++ src/exercises/__init__.py | 1 + 3 files changed, 117 insertions(+) create mode 100644 .patches/registers/registers03.cairo.patch create mode 100644 exercises/registers/registers03.cairo diff --git a/.patches/registers/registers03.cairo.patch b/.patches/registers/registers03.cairo.patch new file mode 100644 index 00000000..8dfd1289 --- /dev/null +++ b/.patches/registers/registers03.cairo.patch @@ -0,0 +1,15 @@ +--- exercises/registers/registers03.cairo 2022-06-09 16:13:26.000000000 -0400 ++++ ./registers03.cairo 2022-06-09 16:11:29.000000000 -0400 +@@ -16,3 +16,3 @@ +- # [ap] = 42; ap++ +- # [ap - 1] = 42 +- # [ap - 1] = 21 ++ tempvar x = 42 ++ assert x = 42 ++ assert x = 21 +@@ -26 +26 @@ +- # assert number = 42 ++ [fp - 3] = 42 +@@ -36,0 +37,2 @@ ++ assert [p_number] = 42 ++ diff --git a/exercises/registers/registers03.cairo b/exercises/registers/registers03.cairo new file mode 100644 index 00000000..af97f0cc --- /dev/null +++ b/exercises/registers/registers03.cairo @@ -0,0 +1,101 @@ +%lang starknet + +# I AM NOT DONE + +# Cairo memory is immutable, which mean that once a memory cell have been assigned a value it be changed. +# The program will crash if someone try to assign a new, different, value to a already initialized memory cell. +# However, trying to assign twice, or more, a memory cell will the same value won't cause any harm. +# +# This property can be used to assert the value of a cell. +# By trying to give it a value to an already initialized memory cell, we can ensure that it already have this specific value, +# if it does not, the call fail + +# TODO +# Rewrite this function in a high level syntax, using tempvar and assert +func crash(): + # [ap] = 42; ap++ + # [ap - 1] = 42 + # [ap - 1] = 21 + + ret +end + +# TODO +# Rewrite this funtion in a low level syntax +func assert_42(number : felt): + # assert number = 42 + + return () +end + +# TODO +# Write this function body so: +# if the memory cell pointed by `p_number` is not initialised, it set it to 42 +# else if the value is initialized and different from 42, it crash +# else, do nothing and return +func assert_pointer_42(p_number : felt*): + return () +end + +######### +# TESTS # +######### + +from starkware.cairo.common.alloc import alloc + +@external +func test_crash(): + %{ expect_revert() %} + crash() + + return () +end + +@external +func test_assert_42(): + assert_42(42) + + %{ expect_revert() %} + assert_42(21) + + return () +end + +@external +func test_assert_pointer_42_initialized(): + let (mem_zone : felt*) = alloc() + assert mem_zone[0] = 42 + assert mem_zone[1] = 21 + + assert_pointer_42(mem_zone) + + %{ expect_revert() %} + assert_pointer_42(mem_zone + 1) + + return () +end + +@external +func test_assert_pointer_42_not_initialized_ok(): + let (mem_zone : felt*) = alloc() + assert mem_zone[0] = 42 + assert_pointer_42(mem_zone) + + assert_pointer_42(mem_zone + 1) + assert mem_zone[1] = 42 + + return () +end + +@external +func test_assert_pointer_42_not_initialized_revert(): + let (mem_zone : felt*) = alloc() + assert mem_zone[0] = 42 + assert_pointer_42(mem_zone) + + assert_pointer_42(mem_zone + 1) + %{ expect_revert() %} + assert mem_zone[1] = 21 + + return () +end diff --git a/src/exercises/__init__.py b/src/exercises/__init__.py index f4274ca9..91844698 100644 --- a/src/exercises/__init__.py +++ b/src/exercises/__init__.py @@ -25,6 +25,7 @@ "registers/registers00", "registers/registers01", "registers/registers02", + "registers/registers03", "revoked_references/revoked_references01", "tricks/no_conditionals", "tricks/assert_bool", From 567a69d9c3f5c9da19c35cffaf63b66ce837cc49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Delabrouille?= Date: Sat, 11 Jun 2022 22:23:18 -0400 Subject: [PATCH 2/3] chore: swap registers 2 and 3 feat: add more task to register assert exercise --- .patches/registers/registers02.cairo.patch | 94 +++--------- .patches/registers/registers03.cairo.patch | 91 ++++++++++-- exercises/registers/registers02.cairo | 159 ++++++++++++++------- exercises/registers/registers03.cairo | 128 +++++++---------- 4 files changed, 253 insertions(+), 219 deletions(-) diff --git a/.patches/registers/registers02.cairo.patch b/.patches/registers/registers02.cairo.patch index ce23b8ad..87e1dc5e 100644 --- a/.patches/registers/registers02.cairo.patch +++ b/.patches/registers/registers02.cairo.patch @@ -1,78 +1,16 @@ ---- exercises/registers/registers02.cairo 2022-05-18 12:53:44.000000000 -0400 -+++ .tmp_solution/registers02.cairo 2022-05-18 11:40:22.000000000 -0400 -@@ -3,0 +4 @@ -+ -@@ -9,6 +10,2 @@ --func sum_array(array_len : felt, array : felt*) -> (sum : felt): -- # [ap] = [fp - 4]; ap++ -- # [ap] = [fp - 3]; ap++ -- # [ap] = 0; ap++ -- # call rec_sum_array -- # ret -+func sum_array(array_len: felt, array: felt*) -> (sum: felt): -+ return rec_sum_array(array_len, array, 0) -@@ -17,16 +14,6 @@ --func rec_sum_array(array_len : felt, array : felt*, sum : felt) -> (sum : felt): -- # jmp continue if [fp - 5] != 0 -- -- # stop: -- # [ap] = [fp - 3]; ap++ -- # jmp done -- -- # continue: -- # [ap] = [[fp - 4]]; ap++ -- # [ap] = [fp - 5] - 1; ap++ -- # [ap] = [fp - 4] + 1; ap++ -- # [ap] = [ap - 3] + [fp - 3]; ap++ -- # call rec_sum_array -- -- # done: -- # ret -+func rec_sum_array(array_len: felt, array: felt*, sum: felt) -> (sum: felt): -+ if array_len == 0: -+ return (sum) -+ end -+ -+ return rec_sum_array(array_len - 1, array + 1, sum + array[0]) -@@ -39,7 +26,31 @@ --func max{range_check_ptr}(a : felt, b : felt) -> (max : felt): -- # let (res) = is_le(a, b) -- # if res == 1: -- # return (b) -- # else: -- # return (a) -- # end -+func max{range_check_ptr}(a: felt, b: felt) -> (max: felt): -+ # Push arguments to the stack -+ [ap] = [fp - 5]; ap++ # range_check_ptr -+ [ap] = [fp - 4]; ap++ # a -+ [ap] = [fp - 3]; ap++ # b -+ -+ # This call will return two values -+ # 1) the updated range_check_ptr -+ # 2) 0 or 1 depending on which of a and b is greater -+ call is_le -+ -+ # Push return values to the stack -+ # There is two of them to push: range_check_ptr and max -+ -+ # Push the first one, the updated range_check_ptr, onto the stack -+ [ap] = [ap - 2]; ap++ -+ -+ # Conditional jump -+ # The following blocks are an assembly level equivalent of the if/else pattern -+ jmp b_is_more if [ap - 2] !=0 # here [ap-2] is the second value returned by is_le, our boolean -+ -+ # Push either a or b to the stack -+ a_is_more: -+ [ap] = [fp - 4]; ap++ -+ jmp done -+ -+ b_is_more: -+ [ap] = [fp -3]; ap++ -+ -+ done: -+ ret -@@ -79 +90 @@ -- -+ +--- exercises/registers/registers02.cairo 2022-06-11 22:20:43.000000000 -0400 ++++ ./registers02.cairo 2022-06-11 22:18:21.000000000 -0400 +@@ -17,3 +17,3 @@ +- # [ap] = 42; ap++ +- # [ap - 1] = 42 +- # [ap - 1] = 21 ++ tempvar x = 42 ++ assert x = 42 ++ assert x = 21 +@@ -27 +27 @@ +- # assert number = 42 ++ [fp -3] = 42 +@@ -37,0 +38 @@ ++ assert [p_number] = 42 +@@ -45,0 +47 @@ ++ assert 42 = [p_number] diff --git a/.patches/registers/registers03.cairo.patch b/.patches/registers/registers03.cairo.patch index 8dfd1289..580e7564 100644 --- a/.patches/registers/registers03.cairo.patch +++ b/.patches/registers/registers03.cairo.patch @@ -1,15 +1,78 @@ ---- exercises/registers/registers03.cairo 2022-06-09 16:13:26.000000000 -0400 -+++ ./registers03.cairo 2022-06-09 16:11:29.000000000 -0400 -@@ -16,3 +16,3 @@ -- # [ap] = 42; ap++ -- # [ap - 1] = 42 -- # [ap - 1] = 21 -+ tempvar x = 42 -+ assert x = 42 -+ assert x = 21 -@@ -26 +26 @@ -- # assert number = 42 -+ [fp - 3] = 42 -@@ -36,0 +37,2 @@ -+ assert [p_number] = 42 +--- exercises/registers/registers03.cairo 2022-05-18 12:53:44.000000000 -0400 ++++ .tmp_solution/registers03.cairo 2022-05-18 11:40:22.000000000 -0400 +@@ -3,0 +4 @@ + +@@ -9,6 +10,2 @@ +-func sum_array(array_len : felt, array : felt*) -> (sum : felt): +- # [ap] = [fp - 4]; ap++ +- # [ap] = [fp - 3]; ap++ +- # [ap] = 0; ap++ +- # call rec_sum_array +- # ret ++func sum_array(array_len: felt, array: felt*) -> (sum: felt): ++ return rec_sum_array(array_len, array, 0) +@@ -17,16 +14,6 @@ +-func rec_sum_array(array_len : felt, array : felt*, sum : felt) -> (sum : felt): +- # jmp continue if [fp - 5] != 0 +- +- # stop: +- # [ap] = [fp - 3]; ap++ +- # jmp done +- +- # continue: +- # [ap] = [[fp - 4]]; ap++ +- # [ap] = [fp - 5] - 1; ap++ +- # [ap] = [fp - 4] + 1; ap++ +- # [ap] = [ap - 3] + [fp - 3]; ap++ +- # call rec_sum_array +- +- # done: +- # ret ++func rec_sum_array(array_len: felt, array: felt*, sum: felt) -> (sum: felt): ++ if array_len == 0: ++ return (sum) ++ end ++ ++ return rec_sum_array(array_len - 1, array + 1, sum + array[0]) +@@ -39,7 +26,31 @@ +-func max{range_check_ptr}(a : felt, b : felt) -> (max : felt): +- # let (res) = is_le(a, b) +- # if res == 1: +- # return (b) +- # else: +- # return (a) +- # end ++func max{range_check_ptr}(a: felt, b: felt) -> (max: felt): ++ # Push arguments to the stack ++ [ap] = [fp - 5]; ap++ # range_check_ptr ++ [ap] = [fp - 4]; ap++ # a ++ [ap] = [fp - 3]; ap++ # b ++ ++ # This call will return two values ++ # 1) the updated range_check_ptr ++ # 2) 0 or 1 depending on which of a and b is greater ++ call is_le ++ ++ # Push return values to the stack ++ # There is two of them to push: range_check_ptr and max ++ ++ # Push the first one, the updated range_check_ptr, onto the stack ++ [ap] = [ap - 2]; ap++ ++ ++ # Conditional jump ++ # The following blocks are an assembly level equivalent of the if/else pattern ++ jmp b_is_more if [ap - 2] !=0 # here [ap-2] is the second value returned by is_le, our boolean ++ ++ # Push either a or b to the stack ++ a_is_more: ++ [ap] = [fp - 4]; ap++ ++ jmp done ++ ++ b_is_more: ++ [ap] = [fp -3]; ap++ ++ ++ done: ++ ret +@@ -79 +90 @@ +- ++ diff --git a/exercises/registers/registers02.cairo b/exercises/registers/registers02.cairo index 4f606c09..94aee194 100644 --- a/exercises/registers/registers02.cairo +++ b/exercises/registers/registers02.cairo @@ -1,48 +1,49 @@ %lang starknet -from starkware.cairo.common.math_cmp import is_le # I AM NOT DONE +# Cairo memory is immutable. +# Once a memory cell has been assigned its value CANNOT be changed. +# The program will crash if someone tries to assign a new, different, value to an already initialized memory cell. +# However, trying to assign a memory cell twice, or more, **with the same value** won't cause any harm. +# +# This property can be used to assert the value of a cell. +# By trying to give it a value to an already initialized memory cell, we can ensure that it already have this specific value, +# if it does not, the call fail + # TODO -# Rewrite those functions with a high level syntax -@external -func sum_array(array_len : felt, array : felt*) -> (sum : felt): - # [ap] = [fp - 4]; ap++ - # [ap] = [fp - 3]; ap++ - # [ap] = 0; ap++ - # call rec_sum_array - # ret -end +# Rewrite this function in a high level syntax, using tempvar and assert +func crash(): + # [ap] = 42; ap++ + # [ap - 1] = 42 + # [ap - 1] = 21 -func rec_sum_array(array_len : felt, array : felt*, sum : felt) -> (sum : felt): - # jmp continue if [fp - 5] != 0 + ret +end - # stop: - # [ap] = [fp - 3]; ap++ - # jmp done +# TODO +# Rewrite this funtion in a low level syntax +func assert_42(number : felt): + # assert number = 42 - # continue: - # [ap] = [[fp - 4]]; ap++ - # [ap] = [fp - 5] - 1; ap++ - # [ap] = [fp - 4] + 1; ap++ - # [ap] = [ap - 3] + [fp - 3]; ap++ - # call rec_sum_array + return () +end - # done: - # ret +# TODO +# Write this function body so: +# if the memory cell pointed by `p_number` is not initialized, set it to 42 +# else, if the value is initialized and different from 42, crash +# else, do nothing and return +func assert_pointer_42(p_number : felt*): + return () end # TODO -# Rewrite this function with a low level syntax -# It's possible to do it with only registers, labels and conditional jump. No reference or localvar -@external -func max{range_check_ptr}(a : felt, b : felt) -> (max : felt): - # let (res) = is_le(a, b) - # if res == 1: - # return (b) - # else: - # return (a) - # end +# Write this function body so: +# if the memory cell pointed by `p_number` is set to 42, do nothing and return +# else crash +func assert_pointer_42_no_set(p_number : felt*): + return () end ######### @@ -52,30 +53,82 @@ end from starkware.cairo.common.alloc import alloc @external -func test_max{range_check_ptr}(): - let (m) = max(21, 42) - assert m = 42 - let (m) = max(42, 21) - assert m = 42 +func test_crash(): + %{ expect_revert() %} + crash() + return () end @external -func test_sum(): - let (array) = alloc() - assert array[0] = 1 - assert array[1] = 2 - assert array[2] = 3 - assert array[3] = 4 - assert array[4] = 5 - assert array[5] = 6 - assert array[6] = 7 - assert array[7] = 8 - assert array[8] = 9 - assert array[9] = 10 - - let (s) = sum_array(10, array) - assert s = 55 +func test_assert_42(): + assert_42(42) + + %{ expect_revert() %} + assert_42(21) + + return () +end + +@external +func test_assert_pointer_42_initialized(): + let (mem_zone : felt*) = alloc() + assert mem_zone[0] = 42 + assert mem_zone[1] = 21 + + assert_pointer_42(mem_zone) + + %{ expect_revert() %} + assert_pointer_42(mem_zone + 1) + + return () +end + +@external +func test_assert_pointer_42_not_initialized_ok(): + let (mem_zone : felt*) = alloc() + assert mem_zone[0] = 42 + assert_pointer_42(mem_zone) + + assert_pointer_42(mem_zone + 1) + assert mem_zone[1] = 42 + + return () +end + +@external +func test_assert_pointer_42_not_initialized_revert(): + let (mem_zone : felt*) = alloc() + assert mem_zone[0] = 42 + assert_pointer_42(mem_zone) + + assert_pointer_42(mem_zone + 1) + %{ expect_revert() %} + assert mem_zone[1] = 21 + + return () +end + +@external +func test_assert_pointer_42_no_set(): + let (mem_zone : felt*) = alloc() + assert mem_zone[0] = 42 + assert mem_zone[1] = 21 + + assert_pointer_42_no_set(mem_zone) + + %{ expect_revert() %} + assert_pointer_42_no_set(mem_zone + 1) + + return () +end + +@external +func test_assert_pointer_42_no_set_crash(): + let (mem_zone : felt*) = alloc() + + %{ expect_revert() %} + assert_pointer_42_no_set(mem_zone) return () end diff --git a/exercises/registers/registers03.cairo b/exercises/registers/registers03.cairo index af97f0cc..4f606c09 100644 --- a/exercises/registers/registers03.cairo +++ b/exercises/registers/registers03.cairo @@ -1,40 +1,48 @@ %lang starknet +from starkware.cairo.common.math_cmp import is_le # I AM NOT DONE -# Cairo memory is immutable, which mean that once a memory cell have been assigned a value it be changed. -# The program will crash if someone try to assign a new, different, value to a already initialized memory cell. -# However, trying to assign twice, or more, a memory cell will the same value won't cause any harm. -# -# This property can be used to assert the value of a cell. -# By trying to give it a value to an already initialized memory cell, we can ensure that it already have this specific value, -# if it does not, the call fail - # TODO -# Rewrite this function in a high level syntax, using tempvar and assert -func crash(): - # [ap] = 42; ap++ - # [ap - 1] = 42 - # [ap - 1] = 21 - - ret +# Rewrite those functions with a high level syntax +@external +func sum_array(array_len : felt, array : felt*) -> (sum : felt): + # [ap] = [fp - 4]; ap++ + # [ap] = [fp - 3]; ap++ + # [ap] = 0; ap++ + # call rec_sum_array + # ret end -# TODO -# Rewrite this funtion in a low level syntax -func assert_42(number : felt): - # assert number = 42 +func rec_sum_array(array_len : felt, array : felt*, sum : felt) -> (sum : felt): + # jmp continue if [fp - 5] != 0 - return () + # stop: + # [ap] = [fp - 3]; ap++ + # jmp done + + # continue: + # [ap] = [[fp - 4]]; ap++ + # [ap] = [fp - 5] - 1; ap++ + # [ap] = [fp - 4] + 1; ap++ + # [ap] = [ap - 3] + [fp - 3]; ap++ + # call rec_sum_array + + # done: + # ret end # TODO -# Write this function body so: -# if the memory cell pointed by `p_number` is not initialised, it set it to 42 -# else if the value is initialized and different from 42, it crash -# else, do nothing and return -func assert_pointer_42(p_number : felt*): - return () +# Rewrite this function with a low level syntax +# It's possible to do it with only registers, labels and conditional jump. No reference or localvar +@external +func max{range_check_ptr}(a : felt, b : felt) -> (max : felt): + # let (res) = is_le(a, b) + # if res == 1: + # return (b) + # else: + # return (a) + # end end ######### @@ -44,58 +52,30 @@ end from starkware.cairo.common.alloc import alloc @external -func test_crash(): - %{ expect_revert() %} - crash() - - return () -end - -@external -func test_assert_42(): - assert_42(42) - - %{ expect_revert() %} - assert_42(21) - - return () -end - -@external -func test_assert_pointer_42_initialized(): - let (mem_zone : felt*) = alloc() - assert mem_zone[0] = 42 - assert mem_zone[1] = 21 - - assert_pointer_42(mem_zone) - - %{ expect_revert() %} - assert_pointer_42(mem_zone + 1) - +func test_max{range_check_ptr}(): + let (m) = max(21, 42) + assert m = 42 + let (m) = max(42, 21) + assert m = 42 return () end @external -func test_assert_pointer_42_not_initialized_ok(): - let (mem_zone : felt*) = alloc() - assert mem_zone[0] = 42 - assert_pointer_42(mem_zone) - - assert_pointer_42(mem_zone + 1) - assert mem_zone[1] = 42 - - return () -end - -@external -func test_assert_pointer_42_not_initialized_revert(): - let (mem_zone : felt*) = alloc() - assert mem_zone[0] = 42 - assert_pointer_42(mem_zone) - - assert_pointer_42(mem_zone + 1) - %{ expect_revert() %} - assert mem_zone[1] = 21 +func test_sum(): + let (array) = alloc() + assert array[0] = 1 + assert array[1] = 2 + assert array[2] = 3 + assert array[3] = 4 + assert array[4] = 5 + assert array[5] = 6 + assert array[6] = 7 + assert array[7] = 8 + assert array[8] = 9 + assert array[9] = 10 + + let (s) = sum_array(10, array) + assert s = 55 return () end From 5c2f46a3115918f015680da1a765440fe50aef8b Mon Sep 17 00:00:00 2001 From: tekkac <98529704+tekkac@users.noreply.github.com> Date: Mon, 13 Jun 2022 10:19:25 +0200 Subject: [PATCH 3/3] (fix): wording --- exercises/registers/registers02.cairo | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/exercises/registers/registers02.cairo b/exercises/registers/registers02.cairo index 94aee194..ee74d6e0 100644 --- a/exercises/registers/registers02.cairo +++ b/exercises/registers/registers02.cairo @@ -3,13 +3,10 @@ # I AM NOT DONE # Cairo memory is immutable. -# Once a memory cell has been assigned its value CANNOT be changed. +# Once a memory cell has been assigned, its value CANNOT be changed. # The program will crash if someone tries to assign a new, different, value to an already initialized memory cell. # However, trying to assign a memory cell twice, or more, **with the same value** won't cause any harm. -# # This property can be used to assert the value of a cell. -# By trying to give it a value to an already initialized memory cell, we can ensure that it already have this specific value, -# if it does not, the call fail # TODO # Rewrite this function in a high level syntax, using tempvar and assert