Thank you. I have a file that is big enough that the lack of editing niceties in PNut is getting in the way of productivity. I have code that runs fin on the P1 that I'm really struggling on the P2; the problem seems to be with nested if/elseif/else. For the moment, I'm assuming the error is mine -- I may call for help later, though.
> @Ariba said:
> Sorry, the dec methode from my example does still not work correct with the version 34c.
> But this time I have found the problematic codeline. It's the elseif that does weird things.
> If I write: else if r or i==1 tx("0")
>
> then it works. If I write elseif r or i==1 tx("0")
>
> then i gets overwritten with 0 or -1
>
> Andy
Andy, Thanks for trying it. I will be back in the shop in a few minutes and will address this. Should be fixed in an hour.
Whoa! I did see your message, but forgot all about it. I will be back home in about 3 hours and I'll get this fixed.
No, it's not your fault, I reported the elseif error already for version 34b and it got not fixed since then.
Thank you, Andy -- I have been pulling my hair out for the last three days trying to make code that has a bunch of elseif statement work. Thankfully, I have a lot of hair!
By the way, Andy, you need to use a period in front of the bracket if you want to call out a bit. Otherwise, it looks like an index to the compiler.
DIRB.[60]
Unfortunately I suspect that will catch out a lot of people. Particularly if there is no warning, which there probably won't be because it is still valid syntax. People will just have to adapt I guess.
Update: Actually maybe if the name of the register being referenced is a special one, like OUTA, OUTB, DIRA, DIRB etc there could be a warning eventually shown in these cases because it is unlikely you'd be using an index this way with the special registers.
I may have missed this detail somewhere, but it seems like with Spin2 I have to explicitly declare a variable on the method slug-line.
This
return someValue
...always throws an error in Spin2. Is this restriction in place due the ability to return multiple values?
Yes. As Rayman said, you need to name all return values after the parameters. You can either do a 'RETURN x,y,z' to return specific values, or just do a RETURN to return the values as last written. All return values are initialized to zero on method entry.
If a method has no return variables specified, it cannot return anything.
Jon and Andy, does v34k fix the problems you were seeing?
I don't know if I am looking past a simple coding error, or if there's still a problem with if/elseif/else. This code -- which compiles on P1 and P2 -- only works on P1; there is no output using the P2.
pub format(p_str, p_args) | idx, c, asc, field, digits
'' Emit formatted string with escape sequences and embedded values
'' -- p_str is a pointer to the format control string
'' -- p_args is pointer to array of longs that hold field values
'' * field values can be numbers, characters, or pointers to strings
idx := 0
repeat
c := byte[p_str++]
if (c == "\")
c := byte[p_str++]
if (c == "\")
tx("\")
elseif (c == "%")
tx("%")
elseif (c == "r")
tx(CR)
elseif (c == "n")
tx(LF)
elseif (c == "t")
tx(TAB)
elseif (c == "q")
tx(34)
elseif (c == 0)
quit
else
tx(c)
Note: There is more to this method, but I started putting it back a small chunk a a time for testing. If I comment out the section that handles "\" and change elseif (c ==0) to if (c == 0) it will print the raw string.
I decided to write a simple test to get away from my project code -- I still think there is a problem with if/elseif/else. In this simple little demo, the problem seems to be in the X (outer) layer. I don't understand the internal mechanics, but it seems like there is a jump error and the code is not exiting properly from the Y layer; it goes back to X and sometimes runs again, often getting trapped in a loop.
dat
TooLow byte "? is too low.", 13, 0
TooHigh byte "? is too high.", 13, 0
pub main() | x, y, z, total
setup()
' open PST, enable, then press Enter
wait_for_terminal(true)
term.str(string("P2 Testing", 13))
' looking for 25x
x := 2
y := 5
z := 7
if (x == 0)
TooLow[0] := "X"
term.str(@TooLow)
elseif (x == 1)
TooLow[0] := "X"
term.str(@TooLow)
elseif (x == 2)
if (y < 5)
TooLow[0] := "Y"
term.str(@TooLow)
elseif (y == 5)
total := (x * 100) + (y * 10) + z
term.str(string("Total is "))
term.dec(total)
elseif (y == 6)
TooHigh[0] := "Y"
term.str(@TooHigh)
else
TooHigh[0] := "Y"
term.str(@TooHigh)
else
TooHigh[0] := "X"
term.str(@TooHigh)
Jon, it looks like the conditional branching is all right. I think something is going on with some other bytecodes, but I'm not sure what.
I've made this little program to test nested IF structures and I can't get it to fail. You can change a..f values to get different results on the LEDs:
con
leds = 56 addpins 7
pub main() | a,b,c,d,e,f
a := 0
b := 0
c := 1
d := 0
e := 0
f := 0
if a
pinwrite(leds,!1)
elseif b
pinwrite(leds,!2)
elseif c
if d
pinwrite(leds,!3)
elseif e
pinwrite(leds,!4)
elseif f
pinwrite(leds,!5)
else
pinwrite(leds,!6)
else
pinwrite(leds,!7)
repeat
pintoggle(63)
waitms(100)
con
leds = 56 addpins 7
pub main() | a,b,c,d,e,f
a := 1
b := 0
c := 0
d := 0
e := 0
f := 0
if a
pinwrite(leds,!1)
elseif b == 1
pinwrite(leds,!2)
elseif c
if d
pinwrite(leds,!3)
elseif e
pinwrite(leds,!4)
elseif f
pinwrite(leds,!5)
else
pinwrite(leds,!6)
else
pinwrite(leds,!7)
repeat
pintoggle(63)
waitms(100)
instead of 'ELSEIF b', it does 'ELSEIF b == 1'. Your code was doing this, too, but I'm not seeing where there's a problem with the '==' operator.
I see the problem now. The branches use RFVARS data for relative offsets and I was not compiling the RFVARS data correctly. When the branch became 64+, it became negative to the hardware. Fixing it now. Sorry about this.
I just posted v34L which fixes this problem of RFVARS not being compiled correctly. This was affecting all branches between 64..128 bytes in IF/ELSEIF/ELSE/CASE/REPEAT blocks. This must have given a real sense of flakiness to anyone using Spin2.
Thanks, Chip, that seems to have fixed things. I'm using a largish if/elseif/else structure in my formatted strings routine for serial output (demo attached)
Jeff Martin and I were talking about the status of the PropellerTool which he's updating to accommodate P2 and we had a neat idea...
We were thinking about how to facilitate rapid development and it occurred to us that we could swap in new Spin2 methods DURING program execution, complete with special debug commands. Modifying a method during application execution is possible because there's an atomic long pointer to each method within each object. If we reserve a few KB of workspace in the hub, we could load new methods into that space and modify the long pointer in the object structure to point to the new method. The next time it gets called, the NEW method runs.
This is neat because it lets you change functionality in critical methods without having to restart your application. The swap-in time, including compilation and download will be just a fraction of a second.
Meanwhile, I started documenting Spin2. Nothing really new here, yet. Just getting what I've already got into Google Doc format:
Comments
No, it's not your fault, I reported the elseif error already for verson 34b and it got not fixed since then.
Andy
Sorry, Andy! I never noticed your message. I will fix it today.
gives an error: internal.
and quit is highlighted
does not blink my LED on P60. I also tried [60-32].
Andy
By the way, Andy, you need to use a period in front of the bracket if you want to call out a bit. Otherwise, it looks like an index to the compiler.
DIRB.[60]
Unfortunately I suspect that will catch out a lot of people. Particularly if there is no warning, which there probably won't be because it is still valid syntax. People will just have to adapt I guess.
Update: Actually maybe if the name of the register being referenced is a special one, like OUTA, OUTB, DIRA, DIRB etc there could be a warning eventually shown in these cases because it is unlikely you'd be using an index this way with the special registers.
This syntax is incompatible to Spin1, but makes some sense. In Spin1 the [index] means bits for SFRs, but bytes/word/longs for variables.
Now you can access a bit from PortA or PortB with the same command:
For single bits PINWRITE (or PINW) may be the better alternative.
That's why we have instructions which handle pinfields instead of bitfields:
PINLOW(pinfield)
PINHIGH(pinfield)
PINTOGGLE(pinfield)
PINREAD(pinfield)
PINWRITE(pinfield, value)
etc.
The pinfield just can't cross 32-pin ports.
In Spin2, it's better to use the PINxxxx instructions than mess with DIRA/DIRB/OUTA/OUTB/INA/INB.
I added '& 1' to your example above to make it failsafe.
The PINxxx instructions can handle up to 32 pins, with the number of additional pins in pinfield[10:6].
The ELSEIF/ELSEIFNOT and NEXT/QUIT bugs were fixed:
https://drive.google.com/file/d/1FYBsZJrqYjXI7dyoOQHHn1HQrZ-a4lJw/view?usp=sharing
The bugs were due to a register not being preserved during reuse.
Thank you Chip.
Thanks, Andy.
This ...always throws an error in Spin2. Is this restriction in place due the ability to return multiple values?
Yes. As Rayman said, you need to name all return values after the parameters. You can either do a 'RETURN x,y,z' to return specific values, or just do a RETURN to return the values as last written. All return values are initialized to zero on method entry.
If a method has no return variables specified, it cannot return anything.
I don't know if I am looking past a simple coding error, or if there's still a problem with if/elseif/else. This code -- which compiles on P1 and P2 -- only works on P1; there is no output using the P2.
Note: There is more to this method, but I started putting it back a small chunk a a time for testing. If I comment out the section that handles "\" and change elseif (c ==0) to if (c == 0) it will print the raw string.
I've made this little program to test nested IF structures and I can't get it to fail. You can change a..f values to get different results on the LEDs:
I will work on this more in the morning.
instead of 'ELSEIF b', it does 'ELSEIF b == 1'. Your code was doing this, too, but I'm not seeing where there's a problem with the '==' operator.
We were thinking about how to facilitate rapid development and it occurred to us that we could swap in new Spin2 methods DURING program execution, complete with special debug commands. Modifying a method during application execution is possible because there's an atomic long pointer to each method within each object. If we reserve a few KB of workspace in the hub, we could load new methods into that space and modify the long pointer in the object structure to point to the new method. The next time it gets called, the NEW method runs.
This is neat because it lets you change functionality in critical methods without having to restart your application. The swap-in time, including compilation and download will be just a fraction of a second.
Meanwhile, I started documenting Spin2. Nothing really new here, yet. Just getting what I've already got into Google Doc format:
https://docs.google.com/document/d/16qVkmA6Co5fUNKJHF6pBfGfDupuRwDtf-wyieh_fbqw/edit?usp=sharing