There's a new release (4.4.0) of fastspin available from https://github.com/totalspectrum/spin2cpp/releases. There are many improvements to the C parser, thanks in large part to @Rayman's helpful bug reports (Ray, I think all the issues you reported above are addressed now). There are also some Spin2 improvements (in SEND and RECV) and a few bug fixes to the BASIC compiler.
@Rayman : I see the problem with EVE2. Fastspin isn't handling initializing bitfields (like "filter :1") properly, because multiple entries have to be compressed down to one actual word in memory. For now you can work around it by removing the ":N" notation from the structure declaration.
Good news! Was able to get Logos example working. But, in addition to the bitfields issue, there some issue with mixing types...
Everything looked good, except the last element in the structure, the uint32. It was getting initialized to bizarre, sometimes negative values...
But, making them all uint32 made it work...
@ersmith I'm having a mixed-language issue when using fixed-point math in FlexBASIC.
This code works fine using IEEE 754 floating point:
dim f as single
dim i as long
f = 1.234567890
i = 42
print "Float test"
printf("Float = %f, Int = %d", f , i )
But if I add the "--FIXED" option on the compiler command line, the value of "f" will be printed as "0.00000". Otherwise the fixed-point math works fine and is about 9x faster than floating point.
Apologies for the really ugly language mash-up, but how do I use C's printf() to display a 16.16 fixed-point value?
@ersmith An old bug is back. Very minor, but I'll stick it out here in case you want to stomp it.
A FOR/NEXT loop without anything inside the loop throws an "unexpected next" error. This code wont compile:
dim a as long
for a = 1 to 10
'nothing here
next a
But this code works fine:
dim a as long
for a = 1 to 10
ASM
nop
END ASM
next a
I would agree that a FOR/NEXT loop without anything inside it is a fairly useless creature (unless it was being used as a pidgin-style delay maybe?), but the syntax is valid.
FWIW, all of the other "empty loop" fixes that you implemented previously still work fine. Only FOR/NEXT is wonky.
Is calling a C function with no argument legal if the declaration has one? I don't think so. The following code compiles without error and outputs "arg=1669342516" which I guess is a random value on the stack.
outputs "bit=2 mask=ffffffff" instead of "mask=3". The shift operation is optimized away because the whole expression is constant. I think the compiler uses ROR or SAR instead of SHR.
Is calling a C function with no argument legal if the declaration has one? I don't think so. ...
IMHO the compiler should say something like "no matching function found for call WaitFall(void)".
It's a good question. I think maybe C sometimes won't check? C++ has to due to overloading, I imagine...
If you use Visual Studio to edit the C code, it will both show you what arguments are needed when you are typing and flag as error with red squiggly underline if wrong.
I took a stab at compiling MicroMax Chess this morning...
Got a couple versions to compile and run, but they don't work quite right... Seems the black pawns are messed up...
This is probably asking too much from FlexC at this stage.
I could probably figure out what is wrong by comparing with PC version, but that'd take a long time, I think...
Anyway, just wanted to point out two things that I had to change to make some of these compile...
First, they seem to declare the types of the parameters to a function like this, which FlexC doesn't like:
D(k,q,l,e,E,z,n)
int k,q,l,e,E,z,n;
{
This is a strange way to do it anyway, I think the author was just trying to save characters in the file for some reason...
The other thing was a goto label with the same name "C" as a local variable. That seems like bad style to me anyway, but they claim this is ANSI C...
Anyway, these two seem like they almost, but not quite work.
outputs "bit=2 mask=ffffffff" instead of "mask=3". The shift operation is optimized away because the whole expression is constant. I think the compiler uses ROR or SAR instead of SHR.
@ManAtWork , the constant 0xffffffff defaults to type int. For a 32-bit int this results in a value of -1. Shifting a -1 to the right will always result in a -1, or 0xffffffff. On a machine with a 64-bit int 0xffffffff will be a positive number, and shifting it 30 bits to the right results in a value of 3.
If you want to force the value 0xffffffff to be unsigned you can put a "u" at the end, such as 0xffffffff. Or you could cast it to unsigned using (uint32_t)0xffffffff.
ManAtWork,
C's >> operator is defined as SAR with signed operands and SHR for unsigned operands. As Dave Hein said, you need to cast your 32bit constant operand to be unsigned to get what you want, or make it a 64bit constant.
This chess code gives me a compile error like this:
error : Internal error : unknown type 2 passed to TypeSize
Also, the code uses the include sys/timeb.h to get the seconds and milliseconds of time and then form milliseconds.
We don't have that, so I did a bad hack.
Is there a good way to do that?
@ManAtWork , the constant 0xffffffff defaults to type int. For a 32-bit int this results in a value of -1.
Ok, but if I assign this constant to a variable declared of type uint32_t I assume that it will be a positive number with all bits set. If I shift that variable right by 30 bits I assume that the result is 3, no matter of the original type of the constant before the assignment. I know that the compiler optimizes the assignment and even the variable away and directly passes the result to the print. But no optimization should ever change the semantics of a program.
Seems I need the asin() function to convert a quaternion to roll, yaw, pitch...
Sadly, seems to be missing from math.h...
Unless I can figure out a trick to use what is there to get it, might have to import from some other math library...
I found "cephes". License appears to be liberal, but not 100% clear...
Actually, Wikipedia appears to show you can get asin from atan.
I got an error in this code that had two semi-colons in a row...
Is this a real error?
int Xoutput=0;;
Yes, actually, that is illegal in ISO C (you can check with gcc -Wall -Wpedantic). It's surprising, but there you go. Most compilers do accept it, but fastspin is using a C parser I got from the web that is fairly strict.
Is calling a C function with no argument legal if the declaration has one? I don't think so. The following code compiles without error and outputs "arg=1669342516" which I guess is a random value on the stack.
IMHO the compiler should say something like "no matching function found for call WaitFall(void)".
It's a bit tricky, because while it could be a compile time error if there are declarations for everything, it actually is a construct that's used sometimes, where the function gets declared in one file and used "wrongly" in another file. I've added a warning for it to the next version of fastspin.
@ManAtWork , the constant 0xffffffff defaults to type int. For a 32-bit int this results in a value of -1.
Ok, but if I assign this constant to a variable declared of type uint32_t I assume that it will be a positive number with all bits set.
The assignment to the variable happens *after* all the calculations are performed, so the type is "int" during the shift. That is, the expression is parsed as:
uint32_t mask = (0xffffffff >> (32-bit));
and not as
(uint32_t mask = 0xffffffff) >> (32-bit);
I need to look carefully at the standard to see if plain "0xffffffff" on its own has to be considered unsigned, but I strongly suspect it's a compiler dependent feature. For portable code you should either cast it to unsigned or put a "u" at the end to make sure it's explicitly unsigned.
The assignment to the variable happens *after* all the calculations are performed, so the type is "int" during the shift. That is, the expression is parsed as:
uint32_t mask = (0xffffffff >> (32-bit));
and not as
(uint32_t mask = 0xffffffff) >> (32-bit);
Ok, that makes sense and I finally get it. That's what I hate about C. Those implicit typecasts are very dangerous. An expression that looks perfectly correct at first sight could actually contain bugs that are very hard to spot. And in most cases there is no way the compiler can warn about it because many "tricks" are commonly used and fully legal in C.
Thanks Eric, not your fault...
I think this is one or the (rare) cases where inline assembler is actually better/clearer than C code.
@ersmith I'm having a mixed-language issue when using fixed-point math in FlexBASIC.
I've updated C's printf to handle fixed point. I've also added "." to the BASIC PRINT USING statement, so you can format the numbers directly in BASIC if you want (e.g. print using "##.####"; x)
I also fixed the empty FOR loop problem you saw (thanks).
There's a beta version of fastspin/flexgui up on my Patreon page with these fixes.
Comments
The filename comes out wrong...
But now, I'm getting a compile error on the above with "too many initializers..."
Here's the code in question.
See build.bat for the compile command line.
There's a ton of chips supported there and I have a feeling they would all work: https://github.com/STMicroelectronics/STMems_Standard_C_drivers
For the P2 part, I used @JonnyMac 's I2C driver from OBEX. It's really great to be able to use Spin files directly in FlexC!
Everything looked good, except the last element in the structure, the uint32. It was getting initialized to bizarre, sometimes negative values...
But, making them all uint32 made it work...
This code works fine using IEEE 754 floating point: But if I add the "--FIXED" option on the compiler command line, the value of "f" will be printed as "0.00000". Otherwise the fixed-point math works fine and is about 9x faster than floating point.
Apologies for the really ugly language mash-up, but how do I use C's printf() to display a 16.16 fixed-point value?
A FOR/NEXT loop without anything inside the loop throws an "unexpected next" error. This code wont compile:
But this code works fine:
I would agree that a FOR/NEXT loop without anything inside it is a fairly useless creature (unless it was being used as a pidgin-style delay maybe?), but the syntax is valid.
FWIW, all of the other "empty loop" fixes that you implemented previously still work fine. Only FOR/NEXT is wonky.
but, if declared as uint instead of int, maybe it should have worked?
It's a good question. I think maybe C sometimes won't check? C++ has to due to overloading, I imagine...
If you use Visual Studio to edit the C code, it will both show you what arguments are needed when you are typing and flag as error with red squiggly underline if wrong.
Got a couple versions to compile and run, but they don't work quite right... Seems the black pawns are messed up...
This is probably asking too much from FlexC at this stage.
I could probably figure out what is wrong by comparing with PC version, but that'd take a long time, I think...
Anyway, just wanted to point out two things that I had to change to make some of these compile...
First, they seem to declare the types of the parameters to a function like this, which FlexC doesn't like: This is a strange way to do it anyway, I think the author was just trying to save characters in the file for some reason...
The other thing was a goto label with the same name "C" as a local variable. That seems like bad style to me anyway, but they claim this is ANSI C...
Anyway, these two seem like they almost, but not quite work.
@ManAtWork , the constant 0xffffffff defaults to type int. For a 32-bit int this results in a value of -1. Shifting a -1 to the right will always result in a -1, or 0xffffffff. On a machine with a 64-bit int 0xffffffff will be a positive number, and shifting it 30 bits to the right results in a value of 3.
If you want to force the value 0xffffffff to be unsigned you can put a "u" at the end, such as 0xffffffff. Or you could cast it to unsigned using (uint32_t)0xffffffff.
Is this a real error?
C's >> operator is defined as SAR with signed operands and SHR for unsigned operands. As Dave Hein said, you need to cast your 32bit constant operand to be unsigned to get what you want, or make it a 64bit constant.
Also, the code uses the include sys/timeb.h to get the seconds and milliseconds of time and then form milliseconds.
We don't have that, so I did a bad hack.
Is there a good way to do that?
Two semicolons like that should not be an error.
Ok, but if I assign this constant to a variable declared of type uint32_t I assume that it will be a positive number with all bits set. If I shift that variable right by 30 bits I assume that the result is 3, no matter of the original type of the constant before the assignment. I know that the compiler optimizes the assignment and even the variable away and directly passes the result to the print. But no optimization should ever change the semantics of a program.
So should output "bit=2 mask=3" unless I miss something. I'm curious what Eric says about this.
I was just reading that u can be upper or lower case... Should there be an "L" at the end too?
Sadly, seems to be missing from math.h...
Unless I can figure out a trick to use what is there to get it, might have to import from some other math library...
I found "cephes". License appears to be liberal, but not 100% clear...
Actually, Wikipedia appears to show you can get asin from atan.
Yes, actually, that is illegal in ISO C (you can check with gcc -Wall -Wpedantic). It's surprising, but there you go. Most compilers do accept it, but fastspin is using a C parser I got from the web that is fairly strict.
It's a bit tricky, because while it could be a compile time error if there are declarations for everything, it actually is a construct that's used sometimes, where the function gets declared in one file and used "wrongly" in another file. I've added a warning for it to the next version of fastspin.
I need to look carefully at the standard to see if plain "0xffffffff" on its own has to be considered unsigned, but I strongly suspect it's a compiler dependent feature. For portable code you should either cast it to unsigned or put a "u" at the end to make sure it's explicitly unsigned.
Or, can there be only one?
How about interrupt handling? Is that possible?
Ok, that makes sense and I finally get it. That's what I hate about C. Those implicit typecasts are very dangerous. An expression that looks perfectly correct at first sight could actually contain bugs that are very hard to spot. And in most cases there is no way the compiler can warn about it because many "tricks" are commonly used and fully legal in C.
Thanks Eric, not your fault...
I think this is one or the (rare) cases where inline assembler is actually better/clearer than C code.
I also fixed the empty FOR loop problem you saw (thanks).
There's a beta version of fastspin/flexgui up on my Patreon page with these fixes.