Wednesday, June 28, 2023

🎉 New version of BASIC Anywhere Machine

Latest version of BASIC Anywhere Machine:  try it now !

The list of enhancements in this new version of BASIC Anywhere Machine is faithful to those mentioned earlier (see the 🚧 In the works post.)

Some things may have changed a wee touch, so I'll mention any deviations in this post and also provide links to relevant documentation in the BASIC Anywhere Machine Programming Reference and User Guide.

Before getting into any details, here's the list:

  • New "View Code Issues" functionality
  • Documentation: Adding Syntax (aka Railroad) Diagrams

  • New UrlQueryString$ function
  • New UrlKey$ function
  • New PUTSTRING statement
  • New SCROLL statement
  • New IFF function
  • New BETWEEN function
  • New CHOOSE function
  • New MIN and MAX functions
  • New DAY$ function
  • New FRAC function
  • Added DIV keyword as an alternative to the "\" operator
  • Improved INSTR function
  • Improved SLEEP statement
  • Improved conversion from base 10 numbers to binary/hexadecimal/octal number systems
  • Added BIN$ as alternative keyword for _BIN$
  • Improved WIDTH statement
  • New HEIGHT statement
  • Improved RANDOMIZE statement
  • Improved DEFtype statements
  • Changed INTEGER data type

Saturday, June 10, 2023

🚧 In the works: Code Issues Notification and Viewing

New "View Code Issues" functionality

BAM's interpreter does not know how to handle a declared sub or function that does not have a matching sub or function definition.  Instead of giving the interpreter the smarts to gracefully report the error (currently, BAM can get entirely locked up as it heads to never-never land), the preprocessor will eventually prevent running and exporting a program when it has the problem.

For now, BAM will let you know about the problem via the Project menu.  Just above the Run menu item, BAM will display a "View Code Issues" menu item as a visual cue to let you know that there's a problem.

Click on the menu "View Code Issues" menu item for details.

The development version and the production version of an application have independent instances of the menu item.


Problems identified in both the development
and production versions of the program



Viewing the details to pinpoint the problems



After the problem is fixed in the development version


After the fixed development version of the program is promoted to production









Wednesday, June 7, 2023

☢ Single-line IF THEN: a statement must immediately follow the THEN keyword !

 Here's an interesting syntax issue which does not result in a very useful error message:


Currently (and for the foreseeable future), BASIC Anywhere Machine does not know how to provide an informative error message for this problem, a syntax problem that has the interpreter completely confused.

When creating a single-line IF-THEN statement, the BASIC Anywhere Machine program will fail if a THEN statement is immediately followed by a colon without any statement between "THEN" and the colon.

So should you run into an error message that does not make any sense at all, take a look at your code in the near vicinity to rule out this kind of syntax problem in any single-line IF-THEN statements.


Saturday, June 3, 2023

🚧 In the works

New "View Code Issues" functionality

Details in this independent post: 

🚧 In the works: Code Issues Notification and Viewing


UrlQueryString$ function

This function returns the URL query string.

When a BAM program is exported as a stand-alone program, the URL to that HTML file can have a query string, providing us a way to pass any number of values to the BASIC program.

This is similar to command line parameters passed to an EXE.

This could also be a way of passing data to a BASIC program, via a URL to that program dynamically generated by something that wants to pass along data to the BASIC program.

Here's a sample program that shows and processes the query string:

PRINT "URL Query String: " + UrlQueryString$

 

UrlKey$ function

This is an include function (i.e. not built-into the interpreter, but rather a BASIC function meant to be included in programs if/when needed.)

Like this:

<<include "UrlKey$">>

The function as is currently implemented:

FUNCTION UrlKey$(key$)
  UrlKey$ = ""
  keyPos% = INSTR(ucase$(UrlQueryString$),{ucase$(key$) + "="})
  IF keyPos% THEN
    step1$ = RIGHT$(UrlQueryString$, LEN( UrlQueryString$ ) - keyPos% - LEN(key$) )
    step2% = INSTR(step1$, "&")
    UrlKey$ = IFF( step2%, LEFT$(step1$, step2% - 1 ), step1$)
  END IF
END FUNCTION


IFF function

Before IFF sample code:

FUNCTION GetUrlKey$(key$)
  GetUrlKey$=""
  keyPos%=INSTR(ucase$(UrlQueryString$),{ucase$(key$) + "="})
  IF keyPos% THEN
    step1$ = RIGHT$(UrlQueryString$, LEN( UrlQueryString$ ) - keyPos% - LEN(key$) )
    step2% = INSTR(step1$, "&")
    IF step2% THEN GetUrlKey$=LEFT$(step1$, step2% - 1 ) ELSE GetUrlKey$=step1$
  END IF
END FUNCTION

After IFF sample code:

FUNCTION GetUrlKey$(key$)
  GetUrlKey$ = ""
  keyPos% = INSTR(ucase$(UrlQueryString$),{ucase$(key$) + "="})
  IF keyPos% THEN
    step1$ = RIGHT$(UrlQueryString$, LEN( UrlQueryString$ ) - keyPos% - LEN(key$) )
    step2% = INSTR(step1$, "&")
    GetUrlKey$ = IFF( step2%, LEFT$(step1$, step2% - 1 ), step1$)
  END IF
END FUNCTION

