Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scratch slot overwritten? #21

Closed
runvnc opened this issue Jul 9, 2021 · 9 comments
Closed

Scratch slot overwritten? #21

runvnc opened this issue Jul 9, 2021 · 9 comments
Assignees

Comments

@runvnc
Copy link
Contributor

runvnc commented Jul 9, 2021

I am not 100% sure but it seems like a number in my scratch space was overwritten in a different function. It says something like let x = thecall() (which always returns 1) and one thing that does is store 6.

But there is another function that always loads from 6, which is supposed to be the parameter of the function. And so the second time I call that function, I always end up with 1 for that number instead of what it was.

Also, random question, is there a way to discard a return value, or not return anything? Because that assignment of x (which I don't use) is what seems to have clobbered my other argument. I am going to try to use a variable declared at the top level or something.

Thanks. By the way, appreciate that you guys have done so many of these v3 v4 updates so quickly.

@algorandskiy
Copy link
Collaborator

And so the second time I call that function, I always end up with 1 for that number instead of what it was.

You are right, it uses scratch space for args passing (since in tealang v1 functions were inlined and arguments were treated as its local vars). Non-inlined function use the same approach but re-allocate local vars on each call based on a higher var address (slot) in parent scope. Could give an example demonstrating the issue?

is there a way to discard a return value, or not return anything?

No, because this would promote using global vars and often is considered as a bad practice.

@algorandskiy algorandskiy self-assigned this Jul 9, 2021
@runvnc
Copy link
Contributor Author

runvnc commented Jul 9, 2021

Unfortunately when I went to clean up the example, I changed something and it was still doing something unexpected, but different from what happened before maybe. And I have a really serious sinus headache and need to sleep. Not to include too much irrelevant information.

The last thing I changed was using three local variables predeclared, rather than reusing a variable multiple times -- not sure that is the same issue I had before. That allowed me to get the expected answer though.

let _ = 0

function newl() {
        apps[0].put("dbg", concat(apps[0].get("dbg"), "\x0d" ))
        return 1
}

function log_(msg) {
    apps[0].put("dbg", concat(apps[0].get("dbg"), msg))
        return 1
}

function log(msg) {
    apps[0].put("dbg", concat(apps[0].get("dbg"), msg))
    let x = newl()

        return 1
}

function printch(digit) {
        let ascii = digit + 48
        let discard = log_(" ")
        let dbg = apps[0].get("dbg")
        apps[0].put("dbg",setbyte(apps[0].get("dbg"), len(dbg)-1, ascii))
        return 1
}

function printFirstDigit(nn) {
    if nn >= 100 {
         _= printch(nn / 100)
         return nn % 100
        }
        if nn >= 10 {
            _= printch(nn / 10)
            return nn % 10
        }
          _= printch(nn)
        return 9999
}

// this version works
function printNum(num) {
    _= log("Start of printNum.")
    let a = 0
    let b = 0
    let c = 0
    a = printFirstDigit(num)
    if a != 9999 {
        b = printFirstDigit(a)
    }
    if b != 9999 {
        c = printFirstDigit(b)
    }
        return 1
}

function logic() {
    apps[0].put("dbg", "")
    _= printNum(74)

    return 1
}

When it was like the following, it was not returning the ASCII digits properly, I think it was just repeating them:

// does not work
function printNum(num) {
    _= log("Start of printNum.")
    let left = printFirstDigit(num)
    if left != 9999 {
        left = printFirstDigit(left)
    }
    if left != 9999 {
        left = printFirstDigit(left)
    }
    return 1
}

@algorandskiy
Copy link
Collaborator

Thank you, I'll take a look over the weekend. Get better!

@runvnc
Copy link
Contributor Author

runvnc commented Jul 10, 2021

By the way, when I tried that same function with shiqizng's version (as of this moment), it gave me a different answer (75) which seems closer but also is not correct. Yours gives 77. The other version of the function with a, b, c outputs 74 correctly.

@pzbitskiy
Copy link
Owner

I confirmed there is problem is slots allocation in functions, it might overwrite variables that used after in parent function scopes. Making functions inline (inline function abc()) should help as a temporary workaround.

@runvnc
Copy link
Contributor Author

runvnc commented Jul 12, 2021

Ok.. so I did not know that Tealang supported inline functions. Did not see it in the documentation. But I can confirm, I started using a macro preprocessor called gpp yesterday on my 'rollstats' test project, because I wanted to save a few instruction executions since I was running out of the 700 or so allocated. When I converted a function into a macro (so that it was inlined) I was able to get the correct answer to my sum (which I mentioned in my other issue).

@pzbitskiy
Copy link
Owner

tealang has functions since v1 even before TEAL v4 callsub/retsub so I had to make them inline. With latest patches I made this explicit with inline keyword.

@runvnc
Copy link
Contributor Author

runvnc commented Jul 12, 2021

Ok thanks for reminding me about the inline then. My silly dice roller thing was just a test to play around. I believe that now I know about the cause and inlining I can go full speed ahead with the rest of our auction contracts in Tealang. As far as I know the thing with byte[] vs uint hopefully is not a blocker related to that.

@algorandskiy
Copy link
Collaborator

Fixed in #28

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants