Jump to content
IGNORED

FastBasic 4.5 - 2021 release


Recommended Posts

Hi all!

 

Finally I published the new FastBasic 4.5 release!!

 

From the 4.5 beta, I added:

- The "ADR()" function and the "&" operator now allow taking the address of a variable, so this code will print 123: " A = 1 : DPOKE &A, 123 : ? A ".

- The "EXEC" statement can be abbreviated to a "@", this makes calling procedures more natural, this will also print 123: " PROC Test A : ? A : ENDPROC : @Test 123 " 

 

This in addition to the added features of the 4.5 beta:

- Parameters for the PROC/EXEC, see the test-release docs,
- Arbitrary characters in string constants by using the hex value, like: PRINT "Hello"$9B"World",

- Added PAUSE without a parameter, this is the same as PAUSE 0, "wait for vsync",
- PROC has a shorter abbreviation: PR.,
- The parser is more robust to syntax errors, I discovered some erroneous inputs that could slow down the parser a lot.


Many improvements to the editor:

- Much faster COPY/PASTE operations,
- Restores left-margin value on exit to DOS,
- Remove P/M graphics when returning to the editor from user programs.

 

And improvements to the cross-compiler:

- Better error messages from some syntax errors, and fixes in parsing of big numbers.
- Check for PROC and EXEC parameters mismatch.
- An option to write an expanded and indented listing from an abbreviated listing, "-l"

 

After a lot of optimizations, I managed to keep the integer IDE at 8192 bytes and the floating-point IDE at 9457 bytes.

 

EDIT: Current release is 4.5.2, adds a few bugfixes and minor optimizations, now the integer IDE is 8166 bytes.

 

As always, you can download the ATR, the manual and the cross-compiler from github: https://github.com/dmsc/fastbasic/releases/

 

Have Fun!

Edited by dmsc
Add information about release 4.5.2
  • Like 14
  • Thanks 6
Link to comment
Share on other sites

Hi, thanks for testing!

 

1 hour ago, vitoco said:

The ATR still says it's an RC!

 

Update: Also the docs... I just checked and version.mk is still from 11 days ago.

Oh, that happens when doing a release at 1AM, forgot to update the version file.

 

2 hours ago, Preppie said:

Getting the following error when trying to run a prog with cross compiler

 

fastbasic-int.exe - system error


libwinpthread-1.dll not found

And this is because my new mingw cross-compiler now links with that DLL by default.

 

Fixed both and did a new release, simply removing the old one, as the only changes are:

- Fixed version string,

- Build on WIN32 using static link flag.

 

Thanks again, have fun!

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

7 hours ago, dmsc said:

- The "ADR()" function and the "&" operator now allow taking the address of a variable, so this code will print 123: " A = 1 : DPOKE &A, 123 : ? A ".

This does not work with FP variables, right?

 

Are variables addresses defined at parser time or run time?

 

If it is at parser time, might this be a step forward to include variables in DLI definitions?

 

Link to comment
Share on other sites

Hi!

3 minutes ago, vitoco said:

This does not work with FP variables, right?

Not (yet). It is easy to add, but I also want to add a "%()" function (equivalent to "$()" for strings) to reference a floating-point "pointers" - so that "A% = 1.23 : P = &(A%) : ? %(P) " will print "1.23".

 

Note that for integers, the equivalent are DPEEK and DPOKE, so you can now do "A = 123 : ? DPEEK( &A ) " to print 123.

This allows passing pointers to procedures to receive a value: " A=1 : @Increment &A : ? A : PROC Increment X: DPOKE X, DPEEK(X) + 1 : ENDPROC" will print "2" - this is similar to the C "void Increment(int *X) { *X = *X + 1; }"

 

3 minutes ago, vitoco said:

Are variables addresses defined at parser time or run time?

