Trick or treat ? Both; depends on what you want or expect ...
VAR
long longVar
word wordVar
PRI First
wordVar := $1234_5678
longVar := wordVar
PRI second
longVar := ( wordVar := $1234_5678 )
These two are not identical in functionality when variable size differs.
Type-size truncation does not apply to assignments within expressions, so in First the resulting value in longVar is $0000_5678, in the Second it is $1234_5678
Hmm, interesting observation! If someone had asked what to expect, a priori, from second, I'd have had to flip a coin to answer. There are equally plausible explanations for either outcome.
Now what if the value used was $1234_8765 ?
Would in the first, the long get the value $8765 (positive) or the sign extended value (because word $8765 < 0)?
I thought SPIN had no unsigned values but after reading page 263 of the manual it looks byte and word
are unsigned.·Does that mean we always need to insert the·sign extend operator ~~ when
comparing types of different sizes?
Another one, be careful checking for <0 with words, when saving space by converting variables to words, or bytes.
say you have a variable
mydata16 word -1
if you want to check for it being < -1 use
if mydata16 == $ffff
or if you want to check for it being <0
if mydata16 & $8000
same with bytes
mydata8 byte -1
checking for -1
if mydata8 == $ff
or for < 0
if mydata8 & $80
don't forget when using signed variables,
mydata8 range is from -128 to 127 although it's actually 0 to 127, 128 to 255=-128 to -1
mydata16 range is from -32768 to 32767 although it's actually 0-32767, 32768 to 65535 = -32768 to -1
As you suspect, it'd hold the value $8765 (positive). But that doesn't imply that you always need to sign extend words when comparing with bytes. If you are storing a value as a word, you're probably doing it in the full knowledge that it isn't a signed quantity.
Think of the 3 available types as
signed long,
unsigned word,
unsigned byte
and you only need to use sign extend (or any of baggers' shortcuts) when you are breaking that convention.
Hmm... In fact I would not had to "toss a coin" as Phil put it
After I had understood that there are NO DATA TYPES or DATA STRUCTURES in SPIN,
most things discussed here can be expected.
Nevertheless they are deep traps!
Using BYTE or WORD means nothing but that whenever storing or reading such a value,
RD/WRBYTE/WORD is used, nothig else.
So look at Hippy's exampla:
longVar := ( wordVar := $1234_5678 )
(a) $1234_5678 is put into a register
(b) This is stored with WRWORD,
(c) This is stored with WRLONG
Two variations (not actually checked, as I have no Propeller here...):
longVar := ( wordVar := $1234_5678 ) + 1
(a) $1234_5678 is put into a register
(b) This is stored with WRWORD
(c) 1 is added
(d) Then i$1234_5679 is stored to longVar
Next variation
longVar := ( wordVar += $1234_5678 )
(a) wordVar is read by RDWORD (initially 0)
(b) $1234_5678 is added
(c) This is stored with WRWORD
(d) This is stored with WRLONG
Whether this is a feature or a bug depends on the documentation
Don't transfer any of your experiences with other languages unquestioned to SPIN!
Post Edited (deSilva) : 12/27/2007 10:53:22 AM GMT
The point of my coin flip comment was that wordVar := $1234_5678, as an expression, could be interpreted in two different ways: the value of the expression before the assignment to wordVar or the value of wordVarafter the assiignment. The manual states, "As with other assignment operators, the Variable Assignment operator can be used within expressions to assign intermediate results...". Although this vaguely implies that the assignment is a mere side effect that doesn't affect the expression's value, it doesn't say so explicitly.
True, Phil. However this "vague implication" together with "Chip's Razor"
("The size of any code should never be increased beyond the barest minimum!")
should have given you all needed clues
True enough. I suppose another argument for the extant behavior is that it doesn't paint us into a corner. At least now, if we want the expression to be the value of the assigned variable, we have the option of writing (wordVar := $1234_5678) & $FFFF. Conversely, had the expression evaluated to wordVar when what we wanted was the full 32 bits, we'd be out of luck.
Given the syntax of Spin, your examples behave in the expected way, and I don't see anything particularly disturbing there. When you use the ellipsis operator, you just have to be careful.
I'm actually more bothered that lookup and its kin allow things like "ABCD" as arguments to begin with. It's an exception to Spin's usual syntax that blurs the distinction between lists (ordered sets) and strings (atomic elements) in a way that could impede more generalized array and string constructors in future versions. (i.e. What is a comma? Is it a list separator here or a concatenation operator?) Although it saves keystrokes and space on the line, the casual observer is going to see "ABCD" as a single atom — as it should be — and not as a disjoint list of individual characters.
LOOKUP ( Index : ExpressionList )
{blah blah}
o ExpressionList is a {blah}. Quoted strings of characters are also allowed; they are treated as a comma-separated list of characters.
Also:
.. Range Indicator. Indicates a range from one expression to another. {blah blah}
So:
a := lookup( 4 : "CBA" .. "A", "X" )
is the same as:
a := lookup( 4 : "C", "B", "A".."A", "X" )
Where the range from "A" to "A" includes only 1 element.
I can almost accept the comma as a sort of concatenation operator in string, since you're constructing something whole out of various-sized pieces. An explicit concatenation operator would be better though. But the comma doesn't work as well in lookup when you're deconstructing big pieces ("ABC") to imply a sequence of little ones ("A", "B", "C"). And the visual congruity breaks down entirely as soon as you throw an ellipsis into the mix. For example, when you look at something like lookup(4 : "121", "123" .. "126"), what's the first thing that comes to mind? If you're like me, it isn't lookup(4 : "1211232126")! As a matter of programming self-discipline, I would avoid mixing an ellipsis with multi-character "chunks".
mirror said...
.. Range Indicator. Indicates a range from one expression to another. {blah blah}
It's all within what's specified in the manual.
But it's a bit disingenuous to put in {blah blah} when, in full, p312 actually says, ".. Range indicator: indicates a range from one expression to another for CASE
statements or an I/O register index. See OUTA, OUTB on page 280, INA, INB on page 226, and DIRA, DIRB on page 212".
No mention of ranges in lookup ( nor lookdown ) descriptions where it would be expected to be found, nor any indication it's even available for those commands.
deSilva said...
Hippy, what are you doing all the day?????
Churning out my Spin Bytecode interpreter. Slowly working my way through the opcodes and having to match functionality with what the manual says. It's a bit of a surprise when there's an opcode but no mention of how it's used
A more interesting issue is what one would expect the following to return ...
a := Lookdown( 200 : 1 .. 100, 200 .. 300 )
Is 1..100 a single group with index 1, 200..300 a single group with index 2, or does 200 have index 101 ? The answer is the later (101). I personally would have expected the former taking the above being shorthand for -
case 200
1 .. 100 : a:= 1
200 .. 300 : a := 2
other : a := 0
I don't have a problem with the two meaning entirely different things. In the lookdown example, the ellipsis (range operator) is used to create (abstractly, at least) a single "flat" list, which is then searched. That much is consistent with range operators mixed with commas in other languages (e.g. Perl). In the case construct, multiple lists are created, each one possibly having a range of choices.
What would be interesting would be for Spin to adopt real references, so something like the following could be equivalent to your case example:
a := lookdown(200 : [noparse][[/noparse]1 .. 100], [noparse][[/noparse]200 .. 300])
Here, the [noparse]/noparse is a constructor for a reference to a list, allowing each referenced list to be an atom. This makes it possible to distinguish between "flattened" lists and structured lists of lists.
Back to assignments within expressions, and here's a potential trap when using SPR bit ranges ...
DIRA := $33
a := ( DIRA |= $C0 )
DIRA := $33
a := ( DIRA[noparse][[/noparse]7..4] |= $C )
In both cases DIRA is set as expected, $F3.
In the first, 'a' result is $F3, in the second 'a' result is $0F.
In the first it passes down the result of the |= operation in the second it passes down the operand sub expression (1) result of the |= operation.
It makes sense for 'DIRB := DIRA |= $C0' and 'DIRB[noparse][[/noparse]7..4] := DIRA[noparse][[/noparse]7..4] |= $C', but 'DIRB := DIRA[noparse][[/noparse]7..4] |= $C' will not give what may be expected.
Edit : (1) That makes sense now, as 'a : = DIRA[noparse][[/noparse]7..4] |= $C' can be taken as ...
tmp := DIRA[noparse][[/noparse]7..4] | $C
DIRA [noparse][[/noparse]7..4] := tmp
a := tmp
Those observations are consistent with the rule that you sniffed out earlier for mixed precision assignments, namely: "The expression value of an intermediate assignment is the value of the expression just before the actual assignment is performed", but with additional precision now as to what "just before" means.
Pretty soon, you'll have to attach the letters "S.P.D." after your name! (That would be "Doctor of Spin Pathology".)
Phil Pilgrim (PhiPi) said...
Those observations are consistent with the rule that you sniffed out earlier for mixed precision assignments, namely: "The expression value of an intermediate assignment is the value of the expression just before the actual assignment is performed"
Right, that can be validated by:
DIRA[noparse][[/noparse]0] := 1
a := (DIRA[noparse][[/noparse]0] ^= 3)
Gooday
As I'm enjoying learning spin from·propeller manual I find difficult exercise to
sort out for me
exercise 7 and 8 will not compile ,
I'm attaching file with exercise also image of outcome after I peas F10 or
11
Please help me with sorting this problem
Kind regards
Viktor
As this is not really something for this more technical thread, the curt answers of Nick and Phil are understandable..
You see: REPEAT and WHILE (or UNTIL) have to match in a rejecting loop, in the same way as IF and ELSE. The compiler does not mind when you shift it a little bit to the right but NEVER to the left.
So indent your WHILE one space more and everything will be fne..
Comments
Th 'flags' variable must be zeroed before use ...
To save C and Z ...
To restore C and Z, 'flags' is left unaltered ...
These two are not identical in functionality when variable size differs.
Type-size truncation does not apply to assignments within expressions, so in First the resulting value in longVar is $0000_5678, in the Second it is $1234_5678
-Phil
Would in the first, the long get the value $8765 (positive) or the sign extended value (because word $8765 < 0)?
I thought SPIN had no unsigned values but after reading page 263 of the manual it looks byte and word
are unsigned.·Does that mean we always need to insert the·sign extend operator ~~ when
comparing types of different sizes?
regards peter
say you have a variable
mydata16 word -1
if you want to check for it being < -1 use
if mydata16 == $ffff
or if you want to check for it being <0
if mydata16 & $8000
same with bytes
mydata8 byte -1
checking for -1
if mydata8 == $ff
or for < 0
if mydata8 & $80
don't forget when using signed variables,
mydata8 range is from -128 to 127 although it's actually 0 to 127, 128 to 255=-128 to -1
mydata16 range is from -32768 to 32767 although it's actually 0-32767, 32768 to 65535 = -32768 to -1
As you suspect, it'd hold the value $8765 (positive). But that doesn't imply that you always need to sign extend words when comparing with bytes. If you are storing a value as a word, you're probably doing it in the full knowledge that it isn't a signed quantity.
Think of the 3 available types as
signed long,
unsigned word,
unsigned byte
and you only need to use sign extend (or any of baggers' shortcuts) when you are breaking that convention.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Help to build the Propeller wiki - propeller.wikispaces.com
Play Defender - Propeller version of the classic game
Prop Room Robotics - my web store for Roomba spare parts in the UK
After I had understood that there are NO DATA TYPES or DATA STRUCTURES in SPIN,
most things discussed here can be expected.
Nevertheless they are deep traps!
Using BYTE or WORD means nothing but that whenever storing or reading such a value,
RD/WRBYTE/WORD is used, nothig else.
So look at Hippy's exampla:
longVar := ( wordVar := $1234_5678 )
(a) $1234_5678 is put into a register
(b) This is stored with WRWORD,
(c) This is stored with WRLONG
Two variations (not actually checked, as I have no Propeller here...):
longVar := ( wordVar := $1234_5678 ) + 1
(a) $1234_5678 is put into a register
(b) This is stored with WRWORD
(c) 1 is added
(d) Then i$1234_5679 is stored to longVar
Next variation
longVar := ( wordVar += $1234_5678 )
(a) wordVar is read by RDWORD (initially 0)
(b) $1234_5678 is added
(c) This is stored with WRWORD
(d) This is stored with WRLONG
Whether this is a feature or a bug depends on the documentation
Don't transfer any of your experiences with other languages unquestioned to SPIN!
Post Edited (deSilva) : 12/27/2007 10:53:22 AM GMT
-Phil
("The size of any code should never be increased beyond the barest minimum!")
should have given you all needed clues
-Phil
a := lookup( 3 : "A" .. "C", "D" .. "F" ) ' returns "C"
is the same as ...
a := lookup( 3 : "A", "B", "C", "D", "E", "F" )
a := lookup( 3 : "ABCDEF" )
They also work in reverse ...
a := lookup( 3 : "C" .. "A", "F" .. "D" ) ' Returns "A"
is the same as ...
a := lookup( 3 : "C", "B", "A", "F", "E", "D" )
a := lookup( 3 : "CBAFED" )
One unusual but acceptable concoction ...
a := lookup( 4 : "ABC" .. "A" ) ' Returns "B"
is the same as ...
a := lookup( 4 : "ABCBA" )
One potential trap ...
a := lookup( 4 : "CBA" .. "A", "X" ) ' Returns "X", not "A"
The trap is only likely to bite if using CON defined constants and the range became reduced to zero gap, eg..
a := lookup( b : MYMIN .. MYMAX, MYMAX_PLUS_1 )
Given the syntax of Spin, your examples behave in the expected way, and I don't see anything particularly disturbing there. When you use the ellipsis operator, you just have to be careful.
I'm actually more bothered that lookup and its kin allow things like "ABCD" as arguments to begin with. It's an exception to Spin's usual syntax that blurs the distinction between lists (ordered sets) and strings (atomic elements) in a way that could impede more generalized array and string constructors in future versions. (i.e. What is a comma? Is it a list separator here or a concatenation operator?) Although it saves keystrokes and space on the line, the casual observer is going to see "ABCD" as a single atom — as it should be — and not as a disjoint list of individual characters.
-Phil
You wil notice that in MOST cases it is exactly so as Hippy found out:
address := string("ABC")
is the same as
address := string("A","B","C")
BYTE "ABC"
ist the same as
BYTE "A", "B", "C"
LOOKUP ( Index : ExpressionList )
{blah blah}
o ExpressionList is a {blah}. Quoted strings of characters are also allowed; they are treated as a comma-separated list of characters.
Also:
.. Range Indicator. Indicates a range from one expression to another. {blah blah}
So:
a := lookup( 4 : "CBA" .. "A", "X" )
is the same as:
a := lookup( 4 : "C", "B", "A".."A", "X" )
Where the range from "A" to "A" includes only 1 element.
It's all within what's specified in the manual.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
-Phil
But it's a bit disingenuous to put in {blah blah} when, in full, p312 actually says, ".. Range indicator: indicates a range from one expression to another for CASE
statements or an I/O register index. See OUTA, OUTB on page 280, INA, INB on page 226, and DIRA, DIRB on page 212".
No mention of ranges in lookup ( nor lookdown ) descriptions where it would be expected to be found, nor any indication it's even available for those commands.
Churning out my Spin Bytecode interpreter. Slowly working my way through the opcodes and having to match functionality with what the manual says. It's a bit of a surprise when there's an opcode but no mention of how it's used
a := Lookdown( 200 : 1 .. 100, 200 .. 300 )
Is 1..100 a single group with index 1, 200..300 a single group with index 2, or does 200 have index 101 ? The answer is the later (101). I personally would have expected the former taking the above being shorthand for -
case 200
1 .. 100 : a:= 1
200 .. 300 : a := 2
other : a := 0
What would be interesting would be for Spin to adopt real references, so something like the following could be equivalent to your case example:
Here, the [noparse]/noparse is a constructor for a reference to a list, allowing each referenced list to be an atom. This makes it possible to distinguish between "flattened" lists and structured lists of lists.
-Phil
DIRA := $33
a := ( DIRA |= $C0 )
DIRA := $33
a := ( DIRA[noparse][[/noparse]7..4] |= $C )
In both cases DIRA is set as expected, $F3.
In the first, 'a' result is $F3, in the second 'a' result is $0F.
In the first it passes down the result of the |= operation in the second it passes down the operand sub expression (1) result of the |= operation.
It makes sense for 'DIRB := DIRA |= $C0' and 'DIRB[noparse][[/noparse]7..4] := DIRA[noparse][[/noparse]7..4] |= $C', but 'DIRB := DIRA[noparse][[/noparse]7..4] |= $C' will not give what may be expected.
Edit : (1) That makes sense now, as 'a : = DIRA[noparse][[/noparse]7..4] |= $C' can be taken as ...
tmp := DIRA[noparse][[/noparse]7..4] | $C
DIRA [noparse][[/noparse]7..4] := tmp
a := tmp
Post Edited (hippy) : 12/31/2007 1:49:49 PM GMT
Those observations are consistent with the rule that you sniffed out earlier for mixed precision assignments, namely: "The expression value of an intermediate assignment is the value of the expression just before the actual assignment is performed", but with additional precision now as to what "just before" means.
Pretty soon, you'll have to attach the letters "S.P.D." after your name! (That would be "Doctor of Spin Pathology".)
-Phil
Right, that can be validated by:
DIRA[noparse][[/noparse]0] := 1
a := (DIRA[noparse][[/noparse]0] ^= 3)
As I'm enjoying learning spin from·propeller manual I find difficult exercise to
sort out for me
exercise 7 and 8 will not compile ,
I'm attaching file with exercise also image of outcome after I peas F10 or
11
Please help me with sorting this problem
Kind regards
Viktor
No "while" statement in SPIN
Nick
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!
The DIY Digital-Readout for mills, lathes etc.:
YADRO
You see: REPEAT and WHILE (or UNTIL) have to match in a rejecting loop, in the same way as IF and ELSE. The compiler does not mind when you shift it a little bit to the right but NEVER to the left.
So indent your WHILE one space more and everything will be fne..
Not just that.
Nick
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!
The DIY Digital-Readout for mills, lathes etc.:
YADRO
Well, WAITCNT as well...