PlayBASIC V1.64P (Work In Progress) Gallery

Started by kevin, August 31, 2013, 02:38:09 PM

Previous topic - Next topic

kevin





PlayBASIC V1.64P  (Work In Progress) Gallery (September 1, 2013 - November 2016)


    This thread will document the changes being made for the PlayBASIC 1.64 revision P.  

  V1.64P4 (Revision #4)  released 24th, Mar, 2016 (Newest!)

  V1.64P3 (Revision #3)  released 20th, Nov, 2015

  V1.64P2 (Revision #2)  released 29th, Dec, 2014

  V1.64P (Revision #1)  released 22nd,Sep,2014



Upgrade History


    For older upgrade work in progress see,

    See  PlayBASIC V1.64O

    See  PlayBASIC V1.64N2 & V1.64N3

    See  PlayBASIC V1.64N

    See  PlayBASIC V1.64M

    See  PlayBASIC V1.64L Learning Edition History (Building learning Edition Thread)

    See  PlayBASIC V1.64L





Upgrade Work In Progress Blog Followes



PlayBASIC V1.64P Beta1/2 - Compiler Tweaks


    While working on the PlayBASIC to DLL  noticed a few situations where the compiler was dropped extra opcodes, or the instructions  being produced could be better arranged.  One such situation was noticed when the writing to static array fields in Type Pointers where the compiler would drop generally 3 opcodes to resolve the address and perform the write.   The pointer instruction set support a fixed offset in write, but this was being overlooked for some unknown reason.   So at least one of those 3 opcodes can be removed by just piping the offset in the write.  Which reduces it to two instructions, so potentially a 1/3 faster.   If the field is a literal, we can precompute the offset at compile time,  which trims this operation back to a single opcode.    Not only will it be faster pointer operations, but the stream lining will help with some the data pooling that occurs around pointers.    

 
    Bench-marked todays build and it's about 35% faster than V1.64O in that situation.

PlayBASIC Code: [Select]
   Type CoolType
x,y,z
a#,b#,c#
ThisString$
IntArray(5)
FltArray#(5)
StrArray$(5)
cool
EndType


DIm You as CoolType
DIm Me as CoolType pointer

you = new cooltype
me =new cooltype
; Me=Address


max=10000

Do
cls


frames++

;------------------------------------------------------------------------
;--[Integer Fields ]-----------------------------------------------------
;------------------------------------------------------------------------

t=timer()
for lp =0 to max

me.x=111
me.y=222
me.z=333

me.z++

next
tt1#+=timer()-t

print " Integer Field:"+str$(tt1#/frames)


;------------------------------------------------------------------------
;--[Float Fields ]-----------------------------------------------------
;------------------------------------------------------------------------

t=timer()
for lp =0 to max
me.a#=111.111
me.b#=222.222
me.c#=333.333
next
tt2#+=timer()-t
print " Float Field:"+str$(tt2#/frames)


;------------------------------------------------------------------------
;--[String Fields ]-----------------------------------------------------
;------------------------------------------------------------------------

t=timer()
for lp =0 to max

me.ThisSTring="String1"
me.ThisSTring="String2"
me.ThisSTring="String3"
me.ThisSTring="String4"
next
tt3#+=timer()-t

print " String Field:"+str$(tt3#/frames)



;------------------------------------------------------------------------
;--[Int Array Fields ]-----------------------------------------------------
;------------------------------------------------------------------------

t=timer()
for lp =0 to max

me.intarray(a) = 1000
me.intarray(a) = 1001
me.intarray(a) = 1002
me.intarray(a) = 1003

next
tt4#+=timer()-t

print "Integer Array Fields:"+str$(tt4#/frames)


;------------------------------------------------------------------------
;--[Flt Array Fields ]-----------------------------------------------------
;------------------------------------------------------------------------

t=timer()
for lp =0 to max

me.fltarray(a) = 1000.111
me.fltarray(a) = 1001.111
me.fltarray(a) = 1002.111
me.fltarray(a) = 1003.111


next
tt5#+=timer()-t

print " Float Array Fields:"+str$(tt5#/frames)


;------------------------------------------------------------------------
;--[String Fields ]-----------------------------------------------------
;------------------------------------------------------------------------

t=timer()
for lp =0 to max
me.Strarray(a) = "cool1"
me.Strarray(a) = "cool2"
me.Strarray(a) = "cool3"
me.Strarray(a) = "cool4"

next
tt6#+=timer()-t

print " String Array Fields:"+str$(tt6#/frames)



print fps()


Sync
loop







kevin


  PlayBASIC V1.64P Beta3- Math Short Cuts + Pointers

       The parser didn't support ++,--, +=, -= operators on pointers, does now.   The VM was also missing support for subtractions from stringref pointers. 
 
PlayBASIC Code: [Select]
         Type Vector
x#,y#,z#
endtype


Dim VectorPointer as Vector pointer
Dim GenericPointer as pointer
Dim BytePointer as byte pointer
Dim WordPointer as word pointer
Dim IntegerPointer as integer pointer
Dim FloatPointer as float pointer
Dim StringPointer as stringref pointer

me=1000

VectorPointer =me
GenericPointer =me
BytePointer =me
WordPointer =me
IntegerPointer =me
FloatPointer =me
StringPointer =me

VectorPointer ++
GenericPointer ++
BytePointer ++
WordPointer ++
IntegerPointer ++
FloatPointer ++
StringPointer ++

VectorPointer --
GenericPointer --
BytePointer --
WordPointer --
IntegerPointer --
FloatPointer --
StringPointer --


VectorPointer +=10
GenericPointer +=10
BytePointer +=10
WordPointer +=10
IntegerPointer +=10
FloatPointer +=10
StringPointer +=10



VectorPointer -=20
GenericPointer -=20
BytePointer -=20
WordPointer -=20
IntegerPointer -=20
FloatPointer -=20
StringPointer -=20

#break

sync
waitkey



kevin

 PlayBASIC V1.64P Beta5- Link List Support In Debugger

    One by product of changing how VM controls type declarations,  is  I've been sifting through some really really old code tucked away all over the place.   Since how the type structures has changed,  then it stands to reason the debugger needs to be aware of these changes also.   While updating the routines I noticed some TODO remarks about getting the view typed array routines to support linked lists from years ago.      In older versions of PB, if you clicked on linked list it would run through the container and not actually the list order.     So today's change includes a mode for literate through the list.  

    For example,

PlayBASIC Code: [Select]
   Type ThisThing
Index
x
EndTYpe


Dim Things as ThisThing list


For lp=1 to 10
Things = new ThisThing
Things.index=lp
Things.x = rnd(1000)
next


For each Things()
print Things.index
print Things.x
next

print "Done"
Sync
waitkey





    If you run this in debug mode F7,  go to the Variables TAB,  click Main then clicks THINGS(), it'll dump this into text box panel



----------------------------------------------------------
THINGS.thisthing
Type =thisthing
Size =112
Bank =177
----------------------------------------------------------


--------------------------------------------------------
THINGS( 10 ).thisthing
--------------------------------------------------------
INDEX  =10
X  =609

--------------------------------------------------------
THINGS( 9 ).thisthing
--------------------------------------------------------
INDEX  =9
X  =296

--------------------------------------------------------
THINGS( 8 ).thisthing
--------------------------------------------------------
INDEX  =8
X  =280

--------------------------------------------------------
THINGS( 7 ).thisthing
--------------------------------------------------------
INDEX  =7
X  =753

--------------------------------------------------------
THINGS( 6 ).thisthing
--------------------------------------------------------
INDEX  =6
X  =938

--------------------------------------------------------
THINGS( 5 ).thisthing
--------------------------------------------------------
INDEX  =5
X  =165

--------------------------------------------------------
THINGS( 4 ).thisthing
--------------------------------------------------------
INDEX  =4
X  =163

--------------------------------------------------------
THINGS( 3 ).thisthing
--------------------------------------------------------
INDEX  =3
X  =501

--------------------------------------------------------
THINGS( 2 ).thisthing
--------------------------------------------------------
INDEX  =2
X  =882

--------------------------------------------------------
THINGS( 1 ).thisthing
--------------------------------------------------------
INDEX  =1
X  =788




kevin

#3
   PlayBASIC V1.64P Beta5/6 - Reading UDT pointer fields

     The current beta seems to be back to normal,  so figured it'd be a good time to try and clean up the code generation when reading from a static array in  UDT pointer.   About a week or so I noticed when writing to the these structures the compiler with spit out more instructions than it needed and assuming reading would be the much the same and it is, but that section of the expression solver is a bit of a mess.    There's some really neat ideas hidden away in it, but trying to the follow logic in some places can be a little more clumsy than i'd like.

      When a UDT pointer with array field offset is detected in an expression, the parser modifies the current tokens state and falls through these a generic resolvers.   Which I'm sure was a good idea back in the day, which was probably 5, 6 or more years ago now, but I'm having  trouble cleaning up the output without breaking some other situation i'd not even considered.   So the best option seems to be detect the specific situation and call a more specific solver..    Have already removed one bogus additions when the field is being offset and hope to get it to be able to pre-solve literal offsets also.     So in some cases it'll only take one read instruction to grab the correct data from the data structure rather than a fixed cost of 3 (or more opcodes).     

      Tested the initial changes and it wins back the same 30% when reading from the structure as the write changes made.   So In the brute force bench mark we get about a 30 millisecond performance improvement.   Not only does this mean the native code translation will be faster, but UDT pointers can actually be quicker than regular typed variables and probably typed arrays also..


PlayBASIC Code: [Select]
   Type CoolType
x,y,z
a#,b#,c#
ThisString$
IntArray(5)
FltArray#(5)
StrArray$(5)
cool
EndType


DIm Me as CoolType pointer

me =new cooltype


max=10000

Do
cls


frames++

;------------------------------------------------------------------------
;--[Integer Fields ]-----------------------------------------------------
;------------------------------------------------------------------------

t=timer()
for lp =0 to max

me.x=111
me.y=222
me.z=333

next
tt1#+=timer()-t

print " Integer Field:"+str$(tt1#/frames)


;------------------------------------------------------------------------
;--[Float Fields ]-----------------------------------------------------
;------------------------------------------------------------------------

t=timer()
for lp =0 to max
me.a#=111.111
me.b#=222.222
me.c#=333.333
next
tt2#+=timer()-t
print " Float Field:"+str$(tt2#/frames)


;------------------------------------------------------------------------
;--[String Fields ]-----------------------------------------------------
;------------------------------------------------------------------------

t=timer()
for lp =0 to max

me.ThisSTring="String1"
me.ThisSTring="String2"
me.ThisSTring="String3"
me.ThisSTring="String4"
next
tt3#+=timer()-t

print " String Field:"+str$(tt3#/frames)



;------------------------------------------------------------------------
;--[Int Array Fields ]-----------------------------------------------------
;------------------------------------------------------------------------

t=timer()
for lp =0 to max

me.intarray(a) = 1000
me.intarray(a) = 1001
me.intarray(a) = 1002
me.intarray(a) = 1003

next
tt4#+=timer()-t

print "Integer Array Fields:"+str$(tt4#/frames)


;------------------------------------------------------------------------
;--[Flt Array Fields ]-----------------------------------------------------
;------------------------------------------------------------------------

t=timer()
for lp =0 to max

me.fltarray(a) = 1000.111
me.fltarray(a) = 1001.111
me.fltarray(a) = 1002.111
me.fltarray(a) = 1003.111


next
tt5#+=timer()-t

print " Float Array Fields:"+str$(tt5#/frames)


;------------------------------------------------------------------------
;--[String Fields ]-----------------------------------------------------
;------------------------------------------------------------------------

t=timer()
for lp =0 to max
me.Strarray(a) = "cool1"
me.Strarray(a) = "cool2"
me.Strarray(a) = "cool3"
me.Strarray(a) = "cool4"

next
tt6#+=timer()-t

print " String Array Fields:"+str$(tt6#/frames)



print ""



;------------------------------------------------------------------------
;--[Int Array Fields ]-----------------------------------------------------
;------------------------------------------------------------------------

t=timer()
for lp =0 to max
me.intarray(a) += 1
me.intarray(a) += 1
me.intarray(a) += 1
me.intarray(a) += 1
next
tt7#+=timer()-t

print "Add To Integer Array Fields:"+str$(tt7#/frames)

Login required to view complete source code


 

kevin

   PlayBASIC V1.64P Beta6 - UDT pointers Continued

      Still working on the compiler, have updated some optimization code to support dealing with typed pointers, which are things types have enjoyed for a  while now.   The expression resolver has a number of pretty simple, but rather effective short cutting mechanics built in. These are little traps that can strip unnecessary moves between VM registers and user variables namely.     They generally work by back tracking the last few opcodes, if the data types match then some these expressions can be short cut.    One of the many benefits of using 3 register opcodes in the VM.    Often it's just match of noticing those situations where a short can be made and wiring it in.  

      Short cuts can turn some code like    X = Player.X into a single VM opcode.   That's of course assuming the field Player.X and the variable X it's returning the result in are the same data type.     If they're different, like say one is an integer and the other is a float, then the exported result from  Player has to be recast prior to being written it to the output variable.   Making it at least a 2 instruction operation.   Without the write tracing, the compiler would always spit out the latter,  so the short cutting just lets it detect situations where the casting isn't necessary and the result can be plugging back into a  previous operation directly.    
   
      Another area that's I've been looking into, is trying to detect and resolve literal array field accesses not only with typed pointers, but regular typed variable/arrays also.  The theory is,  that when you access a static array field within type at a fixed offset, then the compiler should be able to reduce this from it's current 4+ opcodes down to the as low as two opcodes in some explicit cases but probably 3 opcodes in the general use.    Which might sound like mumbo jumbo, but  we're talking about a 20% or more speed up in a fundamental.  

        Changes like these aren't likely to make any big difference to a game with 5, 10, 20 characters on screen, but they would make a sizable impact if there's 100's of characters or programs that insist upon trying brute force solutions.   Obviously a better idea would be to never rely upon brute forcing any solution to begin with, but some people just never learn.

       Only problem I've been having so far is that there's some odd cascading errors that seem to appear when optimizing the static array fields in the select programs.  No idea why..  What a fun afternoon I'm now in for.


kevin

#5
   PlayBASIC V1.64P Beta10 Download

         Surprise Surprise,   BETA 10 of V1.64P upgrade is online and ready for testing.   This beta has a lot of internal changes range from improved code generation and the internal command set interfaces which will be used for building external DLL's with PlayBASIC To Dll.  So  we're keen to find out what if anything has been broken during the update process NOT after.  




kevin

#6
   PlayBASIC V1.64P Beta16 Download

         Here's  BETA 16 of V1.64P upgrade.  This version includes all the internal command set interfaces for use with external DLL's created with PlayBASIC To Dll.    
 
         The process has introduced a lot of small, but necessary changes to the command sets which may have altered the behavior..  So get testing.



  Download

     Old beta removed

kevin

#7
 PlayBASIC V1.64P Beta 17 - Operators and Precedence

        It shouldn't come as any great surprise that changes in this revision are to help with the PlayBASIC To DLL translator and it's ability to produce cleaner and better code generally.   Building the translator means taking a fine tooth comb to the generated byte code and making sure the compiler outputs the leanest set of instructions possible to perform each operation.     While looking over the bit wise/logical operators recently noticed they'd not been set to force an integer result.   So if you had an expression fragment that contained a float, it'd return a float in the legacy VM.    Fortunately this is simple to rectify as the parser has a switch to force an integer return.   This is a bit of a none issue in most programs  since the operators are generally only ever see integers on either side of them, but it can and does actually occur in some code.      

        Having operators return a float isn't an earth shattering problem, it just makes a simple operation messy and slower than need be when such things occur.   The existing translator already supports operations upon integers, but it didn't handle mixtures between integers and floats.  Forcing the compiler to produce an integer only result,  helps the VM keep everything integer and translator produce cleaner machine code from the byte code without making multiple path ways.  

        While looking at the operators again in the compiler and translator, noticed that NOT seems have a precedence issue.  For some reason it's evaluated before the math/compare operators in an expression.  It should be the same as the other operators and occur after them.

        So code like print not a=b  is being evaluated   Not A   then   result_of_Not_A=b  , where  it should do  A=b then do  Not Result_Of_Compare_A_With_B.

        Moreover Not is implemented as a mask and  Xor of the bit zero value on the right hand side.  After a rethink, it'd be better implemented as a equality test with zero then xor.    So code like   Not 45,  would actually be evaluated as Not (44<>0),  Not 1 = 0.    Where it'd currently return 1 since bit zero is OFF, it'll flip that off bit to on.  

         The bad thing about the NOT operator is that your introducing complexity into your expression for no real benefit, as  result = (Not A = B)   and Result = (A <>B) are functionality the same, expect the former is two operations and the latter is single operation.    No big deal in a loop of 1 to 100, but a very big deal when iteration count blows out in both VM and Machine Code.  

  Edit #1:

       Found the problem, the operator trap in the parser was missing the operation level screen.   Once added, the order solves as expected.  

PlayBASIC Code: [Select]
      print not a=b
print not a<>b

print not a#=b#
print not a#<>b#

; thee lines would fail in older versions of PB, since it'd evaluate Not A$ first
print not a$=b$
print not a$<>b$





  Edit #2: Optimizer

           The expression solver now contains logic to optimize & rewrite code fragments like the following.    The optimizer also supports literal Not statements as well so that be evaluated in constant expressions. 

PlayBASIC Code: [Select]
             Print Not 1
Print Not 0

Print Not 1.0
Print Not 0.0

Print Not A=B
Print Not A<>B

Print Not A#=B#
Print Not A#<>B#

Print Not A$=B$
Print Not A$<>B$




           Becomes,

PlayBASIC Code: [Select]
             Print 0
Print 1

Print 0
Print 1

Print A<>B
Print A=B

Print A#<>B#
Print A#=B#

Print A$<>B$
Print A$=B$





          So since we're saving an opcode every time, the object code is smaller and of course faster in both the VM and machine code.  No brainier really.  


kevin

#8
  PlayBASIC V1.64P Beta 18 - Shift Operators

       Just dropping in some more C styled operators with the << and >> which are equivalent of the existing LSR32 and  LSL32 functions (which is what they are in assembly btw).  Just makes dragging code between dialects that little bit simpler.  There's no functionality difference between them.  

PlayBASIC Code: [Select]
       print 1 << 2
print 256 >> 2

a=16
b=4
b#=b

print "variables & literals:"
print a << 4
print a >> 4
print 4 << a
print 4 >> a


print "integer only"
print a << b
print a >> b

print b << a
print b >> a


print "mixtures (floats recast as ints)"
print a << b#
print a >> b#

print b# << a
print b# >> a

Sync
waitkey



kevin

#9
  PlayBASIC V1.64P Beta 18 - Updated Operator Codes For IDE

       The compiler and IDE talk to each other when you first start PlayBASIC up.   The discussion is pretty one sided, but the IDE basically asks PB for it's current internal command, constant and operator list.    


       The board syntax highlighter currently doesn't support them all as you can currently see in this snippet.  (This statement will be obsolette when i next update the board, so they'll appear as per the IDE..)

PlayBASIC Code: [Select]
      ; Testing operators in standard PlayBASIC IDE

a++
a--

a+=b
a-=b
a*=b
a/=b

print a< B
print a> B
print a<>B
print a><B
print a>=B
print a<=B
print a=>B
print a=<B

print 1 << 2
print 256 >> 2

a=16
b=4
b#=b

print "variables & literals:"
print a << 4
print a >> 4
print 4 << a
print 4 >> a


print "integer only"
print a << b
print a >> b

print b << a
print b >> a


print "mixtures (floats recast as ints)"
print a << b#
print a >> b#

print b# << a
print b# >> a

print hex$(255 and 15 << 8)

Sync
waitkey





       Attached is a what it looks like in the classic IDE

 
 Edit #1 - Not Equal Operator

       It appears PB parser would only ID one version of the Not Equal operator, that being <> , where as the inverse also  represents an inequality, but the parser didn't pick it up.  With a quick tinker and it supports >< also.    


  Edit #2 - C styled not Not Equal Operator

        Dropped in the != this in for those who can't live without their c fix..  Same as <>and ><


kevin

#10
   PlayBASIC V1.64P Beta18 Download

         Here's  BETA 18 of V1.64P upgrade, this version contains a number of small fixes from the trig functions that are used in the external command interfaces (PlayBASIC to DLL) through to some optimizations and correction regarding the NOT operator as well as even a few new operators such as the shift left/Right operators <<  and >>



  Download

   Old beta removed




bmorris

I've got a little suggestion for a new graphics command (actually a group of them), which if I remember rightly can be found in qbasic. It is for arcs and sectors of circles and possibly ellipses too, further to full and filled circles and ellipses. You have the same arguments as before - Xpos, Ypos, Radius (X and Y for ellipses), FillMode, optionally Colour - but you also have a start angle and an end angle, for which a starting point would have to be defined, e.g. the vertical. With these commands, you could draw the mouth of a smiley face using the following:

sector xpos, ypos, rad, 0, 90, 270

And pacman using the following:

sectorC xpos, ypos, rad, 1, yellowrgb, 135, 45

What do you think?

kevin

#12
@bmorris,

    Thanks for the suggestion and it does seem doable,  but requests really shouldn't be in these threads.  They just get lost and quickly forgotten.    V1.64P is almost entirely focused on changes required for  PlayBASIC to DLL

    So it's better to put such things in the Request Boards (login required)  (See FAQ (login required))


bmorris

Oh dear, the existence of that subforum had slipped me by! If the idea does get forgotten, I'll repost it there ahead of 1.65 or later.

kevin


   PlayBASIC V1.64P Beta 19/20

             The V1.64P revision has only had a few changes late last year, none of them were really user related (just the odd tweak for how PB and PlayBASIC 2 DLL communicate) ,  although tonight i've been looking over the GetArray and SetArray commands.   These are a way a user can access arrays through a stub array.   So if you create a stub (and array with no data of it's own) via MakeArray, you can copy the 'pointer/buffer' from any other array into the stub via getting that arrays index via GetArray and then setting it via SetArray.    The array indexes are linear, so you can actually write code that runs through a block of similar arrays without having to pass them.    The process is basically the same as how and array is passed into a function or psub anyway.. 


 
PlayBASIC Code: [Select]
    Dim Table(100)
Dim Table2(1000)


; make a stub array called Me()
MakeArray Me()


; Me() now contains a copy of buffer that Table() officially owns
SetArray Me(), GetArray(Table())


; see me is now 100 elements in size
Print GetArrayElements(Me())


; put some data in table are indexes 0,1,2
Table(0) = 111
Table(1) = 222
Table(2) = 333

; show what me()'s looking at
print Me(0)
print Me(1)
print Me(2)

Sync
waitkey





        While working on PlayBASIC to DLL noticed the GetARRAY function can be pre computed at compile time, currently there's actually a library function that preforms the rather trivial calculation at runtime.    SetArray is little more difficult as it's scope aware, which is fine for the VM environment, but a little difficult in translated version, without piping all the compile time data into the DLL, which i'm not too keen on.   Originally the SetArray would let you set and get between any array regardless of scope.  I forget why it was changed, but have a feeling that could well get reverted at some point in the near future :)