Posts: 92
Threads: 8
Joined: Mar 2011
Reputation:
0
Hello.
I got a program that works fine under 130s1121 but not under 140s1876. When I try to compile it then it bombs with this message:
Traceback (most recent call last):
File "/home/pi/zxbasic/zxb.py", line 348, in <module>
sys.exit(main(sys.argv)) # Exit
File "/home/pi/zxbasic/zxb.py", line 274, in main
translator.visit(zxbparser.ast)
File "/home/pi/zxbasic/ast_/ast.py", line 105, in visit
stack.append(self._visit(stack.pop()))
File "/home/pi/zxbasic/arch/zx48k/translator.py", line 143, in _visit
return NodeVisitor._visit(self, node)
File "/home/pi/zxbasic/ast_/ast.py", line 118, in _visit
return meth(node)
File "/home/pi/zxbasic/ast_/ast.py", line 122, in generic_visit
raise RuntimeError("No {}() method defined".format('visit_' + node.token))
RuntimeError: No visit_SAVE() method defined
Usage: zxbasm.py <input file> [options]
I do not wnat to share the source on a forum, is there any way that I can get the source to you Boriel so that you can have a look at it?
Also, under the old version if you had a wihite paper and a black ink but a yellow border then the SAVE command did change the paper color to yellow afterwards and the tape message got displayed in paper yellow instead of white. Highly fishy. And if I tried to compile this program with -O3 then it bombed so I had to set it back to -O1. Now it totally refuses to compile under the new version. Help would be good here Boriel.
Posts: 92
Threads: 8
Joined: Mar 2011
Reputation:
0
After further investigation I found out that the program does compile if I remove the SAVE command so this is a regression bug but it still bombs if I try to compile it with -O3 with this message, I had to stop the compiler from running by hitting Ctrl-C.
Traceback (most recent call last):
File "/home/pi/zxbasic/zxb.py", line 348, in <module>
sys.exit(main(sys.argv)) # Exit
File "/home/pi/zxbasic/zxb.py", line 301, in main
asm_output = optimize(asm_output) + '\n'
File "/home/pi/zxbasic/optimizer.py", line 2296, in optimize
x.optimize()
File "/home/pi/zxbasic/optimizer.py", line 1948, in optimize
regs.op(i1, o1)
File "/home/pi/zxbasic/optimizer.py", line 869, in op
self.set('a', 0xFF ^ self.getv('a'))
TypeError: unsupported operand type(s) for ^: 'int' and 'NoneType'
Something strange going on here.
Posts: 92
Threads: 8
Joined: Mar 2011
Reputation:
0
I did not have to hit Ctrl-C but I was impatient. I did manage to track down the line that caused -O3 to fail.
Example:
dim a as ubyte
dim b as uinteger
a = peek(b) bxor 2
Posts: 92
Threads: 8
Joined: Mar 2011
Reputation:
0
Still more research:
The example above compiles fine and it even compiles fine with a = peek(b) bxor 255.
The example below does not compile under -O3.
dim a as ubyte
dim bPtr as uinteger
for bPtr = 32768 to 32768 + 25
a = peek(bPtr) bxor 255
poke bPtr, a
next bPtr
If you change bxor to 25 or any other number but 255 and 255 does translate to cpl in assembly then it does compile.
Now I do not have to share the source.
It is up to you now Boriel.
Posts: 92
Threads: 8
Joined: Mar 2011
Reputation:
0
A comment errata:
"__LMULLOOP:
jr nc,__LMULNOADD ; JP is 2 cycles faster than JR. Since it's inside a LOOP
; it can save up to 33 * 2 = 66 cycles
; But JR if 3 cycles faster if JUMP not taken!
add hl,de ; result += mpd"
From mult32. It should read: But JR is 3 cycles faster if JUMP not taken!
Posts: 1,789
Threads: 56
Joined: Aug 2019
Reputation:
25
But wasn't this fixed years ago? hock:
Posts: 92
Threads: 8
Joined: Mar 2011
Reputation:
0
There was a problem with the SAVE printing but the color was never tested and the -O3 bombs and if I include a SAVE command for the new version then it bombs.
Posts: 92
Threads: 8
Joined: Mar 2011
Reputation:
0
I do hope that the over and inverse flags are not touched but you never know right.
Posts: 92
Threads: 8
Joined: Mar 2011
Reputation:
0
Another thing, when I tried to save out a string array using the SAVE DATA combination under the old version all I got out was junk. Maybe I only got the pointers but I did not get the data and the saved block was of the wrong size or much shorter than it should have been. I had to use complex workarounds, both because of this bug and the recently fixed bug where ArrayName(1)="Test" would not work. It is the little things that make or break a compiler. When can we expect fixes to this? It should have saved out the data elements and their length but no such luck. I have to "emanate" the array into memory and then back again using my own routines.
Posts: 1,789
Threads: 56
Joined: Aug 2019
Reputation:
25
Darkstar Wrote:Another thing, when I tried to save out a string array using the SAVE DATA combination under the old version all I got out was junk. Maybe I only got the pointers but I did not get the data and the saved block was of the wrong size or much shorter than it should have been. I had to use complex workarounds, both because of this bug and the recently fixed bug where ArrayName(1)="Test" would not work. It is the little things that make or break a compiler. When can we expect fixes to this? It should have saved out the data elements and their length but no such luck. I have to "emanate" the array into memory and then back again using my own routines.
Which command do you use exactly? Save data with strings is complicated because they're dynamic. Only SAVE "xxx" DATA: is allowed (or should be) to save string arrays (and ALL the data state of the program).
Posts: 92
Threads: 8
Joined: Mar 2011
Reputation:
0
From the Wiki:
"SAVE "xxx" DATA <varname>( )
This behaves like the original Sinclair BASIC, but here you can save/load/verify not only arrays, but single variables. Parenthesis can be omitted (in Sinclair BASIC they were mandatory). You can also use LOAD/VERIFY with this.
SAVE "xxx" DATA
With no varname saves ALL the entire user variable variable área plus the HEAP memory zone. That is, it saves all the program state. You can also use LOAD/VERIFY with this."
So I used SAVE "Content" DATA ArrayOfContent (). I did not omit the parenthesis and use ArrayOfContent nor did I use ArrayOfContent (0) were 0 stands for the first element in the array. I only wanted the array data or the contents of the array saved but it did not work contrary to what the wiki says and what the original language was capable of.
Boriel wrote:
"Save data with strings is complicated because they're dynamic."
I know, all of those pointers pointing to various places in memory and if one element chances size and becomes bigger then it has to be relocated and the pointer changed leading to fragmentation of the linier data causing it not to become linier or if it becomes smaller, well, basically same effect in the end. This is not trivial to get around I know. But in my instance all I needed was the contents of one particular string array and not all the other stuff that was on the heap and data area as it would have seriously gotten in my way leading to a lot of extra work and problems, a very dirty and unclean approach. So I was FORCED to write my own routines and cycle through the array and poke it's contents to a memory area that was above the boundaries of the compiled program and to get it back I had to read from that memory location through peek and a temporary string variable and then assign that temporary variable to the array again. If only that worked because of the ArrayName(Index)=TempVar bug, so it was time for yet another workaround. But there is a problem with this approach, I have to write my own routines and they take memory and if I am working with large string arrays then this approach doubles the memory they take contents wise.
But I have been thinking, would not a functionality similar to REDIM solve this and that functionality is then to be deployed automaticly when the program encounters
SAVE DATA ArrayName, string or numeric. That should get the contents arranged in a linier fashion so it can be saved out in a proper fashion.
Like I said, it is the little things like REDIM, ERASE and SELECT CASE, DIM ArrayName(1) AS STRING => {"Hello","I am a string array"} [Index base 0] in the absence of
DATA lines and ByRef, ByVal including arrays and optional parameters and a warning disabling scheme that make or break a language and/or a compiler. Along with
proper FOR/NEXT loops instead of the C style loops that are now used and if the compiler sees in can get away with using C style loops then it should be smart enough to use it without any user intervention in the form of switches.
To me this is bare minimum. Note I did not go into asking for support for TYPEs, a standard fare with QBASIC; or UNIONS, or OOP or a switch from 40bit floats to 32bit
floats and that should lessen ZX ROM dependency making the compiler even more retargetable to other machines than it is right now. Nor am I asking for that all commands to use the heap like both of the SAVE and LOAD commands as that lessens even more the dependency of platform specific configurations and not to mention it makes the compiler more consistent. And I did not ask for more input/output choices like the ability to deal with 128K disks and RAM disks or even the disk systems that are available for the 48K machine. Put all of that together then you have a real usable compiler, well, maybe apart from OOP and UNIONS, that reaches beyond the bare minimum. After that UNIONS and OOP and 128K memory management and the support for the PLAY command can be considered to make an outstanding compiler.
But as it is, despite of the excellent refactoring effort, the compiler does not reach the bare minimum that can then be built upon.
My thoughts.
Posts: 92
Threads: 8
Joined: Mar 2011
Reputation:
0
To add to the bare minimum: The ability to specify where the program state and the heap goes as it would be excellent for ROM files to name one use for it and to add to
that, a list of all ROM addresses that the compiler uses on the Wiki. Further more, if you specify a ROM compile option and a machine like the ZX then it pulls the ROM code inline to the compiled program to get rid of ROM code dependency.
Posts: 1,789
Threads: 56
Joined: Aug 2019
Reputation:
25
Darkstar Wrote:To add to the bare minimum: The ability to specify where the program state and the heap goes as it would be excellent for ROM files to name one use for it and to add to
that, a list of all ROM addresses that the compiler uses on the Wiki. Further more, if you specify a ROM compile option and a machine like the ZX then it pulls the ROM code inline to the compiled program to get rid of ROM code dependency. This is (still) planned, but other people should learn how to create compiler plugins. This is (supposedly) the purpose of this refact.
Posts: 92
Threads: 8
Joined: Mar 2011
Reputation:
0
Later the same mechanism can be developed further to use ROM files of one own making and the RAM memory area to store one program compiled from one source with one runtime library in ROM, this could even prove useful for 128K memory management if handled correctly.
Posts: 92
Threads: 8
Joined: Mar 2011
Reputation:
0
Boriel wrote:
"This is (still) planned, but other people should learn how to create compiler plugins. This is (supposedly) the purpose of this refact."
Yes, very good, very good.
But people can not learn without documentation.
|