NEWTON

NEWTON


Popular tags

    How to use get_fp_and_pc in Cairo Lang?

    Asked

    3 months ago

    58

    views


    0

    Hello! This is day 11 of the 17 days of the Cairo Challenge. And I have no idea how to solve the playground exercise “Address of locals”. Perhaps you can help me?

    // When Cairo needs to retrieve the *address* of a local variable,
    // it needs to be told the value of the frame pointer register, fp
    // (see [here](https://cairo-lang.org/docs/how_cairo_works/functions.html#fp-register)).
    //
    // This can be done by setting a reference named __fp__ to the value, which
    // can be obtained using the library function get_fp_and_pc().
    //
    // 1. Try to run the code as-is, and make sure you understand the error.
    // 2. Uncomment the line setting __fp__, and run again.
    //    The code should now work and you should be able to see that `x` was set
    //    to 1000.
    // 3. Uncomment the line calling foo() and try to run the code.
    //    Fix the code by adding exactly one word to it.
    //    Hint: Revisit the "Revoked references" challenge.
    
    from starkware.cairo.common.registers import get_fp_and_pc
    
    // Returns a^3 for a != 0 and 1 otherwise.
    func foo(a) -> (res: felt) {
        if (a == 0) {
            return (res=1);
        } else {
            return (res=a * a * a);
        }
    }
    
    func main() -> () {
        alloc_locals;
    
        // let (__fp__, _) = get_fp_and_pc();
        local x: felt;
        // let (x) = foo(a=10);
        local y: felt* = &x;
        assert [y] = 1000;
        return ();
    }
    

    Answers to this question are a part of the ✨ 17 days of Cairo Lang with Playground & Newton. ✨

    Vote for your favorite answer - the best answer will win a $10 award. A new day – a new reward! During the next 17 days, our goal is to attract more developers to the Cairo language and to systematize the knowledge of Cairo lang. Read rules

      #17daysOfCairocairo-beginnerscairoplayground

    Newton

    asked

    3 months ago


    2 answers

    0

    Accepted answer

    Running code as-it-is

    Error Received:

    Error: code:30:22: Using the value of fp directly, requires defining a variable named __fp__.
        local y: felt* = &x;
                         ^^
    

    Error Explanation

    From Problem comment:

    To retrieve the address of a local variable, it needs to be told the value of the frame pointer register, fp.This can be done by setting a reference named fp to the value, which can be obtained using the library function get_fp_and_pc().

    Reason:

    When a function starts the frame pointer register (fp) is initialized to the current value of ap. During the entire scope of the function (excluding inner function calls) the value of fp remains constant. ap may change in an unknown way when an inner function is called, so it cannot reliably be used to access the original function’s local variables and arguments anymore after that. Thus, fp serves as an anchor to access these values.

    Source:

    https://cairo-lang.org/docs/how_cairo_works/functions.html#the-fp-register

    Solution(First part)

    Uncommenting line get_fp_and_pc()

    from starkware.cairo.common.registers import get_fp_and_pc
    
    // Returns a^3 for a != 0 and 1 otherwise.
    func foo(a) -> (res: felt) {
        if (a == 0) {
            return (res=1);
        } else {
            return (res=a * a * a);
        }
    }
    
    func main() -> () {
        alloc_locals;
        let (__fp__, _) = get_fp_and_pc(); 
        local x: felt;
    
        // let (res) = foo(a=10);
        local y: felt* = &x;
        assert [y] = 1234;
    
        return ();
    }
    

    Code run successfully.

    Final Solution

    2. Uncommenting the function foo calling:

    Used serialize_word to print the result

    %builtins output
    
    from starkware.cairo.common.serialize import serialize_word
    from starkware.cairo.common.registers import get_fp_and_pc
    
    // Returns a^3 for a != 0 and 1 otherwise.
    func foo(a: felt) -> (res: felt) {
        if (a == 0) {
            return (res=1);
        } else {
            return (res=a * a * a);
        }
    }
    
    func main{output_ptr: felt*}() -> () {
        alloc_locals;
        let (__fp__, _) = get_fp_and_pc();
        local x: felt;
        let (res) = foo(a=10);
        local y: felt* = &x;
        assert [y] = 1234;
        serialize_word(res);
    
        return ();
    }
    

    Ishita Rastogi

    answered

    3 months ago

    0

    This is my answer to today's challenge one thing that I got confused about was why we would need to initialize fp to use it? What happens when you initialize a fp with get_fp_and_pc()?

    from starkware.cairo.common.registers import get_fp_and_pc
    
    // Returns a^3 for a != 0 and 1 otherwise.
    func foo(a) -> (res: felt) {
        if (a == 0) {
            return (res=1);
        } else {
            return (res=a * a * a);
        }
    }
    
    func main() -> () {
        alloc_locals;
    
        let (__fp__, _) = get_fp_and_pc();
        local x: felt;
        let (local res) = foo(a=10);
        local y: felt* = &x;
        assert [y] = 1234;
        return ();
    }~~~~
    

    answered

    3 months ago

    Your answer

    NEWTON

    NEWTON