In the 6502 compiler, defined at run-time, as the parser does not know the address until emitting all program bytecode. In the cross-compiler, the address is known at assembly-time, but the byte-code generated also calculates the address at run-time, this is so that the code is smaller (load #var is two bytes).

 

3 minutes ago, vitoco said:

If it is at parser time, might this be a step forward to include variables in DLI definitions?

Ah, yes.. but it is not possible in the 6502 compiler now without adding a new pass to the compiler: at parsing time add all locations that reference a variable address into a list, and at end of parsing (when we know the final address of variables), we need to go through the list filling locations with the new address. This is currently done with PROC, but there is no final pass as the locations are filled when the parser first see the PROC definition. And in the case of DATA, the parser needs the definition before referencing it.

 

All this little additions to the language would be very simple in the cross-compiler, as multiple passes are trivial to do - in fact, the optimizer does an unbounded number of passes through the bytecode - but the 6502 parser is really optimized for speed and size, so it does always only one pass through the hole program generating the byte-code directly.

 

Have Fun!

  • Like 4
Link to comment
Share on other sites

4 hours ago, PaultheRoman said:

So, is this a program for the A800, or is this like a replacement ROM (as in OS) for it? I'm kind of confused.

It's a program of the BASIC language.  You load it like any other game/program from disk (or SD device) and you'll have a new and faster version of BASIC.

 

It also works as a cross compiler.  You program in a text editor on your PC then it will compile the code into a XEX file that can be run by ALTIRRA or written to SD device and played on a real machine.

 

 

  • Thanks 1
Link to comment
Share on other sites

I just found that INC and DEC cannot be used on array elements of BYTE datatype. Trying to do that returns a parser error in the IDE. These work OK with WORD array elements.

 

I previously discovered that they don't work over FP variables, but that made sense because on how those statements work (related to 6502 opcodes). 

 

I think these restrictions should be pointed out in the manual, or included in the syntax/runtime ;-)

 

Edited by vitoco
typo
Link to comment
Share on other sites

9 minutes ago, vitoco said:

I just found that INC and DEC cannot be used on array elements of BYTE datatype. Trying to do data returns a parser error in the IDE. These work OK with WORD array elements.

 

I previously discovered that they don't work over FP variables, but that made sense because on how those statements work (related to 6502 opcodes). 

 

I think these restrictions should be pointed out in the manual, or included in the syntax/runtime ;-)

 

Yeah, he's pointed this out in the past.  Why don't you go over to github and change the manual?  I should probably figure out github too so I can help a little.

 

Link to comment
Share on other sites

I have just been experimenting with FastBasic 4.5 and this is a great product.

 

I am looking to use this within a project of mine. I would like to have my compiled Basic programs on different cartridge banks. I will then call them with a set of parameters which I set in the zero page. Think of each compiled program as a library of functionality that I can quickly develop in Basic.

 

Due to working from cartridge, I need to ensure that all the variables (which are obviously read and write, which cartridge is not), I need to ensure that my variables are stored in a location that the rest of my mini-programs on cartridge won't touch. How can I set where that is located? Lets imagine I want to store them at $1F00, how do I specify that?

Link to comment
Share on other sites

What timing! I was just thinking of trying my hand at BASIC and saw this post. ?

 

I downloaded the ATR and loaded it into my 1200XL. Unfortunately, I am getting strange behavior,

 

It seems that errors are latched and cannot be cleared. For example, if I had a "bad loop" parsing error and delete the code for the loop FastBasic is still reporting a "bad loop" parsing error. Is there something I need to do clear the error?

 

When I press Control-L to load a file I am prompted with a "Save?" line instead. 

 

The manual is only 29 pages long, including the cover page. I like that. Nice and short. I also like not having to use line numbers. What a relief! ? I also like the idea of procedure too.

 

I know I could never make anything like this so I appreciate your work! Thanks!

Link to comment
Share on other sites

1 hour ago, 1200XL M.U.L.E. said:

It seems that errors are latched and cannot be cleared. For example, if I had a "bad loop" parsing error and delete the code for the loop FastBasic is still reporting a "bad loop" parsing error. Is there something I need to do clear the error?

I think I've got "bad loop" also on unbalanced IF-ENDIF.

 

1 hour ago, 1200XL M.U.L.E. said:

When I press Control-L to load a file I am prompted with a "Save?" line instead. 

When you press Control-L after modifying the current source code, it prompts you to save it first. If you want to discard that buffer, press Control-C and it will prompt for the file to load. Warning: when you want to reload the source file because you broke it while testing, if you don't cancel the save, you will overwrite the good file in the disk with the broken code.

 

 

Edited by vitoco
  • Like 1
  • Thanks 1
Link to comment
Share on other sites

Hi all!

 

I could not reply earlier, this was a very busy week at work!

 

On 3/12/2021 at 1:16 PM, vitoco said:

