Spin2 Operator Syntax
 cgracey            
            
                Posts: 14,287
cgracey            
            
                Posts: 14,287            
            
                    Here is what I've got, so far. I'm not sure how this aligns with other languages, but it's open for review so we can maximize the sweet spot:
The equality operators can no longer be used as assignment modifiers (i.e. "x >= y" assigns x>y to x). This allows both versions of =>/>= and =</<=.
The idea here is that any of the "unary" operators could also be used alone with a variable to modify the variable.
Any of the "binary" operators could be used after a variable and then followed with an "=" to create a self-modifying assignment (i.e. x += 3).
                
                            Op	Example		Type		Description
-----------------------------------------------------------------------------
NOT	NOT x		unary		Boolean NOT (0 = -1, non-0 = 0)
!	!x		unary		Bitwise NOT, 1's complement
-	-x		unary		Negation, 2's complement
||	||x		unary		Absolute value
>|	>|x		unary		Encode MSB, 0..31
|<	|<x		unary		Decode, 1 shl (x & $1F)
~	~x		unary		Sign-extend from bit 7
~~	~~x		unary		Sign-extend from bit 15
SQRT	SQRT x		unary		Square root
LOG	LOG x		unary		Unsigned to logarithm
EXP	EXP x		unary		Logarithm to unsigned
AND	x AND y		binary		Boolean AND (x <> 0 AND y <> 0, returns 0 or -1)
OR	x OR y		binary		Boolean OR (x <> 0 OR y <> 0, returns 0 or -1)
&	x & y		binary		Bitwise AND
|	x | y		binary		Bitwise OR
^	x ^ y		binary		Bitwise XOR
>>	x >> y		binary		Shift right
<<	x << y		binary		Shift left
~>	x ~> y		binary		Shift arithmetic right
<~	x <~ y		binary		Shift arithmetic left
->	x -> y		binary		Rotate right
<-	x <- y		binary		Rotate left
><	x >< y		binary		Reverse y LSBs of x and zero-extend
#>	x #> y		binary		Ensure x => y
<#	x <# y		binary		Ensure x <= y
+	x + y		binary		Add
-	x - y		binary		Subtract
*	x * y		binary		Multiply
/	x / y		binary		Divide, return quotient
//	x // y		binary		Divide, return remainder
**	x ** y		binary		Scale, unsigned (x * y) >> 32
*/	x */ y		binary		Fraction, unsigned {x, 32'b0}/y
<	x < y		equality	Check less than,		returns 0 or -1
=<, <=	x <= y		equality	Check equal or less than,	returns 0 or -1
==	x == y		equality	Check equal,			returns 0 or -1
<>	x <> y		equality	Check not equal,		returns 0 or -1
=>, >=	x => y		equality	Check equal or greater than,	returns 0 or -1
>	x > y		equality	Check greater than,		returns 0 or -1
The equality operators can no longer be used as assignment modifiers (i.e. "x >= y" assigns x>y to x). This allows both versions of =>/>= and =</<=.
The idea here is that any of the "unary" operators could also be used alone with a variable to modify the variable.
Any of the "binary" operators could be used after a variable and then followed with an "=" to create a self-modifying assignment (i.e. x += 3).

 
                            
Comments
edit: I'm not arguing that they should be added. Just confirming that they weren't accidentally left off the list.
-Phil
I just didn't list those. We'll get to them.
That thought occurred to me, too, but I'm not sure what I think about it.
So, that's better than <= where it gives no error but doesn't do what you might think...
BTW: Noticed Lua uses "~=", which I think is slightly worse than "<>"
It resolves my main gripe with the Spin1 operators (the <= and >= ones).
There is a chorus of calls to harmonize the Spin 2 operators with other common languages, C/C++, C#, Java, Javascript, Perl etc....
This makes a lot of sense as it removes a lot of confusion for those coming to Spin from other languages. There is no particular reason why Spin operators should be different. Given the other huge changes to Spin/PASM that break all pre-existing code now is the time to harmonize the operators.
Of course Spin is syntactically very different from those other languages, but those differences are more obvious. The operator confusion is, well, confusing.
Personally I think all the other "non-standard" operators should have a function style syntax, MAX(), ROT(), etc. Makes things much more readable.
So, while I said I was happy in the last message, I think I would be happier with the additional change Heater suggests.
My only concern with this, though, is that you now have reserved function names. While it might not be an issue with Spin 2, you potentially cause conflicts if you and more reserved function names in Spin 3 (and so on). So... what if Spin 2 (and beyond) used a different syntax for these functions. For instance, would it be okay to have something like:
x := {extend y, 7}This would serve two purposes:
* Ensure that new functions could be added without conflicts
* Make it it obvious which functions are intrinsic to the interpreter
(edit: don't get fixated on the use of braces. I just used those because it wasn't parentheses. In reality, braces won't work because they're already used for comment blocks.)
"if x<-5" *should* evaluate identically to "if x < -5", but it doesn't.
Maybe <<< and >>> instead? Those to me read much more like "special shifts" than <- and ->.
I'm with David on supporting one or the other for the inequality ops - supporting both is worse.
I'm torn on sign extension - in C, the ~ operator is binary not, so to me, "~1" means "0xFE" (as a byte). I like the compactness of the sign extension operators, but find them hard to read. In C that's typically done just by type casting. For example, to sign extend something you'd do this:
It could be done shorter as builtin functions:
That would allow making ! be logical not, which is how most languages do it, though Python uses "not", so there's less consensus here.
For #> and <#, if you're supporting built-in functions, maybe max() and min() ? I always found the syntax of these really hard to read. x = max(x, 0), or x = min(x, 10) is pretty normal.
You know, that one surprises me. The docs say that negate has precedence over rotate-left.
That looks more like lambda notation, e.g. Lisp.
-Phil
Yeah, I thought about that when I was typing it. I was just looking for something that wasn't x(y). I suppose you could do x{y}, but that looks weird (to me, at least). Suggestions welcome!
Languages like C will produce different bit patterns in the result depending on the type of thing being shifted. Signed integers get the sign bit propagated down. Unsigned shifts zeros into the top.
Spin only has signed LONGs so there is a problem there.
Javascript gets around this, yes it can deal with 32 bit integers, by providing:
>>, Shift right propagating the sign bit down from bit 31. (Signed)
>>>, Shift right filling the top with zero bits. (Unsigned)
This is the way to go in Spin I think.
It'd be worth testing that, just to be sure. I know I've been bitten by a number of these in the past, but it's possible that this particular case isn't one of them. That said, the fact that "x <- 5" isn't necessarily the same as "x<-5" is just as bad.
Yes, I agree with this approach. Expressions are easier to scan that way.
Yes, that is simply broken.
Yes, I'll find a list of how others that use function syntax manage this already.
Below is a collection of other languages added in the fName, Op Use columns.
In most cases there is an easy alignment, and I think the BSR, BSL can be used, along with SAR,SAL
You may need to add BSL for symmetry, if PASM has the equivalent ?
I'm not sure if Spin LOG is natural, or base 10 ?, but others have both LOG() and LN()
Comments is another area, and the // as comment EOL is now pretty much universal.
I've found cases where both (* *) and /* */ are also allowed/tolerated for block comments.
Allowing nested comments is also a good language idea.
Op Example fName Op Use Type Description -------------------##########################------------------------------------------------- NOT NOT x NOT OUT:=NOT IN unary Boolean NOT (0 = -1, non-0 = 0) || ||x ABS ABS(n) unary Absolute value >| >|x BSR? unary Encode MSB, 0..31 BSL? Encode LSB, 0..31 bsf (Bit Scan Forward) and bsr (Bit Scan Reverse) |< |<x 1 SHL x unary Decode, 1 shl (x & $1F) SQRT SQRT x SQRT SQRT(Re) unary Square root LOG LOG x LOG LOG(Re) b10 unary Unsigned to logarithm LN LN(Re) nl unary Unsigned to logarithm EXP EXP x EXP EXP(Re) nl unary Logarithm to unsigned AND x AND y AND & binary Boolean AND (x <> 0 AND y <> 0, returns 0 or -1) OR x OR y OR binary Boolean OR (x <> 0 OR y <> 0, returns 0 or -1) & x & y & binary Bitwise AND | x | y binary Bitwise OR ^ x ^ y XOR binary Bitwise XOR >> x >> y SHR 0in binary Shift right << x << y SHL 0in binary Shift left ~> x ~> y SAR binary Shift arithmetic right <~ x <~ y SAL binary Shift arithmetic left -> x -> y ROR binary Rotate right <- x <- y ROL binary Rotate left // x // y MOD - n MOD m binary Divide, return remainder EXPT ** < x < y LT < equality Check less than, returns 0 or -1 =<, <= x <= y LE <= equality Check equal or less than, returns 0 or -1 == x == y EQ = equality Check equal, returns 0 or -1 <> x <> y NE <> equality Check not equal, returns 0 or -1 =>, >= x => y GE >= equality Check equal or greater than, returns 0 or -1 > x > y GT > equality Check greater than, returns 0 or -1 Assign := n := m Unused ~ ! Used % $ @ Others MAX MAX(A,B,C) MIN MIN(A,B,C) Comment EOL // Comment Block /* txt */ Comment Block (* txt *) Trigonometric functions : SIN COS TAN ASIN ACOS ATAN Radians Appendix: 6.6.4.3 Bit Scanning: BSF and BSR (asm notes) The bsf (Bit Scan Forward) and bsr (Bit Scan Reverse) instructions search for the first or last set bit in a 16 or 32 bit quantity. The general form of these instructions is bsf dest, source bsr dest, source Bsf locates the first set bit in the source operand, searching from bit zero though the H.O. bit. Bsr locates the first set bit searching from the H.O. bit down to the L.O. bit. If these instructions locate a one, they clear the zero flag and store the bit index (0..31) into the destination operand. If the source operand is zero, these instructions set the zero flag and store an indeterminate value into the destination operand.-Phil
Any combination of weird symbols that gets the job done is as good as any other.
My point is that there is no particular reason to use a different combination of weird symbols than millions of other programmers around the world use. Especially if one might want to attract those people into the fold and make their life easy.
Hmm...Having said that. "~>" is not fine at all. The "~" is often taken as a "NOT". The ">" is a obviously "greater than". So at first glance it looks like a "not greater than".
It's just awful.
To me, all of this "It's just awful" & "Although I do wish" teeth gnashing is readily solved by merely adding the word operators SHR,SHL,ASR,ASL
No conflicts there, so those can co-exist even without a mode switch. Looks like BSR and BSL can also be added.
I have one example in front of me that does include ADD() as an alias for +.
Yes, at first glance that seems silly, but then they allow ADD,SUB as a graphical element in the graphical entry schemes, and ADD,SUB also works for records like Time types.
All makes good sense, when you see the real examples in front of you.
The key point here is they are aliases, so you are perfectly free to use + and -, like we always have.
Going from "x + y" to "ADD(x, y)" is not just an alias. It's a total syntactic rearrangement.
Or do you mean "x ADD y" ?
We could do that is C++ with some #defines and operator overloading.
Too weird.
Not to mention the symmetry with PASM.
(edit: further, given Parallax's educational leanings, wouldn't the removal of all operators, except maybe assignment, be better? Operators are comparatively opaque and can often get novices, and sometimes experts, in trouble without even knowing it.)
No, no, your first expression should be: S expressions all the way
It's the normal syntax in Spin for float expressions:
Ha! Yes. Let's turn SPIN into LISP. Or Scheme perhaps.
@Ariba Is it?
That is not in the manual.