Welcome, Guest
You have to register before you can post on our site.

Username
  

Password
  





Search Forums

(Advanced Search)

Forum Statistics
» Members: 259
» Latest member: Jeffreybub
» Forum threads: 1,074
» Forum posts: 6,434

Full Statistics

Online Users
There are currently 374 online users.
» 1 Member(s) | 371 Guest(s)
Bing, Google, Zoran

Latest Threads
.tap file code not execut...
Forum: Help & Support
Last Post: Zoran
04-28-2025, 10:59 AM
» Replies: 4
» Views: 181
Exit from more than one l...
Forum: Wishlist
Last Post: Duefectu
04-23-2025, 10:06 PM
» Replies: 3
» Views: 255
put small ASM programs li...
Forum: How-To & Tutorials
Last Post: Zoran
04-18-2025, 02:02 PM
» Replies: 6
» Views: 1,510
Creating +3 Menus - Loadi...
Forum: Help & Support
Last Post: merlinkv
04-16-2025, 02:08 PM
» Replies: 6
» Views: 511
Randomize not very random...
Forum: Help & Support
Last Post: Zoran
04-08-2025, 10:40 AM
» Replies: 4
» Views: 414
Scope rules
Forum: Bug Reports
Last Post: Zoran
04-04-2025, 09:46 AM
» Replies: 2
» Views: 286
Using constants not allow...
Forum: Bug Reports
Last Post: baltasarq
03-19-2025, 10:00 PM
» Replies: 8
» Views: 1,003
404 page not found
Forum: Documentation
Last Post: boriel
03-08-2025, 07:16 PM
» Replies: 5
» Views: 2,842
Spectrum keywords codes
Forum: Bug Reports
Last Post: boriel
03-08-2025, 11:00 AM
» Replies: 1
» Views: 392
ZXodus][Engine
Forum: ZX Basic Compiler
Last Post: boriel
02-19-2025, 11:43 PM
» Replies: 69
» Views: 213,413

 
  CODE <constant string> is broken (*solved*)
Posted by: britlion - 05-08-2009, 06:08 PM - Forum: Bug Reports - Replies (2)

I was playing with some complex code from the "One Liners" stuff. The following program behaves completely differently in basic as opposed to going through the compiler. Actually, it crashes when run compiled. (I tried several different types for f and g). Oddly, at the first PLOT, there appears some other changes to the screen - a few bytes of corruption. Something weird is happening there. There are more brackets than I need - mostly in an attempt to make sure the math functions are coming out clearly. Try it in BASIN and then compile it.

I know the functions are unnecessarily complex. That's the nature of the one liner type code. Nonetheless, it ought to behave when compiled just like the interpreted version. Shouldn't it?

Code:
DIM f,g as UBYTE

1  PRINT AT 9,9;"SIMON"
3  FOR f=1 TO 4
4     INK f
5     FOR g=1 TO 32
6         PLOT INT ABS((SGN (f-2.5)*80)+24+g), INT (((CODE "0202"(f TO f)-49)*99)-48+g)
7         DRAW 32,0
8     NEXT g
9     goto 11
10  STOP
11  PRINT INK f; OVER 1;AT CODE "1919"(f TO f)-44,CODE "0099"(f to f)-41;f
12     NEXT f
13  LET f=1
14  goto 9

Print this item

  Version 1.1.7 released!
Posted by: boriel - 05-03-2009, 10:27 AM - Forum: ZX Basic Compiler - No Replies

What's new since 1.1.4:

  • + Added the ELSEIF construct to the IF THEN ELSE sentence
  • + Added more optimizations in some jumps
  • + Added the USR function (both for Strings and Floats). Yes, you can now use USR "a" to get the address of the UDG table (instead of PEEK Uinteger 23675), and also can do RANDOMIZE USR 40000 (if you want to call a legacy machine-code routine; other than that it's useless).
  • * Optimized some print string generated code (now it's smaller)
  • ! Fixed many optimization bugs (almost five). Thanks to LCD
  • ! Fixed ChangeLog file
  • - Internal refactored code (somewhat)
  • ! BOLD and ITALIC could not be used as permament attributes,
    only as temporary ones. Now they are allowed as permament.
  • * Some more syntax compatibility with Sinclair BASIC. Expressions
    like F$(5), F$() or F$(TO) are now allowed. So expressions like PRINT ;;; are.
  • ! single PRINT sentences were not working (they should print a
    newline).
  • * Minor grammar corrections.
  • ! Using a suffix like '$' in a function declaration was being
    ignored. Now this also works ok.
  • + Added suport for PRINT , (Thanks to britlion and LCD for the
    suggestions and bug detection)
  • * Fixed a potential optimization bug for SHR and SHL

TODO:
  • Bitwise instructions for AND, OR, XOR, NOT
  • CLEAR to fill memory areas
  • READ, DATA and RESTORE
  • SAVE & LOAD

Print this item

  Wish: Documentation!
Posted by: britlion - 04-29-2009, 08:27 PM - Forum: Wishlist - Replies (4)

There are lots of things in the compiler that are mentioned obliquely in changelogs.

Please - at least get the list of reserved words up to date so that we know something is there.

Please, document DIM! This keyword is used in so many different ways - to set types, to dimension arrays, to set constants and to block fill arrays with =>

We're a little in the dark generally - and willing to work with that - but I think I'd like to request documentation and examples for DIM be top of the pile!

Print this item

  DIM issue
Posted by: britlion - 04-29-2009, 08:17 PM - Forum: Wishlist - Replies (5)

Why does

Code:
DIM list(1) AS uByte => {24,2}

compile just fine, but

Code:
DIM p(1) AS String => {"Word","Word"}

Will not. I thought initializing arrays this way was a replacement for READ and DATA, which are not supported! I love being able to block fill an array at compile time with numbers. Can I not do the same thing with strings? How do I replace:

DATA "STRING","STRING","STRING" then?

Print this item

  Print issues (*fixed*)
Posted by: britlion - 04-29-2009, 12:31 PM - Forum: Bug Reports - Replies (3)

Big issue: I notice print doesn't support commas.

Print "1","2" doesn't line up in columns. It won't even compile!

Print "1"+CHR$(6)+"2" does compile, but the print routine seems to ignore the tab.

I'm not sure how to work around this for spectrum programs that format text out in columns, or use commas to hop to the next line.



Optimization freak (I am. If I can save one assembler instruction, that's at least a byte saved!)

I notice that:

PRINT "1";
PRINT "2"

and PRINT "1";"2"

Produce exactly the same assembler code! Bravo. But

PRINT "1"+"2" is quite a lot shorter - the compiler sees it can combine the strings into one label.

Similarly:

PRINT INK1;"BLUE";INK 2;"RED"

is quite a lot longer in assembler than:

PRINT CHR$(16)+CHR$(1)+"BLUE"+CHR$(16)+CHR$(2)+"RED"

Your print routine parses both the above lines identically. The second, while far less decipherable to a human), to the compiler is a whole 14 bytes shorter in the assembler. Given how common print and combined color codes are in code, I suspect there is a notable size optimization that could be made in compiled code.


Off this post's topic:
The other one I noticed would be not storing a variable in a register if we don't need to:

Code:
LET A=A+1
LET A=A*2

Does Load, increment, store, multiply, store.

First up, I noticed it doesn't reload from store in the middle. It also recognizes multiply by two, and does the bitshift. That's very cool. It doesn't need to store in the middle tho!

(Is it worth optimizing double and triple bitshifts for *4 and *8 and so on? These are common multipliers, if only for screen coordinates.)

Print this item

  Feature: Italics!
Posted by: britlion - 04-29-2009, 12:09 PM - Forum: Wishlist - Replies (9)

I was rummaging through the .asm code, and I note it's pretty well optimized - though I can see places that could be neater. But that's for another time.

I noticed one of the runtime code blocks was labelled Italics..

So, curious, I tried compiling:

PRINT ITALIC 1; "Italics?"

And it worked perfectly! This isn't documented anywhere! What an awesome little addition to the language.
(It prints the text with the top a pixel to the right and the bottom a pixel to the left, and the middle left alone)

This should probably be added to the reserved words list.

Print this item

  Faster multiply?
Posted by: britlion - 04-28-2009, 09:34 PM - Forum: ZX Basic Compiler - Replies (8)

Okay, I confess: I'm not an assembler user. This is why I need a compiler.

That said, I love to nosey into things I don't understand. I often learn from that.

I was looking at an old piece of assembler code I found, when trying (fairly unsuccessfully) to learn Z80 code:

8 Bit number multiply

Rotates Num 1 round to examine it. Rotates Num2 up. Adds HL and DE if the bit is set.
Result is Num1 * Num2 in HL.

LD HL,0
LD DE, (NUM2)
LD A, (NUM1)
LOOP RR A (Divide A by 2 - copying the 1's column bit into the carry flag.)
JR NC, JP1 (Jump over the add if we have to)
ADD HL,DE
JP1 RET Z (Leave when we finish - A has gone to zero)
SLA E }
RL D } Multiply DE*2
JR LOOP


naturally, when I found this again, I couldn't resist comparing it to the 8 bit multiply assembler in the library. I'm not sure which is faster (Boriel's code is a little unclear in the fastcall case which registers are set with parameters; I think it's A and HL tho. I have a suspicion this code is faster, if only because it doesn't loop for a whole 8 bits if A is small - it quits as soon as A hits zero, which might optimize a few loops out.

Anyway, just for your perusal. Like I said, I'm a little beyond my depth on this one; but I love to optimize where I can!

I'm glad LCD mentioned the HISOFT compiler - because I think it does an awesome job. The limitation with it is that it's ON the spectrum, so you need room for basic + compiler + compiled code [though it can be clever and delete the basic as it goes to make more room]. I'm hoping Boriel's compiler will eventually Exceed the speed of Hisoft's - because it can be much cleverer outside the Spectrum than one locked into it!

Print this item

  String Slicing (*solved*)
Posted by: britlion - 04-27-2009, 07:32 PM - Forum: Bug Reports - Replies (3)

Not sure whether this is as intended, but it's not quite compatible with Sinclair Basic:

LET K$="1234567890"
PRINT K$(TO 3)
PRINT K$( 3 TO)

All seems to compile - though strings are numbered from 0, whereas Sinclair basic numbers them from 1.

So ZX Basic gives the output:

1234, where Sinclair basic would give the output 123

If the aim is to be able to compile Sinclair Basic, we're not there with that one. (Perhaps a switch, or configurable option?)

Also:

Print K$(3) fails. We would need to use k$(3 TO 3). Is this a bug?

PRINT K$( TO ) also fails, and ZX Basic allows it. It's an unusual corner case, though - it means the same thing as just K$. If it was to be supported for compatibility, a preprocessor tweak ought to be able to optimize it to disappear before the compiler saw it.

Print this item

  Optimisation level 3 Bug (*solved*)
Posted by: LCD - 04-10-2009, 06:22 PM - Forum: Bug Reports - Replies (5)

Hi Boriel,

I wrote the following little game (which is supposed to become a "Jewel Quest" clone one day :-):

Code:
dim a as uinteger
dim x as ubyte
dim y as ubyte
dim solv as ubyte
dim posx as uinteger
dim posy as uinteger


sub field(x as uinteger,y as uinteger,obj as ubyte)
  dim adr as uinteger
  dim adr1 as uinteger
  dim col as ubyte
  adr=22528+x*3+y*96
  adr1=50064+x+y*8
  col=56
  if obj=0 then col=2:end if
  if obj=1 then col=3:end if
  if obj=2 then col=4:end if
  if obj=3 then col=5:end if
  if obj=4 then col=6:end if
  if obj=5 then col=7:end if
  if obj=64 then col=48:end if
  if peek adr1 then col=col+8:end if
  poke adr,col:poke adr+1,col:poke adr+2,col
  poke adr+32,col:poke adr+33,col:poke adr+34,col
  poke adr+64,col:poke adr+65,col:poke adr+66,col
end sub
sub DisplayField()
  adr=50000
  for y=0 to 7
    for x=0 to 7
      a=peek(adr)
      adr=adr+1
      field(x,y,a)
    next x
  next y
end sub
sub ClearField(x as uinteger,y as uinteger)
  poke 50000+x+y*8,64
  poke 50064+x+y*8,1
end sub

function GetFieldObj(x as uinteger,y as uinteger) as ubyte
  return peek (50000+x+y*8)
end function
sub SetFieldObj(x as uinteger,y as uinteger,obj as ubyte)
  poke 50000+x+y*8,obj
end sub

function CheckBoard(x as integer,y as integer)
  solved=0
  dim current as ubyte
  dim c1 as ubyte
  dim c2 as ubyte
  current=GetFieldObj(x,y)
  c1=GetFieldObj(x-1,y)
  c2=GetFieldObj(x-2,y)
  if x>3 then
    if c1=current and c2=current and GetFieldObj(x-3,y)=current and GetFieldObj(x-4,y)=current then for a=0 to 4:ClearField(x-a,y):next a:solved=solved+1:end if
  end if
  if x>2 then
    if c1=current and c2=current and GetFieldObj(x-3,y)=current then for a=0 to 3:ClearField(x-a,y):next a:solved=solved+1:end if
  end if
  if x>1 then
    if c1=current and c2=current then for a=0 to 2:ClearField(x-a,y):solved=solved+1:next a:end if
  end if
  c1=GetFieldObj(x,y-1)
  c2=GetFieldObj(x,y-2)
  if y>3 then
    if c1=current and c2=current and GetFieldObj(x,y-3)=current and GetFieldObj(x,y-4)=current then for a=0 to 4:ClearField(x,y-a):next a:solved=solved+1:end if
  end if
  if y>2 then
    if c1=current and c2=current and GetFieldObj(x,y-3)=current then for a=0 to 3:ClearField(x,y-a):next a:solved=solved+1:end if
  end if
  if y>1 then
    if c1=current and c2=current then for a=0 to 2:ClearField(x,y-a):solved=solved+1:next a:end if
  end if
  return solved
end function
sub fieldupdate()
  for x=0 to 7
    for y=0 to 7
      if GetFieldObj(x,y)=64 then
        ypos=y
        while ypos>0
          SetFieldObj(x,ypos,GetFieldObj(x,ypos-1))
          ypos=ypos-1
        end while
        SetFieldObj(x,0,rnd*5)
      end if
    next y
  next x
end sub
function SolveField() as ubyte
  solv=0
  for y=0 to 7
    for x=0 to 7
      solv=solv+CheckBoard(x,y)
    next x
  next y
  return solv
end function
sub PutCoin(x as uinteger,y as uinteger)
  print at y,x;"\  \..\  "
  print at y+1,x;"\ :\::\: "
  print at y+2,x;"\  \''\  "
end sub

sub DisplayCursor(x as integer,y as integer,mode as byte)
  dim adr as uinteger
  dim newcol as ubyte
  adr=22528+x*3+y*96
  poke 65535,peek adr
  asm
    ld a,(65535)
    and 7
    ld (65535),a
  end asm
  if mode then
    poke 65535,(peek 65535)+56
  else
    adr1=50064+x+y*8
    if peek adr1 then
      poke 65535,peek 65535+8
    end if
  end if
  newcol=peek 65535
  poke adr,newcol
  poke adr+1,newcol
  poke adr+2,newcol
  poke adr+32,newcol
  poke adr+33,newcol
  poke adr+34,newcol
  poke adr+64,newcol
  poke adr+65,newcol
  poke adr+66,newcol
end sub






randomize

for a=0 to 63
  poke 50000+a,rnd*5
  poke 50064+a,0
next a
asm
  ld hl,50000
  ld de,50128
  ld bc,64
  ldir
end asm

paper 0:ink 7:border 0:cls
'poke 23607,127
'poke 23606,16

print at 2,0;"Controls"
print at 4,0;"1) Keyboard"
print at 5,0;"2) Sinclair Joystick"

controls1:
if inkey$="1" then
  up$="q"
  dw$="a"
  le$="o"
  ri$="p"
  fi$="m"
  goto controls2
end if
if inkey$="2" then
  up$="9"
  dw$="8"
  le$="6"
  ri$="7"
  fi$="0"
  goto controls2
end if
goto controls1
controls2:
cls



for y=0 to 7
  for x=0 to 7
    PutCoin(x*3,y*3)
  next x
next y
posx=4
posy=4

solveboard:
  solv=SolveField()
  DisplayField()
  fieldupdate()
  if solv then goto solveboard:end if
controlloop0:
DisplayCursor(posx,posy,1)
for a=0 to 5:pause 1:next a
controlloop1:

if inkey$=up$ and posy>0 then DisplayCursor(posx,posy,0):posy=posy-1:DisplayCursor(posx,posy,1):goto controlloop0:end if
if inkey$=dw$ and posy<7 then DisplayCursor(posx,posy,0):posy=posy+1:DisplayCursor(posx,posy,1):goto controlloop0:end if
if inkey$=le$ and posx>0 then DisplayCursor(posx,posy,0):posx=posx-1:DisplayCursor(posx,posy,1):goto controlloop0:end if
if inkey$=ri$ and posx<7 then DisplayCursor(posx,posy,0):posx=posx+1:DisplayCursor(posx,posy,1):goto controlloop0:end if
if inkey$=fi$ then gosub activate:end if

goto controlloop1
activate:
  asm
    ld hl,50000
    ld de,50128
    ld bc,64
    ldir
  end asm
  if inkey$=up$ and posy>0 then
    adr=50000+posx+posy*8
    a=peek adr
    b=peek (adr-8)
    poke adr,b
    poke adr-8,a
    gosub check
    return
  end if
  if inkey$=dw$ and posy<7 then
    adr=50000+posx+posy*8
    a=peek adr
    b=peek (adr+8)
    poke adr,b
    poke adr+8,a
    gosub check
    return
  end if
  if inkey$=le$ and posx>0 then
    adr=50000+posx+posy*8
    a=peek adr
    b=peek (adr-1)
    poke adr,b
    poke adr-1,a
    gosub check
    return
  end if
  if inkey$=ri$ and posx>0 then
    adr=50000+posx+posy*8
    a=peek adr
    b=peek (adr+1)
    poke adr,b
    poke adr+1,a
    gosub check
    return
  end if

  complete=0
  for a=0 to 63
    if peek(50064+a) then complete=complete+1:end if
  next a
  if complete=64 then
    goto won
  end if

goto activate
check:
  solv=SolveField()
  if solv then
    DisplayField()
    goto solveboard
  else
    asm
      ld hl,50128
      ld de,50000
      ld bc,64
      ldir
    end asm
    goto controlloop0
  end if
  return

won:
cls
print "Congratulations"

The Problem is:
It works with Optimisation Level 2, but on Optimisation level 3 it throws "Unexpected tokem IX [IX] at line 1208"

Print this item

  Version 1.1.4 released!
Posted by: boriel - 03-30-2009, 06:46 AM - Forum: ZX Basic Compiler - No Replies

Changes from Version 1.1.2 to 1.1.4

  • + The peephole optimizer has been enabled and seems to be working
    reasonabily well (use -O3 for higher optimization).
  • ! When a DIV BY ZERO error occurs with floating point numbers the program
    crashes and resets the computer. This behaviour has been fixed
    and now returns 0 value and sets the error code 6 (Numbert Too big)
    in the ERR_NR system variable.
  • * Refactorization of the assembler and compiler so they now
    shared the OPTIONS in a better way (still to be finished). This
    makes easier to program future compiler options. Now also --debug
    flag is additive, showing more verbosity the more it is used.
  • + Memory optimization: The PRINT routine (which is about 1K) is not
    included if not USED.
  • ! Fixed a bug in negative constant integer typecasting (Thanks to LCD
    at WOS for reporting it! ;-)). It was causing decremental FOR..NEXT
    to fail.
  • ! Scientific notation numbers (e.g. 2e10) were not correctly parsed.
    Fixed. Thanks again to LCD. ;-)
  • + Added TAB compatibility for the PRINT command (both as a command
    and as a CHR$ control character).
  • * PRINT code optimized for size, maintaining speed.

====
TODO:
  • Some little more peephole optimizations.
  • Implementation of SAVE/LOAD/VERIFY with DATA/CODE/SCREENS (And maybe even the BASIC zone)
  • 8 bits AND/OR/NOT/XOR instructions
  • READ/DATA/RESTORE (mostly for compatibility)
  • CLEAR for filling memory zones.
  • USR n and USR n$ function (mostly for compatibilty)

Print this item