What’s wrong with the following code? (Hint: try to replace ap += SIZEOF_LOCALS with alloc_locals and see what happens) Can you fix it without changing the order of the variable definitions in the code?
func main():
tempvar x = 0
local y
ap += SIZEOF_LOCALS
y = 6
ret
end
Solution
If we try to compile and run the program we get the following error:
$ cairo-compile exercise.cairo --output exercise.json
$ cairo-run --program=exercise.json --print_memory --relocate_prints
>>>
exercise.cairo:6:5: Error at pc=0:4:
An ASSERT_EQ instruction failed: 0 != 6.
y = 6
^***^
To understand what’s happening we have to remember that the tempvar keyword uses the ap pointer while the local keyword uses the fp pointer and that both pointers point to the same memory address at the beginning of every function.
Replacing both keywords with their underlying implementation using the ap and fp pointers helps shed some light on the problem.
func main():
# tempvar x = 0
[ap] = 0; ap++
let x = [ap - 1]
# local y
# ap += SIZEOF_LOCALS
# y = 6
[fp] = 6
ret
end
Initially both ap and fp pointers point to the same memory address where we store the value 0. Then we try to reassign the value 6 to the same memory address causing the assignment operator to turn into an assert that compares if 0 is equal to 6 which is false and makes the program exit with a failure.
To fix this problem without changing the order x and y are initialized, we have to move the ap pointer forward enough places to create a reserved memory area for local values that use the fp pointer, before we make use of the tempvar keyword that uses the ap pointer.
func main():
ap += SIZEOF_LOCALS
tempvar x = 0
local y
y = 6
ret
end
Our program now executes successfully and we can see both values stored in memory.
Addr Value
-----------
⋮
1 290341444919459839
2 1
3 5189976364521848832
4 0
5 4613797087195136000
6 6
7 2345108766317314046
8 12
9 12
10 6
11 0
Reference
The exercise in this article can be found in this section of the Cairo docs.