'----------------------'
' Eightball Unit Tests '
'----------------------'

byte status=0
word counter=1
word fails=0

'------------------
' Word variables
'------------------
pr.msg "Word vars:"; pr.nl
word w1=10
word w2=100
word w3=50
w1=10
status=(w1==10)&&(w2==100)&&(w3==50)
call expect(status)

w2=w2+10
status=(w1==10)&&(w2==110)&&(w3==50)
call expect(status)

w2=w1+10
status=(w1==10)&&(w2==20)&&(w3==50)
call expect(status)

'------------------
' Byte variables
'------------------
pr.msg "Byte vars:"; pr.nl
byte b1=10;
byte b2=100;
word b3='a';
call expect((b1==10)&&(b2==100)&&(b3=='a'))

b2=b2+10
call expect((b1==10)&&(b2==110)&&(b3=='a'))

b2=b1+10
call expect((b1==10)&&(b2==20)&&(b3=='a'))

'------------------
' Word arrays
'------------------
pr.msg "Word arrays:"; pr.nl
word wpre=0
word warr[10]={12,12,12,12,12,12,12,12,12,12}
word wpost=0

pr.msg "Size of word (4 for interpeter, 2 for 6502 & VM): "
pr.dec (&warr[2]-&warr[1])
pr.nl

call expect((wpre==0)&&(warr[0]==12)&&(warr[1]==12)&&(warr[2]==12)&&(warr[9]==12)&&(wpost==0))

warr[1]=123
call expect((wpre==0)&&(warr[0]==12)&&(warr[1]==123)&&(warr[2]==12)&&(warr[9]==12)&&(wpost==0))

'------------------
' Byte arrays
'------------------
pr.msg "Byte arrays:"; pr.nl
byte bpre=0
byte barr[2*5]={12,12,12,12,12,12,12,12,12,12}
byte bpost=0

call expect((&barr[2]-&barr[1])==1)

call expect((&barr[4]-&barr[1])==3)

call expect((bpre==0)&&(barr[0]==12)&&(barr[1]==12)&&(warr[2]==12)&&(barr[9]==12)&&(bpost==0))

barr[1]=123
call expect((bpre==0)&&(barr[0]==12)&&(barr[1]==123)&&(warr[2]==12)&&(barr[9]==12)&&(bpost==0))

'------------------
' For loop
'------------------
pr.msg "For loop:"; pr.nl
word sum=0
word iw=0

for iw=1:3
 sum=sum+iw
endfor
call expect(sum==6)

sum=0
byte ib=0
for ib=1:3
 sum=sum+ib
endfor
call expect(sum==6)

'------------------
' While loop
'------------------
pr.msg "While loop:"; pr.nl
sum=0
iw=0
while iw<4
 sum=sum+iw
 iw=iw+1
endwhile
call expect(sum==6)

sum=0
ib=0
while ib<4
 sum=sum+ib
 ib=ib+1
endwhile
call expect(sum==6)

'------------------
' If/Endif
'------------------
pr.msg "If/Endif:"; pr.nl
iw=123
ib=0
if iw==123
  ib=1
endif
call expect(ib==1)

iw=124
ib=0
if iw==123
  ib=1
endif
call expect(ib==0)

'------------------
' If/Else/Endif
'------------------
pr.msg "If/Else/Endif:"; pr.nl

iw=123
ib=99
if iw==123
  ib=1
else
  ib=0
endif
call expect(ib==1)

iw=124
ib=99
if iw==123
  ib=1
else
  ib=0
endif
call expect(ib==0)

'------------------
' Pointers/Addresses
'------------------
pr.msg "Pointers/Addresses:"; pr.nl

word ptr=&iw
*ptr=9999
call expect(iw==9999)

ptr=&ib
^ptr=73
call expect(ib==73)

call expect(&warr[0]==&warr)

'------------------
' Call subroutine
'------------------
pr.msg "Call sub:"; pr.nl
call gv1()
call expect(iw==987)

call gb1()
call expect(ib==$ae)

call gwa1()
call expect(warr[3]==1234)

call gba1()
call expect(barr[7]==$34)

call c1()
call expect(iw==555)

call noret()
call expect(iw==9876)

'------------------
' Subroutine params
'------------------
pr.msg "Sub params:"; pr.nl

warr[0]=100
call pw1(warr[0])
call expect(iw==200)

barr[2]=10
call pb1(barr[2])
call expect(iw==20)

warr[0]=10
warr[1]=20
call pw2(warr[0],warr[1])
call expect(iw==200)

barr[0]=10
barr[1]=20
call pb2(barr[0],barr[1])
call expect(iw==200)

warr[0]=500
warr[1]=750
call add(warr[0],warr[1],&iw)
call expect(iw==1250)

warr[0]=500
warr[1]=750
call add(warr[0],warr[1],&warr[2])
call expect(warr[2]==1250)

word a1=&iw
call ppw1(2345, a1)
call expect(iw==2345)

call ppw1(2345, &iw)
call expect(iw==2345)

word a2=&ib
call ppb1(110, a2)
call expect(ib==110)

pr.msg " Recursive:"; pr.nl
call recurse1(5, &iw)
call expect(iw==120)

pr.msg " Array pass by ref:"; pr.nl
word AA[10]={}
call setwarray(AA, 10)
call sumwarray(AA, 10)
call expect(iw==45)