I just found that INC and DEC cannot be used on array elements of BYTE datatype. Trying to do that returns a parser error in the IDE. These work OK with WORD array elements.

Yes, INC and DEC does not work on BYTE values. See https://github.com/dmsc/fastbasic/issues/14

 

On 3/12/2021 at 1:16 PM, vitoco said:

I previously discovered that they don't work over FP variables, but that made sense because on how those statements work (related to 6502 opcodes). 

 

I think these restrictions should be pointed out in the manual, or included in the syntax/runtime ;-)

I would add a note.

 

On 3/12/2021 at 2:20 PM, danwinslow said:

why wouldn't they work in byte array elements? That seems odd.

INC and DEC receive a pointer to a 16 bit quantity, an perform the 16 bit operation. To implement INC or DEC on bytes I would need to add two new bytecodes to the interpreter, one for "INC BYTE" and another for "DEC BYTE", and then add support to the parser for generating the code.

 

 

Have Fun!

Link to comment
Share on other sites

Hi!

17 hours ago, snicklin said:

I have just been experimenting with FastBasic 4.5 and this is a great product.

 

I am looking to use this within a project of mine. I would like to have my compiled Basic programs on different cartridge banks. I will then call them with a set of parameters which I set in the zero page. Think of each compiled program as a library of functionality that I can quickly develop in Basic.

 

Due to working from cartridge, I need to ensure that all the variables (which are obviously read and write, which cartridge is not), I need to ensure that my variables are stored in a location that the rest of my mini-programs on cartridge won't touch. How can I set where that is located? Lets imagine I want to store them at $1F00, how do I specify that?

 

The correct way to do this is by having the generated bytecode in ROM and all the variables in RAM.

 

When using the cross-compiler (that you need to do, since it is the only way to separate the bytecode from the interpreter), the compiler generates and ASM file with all the bytecode. This bytecode can be placed in ROM, but beware of DATA statement and constant strings - as the interpreter stores pointers to strings and to data, and if the rom then is banked out, those would not be there.

 

Variables are placed in a page-aligned area at the start of the heap, the cross-compiler links with the code at src/standalone.asm: https://github.com/dmsc/fastbasic/blob/master/src/standalone.asm

There you see the "heap_start" definition. This is important, as just after the variables the interpreter places all the DIM arrays and dynamic strings. At startup the interpreter allocates memory for the variables as one big array and clears the values to zero. In your example, just set "heap_start = $1F00".

 

Note that you can also have the interpreter in ROM, but to do that you need to compile the interpreter assembly code with --asm-define NO_SMCODE  :

- Edit the Makefile, add "-D NO_SMCODE" to the CA65_FLAGS

- Compile FastBasic

- Use the cross compiler passing the "-C:build/compiler/fastbasic-cart.cfg" flag to link using the supplied cart linker configuration.

 

Have Fun!

Link to comment
Share on other sites

13 hours ago, 1200XL M.U.L.E. said:

What timing! I was just thinking of trying my hand at BASIC and saw this post. ?

 

I downloaded the ATR and loaded it into my 1200XL. Unfortunately, I am getting strange behavior,

 

It seems that errors are latched and cannot be cleared. For example, if I had a "bad loop" parsing error and delete the code for the loop FastBasic is still reporting a "bad loop" parsing error. Is there something I need to do clear the error?

No, that should not happen. Please, post the code that shows an error (you can take a picture of your TV or monitor). As @vitoco said, "bad loop" is also shown on other constructs. I should clarify parser errors, currently the possible errors are:

- "undef label" : You tried to call a PROC that was never defined.
- "too long" : The current line is too long for the parser - this means that the generated code is more than 256 bytes or that the expression is too complicated.
- "bad loop" : This means that the parser found an "ELSE/ENDIF/ENDPROC/WEND/LOOP/UNTIL/NEXT" without the corresponding starting "IF/PROC/WHILE/DO/REPEAT/FOR", or an "EXIT" outside a loop.
- "no end loop/proc/if" : After the file was completely parsed, there is a missing loop ending.

- "parse error" : The parser could not parse a complete line. Note that the parser is greedy, it always parses the longest possible part of a line, so the reported position is the rightmost position which the parser could reach.
 

The cross compiler has better error reporting, and also reports which word could continue parsing at a given point.

 

13 hours ago, 1200XL M.U.L.E. said:

When I press Control-L to load a file I am prompted with a "Save?" line instead. 

