Programmable Calculator / Simple BASIC interpreter

406 views
Skip to first unread message

Paul Bowers

unread,
Jul 16, 2023, 11:52:25 AM7/16/23
to Sailforms Users
Yes, I am being serious - How far can I push SailForms ? Can I use it to write apps more than just forms and tables. 

Well here is my prototype Programable Calculator - it will evolve over time - but the core is working - and I thought some of you might like to play with it and even make suggestions or take some learnings on techniques I have used.

Performance is not to bad either.

Syntax checking is still simple - so make sure you are tight with source code - see my examples. (There is a help button) - have fun - but it does make you think about SailForms in a completely new way,

commands that are working are (LET, PRINT, COMPUTE, GOTO, INT, STOP) - I am working on IF THEN and INPUT and simulated Files (READ# and WRITE#) and so on.

I have attached the SFG. SmartSelect_20230715-135848_Pro.jpgSmartSelect_20230715-135919_Pro.jpgSmartSelect_20230716-163521_Pro.jpgSmartSelect_20230716-163541_Pro.jpg 
Programable_Calculator_1.sfg
Message has been deleted

Paul Bowers

unread,
Jul 19, 2023, 9:22:00 AM7/19/23
to Sailforms Users
Attached is a baseline version thats worth a play - a fully functional programmable calculator (more like the pocket PC of old) where you can write your own apps - - i have included a bunch of demo test apps to see just what is possible 

The applets (programs) are stored in a table, and compiled by an option in the EDITOR - for those with fat fingers i have dropped in a programmer large key keyboard. Once the app is compiled it is stored in a PCODE table (Parsed Code) which facilitates faster execution in the RUNTIME form, as there is reduced overhead of parsing the code. Variable are defined and held in a working HEAP table - which can be seen in real-time on the RUNTIME form under the virtual console.

Sequential files are simulated to a FILE table - from which you can export to a CSV or access from other forms.

commands implemented are

DIM  to allocate a variable (single letter) to the Heap A% through Z% and A$ through Z$ and then assign a initial value
LET to compute using variables on the heap. A%=A%+B% (supports +-*/ operators)
PRINT variable from the heap or literal in '' - if the line is ended with a comma then this supressed CRLF to enable concatenated printing
IF THEN decision based branching using values from the heap or literals IF A%=B% THEN label - IF A$="Y" THEN label
GOTO label - unconditional jump
FIRST filename - sets file pointer at the first record of virtual file in the FILE table labelled as FILENAME
READ reads data record at current vFILE location into variable on heap (READ 'FILE1),A$;
WRITE write to the file in vFILE with specified filename at the next file location in the FILE table
DELETE filename - deletes all records for FILENAME from the vFILE table
INDEX - compacts the FILE table and reindexes - following deletions and writes - think of it like CLOSE filename
CLS 0; clears the console 
STOP RUN - stops the programe - should be the last line of the program.
line labels must start a line and be followed by a colon LABEL1: used for GOTO and IF THEN branching - for speed of execution the compile routing creates a navigation table so at runtime we dont need to scan and parse for the jump.

Enjoy - and suggestions for additional functions or features please let me know - 

what am i thinking about next - 

arrays (well 2 dimensional)
console advance printing format and location control - that may be a challenge !
random keyed file access (GET and PUT)
scanner input
result push back to the calculator
may be a landscape SQWERTY programmer keyboard. 

Paul. 

On Monday, 17 July 2023 at 08:01:22 UTC+1 Paul Bowers wrote:
updated version with IF THEN and INPUT implemented

I know of a bug with the HEAP reset if you attempt to rerun an app with heavy HEAP actions - such as COMPUTE and INPUT without
 exiting the form and going back in - still trying to work out where the issue lies - me or SailForms itself.
Programable_Calculator_1.sfg

Paul Bowers

unread,
Jul 19, 2023, 9:37:32 AM7/19/23
to Sailforms Users
SmartSelect_20230719-142815_Pro.jpgSmartSelect_20230719-142839_Pro.jpgSmartSelect_20230719-142910_Pro.jpgSmartSelect_20230719-142951_Pro.jpg
 i forgot to mention the INPUT A$ command - this is interesting - for now i popup an input field and enter button - its was easier than trying to do it on the console text field - but may look at that for a future version.

Paul.

Paul Bowers

unread,
Jul 19, 2023, 9:43:48 AM7/19/23
to Sailforms Users
SmartSelect_20230719-144135_Pro.jpg
the programmer keyboard

HARVEY ARIZA

unread,
Jul 20, 2023, 4:44:33 PM7/20/23
to Sailforms Users
very interesting, it would be necessary to know how far sailforms will go from now on.

Paul Bowers

unread,
Jul 20, 2023, 5:32:44 PM7/20/23
to Sailforms Users
SmartSelect_20230720-220754_Pro.jpgSmartSelect_20230720-220814_Pro.jpgSmartSelect_20230720-220825_Pro.jpgSmartSelect_20230720-221024_Pro.jpgSmartSelect_20230720-221104_Pro.jpgSmartSelect_20230720-221136_Pro.jpg


After so serious keyboard bashing here is a major jump forward in functionality. I have done a heap of debugging and sorted the issues in PRINT with regard to CRLF processing. I have sorted the memory leak in HEAP processing in DIM, LET, VAL and INT commands. I have added CHAIN to another program with LOCAL or GLOBAL HEAP so you can pass data into the called program. vFile functionality to WRITE, READ, FIRST, DELETE, INDEX a file and ability to export to CSV

IF and LET and been extended to support +-/* and > < and ! (NOT EQUAL). I have also started string support in LET so you can concatenate them and convert from number to string etc and back again. Also made INPUT command popup better.

with all the added commands I have done some performance work to put the most frequent command at the top of the selector etc, and done some  optimisation of functions to speed them up.

There is an active trace and heap monitor on the RUNTIME form.

and finally some GUI tidy up to make it look better as well as the ability to layout the application code to make it more readable to allow indented and labels etc.

so enjoy playing - again suggestions for improvements or features welcome

if the program has a lot of heap activity (like printing the times table matix) with a lot of calculations it can get sluggish - I am thinking of a way to cache the heap to the runtime form to remove the remote table lag 
ideas on this would be useful. I suspect the answer may be in a local text field using Indexof and substr features in a fix length field structure to simulate an array table.- we shall see how fast that works out.



Programable_Calculator_2.sfg

Paul Bowers

unread,
Jul 25, 2023, 3:21:18 AM7/25/23
to Sailforms Users
I thought this would be a good time to give an update. I said at the start of this project that it would evolve over time - and it certainly has done so.

In my last version I was concerned about how it could get sluggish at runtime  - my assumption at the time was that a remote table HEAP was the reason. and I experimented with a local stack concept of keeping and maintaining a variable array in a form text field. This worked out quite easy to do in the end - using a vertical bar char as an element separator and INDEXOF to locate, SUBSTRING to extract and REPLACE string commands to managed. HOwever, it did not appear to be any faster than remote table. So what was the reason - quite obvious in the end. The COMPILER engine was creating a pCode table spiting commands from operands - and then at RUNTIME parsing the operands on the fly. As functions LET and IF became more complex with added capability they became slower and slower to parse and break up. The solution therefore was to move this on-the-fly (You could call it JIT Processing (Just In Time) to the compiler stage and hold more parsed columns in the pCode. This resulted in between 40 and 50% performance increase at RUNTIME. Much Better.

This version also adds a number of expanded features and commands.

A virtual FILE browser and Editor (which ASCII/HEX dump of the record, a LOG of program runs and results (still Work in Progress),

a list of commands supported is

LABELS: for IF and GOTO navigation
MAIN: Entry point into an application when CHAINing
INPUT var%
INPUT string$
PRINT var%, the end comma suppresses CRLF
PRINT var$,
IF VAR {operator} VAR THEN label
GOTO label
DIM var=value
DIM var=INT(var)  - a sort of REDIM to force decimal number back to integer
LET var=var+var (+-/*)
LET var-VAL(var$) - convert string to number
LET VAR=MID$(VAR$,start,len)  - extdact sub part of a string start and end can be a VAR% or numeric literal
HEAP GLOBAL - retain the current heap when chaining
HEAP LOCAL - clear the heap when chainging
DELETE filename  - purge vFILE records from the FILE table#
FIRST filename - locate to the first record for a file in the vFILE table
WRITE filename,var
READ filename,var
INDEX files - resequence the vFILE table following deletions
STOP RUN - ends a program and must be the last line
CHAIN program
DROP var - removes a var from the HEAP create with a previous DIM

Whats next - Probably augment PRINT capability with multiple literals and var and may be some FMT (formatting of vars FMT('%%',a%) etc)
need to return syntax errors on compile as the code becomes more complex. Mix var and literals in the LET functions.
PUSH CALC to return a value back to the main calculator form

If anyone has a desire for a specific feature let me know.


Enjoy 

Paul
Programable_Calculator_1.sfg

Paul Bowers

unread,
Jul 28, 2023, 10:19:48 AM7/28/23
to Sailforms Users
SmartSelect_20230728-150008_Pro.jpgSmartSelect_20230728-150050_Pro.jpgSmartSelect_20230728-150110_Pro.jpgSmartSelect_20230728-150131_Pro.jpg
I have done some major updates to the both the compiler and runtime engines - fixed some bugs too. 

the vFile capability has had a major revamp - the the introduction of OPEN filename; CLOSE filename; READ filename; WRITE filename: DELETE filename; CREATE filename; DELREC filename; and SEARCH Filename, pattern$

I have added a heap of new functions VAL, ASC, LEN, INSTR, REPLace; HEX$, PUSH to the Calculator journal, DROP var from the HEAP (useful if your chaining and want to retain part of the HEAP)
 and CLS lineno (0 clears the console) any other number wipes from that line down.

There is a new FILE Browser editor form , application run log - which also saves the console output - export program to txt file and export file to CSV file.

I have kept an eye on RUNTIME performance and moved as much pre-processing to the COMPILER as possible.

I would like an non-proportional font in the File editor for the ASCII dump section - but I am limited here to the capability of SALFORM itself.

I have not look at screen size scaling - but I think moving fields around should be quite easy if you need to scale for your phone (I run on a SAMSUMG A12) 
so it should run nicly on a fast higher spec phone.

whats next ? I would like to mix var and literals in LET statements, Do formatted Printing and more complex printing - IF I get a wet rainy weekend - I might tackle that.

Enjoy

Paul.
Programable_Calculator_2.sfg

Paul Bowers

unread,
Jul 28, 2023, 10:33:57 AM7/28/23
to Sailforms Users
the look and feel has had a tidy up too
SmartSelect_20230728-152341_Pro.jpgSmartSelect_20230728-152403_Pro.jpgSmartSelect_20230728-152421_Pro.jpgSmartSelect_20230728-152516_Pro.jpgSmartSelect_20230728-152557_Pro.jpg

I hope that you find it useful - just to get techniques to solve problems or ways of doing things if nothing else. For me its just keeping my hand in to prove a classically trained programmer (started life on IBM mainframe and IBM Point of Sale) can still produce apps - to challenge the new kids on the block !

HARVEY ARIZA

unread,
Jul 28, 2023, 7:28:43 PM7/28/23
to Sailforms Users
Interesting. 

Paul Bowers

unread,
Aug 1, 2023, 7:37:13 AM8/1/23
to Sailforms Users
Screenshot_20230731-152532_Pro.jpg

I mentioned in one of my earlier posts that I would look at an horizontal screen layout - just to see what could be done.
Heres a view of the prototype so far - not enough space in the console view to edit a program but can be used like a real-time mode
pocket computer of the 1980 era.

I have LOG,COS,SIN,TAN,EXP,ACN,ASN etc all functional - and will add HEX etc and then look at more complex stuff like brackets ! 
and then may be functions !

My thoughts are with the Programmer Keybaord form - how to locate the cursor in the middle of a text field ! It may be easier to convert to a table and 
then select line by line to edit ! we shall see what works out.

Paul.

HARVEY ARIZA

unread,
Aug 1, 2023, 9:01:34 PM8/1/23
to Sailforms Users
Seriously all that can be done with Sailforms, you're talking about compiling a program inside sailforms.

Paul Bowers

unread,
Aug 2, 2023, 3:46:57 AM8/2/23
to Sailforms Users
Yes, all of this is being done inside of SailForms - to be clear when I refer to the compiler - I do not mean it will create a native Android standalone application - that would be difficult to achieve in an efficient way.

Let me explain what is happening inside this.

Start with a form - call it editor - containing text fields for program name, description and a large text field to contain your applet. A text field can contain multiple lines - in fact many - I think up to 32K

Then add some buttons Save being one and "Compile" and "RUN" being the others

YOu can then add other form - called Library - its contains a remote table to the editor form - and hey presto a list of your applications.

The magic is on the editor form - a couple of off screen fields where you put the logic in the WHEN GETS FOCUS actions. So when you press the compile button apart from clearing some variables it does a SET FOCUS command and transfers control to your hidden field. This hidden field is then recursed by setting focus back to itself - don't forget to put an exit clause out otherwise it will run on forever. The first command is always a set focus to a dummy field - to forces the loop back on the end - in this way you can create functions and subroutines. An hence program logic that can be run. 

So what does the COMPILE function do - is takes each line of the applet in the editor form and breaks it down into a pCode (Parsed Code) table - one record per line of the programme - its gives each line an address (record number) and then breaks the line down into command and operands, and labels. It then creates an index of labels (used by GOTO, THEN, and CHAIN) tagging the address in the pCode table a a jump point at runtime.

So runtime - again a form with a text field that is the output console - a view of the variable heap - the run button sets the program pointer to the address in the pCOde table of the first line of the applet. Then takes that line from the pCode and looks at the command - There is a IF CMD="command" for each supported command that takes the operands and actions them - Then the program pointer is increased and then next line (recursed by SET FOCUS EXEC) - when STOP RUN command is encountered it all stops. - There is a lot of code behind this... as you would expect. So the more processing that can be done at COMPILE time keeps the RUNTIME as fast as possible by keeping its focus on executing the commands and not parsing the application source code.

As the complexity of supported code has grown there is now a need for a syntax checker - This is work in progress.

So while there is now 20 forms in this IDE/RUNTIME it is still within the bounds of what can be done with SailForms. This program is probably the closest to MS Access for windows that is currently available for Android.

Paul.
SmartSelect_20230802-084324_Pro.jpg

Paul Bowers

unread,
Aug 2, 2023, 3:51:48 AM8/2/23
to Sailforms Users
SmartSelect_20230802-084907_Pro.jpg

Paul Bowers

unread,
Aug 13, 2023, 7:14:10 AM8/13/23
to Sailforms Users
Attached is my latest build. It has a huge number of added features

Do while
Gosub return
For next
Array support
Syntax checker
Mixed variables and literals
Extended range of functions in let
Ascii support

And so on
Example in the program Library

Some practical examples such as dec2hex and hex2dec call on these extended functions

Enjoy

Park

Programable_Calculator.sfg

Paul Bowers

unread,
Aug 13, 2023, 7:28:44 AM8/13/23
to Sailforms Users
SmartSelect_20230803-151815_Pro.jpg

Forgot to mention, started playing with some basic graphics, block ones anyway

Paul Bowers

unread,
Aug 30, 2023, 9:17:54 AM8/30/23
to Sailforms Users
SmartSelect_20230830-135156_Pro.jpg

Its been a couple of weeks since my last update, and I have been working on another project for the village museum and history society
to create a solution to browse all the records and photos (55,000 entries and 10,000 photos) - I found the best way to link the photos was via a local 
host URL from a text/Web field - but thats another thread.

Have I reached the end on this project. Well, not quite. I have added a heap of new functions to the LET command and IF x GOSUB support etc. but the issue is with any interpreted runtime - the more functions you put in the slower it can get. I have sequenced the most used commands etc near the top of the 
parser selector - to speed up etc - but there must be a way of making apps run quicker. Some complex math operations are quite sluggish. So the answer
was quite simple in the end. I have implemented a simple inline assembler mode. Still interpreted, but  run on its own parsing thread, and with a very small
subset of commands with no realtime on the fly parsing - it at least 50% faster on execution of those functions. I have also started a Syntax checker feature.

Define variables in BASIC mode to push them on to the heap. You can then use PULL and PUSH in ASM mode to access them and enable your assembler function to interact with BASIC.

The ASM command in the BASIC program triggers handover of the runtime to the Assembler. The HLT is the last command of the assembler and returns back to the BASIC code.

The assembler has two registers X and Y - both integer group variables 

I have implemented the following assembler commands -X and Y are fully interchangeable 

MOV X,Y 
MOV VAL,Y 
INC X 
DEC X 
ADD X,Y
ADD val X 
SUB X,Y
SUB val,Y
DIV X,Y
DIV val,Y
MUL X,Y
MUL val,Y
PULL A%,X
PUSH Y,A%
JNZ X,STEPS (or -STEP) Jump if register is not zero - for relative branching - no navigation lookup
CMP X,Y
CMP VAL,Y  
JLT label based on last CMP result - Jump if less than
JGT label Jump if greater than
JEQ label Jump if equall
JNE label Jump not equal
HLT STOP and return to BASIC

BASIC now supports the following commands and functions

LABELS:
MAIN: ENTRY POINT FOR CHAINING
REM OR !
INPUT VAR%;
INPUT STRING$;
PRINT VAR%,;  COMMA SURPRESSES CRLF
PRINT VAR$,
PRINT FMT('%%',VAR%), LEADING ZEROS
PRINT FMT('##',VAR%) LEADING SPACES
IF VAR {OPERATOR} VAR THEN LABEL
IF VAR {OPR} VAR GOSUB LABEL
GOTO LABEL
GOSUB LABEL
RETURN
FOR VAR=VAL TO VAL STEP LITERAL (CAN BE NEGATIVE TO COUNT DOWN)
NEXT VAR
DO, WHILE VAR%<>=!VAL
DIM VAR$='VALUE'
DIM VAR%=LITERAL
DIM VAR%=INT(VAR%); {ROUNDS UP OR DOWN FP VARIABLE}
ARRAY VAR
SET VAR(X%,Y%)=VAR
GET VAR=VAR(X%,Y%)
LET VAR=VAR+VAR; (+-*/^)
LET VAR=VAL(VAR$)
LET VAR=MID$(VAR$,START,LEN)
LET VAR%=INSTR$(VAR$,VAR$);
LET VAR$=REP$(VAR$,VAR$)
LET VAR$=HEX$(VAR%)
LET VAR$=ASC(VAR%)
LET VAR%=LEN(VAR$)
LET VAR%=CHR$(VAR$)
LET VAR%=MOD(VAR%,VAR%)
LET VAR%=ABS(-VAR%)
LET VAR$=DATE$()
LET VAR$=TIME$()
LET VAR%=INT(VAR) TRUNCATES FP VARIABLE
LET VAR$=STRING$(VAR$,LITERAL)
LET VAR$=STRING$(VAR$,VAR%)
LET VAR$=UCASE(VAR$)
LET VAR$=LCASE(VAR$)
LET VAR=VAR
HEAP GLOBAL 
HEAP LOCAL
DELETE 'FILENAME'
OPEN FILENAME
WRITE FILENAME,VAR
DELREC FILENAME
READ FILENAME,VAR
CLOSE FILENAME
SEARCH FILENAME,PATTERN$, RESULTS$. NOF IS NOT FOUND
STOP RUN
CHAIN PROGRAM
DROP VAR - REMOVES ENTRY FROM HEAP
PUSH VAR% -PUSH VAL TO CALC SCREEN JOURNAL
CLS LINENO
CLS VAR%
ASM START OF ASSEMBER ROUTINE
HLT END OF ASSEMBLER ROUTINE

is this the end - we shall see what ideas come to front - may be some simple SQL - we shall see how that pans out. but I appear to be able to push SailForms a bit more yet.
Programable_Calculator.sfg
Reply all
Reply to author
Forward
0 new messages