This directory contains the sources and make files for an
Atari BASIC compatible basic dialect.

This is based on Atari Basic, as developed by Paul Laughton and Kathleen O'Brien,
Shepardson Microsystems, as found in: The Atari BASIC SOURCE BOOK by
Bill Wilkinson, Compute! Publications (1983)

Basic++ fixes a couple of known Atari Basic bugs and includes a couple of improvmenents
without impacting compatibility with existing basic code. It does not attempt to
extend the Atari Basic dialect beyond its current syntax. If you are interested in a
more powerful Atari Basic, get TurboBasic, Basic XL or Basic XE. Basic++ is a
"best efford" to squeeze as many useful Basic features into the 8K cartridge ROM space
as possible.

Basic++ sources are based on Rev.A Atari Basic, as published in the Compute! book
cited above, with many improvements and refinements. Source code was completely reviewed
and refined, and was made more concise to the original leaving headroom for some new
features.

At this time, the following Atari Basic bugs have been fixed:

- The parser allowed INPUT without any parameters. Now it needs to take at least one
  variable.
- A Ctrl-U as last component of a string argument to PRINT worked as if the PRINT
  statement included a semicolon.
- It was possible to DIM two-dimensional arrays overrunning the available memory
  because any type of overflow check was missing.
- A downwards block move of an exact multiple of 256 bytes moved the wrong memory.
- Basic Rev. A crashed on cascaded versions of multiple unary operators, in particular
  PRINT NOT NOT A or PRINT ++2 or PRINT --X crashed. Atari "resolved" this issue in
  Rev.B by not parsing such expressions, Basic++ allows then and implements them
  correctly.
- LOCATE apparently did not restore the input buffer pointer correctly and could have
  caused errors if followed by a VAL() that required the pointer to be seated
  correctly. Basic++ fixes VAL.
- NOTE and STATUS were also parsed correctly if their arguments were arrays.
  However, none of them worked with arrays correclty, so the parser was adapted
  accordingly to accept only simple numeric variables.
- POINT did not accept arbitrary expressions, though it could. Fixed that.
- CHR$(a)=CHR$(b) was always true, regardless of a and b, the same bug holds true
  for STR$(a)=STR$(b). Fixed both bugs.

The following improvements have been made:

- The SQR function in Atari Basic was unbearably slow and unprecise as it uses the
  ancient Heron method. Numerical inaccuracies of the math pack division pile up and
  resulted in loss of accuracy. The new code uses a "digit by digit" algorithm that
  is not only faster, but precise up to the last digit ("one ulp" precision).
- The power function ("^" operator) was implemented in a very naive way and resulted
  in precision loss. Atari "fixed" that in Rev.B by rounding results, Basic++ uses a
  "divide and conquer" method by first computing the integer part and splitting off
  the fractional part when necessary. This improves precision and stability and
  ensures correct results for integer arguments.
- Atari Basic stored line numbers and offsets as return address for FOR-NEXT loops and
  GOSUB expressions and hence required a complete line-search to return to the
  previous statement. Similar to TurboBasic, Basic++ stores in addition an absolute
  address and continues from this address directly bypassing the search if it can
  ensure that the source code has not been modified in between.
- Atari Basic used a very ugly and hacky method of temporarily fiddling an EOL into
  strings used as file specifications when interfacing to CIO. Basic++ avoids touching
  the user program or code and copies the string before modifying it.
- Basic++ allows an empty second argument to LIST to list up to the end of the source,
  i.e. "LIST 100," lists all lines from line 100 on.
- Basic++ handles denormalized floating point numbers now correclty, especially when
  comparing numbers and testing numbers for zero.
- Basic++ "string variable splicing" now also allows empty splices. In particular,
  if "A$="HELLO"", then A$(6) is valid and returns the empty string. Similarly,
  A$(4,3) is the empty string. This avoids some pointless boundary checks when splicing
  strings.
- If RESET was pressed in the middle of a line or variable insertion, Atari Basic might
  have left an unusable program that crashed the system on a LIST. Basic++ will detect
  such cases and will clean up its program areas in such a case.
- The line seach for GOTO and GOSUB has been improved by avoiding a full search in case
  the target line is known to lie below the current line. It is then sufficient to search
  from the current line instead.
- If two CHR$s or two STR$s where part of the same expression, the second call would
  overwrite the result of the first. Hence, CHR$(A)=CHR$(B) would always evaluate
  to 1, regardless of whether A or B were equal. Similarly, STR$(A)=STR$(B) would
  evaluate to 1 if the number of digits in A and B are equal, regardless of their
  value.
- The parser allowed STATUS and NOTE to accept an array as argument, though the statements
  never worked correctly with array elements as arguments. Basic++ handles arrays for
  STATUS and NOTE correctly, and also allows them for LOCATE, INPUT and READ.
- For some strange reason, the parser did not allow arbitrary expressions for the arguments
  of POINT, though the statement supported them.
- The output of some transcendental functions have been improved. ATN returns now -90 or
  90 precisely for very large or very small arguments, and CLOG and LOG return 0 precisely
  for the argument 1.
- Access of one-dimensional array elements avoids now a multiplication and hence should
  be faster.
- Basic++ supports an AUTORUN.BAS file. If one is found when coldstarting the system, it
  is loaded and run.
- A binary file (basic.exe) for testing is now also generated by the build-process. The
  file includes the same basic plus a relocator that places it in memory where it finds
  room.