This was added as popular request: whenever you modify the source, the IDE will ask to save the old file before loading a new one (or any other operation that clears the buffer). You can skip the save by pressing CONTROL-C, then you will see the LOAD prompt.

 

13 hours ago, 1200XL M.U.L.E. said:

The manual is only 29 pages long, including the cover page. I like that. Nice and short. I also like not having to use line numbers. What a relief! ? I also like the idea of procedure too.

I always ask for help with the manual - as I'm not a native English speaker, any help fixing gramatical errors and expanding it is appreciated!

 

13 hours ago, 1200XL M.U.L.E. said:

I know I could never make anything like this so I appreciate your work! Thanks!

Tank you for your words!

 

Have Fun!

 

Link to comment
Share on other sites

1 hour ago, dmsc said:

Hi!

 

The correct way to do this is ...

 

Thank you DMSC for your reply. I will try this out later.

 

For convenience though, could a future version have a command line option to be able to specify the chosen heap location? Would that be practical?

 

By the way, your English is extremely good, I couldn't tell that it wasn't your native language, apart from that it says above that you are in Chile.

Link to comment
Share on other sites

2 hours ago, dmsc said:

There you see the "heap_start" definition. This is important, as just after the variables the interpreter places all the DIM arrays and dynamic strings. At startup the interpreter allocates memory for the variables as one big array and clears the values to zero. In your example, just set "heap_start = $1F00".

That explains a lot, but I still do not find how the variables are sorted in that area. I defined a lot of variables and arrays in the IDE, and when I printed their respective addresses, they were not in sequential order.

 

Is this how CLR statement works?

 

Edited by vitoco
Added CLR comment
Link to comment
Share on other sites

Hi!

 

1 hour ago, vitoco said:

That explains a lot, but I still do not find how the variables are sorted in that area. I defined a lot of variables and arrays in the IDE, and when I printed their respective addresses, they were not in sequential order.

 

Variables should be in "program appearance order" :) 

 

Whenever the parser defines a new variable, it assigns that variable a new number. The address of variables is "heap_start + var_num * 2". String variables and arrays also use one variable number (where the address of the string or array is stored), but you can't get the pointer address, and floating-point variables use three numbers (6 bytes).

 

On the other hand, DATA arrays don't use a variable for the address, those are handled the same way as procedures, where the parser stores the data inline in the program and fixes the address at that time.

 

For example, see this program:

A=12
B=23
C$="HELLO"
D=45
E%=1.1
F=67

? &A, &B, &D, &F

From the IDE, it prints: 18176   18178   18182  18190

 

You can deduce that, variable A uses two bytes, then B and C use 2 bytes each, then D uses two bytes and E finally uses 6 bytes, and all variables are in memory in the correct order.

 

1 hour ago, vitoco said:

Is this how CLR statement works?

Yes, CLR simply calls the variable initialization again: the top-of-memory pointer is moved back to heap_start, variable area is allocated again and cleared to zero.

 

Have Fun!

Link to comment
Share on other sites

Hi!

2 hours ago, snicklin said:

Thank you DMSC for your reply. I will try this out later.

 

For convenience though, could a future version have a command line option to be able to specify the chosen heap location? Would that be practical?

 

That could be possible, it is a matter of defining the heap_start symbol as "weak" and defining the value in the linker command line with "-D heap_start=$1F00".

 

But I think that a better option would be to set the heap in it's own segment in the assembler, so placing it at an arbitrary location would be easy from the linker configuration. As FastBasic relies on the LD65 linker, it brings a lot of flexibility to the compilation process.

 

There is one other detail: currently the heap grows on each allocation (for strings and arrays), this is managed in "alloc_array" procedure, inside src/interp/clearmem.asm , and it compares the heap pointer with MEMTOP to see if there is enough memory for the new allocation. If you move the heap, it will always grow to MEMTOP, so you must be sure that there is no other memory in use between heap_start and MEMTOP.

 

2 hours ago, snicklin said:

By the way, your English is extremely good, I couldn't tell that it wasn't your native language, apart from that it says above that you are in Chile.

Thank you!

 

Link to comment
Share on other sites

@dmsc, I will help some more on the manual! All of the previous work and a lot more I had done was on a laptop that was stolen a few months back. Just let me know what I need to do!

 

Thank you very much for this new version! I am really impressed by the speed increases using the cross compiler.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...