byte BB[10]={}
call setbarray(BB, 10)
call sumbarray(BB, 10)
call expect(iw==45)

call pbrfirstlevel(AA)
call expect(AA[3]==123)

call wrapper()

'------------------
' Invoke func
'------------------
pr.msg "Invoke func:"; pr.nl
call expect(sqr(10)==100)

pr.msg " Recursive:"; pr.nl
iw=recurse2(5)
call expect(iw==5*4*3*2)

iw=recurse3(5)
call expect(iw==5*4*3*2)

'------------------
' Locals
'------------------
pr.msg "Locals:"; pr.nl
iw=123
call lw1()
call expect(iw==123*2)

iw=123
call lb1()
call expect(iw==123*2)

iw=123
call lw2()
call expect(iw==123*4)

iw=123
call lb2()
call expect(iw==123*4)

call lpw1()
call expect(iw==1)

call lpb1()
call expect(iw==1)

call gp1()
call expect(iw==1)

'------------------
' Consts
'------------------
pr.msg "Consts:"; pr.nl
const cstsz=10
word AAA[cstsz]={}
byte iii=0
word summ=0
for iii=0:cstsz-1
  AAA[iii]=10
endfor
for iii=0:cstsz-1
  summ=summ+AAA[iii]
endfor
call expect(summ==cstsz*10)

'------------------
call done()
'------------------

end

'
' Test subroutines
'
sub gv1()
  iw = 987; ' Set global word
  return 0
endsub

sub gb1()
  ib = $ae; ' Set global byte
  return 0
endsub

sub gwa1()
  warr[3] = 1234; ' Set global word array member
  return 0
endsub

sub gba1()
  barr[7] = $34; ' Set global byte array member
  return 0
endsub

sub pw1(word xx)
  iw = xx * 2
  return 0
endsub

sub pb1(byte xx)
  iw = xx * 2
  return 0
endsub

sub pw2(word xx, word yy)
  iw = xx * yy
  return 0
endsub

sub pb2(byte xx, byte yy)
  iw = xx * yy
  return 0
endsub

sub add(word a, word b, word sumaddr)
  *sumaddr=a+b
  return 0
endsub

sub ppw1(word val, word addr)
  *addr=val
  return 0
endsub

sub ppb1(byte val, word addr)
  ^addr=val
  return 0
endsub

sub c1()
  call c2()
  return 0
endsub

sub c2()
  call c3()
  return 0
endsub

sub c3()
  iw = 555
  return 0
endsub

sub noret()
  iw = 9876
endsub

sub sqr(word x)
  return x*x
endsub

sub recurse1(word x, word addr)
  if x==0
    *addr=1
  else
    call recurse1(x-1,addr)
    *addr=*addr*x
  endif
endsub

sub setwarray(word A[], word len)
  word i=0
  for i=0:len-1
    A[i] = i
  endfor
endsub

sub sumwarray(word A[], word len)
  word i=0
  iw=0
  for i=0:len-1
    iw=iw+A[i]
  endfor
endsub

sub setbarray(byte A[], word len)
  word i=0
  for i=0:len-1
    A[i] = i
  endfor
endsub

sub sumbarray(byte A[], word len)
  word i=0
  iw=0
  for i=0:len-1
    iw=iw+A[i]
  endfor
endsub

sub pbrfirstlevel(word XX[])
  call pbrsecondlevel(XX)
endsub

sub pbrsecondlevel(word XX[])
  byte i=0
  for i=0:9
    XX[i]=123
  endfor
endsub

sub wrapper()
  word xyz[10]={}
  call pbrfirstlevel(xyz)
  call expect(xyz[3]==123)
endsub

sub recurse2(word x)
  if x==0
    return 1;
  else
    return recurse2(x-1)*x
  endif
endsub

' Why does this not work, even though
' recurse2() works fine??
sub recurse3(word x)
  if x==0
    return 1;
  else
    return x*recurse3(x-1)
  endif
endsub

sub lw1()
  word loc=2
  iw=iw*loc
  return 0
endsub

sub lb1()
  byte loc=2
  iw=iw*loc
  return 0
endsub

sub lw2()
  word loc=0
  loc=4
  iw=iw*loc
  return 0
endsub

sub lb2()
  byte loc=0
  loc=4
  iw=iw*loc
  return 0
endsub

sub lpw1()
  iw=0
  word xx=0
  word addr=&xx
  *addr=1234
  if xx==1234
    iw=1
  endif
  return 0
endsub

sub lpb1()
  iw=0
  byte xx=0
  word addr=&xx
  ^addr=123
  if xx==123
    iw=1
  endif
  return 0
endsub

sub gp1()
  iw=0
  word addr=&iw
  *addr=5436
  if iw==5436
    iw=1
  endif
  return 0
endsub

'
' Utility subroutines
'
sub expect(byte b)
  pr.dec counter
  pr.msg ": "
  counter=counter+1
  if b
     pr.msg "  Pass "
  else
     pr.msg "  FAIL "
     fails=fails+1
  endif
  pr.nl
  return 0
endsub

sub done()
  if fails==0
    pr.msg "*** ALL "; pr.dec counter-1; pr.msg " TESTS PASSED ***"; pr.nl
  else
    pr.msg "*** "; pr.dec fails; pr.ch '/'; pr.dec counter-1; pr.msg " TESTS FAILED ***"; pr.nl
  endif
endsub

