Shop OBEX P1 Docs P2 Docs Learn Events
New BASIC compiler for Prop1 and Prop2 - Page 2 — Parallax Forums

New BASIC compiler for Prop1 and Prop2

2456720

Comments

  • My wish is probably more of a driver/object thing but to be able to handle Modbus and BiSS-C would make the Prop very attractive to the process control world.
  • Mickster wrote: »
    My wish is probably more of a driver/object thing but to be able to handle Modbus and BiSS-C would make the Prop very attractive to the process control world.

    Yeah, that's definitely a driver/object issue. Are there already Spin drivers for these? If so my BASIC will be able to import them and you could use them directly.

    @jmg: Thanks for the examples. I like the idea of having OPEN call a "driver" function that'll return a handle that can be used to re-vector the PRINT and INPUT routines. So something like:
      OPEN SerialDriver(outpin, inpin, baud) AS #1
    
    I guess ideally we would allow functions to return classes, so a SerialDriver that uses Spin FullDuplexSerial could be defined something like:
    #include "propdriver.bi"
    
    class fullduplexserial input "FullDuplexSerial.spin"
    
    ' the Spin object we will wrap
    dim myser as fullduplexserial ptr
    ' the BASIC driver object
    dim mydriver as IODriver ptr
    
    ' function to be called by Open
    function SerialDriver(outpin, inpin, baud) as IODriver ptr
      ' create a new Spin object and start it up
      myser = new fullduplexserial
      myser.start(outpin, inpin, 0, baud)
      ' now create the BASIC driver to wrap it
      mydriver = new Driver
      ' tell the driver which methods to use for input and output
      mydriver.setoutputmethod(@myser.tx)
      mydriver.setinputmethod(@myser.rx)
      return mydriver
    
  • jmgjmg Posts: 15,140
    edited 2018-09-07 03:32
    ersmith wrote: »
    @jmg: Thanks for the examples. I like the idea of having OPEN call a "driver" function that'll return a handle that can be used to re-vector the PRINT and INPUT routines. So something like:
      OPEN SerialDriver(outpin, inpin, baud) AS #1
    

    FreeBASIC also allows this form too, be nice to support that as well ?
      OPEN SerialDriver(outpin, inpin, baud) AS Const_Name
      PRINT #Const_Name,"Text"
    


    Attached below is more experiments with emulate/simulate of the Prop CNT & WAITCNT as Subroutines/Functions.
    If you can tolerate that syntax, RdCNT(), WAITCNT(WayPoint) look to emulate quite well.
    Addit - just checked and FreeBASIC seems to also tolerate no brackets RdCNT, WAITCNT WayPoint

    I took 1.0000s wait code from Bean's SimpleFreqency Counter and coded a FreeBASIC precision version, that hopefully snaps to 80MHz SysCLKs, in uInt32
    I found via experimenting that Windoze needs a round-down margin on the sleep, of around 21ms, as it likely is Sys Tick coarse.
    Seems to work ok in Win10, 32b & 64b compilers. Be interesting to see if it works on Linux ?

    Table at the end is the reported 1.000 second delay, and the PollCheck loop counter.
    'http://www.freebasic.net/wiki/wikka.php?wakka=KeyPgOpenCom 
    ' "COMn: [ baudrate ][ , [ parity ][ , [ data_bits ][ , [ stop_bits ][ , [ extended_options ]]]]]"
    '    where,
    ' n
    '   Com port to open. "1", "2", "3", "4", etc. Some platforms will support more serial ports depending on how the operating system is configured. 
    '   Where n is not given, "COM:" will map to "COM1:", except on Linux where "COM:" maps to "/dev/modem" 
    'baudrate
    '   "300" (default), "1200", ..., etc.
    'parity
    '   "N" (none), "E" (even, default), "O" (odd), "S" (space), "M" (mark), "PE" (QB-quirk: checked, even parity)
    'data_bits
    '   "5", "6", "7" (default) or "8".
    'stop_bits
    '  "1", "1.5" or "2". (default value depends on baud rate and data bits, see table below)
    'extended_options  Miscellaneous options. (See table below)
    '
    'Option	Action
    ' 'CSn'	Set the CTS duration (in ms) (n>=0), 0 = turn off, default = 1000
    ' 'DSn'	Set the DSR duration (in ms) (n>=0), 0 = turn off, default = 1000
    ' 'CDn'	Set the Carrier Detect duration (in ms) (n>=0), 0 = turn off
    ' 'OPn'	Set the 'Open Timeout' (in ms) (n>=0), 0 = turn off
    ' 'TBn'	Set the 'Transmit Buffer' size (n>=0), 0 = default, depends on platform
    ' 'RBn'	Set the 'Receive Buffer' size (n>=0), 0 = default, depends on platform
    ' 'RS'	Suppress RTS detection
    ' 'LF'	Communicate in ASCII mode (add LF to every CR) - Win32 doesn't support this one
    ' 'ASC'	same as 'LF'
    ' 'BIN'	The opposite of LF and it'll always work
    ' 'PE'	Enable 'Parity' check
    ' 'DT'	Keep DTR enabled after CLOSE
    ' 'FE'	Discard invalid character on error
    ' 'ME'	Ignore all errors
    ' 'IRn'	IRQ number for COM (only supported (?) on DOS)
    
    
    #include "windows.bi"
    #include "file.bi"
    
    Declare Function RdCNT() As uinteger
    Declare Sub WAITCNT (WaitForwardValue As uinteger)
    
    
    dim as HANDLE h
    dim as COMMPROP cp
    dim as integer res,wb
    Dim b As String
    Dim n as Long
    ' COM4 is SiLabs CP2102N
    ' COM5 is Nuvoton VCP
    Const AS Long cCom = 16
    
    
    ' If Open Com ("com1:9600,n,8,1,cs,rs,ds,bin" For Binary As #1) <> 0 Then
    'If Open Com ("com5:3906,n,8,1,cs,rs,ds,bin" For Binary As #1) <> 0 Then  '3906 is lowest baud for 16MHz/16/256
    ' if open com ( "COM5:9600,N,8,1,DS,TB32000,RB32000" for binary as #1 ) <> 0 then
    ' if open com ( "COM4:9600,N,8,1,DS,TB32000,RB32000" for binary as #1 ) <> 0 then
    If Open Com ("COM16:115200,n,8,1,cs0,rs,ds0,cd0,bin,op2000,TB32000,RB32000" For Binary As cCom) <> 0 Then  'generic baud 
      n = Err()
      Print "unable to open serial port, (press any key) Error Code: ";n
      Sleep
      End
    else
      n = Err()
      Print "No error on Open Com, Error Code: "; n  'always 0 ?
    End If
    h = cast(HANDLE, FileAttr(cCom, fbFileAttrHandle))
    
    if( GetCommProperties( h, @cp ) = 0 ) then
      print "GetCommProperties(): Error "; GetLastError()
    else
      print "dwCurrentTxQueue: "; cp.dwCurrentTxQueue  ' always reports 0, 16384 for Nuvoton or 0,640 for CP2102N ????
      print "dwCurrentRxQueue: "; cp.dwCurrentRxQueue ' not quite how example http://www.freebasic.net/forum/viewtopic.php?t=6172&highlight=transmit+timeout claims ??
      print "cp.dwMaxBaud: ";     cp.dwMaxBaud
      print "cp.dwSettableBaud: ";     cp.dwSettableBaud
      print "cp.wSettableData: ";     cp.wSettableData
      print "cp.dwMaxTxQueue: ";cp.dwMaxTxQueue
      print "cp.dwMaxRxQueue: ";cp.dwMaxRxQueue
      print "cp.dwSettableParams: ";cp.dwSettableParams
    end if
    
    res=PurgeComm(h,PURGE_TXCLEAR)'clear Write only
    print "Purge res: ";res
    
    
    Print "Sending command: AT+CrLf"
    
    'Print #cCom, "AT" + Chr(13, 10);
    Print #cCom, "UUUU";    ' 4  char ?
    Print "Response: (queue.0) = ";LOC(cCom)
    
    Sleep 500,1
    
    Print "Response: (queue.500) = ";LOC(cCom)
    
    While( LOC(cCom) > 0 )
      Input #cCom, b
      Print b;
    Wend
    Close #cCom
    
    
    ' If the processor has a precision timer (as the Performance Counter Pentium processors from Intel have) and the OS uses it, 
    ' the precision is linked to the processor clock and microseconds can be expected. 
    
    ' Var f  = Cast(Double, 0.0) also supported
    Const As Double tP1_CLK = 1/80.0e6                ' Period of PropSysCLK
    Const As Uinteger FREQ =  80000000
    Const As Uinteger ONESEC = FREQ + 4 
    Const As Uinteger t1ms = CUint(.001/(1/80.0e6))   ' Sysclks in 1ms 
    
    Dim Shared As Double StartD,EndD
    Dim Shared as uinteger PollCheck
    
    Var Start = Timer()       ' Auto-selects double type ? (64b real)
    
    
    Print "chars to screen ",(Timer-Start)/tP1_CLK   ' delays in P1 sysclocks 
    Print "chars to screen ",(Timer-Start)/tP1_CLK
    Print "chars to screen ",(Timer-Start)/tP1_CLK
    Print "t1ms ",t1ms
    
    Print "Start WAITCNT, ", ONESEC
    Var LoopC = 0
    WHILE LoopC < 60 
      Var WayPoint = RdCNT() + ONESEC       ' Uinteger Prop CNT walk-ahead, for WAITCNT
      Var StartT = Timer()  
      WAITCNT(WayPoint)                     ' Close to Prop WAITCNT
      Var EndT = Timer()   
      Print " END WAITCNT",EndT-StartT, EndD-StartD, PollCheck
      LoopC = LoopC +1 
    WEND  
    Sleep    ' press any key to exit 
    
    
    Function RdCNT()  As uinteger
      return CUint(Timer/tP1_CLK)
    end function
    
    Sub WAITCNT (WaitForwardValue As uinteger)
      VAR SleepRounded = ((WaitForwardValue-RdCNT())/t1ms)-21   ' 20ms OK, Experimental trim-down, need finite loops 16,18ms fail 19ms is marginal, choose 21ms - test on other PC's ?
      if SleepRounded >= 0 then 
        Sleep(SleepRounded)  'round down, so most of time is Sleep, 
      end if  
      Var AbsDiff = ABS(WaitForwardValue-RdCNT() )     ' 99% of time this is small, but in rare cases, RdCNT will be MAX, and WaitForwardValue will have wrapped 
      PollCheck = 0
      StartD = Timer()
      While AbsDiff >= ABS(WaitForwardValue-RdCNT() )  ' look for reversal of setpoint diff, diff decreases until it hits match, then starts to increase.
       AbsDiff = ABS(WaitForwardValue-RdCNT() )
       PollCheck = PollCheck + 1
      wend 
      EndD = Timer()
    end Sub
    
    '  While (RdCNT() < WaitForwardValue )    ' finer timing for the last fractional bit ok in 32b, !BUT! this can exit early on wrap case, might not matter, as it's a few ms ?
    '  While (CDbl(RdCNT()) < CDbl(WaitForwardValue) )    ' finer timing for the last fractional bit , but also not wrap proof
    
    
    ' UUUUchars to screen          0.0003803819417953491 Timer resolves to fractional ms, 
    ' chars to screen              0.0007216352969408035
    ' chars to screen              0.001131524331867695
    ' press any key
    '  
    ' UUUUchars to screen          11058.67326259613  scaled as P1_SysCLKs
    ' chars to screen              32123.99780750275
    ' chars to screen              98706.89362287521
    
    
    
    ' Sleep -20ms     1 Second                  Poll dT                    PollCheck 
    ' END WAITCNT   1.0000019245781             0.0008463980630040169      5058
    ' END WAITCNT   1.000000320840627           0.001199839171022177       7155
    ' END WAITCNT   1.000003849156201           0.001386181451380253       7402
    ' END WAITCNT   1.000000641681254           0.0008810367435216904      5267
    ' END WAITCNT   1.000000320840627           0.0007209940813481808      4193
    ' END WAITCNT   1.000001282896847           0.0007909121923148632      3654
    ' END WAITCNT   1.000000641215593           0.001452892553061247       17501
    ' END WAITCNT   1.000000320840627           0.0008095144294202328      4838
    ' END WAITCNT   1.000000641215593           0.0005359346978366375      6005
    ' END WAITCNT   1.000000320840627           0.001278417184948921       7492
    ' END WAITCNT   1.000001924112439           0.0006940527819097042      4148
    ' END WAITCNT   1.000000320840627           0.0009403713047504425      5621
    ' END WAITCNT   1.00000096205622            0.001378804445266724       7303
    ' END WAITCNT   1.000000320840627           0.001177388243377209       14496
    ' Sleep -21ms  - appears to have 1-2ms headroom.
    ' Start WAITCNT,              80000004
    '  END WAITCNT   1.000000320840627           0.002297687344253063       27818
    '  END WAITCNT   1.000000320374966           0.002082479186356068       25214
    '  END WAITCNT   1.000002565793693           0.002000694163143635       11840
    '  END WAITCNT   1             0.001514151692390442       18941
    '  END WAITCNT   1             0.002052330877631903       25466
    '  END WAITCNT   1             0.00162897165864706        19920
    '  END WAITCNT   1             0.002414110582321882       27283
    '  END WAITCNT   1.000000320840627           0.002109741326421499       23042
    '  END WAITCNT   1.000000320840627           0.001878176350146532       22379
    '  END WAITCNT   1             0.002435599453747273       22901
    '  END WAITCNT   1.000000641215593           0.002007750328630209       11925
    '  END WAITCNT   1.000001282896847           0.002022824250161648       24741
    '  END WAITCNT   1.000000641215593           0.001587918493896723       19425
    '  END WAITCNT   1.00000096205622            0.002033408265560865       12133
    '  END WAITCNT   1             0.002054576296359301       24889
    '  END WAITCNT   1.000000320840627           0.002412828151136637       14408
    '  END WAITCNT   1.000000320840627           0.002099157311022282       12525
    '  END WAITCNT   1.00000288663432            0.001507736742496491       16864
    '  END WAITCNT   1             0.001880421303212643       11226
    '  END WAITCNT   1             0.002069971058517695       25527
    '  END WAITCNT   1.000000320840627           0.002303139306604862       28354
    '  END WAITCNT   1.000000320840627           0.00224508810788393        21464
    '  END WAITCNT   1.000001282896847           0.002430467866361141       27165
    '  END WAITCNT   1.000000320840627           0.001630575396120548       19473
    '  END WAITCNT   1.000000320840627           0.001637310720980167       19703
    '  END WAITCNT   1.000001924112439           0.001506453845649958       8988
    '  END WAITCNT   1.000001282896847           0.002158171031624079       12899
    '  END WAITCNT   1             0.001809541136026382       10801
    '  END WAITCNT   1.000001924112439           0.001496831886470318       8867
    '  END WAITCNT   1.000002565793693           0.001582145225256681       9410
    '  END WAITCNT   1.000000641681254           0.002288706600666046       13382
    '  END WAITCNT   1.000001282896847           0.002237069886177778       13238
    '  END WAITCNT   1             0.001288359519094229       15476
    '  END WAITCNT   1.000000320374966           0.002285178750753403       25487
    '  END WAITCNT   1             0.001534357201308012       18901
    '  END WAITCNT   1             0.002390056382864714       14153
    '  END WAITCNT   1.000000320840627           0.002082800026983023       12427
    '  END WAITCNT   1             0.001740584615617991       21381
    '  END WAITCNT   1.000000320840627           0.002255672123283148       13461
    '  END WAITCNT   1.000001282896847           0.002162340562790632       23436
    '  END WAITCNT   1             0.002442976459860802       14312
    '  END WAITCNT   1.000000320840627           0.00232334528118372        13768
    '  END WAITCNT   1             0.002074782270938158       11472
    '  END WAITCNT   1.000001603737474           0.001473418902605772       7573
    '  END WAITCNT   1.000001282896847           0.001449364703148603       17849
    '  END WAITCNT   1.000000641681254           0.00186117785051465        10907
    '  END WAITCNT   1.000001603737474           0.002372095827013254       13954
    '  END WAITCNT   1             0.00146379740908742        8754
    '  END WAITCNT   1.000002245418727           0.002245408948510885       13275
    '  END WAITCNT   1.000000320840627           0.002404168248176575       29444
    '  END WAITCNT   1.000001282896847           0.001857329159975052       11083
    '  END WAITCNT   1.00000096205622            0.002300573512911797       28658
    '  END WAITCNT   1.000000641681254           0.001931417267769575       11456
    '  END WAITCNT   1.000001282896847           0.001985619775950909       11653
    '  END WAITCNT   1.000000320840627           0.002100440207868815       26394
    '  END WAITCNT   1.0000019245781             0.002055859193205833       25121
    '  END WAITCNT   1.00000096205622            0.002381717786192894       29307
    '  END WAITCNT   1.000000320840627           0.001577334478497505       19569
    '  END WAITCNT   1.000000320840627           0.002189281396567822       20885
    '  END WAITCNT   1             0.001560336444526911       19085
    
    

  • I've thought about it some more and I think we'll need the garbage collector after all -- if not for strings, then for driver objects (like the full duplex serial wrapper I posted earlier). It'll also simplify things immensely if strings are just pointers to character (as in Spin and C). The major annoyance with a mark-and-sweep collector is finding the references, so we'll have to guarantee that dynamic pointers are stored in HUB memory. If we're not optimizing at all this is trivial (all the local variables will end up on the stack in HUB memory) but this will require some work for the optimized case where pointers are in COG memory.

    The tough part is that the failure mode (we run out of memory and garbage collect in the middle of some operation where a temporary is in a register but not stored in HUB yet) is going to be rare and hard to test.

    I guess for the single COG case it wouldn't be too hard to scan COG memory for pointers, but for multi-threaded programs I don't know how we can do this. On P2 we could interrupt all the COGs and tell them to scan their own memory for pointers, but for P1 we'd have to somehow arrange for COGs running the BASIC code to poll periodically. Maybe the LMM loop could check for a flag, but that seems painful for such a rare case (and also precludes FCACHE).

    Any ideas?
  • @jmg thanks again for the sample code, it gives some good inspiration. I do want to warn that I don't regard FreeBasic compatibility as a firm requirement -- I want it to be compatible in a general sense, but there are going to be some things in my basic that don't exist in FreeBasic and vice-versa. You have shown that debugging code on the PC is feasible, so definitely I'd like to keep the ability to write useful code in a common subset of the languages.

    A few differences that exist already:

    (1) There are some Prop specific pseudo-arrays, input(), output(), and direction(), which correspond to the INA, OUTA, and DIRA registers (so you can say something like "output(1) = 1" to set pin 1 high). That's going to be platform specific no matter what, so I think it'll always be hidden by #ifdefs

    (2) I think FreeBasic treats A$ and A as the same identifier. I'd rather not do that -- my parsing code treats the type flag at the end of an identifier as part of the name. That's the way I remember Microsoft BASIC working back in the day, and it seems more natural to me.

    (3) Right now I ignore underscores in identifiers, to match the way they are ignored in numbers. I'm not sure if FreeBasic does that.

    Having said all that, I think I've made progress towards getting useful code running. I was able to run a Fibonacci test today:
    dim as integer r, t
    
    print "hello, world"
    
    function fibo(n)
      if (n < 2) then
        return n
      else
        return fibo(n-1) + fibo(n-2)
       end if
    end function
    
    for i = 1 to 8
      t = getcnt()
      r = fibo(i)
      t = getcnt() - t
      print "fibo(", i, ") = ", r, "  took ", t, " cycles"
    next
    

    this produced the output:
    hello, world
    fibo(1) = 1  took 576 cycles
    fibo(2) = 1  took 1504 cycles
    fibo(3) = 2  took 2432 cycles
    fibo(4) = 3  took 4288 cycles
    fibo(5) = 5  took 7072 cycles
    fibo(6) = 8  took 11712 cycles
    fibo(7) = 13  took 19136 cycles
    fibo(8) = 21  took 31200 cycles
    

    The fibo(8) time of 31200 cycles compares to 31072 cycles for fastspin, 10992 cycles for PropGCC LMM, 58800 cycles for PropGCC CMM, and 137360 cycles for regular Spin.
  • That timing is impressive. Can you show the amount of memory used (hub and/or cog) for each. I am particularly interested in comparisons with PropGCC LMM and CMM.

    Is the code you showed compiled into PASM and fit into a cog? If so how would you treat large programs.

    Thanks
    Tom

  • The BASIC compiler creates LMM code by default, just like fastspin and PropGCC (in LMM mode). It is possible to create COG code too. The COG version is 800 bytes long (total) and takes 9140 cycles for fibo(8).

    Breaking the sizes down into hub/cog for all of these is a lot of work, and probably not too useful for such a small demo. But the total sizes for LMM are:
    Spin        960 bytes
    fastbasic  1124 bytes
    fastspin   1888 bytes
    GCC CMM    1920 bytes
    GCC LMM    6172 bytes
    

    The size difference is almost all in the I/O libraries. The C version is pulling in printf, which adds a lot of overhead. Most of the size in the Spin and fastspin versions is associated with the FullDuplexSerial object. "fastbasic" (what I'm calling it for now, since it's based on fastspin) has a very tiny I/O library right now which saves space, but it's likely to grow as more features are added.

    The actual recursive fibo function compiles to 100 bytes in both fastspin and fastbasic; this is also the same as Catalina C in LMM mode. PropGCC needs only 84 bytes in LMM, 26 bytes in CMM. In Spin it's 25 bytes.

    I don't have a recursive version of fibo for PropBasic because PropBasic has very limited support for recursion (it has no local variables and quite a restrictive expression syntax). But I in general I expect it would generate pretty similar code to my BASIC for this kind of function, which is very straightforward. Spin's smaller size is due to its having a stack based bytecode interpreter, which is pretty much ideal for this kind of code. GCC has some fancy optimizations which reduce the recursion inside fibo(), and which also reduces the size needed. Otherwise I'd expect any straightforward LMM translation of the function to be about 100 bytes long.
  • jmgjmg Posts: 15,140
    ersmith wrote: »
    I don't have a recursive version of fibo for PropBasic because PropBasic has very limited support for recursion (it has no local variables and quite a restrictive expression syntax). But I in general I expect it would generate pretty similar code to my BASIC for this kind of function, which is very straightforward. Spin's smaller size is due to its having a stack based bytecode interpreter, which is pretty much ideal for this kind of code. GCC has some fancy optimizations which reduce the recursion inside fibo(), and which also reduces the size needed. Otherwise I'd expect any straightforward LMM translation of the function to be about 100 bytes long.

    An interesting PropBasic comparison, could be to port Bean's Frequency Counters (simple, and Reciprocal) ?

  • jmgjmg Posts: 15,140
    ersmith wrote: »
    (1) There are some Prop specific pseudo-arrays, input(), output(), and direction(), which correspond to the INA, OUTA, and DIRA registers (so you can say something like "output(1) = 1" to set pin 1 high). That's going to be platform specific no matter what, so I think it'll always be hidden by #ifdefs
    Yes, there will always be #ifdefs needed.
    ersmith wrote: »
    (2) I think FreeBasic treats A$ and A as the same identifier. I'd rather not do that -- my parsing code treats the type flag at the end of an identifier as part of the name. That's the way I remember Microsoft BASIC working back in the day, and it seems more natural to me.

    Default FreeBASIC gives this error, as the suffix $ is deprecated, but I think you can tolerate it with a switch.
    COM4_Test.bas(45) error 147: Suffixes are only valid in -lang deprecated or fblite or qb, found 'b' in 'Dim b$ As String'
    
    ersmith wrote: »
    (3) Right now I ignore underscores in identifiers, to match the way they are ignored in numbers. I'm not sure if FreeBasic does that.
    FreeBASIC coughs on 80_000_000, but ignoring underscores inside names seems a little strange/risky to me, as it's a valid asciii char.
    That said, I do not use underscores in VAR names much, but they are rather more common in file names.

  • jmg wrote: »
    ersmith wrote: »
    (3) Right now I ignore underscores in identifiers, to match the way they are ignored in numbers. I'm not sure if FreeBasic does that.
    FreeBASIC coughs on 80_000_000, but ignoring underscores inside names seems a little strange/risky to me, as it's a valid asciii char.
    That said, I do not use underscores in VAR names much, but they are rather more common in file names.

    Ah, I see. For now fastbasic accepts (and ignores) underscores inside numbers and inside variable names. In strings such as file names of course every character is kept and valid.

    For example, SomeVar, Some_Var, somevar, and some_var all refer to the same variable name.

    That's probably going to be the most controversial quirk, but I really think if your variables are case insensitive then ignoring underscores makes sense too. (The other logical alternative is to be like C and treat all characters as literal ASCII, so "A" and "a" are different variables.) If there's a lot of pushback I could change that (or make it an option).

    Ignoring underscores inside numbers is a Spin feature I really like, and shouldn't break anything.

    Eric
  • jmgjmg Posts: 15,140
    ersmith wrote: »
    Ignoring underscores inside numbers is a Spin feature I really like, and shouldn't break anything.

    Yes, a nice feature that's common in microcontroller space, and I've posted a Feature Request for underscores in numbers in the FB forum.

  • Making some more progress. I've got most integer features implemented now, although there's still some work to do on properly mixing unsigned and signed variables. I've added some pseudo-arrays for the input, output, and direction bits. For example, a program to toggle 3 pins is:
    rem simple program to toggle a pin
    
    const lopin = 16
    const hipin = 18
    
    let mscycles = clkfreq / 1000
    
    direction(lopin,hipin) = output
    
    do
      output(lopin,hipin) = &b101
      pausems 500
      output(lopin,hipin) = &b010
    loop
    
    sub pausems ms
      waitcnt(getcnt() + ms * mscycles)
    end sub
    

    @yeti has been able to get a mandelbrot program ported to the git version of fastspin/basic, which is pretty amazing given how sparse the documentation is so far -- kudos to him!
  • I'm still trying to figure out what to call this thing, which is a compiler that can handle both Spin and BASIC. Names I've toyed with:

    (a) fastspin: that's what it's called now, but obviously that's kind of leaving out the BASIC part from the name, so not very good!

    (b) multiprop: Multiple language compiler for Propeller. The various language dialects would be MultiSpin, MultiBASIC, etc. There was a MultiBASIC for the ZX Spectrum, but that was many years ago, so I don't think there'd be much confusion.

    (c) guppy: short for "Grand Unified Propeller Programming sYstem". The dialects would be "Guppy BASIC", "Guppy Spin", etc. Seems a bit friendlier than "multiprop", but not as professional.

    Any opinions? Other suggestions?
  • Dave HeinDave Hein Posts: 6,347
    edited 2018-09-11 01:00
    Baspin

    EDIT: Forget Baspin. The urban dictionary says it's slang for stinking, filthy, dirty or diseased. Also, there's a company named Baspin in a Spanish speaking country that makes protective gloves.
  • Dave Hein wrote: »
    Baspin

    EDIT: Forget Baspin. The urban dictionary says it's slang for stinking, filthy, dirty or diseased. Also, there's a company named Baspin in a Spanish speaking country that makes protective gloves.

    Heh heh... guess we'll cross that one off the list then :). Thanks for checking though.

    Also, I'd like to avoid restricting it to just the two languages BASIC and Spin. Over time there may be some more languages added. You'll notice that the "basic" branch has 3 directories inside "frontends/" :).
  • ersmith wrote: »
    Dave Hein wrote: »
    Baspin

    EDIT: Forget Baspin. The urban dictionary says it's slang for stinking, filthy, dirty or diseased. Also, there's a company named Baspin in a Spanish speaking country that makes protective gloves.

    Heh heh... guess we'll cross that one off the list then :). Thanks for checking though.

    Also, I'd like to avoid restricting it to just the two languages BASIC and Spin. Over time there may be some more languages added. You'll notice that the "basic" branch has 3 directories inside "frontends/" :).
    How about Lisp? :smile:

  • ersmith wrote: »
    I'm still trying to figure out what to call this thing, which is a compiler that can handle both Spin and BASIC. Names I've toyed with:

    (a) fastspin: that's what it's called now, but obviously that's kind of leaving out the BASIC part from the name, so not very good!

    (b) multiprop: Multiple language compiler for Propeller. The various language dialects would be MultiSpin, MultiBASIC, etc. There was a MultiBASIC for the ZX Spectrum, but that was many years ago, so I don't think there'd be much confusion.

    (c) guppy: short for "Grand Unified Propeller Programming sYstem". The dialects would be "Guppy BASIC", "Guppy Spin", etc. Seems a bit friendlier than "multiprop", but not as professional.

    Any opinions? Other suggestions?

    Guppy sounds good to me, unless folks are allergic to fish...
  • jmgjmg Posts: 15,140
    ersmith wrote: »
    I'm still trying to figure out what to call this thing, which is a compiler that can handle both Spin and BASIC.
    and also PASM & PASM2 ?
    ersmith wrote: »
    Names I've toyed with:

    (a) fastspin: that's what it's called now, but obviously that's kind of leaving out the BASIC part from the name, so not very good!
    yes, that leaves too much on the table

    ersmith wrote: »
    (c) guppy: short for "Grand Unified Propeller Programming sYstem". The dialects would be "Guppy BASIC", "Guppy Spin", etc. Seems a bit friendlier than "multiprop", but not as professional.
    I find a quick run past urban dictionary can give a guide to how a name might come across in the wider world contexts... and guppy does not stack up well.
    ersmith wrote: »
    (b) multiprop: Multiple language compiler for Propeller. The various language dialects would be MultiSpin, MultiBASIC, etc. There was a MultiBASIC for the ZX Spectrum, but that was many years ago, so I don't think there'd be much confusion.
    'Multi' is somewhat overused, but I think there is merit in what IEC61131 does, which is include multiple formal language arms. ( tho the core name of IEC61131-3 is the total opposite of snappy/cool the Any+Mix nature is great)

    That could lead to
    "Want to Mix Any Language on Any cores ? - use MixAny.BASIC, MixAny.Spin, MixAny.PASM ! " (Could you do MixAny .Blockly?)

    The 'Spin' name itself I am still two minds over. Mind pollution crossover from the Corporate/Political/Media universes mean 'Spin' is more tarnished every year.
    Spin also desperately needs a cleanse pass, but should the output result of that exercise still be called Spin, or should spin be deprecated ?


  • David Betz wrote: »
    How about Lisp? :smile:

    That would be an interesting challenge! I have no idea how to go about compiling Lisp to machine language. Handling eval, in particular, seems like it would be tricky. Obviously it's possible since there are native code Lisp compilers out there, like Chicken Scheme. Is compiling to C or PASM something you've looked at?

  • jmg wrote: »
    ersmith wrote: »
    I'm still trying to figure out what to call this thing, which is a compiler that can handle both Spin and BASIC.
    and also PASM & PASM2 ?
    I thought PASM was defined as "the stuff in a DAT section inside a Spin file"? I guess there's some potential confusion, but yeah, fastspin+basic can handle everything in Spin, including the PASM/PASM2 inside DAT (and the somewhat limited PASM/PASM2 inside an ASM/ENDASM block).
    I find a quick run past urban dictionary can give a guide to how a name might come across in the wider world contexts... and guppy does not stack up well.
    There are certainly worse out there :)
    That could lead to
    "Want to Mix Any Language on Any cores ? - use MixAny.BASIC, MixAny.Spin, MixAny.PASM ! " (Could you do MixAny .Blockly?)

    Intestesting idea. I hadn't thought of the "mix" angle of mixing languages, but something along those lines seems promising.

    (Blockly is a whole other can of worms, but I think Blockly can be converted to Spin can't it?)
    The 'Spin' name itself I am still two minds over. Mind pollution crossover from the Corporate/Political/Media universes mean 'Spin' is more tarnished every year.
    Spin also desperately needs a cleanse pass, but should the output result of that exercise still be called Spin, or should spin be deprecated ?

    Wow, you've given me a great idea -- the new compiler is not Spin, so perhaps it should be called PINS (recursively "PINS Is Not Spin"). Then we'd have PINS Basic, PINS Pascal, etc... not sure what to call the default Spin based dialect, "PINS Spin" doesn't really sound right. Maybe "PINS Original".
  • yetiyeti Posts: 818
    edited 2018-09-11 10:24
    The naming problem:
    Put Spin, PASM, BASIC, ... in your "blender" and run the resulting smoothie on your Propeller...
    Ok... to avoid conflicts with the animation program "blender", "propblender" may be better?
    Is there another compact word for a smoothie-maker?
    The next generation of Propeller loaders should accept ".smoothie" as alternative to ".binary" too... ;-)
  • jmgjmg Posts: 15,140
    ersmith wrote: »
    I thought PASM was defined as "the stuff in a DAT section inside a Spin file"? I guess there's some potential confusion...

    hehe, Yes that's how it's 'managed' now, archaic & clunky, and which creates massive wider industry confusion amongst those who are well-used to the file-extension indicates file contents norm .C/.ASM/.LST/.MAP/.BAS/.PAS/.PY


  • ersmith wrote: »
    David Betz wrote: »
    How about Lisp? :smile:

    That would be an interesting challenge! I have no idea how to go about compiling Lisp to machine language. Handling eval, in particular, seems like it would be tricky. Obviously it's possible since there are native code Lisp compilers out there, like Chicken Scheme. Is compiling to C or PASM something you've looked at?
    I haven't really done anything other than compilers that target byte code VMs that I defined myself. I'm thinking of writing a PASM code generator for the C-like language I'm working on now though.
  • SPASIC?

    It seems that the very hint of the name BASIC, turns people off and today, the acronym no-longer applies.

    I am sure that there would be many more adopters of PropBasic if it had been named PASM-RAD or something similar.
  • BeanBean Posts: 8,129
    I have to agree with Mickster.
    Put the word BASIC in the name of a language, and it is sure to be ignored by...Pretty much everyone.

    Bean
  • jmgjmg Posts: 15,140
    Bean wrote: »
    I have to agree with Mickster.
    Put the word BASIC in the name of a language, and it is sure to be ignored by...Pretty much everyone.

    Yes and no.
    This is not just a single language, it is a development flow offering many flows into many cores (well, cores in one die, & I guess it could actually manage 2 die or 4 die projects ?)

    The development flow needs the catchy name.
    I think it's fine to keep BASIC, and 'can be compatible with FreeBASIC' is a solid enough cornerstone, it's not treated as a banner item.
    No one thinks ASM is sexy, but everyone prefers a microcontroller system that can do it when they need it.
    eg IEC61131 uses the totally deadpan LD FBD ST IL SFC internal language flow names

    ersmith wrote: »
    That could lead to
    "Want to Mix Any Language on Any cores ? - use MixAny.BASIC, MixAny.Spin, MixAny.PASM ! " (Could you do MixAny .Blockly?)

    Interesting idea. I hadn't thought of the "mix" angle of mixing languages, but something along those lines seems promising.

    (Blockly is a whole other can of worms, but I think Blockly can be converted to Spin can't it?)

    This raises a very good systems question


    I don't know Blockly needs to be fully converted, just easily co-operated with.

    eg Something like an include file 'rosterboard/table' for any CORE on the chip you link to. (usually this is 8, but it seems 2,3,4 dice here is actually just a bigger form)

    What file needs to be downloaded-once eg 5 cores may enter the same file name, and a can-single-build project would have a single download file.

    *Size & Where it goes if not already in file
    *HUB resource it expects as own : Address and die#
    *Interface rules : Named variables and FIFOs : address and die#

    that becomes like a poor mans linker, you co-operate on the big resource pieces.

  • ersmith wrote: »
    (Blockly is a whole other can of worms, but I think Blockly can be converted to Spin can't it?)
    Blockly produces C code so you should be able to handle it if you support C.

  • @jmg I dunno, I think that FreeBASIC appeals to those who already realise that BASIC has not been Beginners All-purpose Symbolic Instruction Code since QuickBASIC and TurboBASIC appeared, back in the 80's.
    It seems to have picked up where PowerBASIC left off after the death of Bob Zale.

    The problem is that we are stuck with the stigma of line numbers and GOTOs, resulting in spaghetti code due to ignorance.

    Today I use:
    QuickBASIC
    PowerBASIC
    RFO BASIC (Android interpreter)
    B4A (BASIC for Android compiler)
    Micromite
    Bypic (BASIC/C hybrid)
    PropBasic

    The only GOTO that I have ever used is with PropBasic because it translates directly to jmp.

    After 33 years of using this language which resulted in a 80-employee business, other programmers still attempt to ridicule my choice of programming language.
    If I was using slow, clunky Python, I would be totally cool.

    For me, PropBasic is high level PASM with a BASIC-like syntax.
  • jmgjmg Posts: 15,140
    Mickster wrote: »
    ....
    After 33 years of using this language which resulted in a 80-employee business, other programmers still attempt to ridicule my choice of programming language.
    ..
    Hehe yes, there are always reflex dinosaurs, but amongst the thinking programmers, many are at least basic aware.

    Over in AVR land, someone was asking about his customer who was asking about adding a BASIC script, into their existing 'plc like' custom controller based on a MegaAVR and project developed in C.
    Does not sound like cheap plant or equipment.

    No one said the customer was nuts, they focused on what Basic's are out there, to allow a small interpreter.

    Choices are to patch-in almost any assembler/binary BASIC and use that, or another path is to use Basic generates C, and then their C project links-in that.
    One path is RAM limited, needs to be reloaded on power, and not easily tested without consuming costly plant, the other is flash limited, stays there over power cycles, but can be tested away from plant.

    FreeBASIC shows code generation backends for gas|gcc|llvm - not sure how much road tested / proven those are

    (Did someone mention a LLVM player in P2 ? :)

    There is actually quite a large catchment of people exactly like this guys customer.
    Someone whose day-job is not programming, but who needs to be able to code-together 'plc like' plant, resulting in systems that run some portion as BASIC like

    The P2 actually makes that question simpler in many ways : you could give one CORE to the customer as a sandbox, with rules on HUB resource, whilst doing product-engine-room work, in the other 7 CORES.


  • I would stick a Micromite on the front end.

    They support more than just PICs now and you get a ton of extra features.
Sign In or Register to comment.