Heads-up !!!  All three expressions in the function will all be evaluated every time that IFF function is executed.  So this function could be a performance hit (especially in a loop) if either or both TRUE and FALSE expressions are complex.  Best for these to be literals, constants, variables, or functions/expressions that are not complex (i.e. simple and quick to resolve.)  When dealing with complex expressions, better to go the traditional IF-THEN-ELSE route.

MIN and MAX functions

returnValue = MIN( expression1, expression2)
returnValue = MAX( expression1, expression2)

BIN$ function

BAM already had this function implemented as _BIN$ for compatibility with QB64/QB64pe.

Now:  if compatibility with QB64/QB64pe is not a concern, use either one you prefer.  Eventually, BIN$ will differ by having an optional second parameter: width.

DAY$ function

Returns the current day of the week in abbreviated form (SUN, MON, TUE, WED, THU, FRI, SAT)


DIV Operator

Integer division (an alternative to the already existing "\").

Whereas MOD returns the remainder after dividing two numbers, DIV returns the quotient after dividing two numbers.

FRAC function

returnValue = FRAC( numericExpression )

FRAC returns the fractional part of a number.


BETWEEN function

returnValue = BETWEEN( CheckedValue, MinValue, MaxValue)

CheckedValue, MinValue, and MaxValue can be any kind of expression that results in any one of the primitive data types (a string or any of the numeric data types).

If the CheckedValue is between MinValue and MaxValue, or equal to either MinValue or MaxValue, then BETWEEN returns -1 (i.e. TRUE);  Otherwise, BETWEEN returns 0 (i.e. FALSE).


CHOOSE function

returnValue = CHOOSE( ChoiceIndex%, ResultExpression1, ResultExpression2 [, ...])

  • ChoiceIndex% is any kind of expression that results in any integer inclusively between 1 and the number of ResultExpression* parameters specified; if the expression results in an invalid number, the CHOOSE function will return nothing (0 assigned to a numeric variable, empty string to a string variable)


DEFtype Statements: Improved Compatibility

BAM's syntax for the DEFtype statements, as per original wwwBASIC  code:

DEFtype letter - letter [, letter - letter]

Unlike classic BASIC implementations, BAM did not allow single letters, allowing only letter ranges.

Now, BAM allows letter ranges and single letters, and a mixture of those declarations in one statement.

So for all DEFtype statements, the syntax:

DEFtype letterExpression [, letterExpression]

  • type is one of the following: DBL, INT, LNG, SNG, STR
  • letterExpression can be one of:
    • a single letter
    • a letter range consisting of two letters separated by a dash (i.e. a minus sign)
      • startingLetter - endingLetter
      • the range is inclusive
    • this parameter is required
  •  [, letterExpression]
    • the square brackets says that more letterExpressions are optional: there can be none, one, or many. added after the first DEFtype parameter
    • each occurrence must be preceded by a comma


Improvements to BIN$, _BIN$, HEX$, OCT$

All were mishandling non-integer numbers.  Now, all functions round numbers to integers before converting those to the other numeric system.

HEX$ and OCT$ were not converting negative numbers to negative number representations of the other systems.  BAM was effectively stripping the negative sign, converting the number, and then adding the sign as a prefix to the number.  The functions in the new version of BAM returns converted numbers the same way as GW-BASIC and QB64.


SLEEP Improvement

The SLEEP statement now allows for no parameter.  When no parameter is provided, the  program will pause until a keyboard key is pressed.

For QBASIC compatibility: if the parameter = 0, that will also cause the program to pause until a keyboard key is pressed. 

 

INSTR Improvement

Previously allowed only two parameters.  Now allows two or three parameters.

Syntax Options:

INSTR(baseString$, searchString$)
INSTR(start%, baseString$, searchString$)


WIDTH improvement

Fixed issue with console window not being quite right after WIDTH and until the browser window gets resized.

Also, a note: the WIDTH statement effectively changes the width of the console not only for text, but for graphics too.  So WIDTH(numberOfColumns%) sets the width of the console to numberOfColumns% * 8.


RANDOMIZE compatibility improvement

BAM previously required a parameter for the RANDOMIZE statement.  Now, BAM also accepts the RANDOMIZE statement without a parameter.

Although BAM ignores the RANDOMIZE statement (BAM's RND function does not need to be seeded), BAM does recognise and validate the statement for compatibility with other BASIC implementations.

Typically, when RANDOMIZE has no parameter, the program will pause and ask for a value.  BAM skips this.  

HEIGHT statement

Since seemingly forever BASIC has had the WIDTH statement to set the number of character columns on a screen, why not have a statement to specify the number of character rows?


PUTSTRING statement

The statement places a string on the screen at the specified x and y pixel coordinates.


INTEGER data type

"INTEGER" was previously treated by BASIC Anywhere Machine as equivalent to a LONG integer.

"DEFINT" defines variables that begin with a specified letter as SHORT integer.

To be consistent with DEFINT, and to be consistent/compatible with GW-BASIC, QBASIC, and QB64, "INTEGER" has been changed to be treated as equivalent to  SHORT integer.


SCROLL statement

Scroll the entire screen, or part of the screen either vertically, horizontally, or both.

 

Documentation: Adding Syntax Diagrams






📚 FUNCTION (and SUB): variable arguments, by default, are "passed by reference"

Preamble A primer on "call-by-reference" vs "call-by-value" BAM HOWTO (BTW:  "call-by-reference" aka "pas...