P-Charme interpreter                                         Frans van Hoesel
=============================================================================
An interpreter for structured BASIC.


Statements and functions
------------------------

AUTO          Automatic line-numbering and indentation               A.

  Examples: AUTO          - first line  10, each next one  10 higher.
            AUTO 40       - first line  40, each next one  10 higher.
            AUTO ,20      - first line  10, each next one  20 higher.
            AUTO 100,100  - first line 100, each next one 100 higher.


BEEP          Generate sound                                         BE.

  Emits a tone of a specific pitch and duration. The syntaxis is:

    BEEP ,


BSAVE         Basic save                                             BS.

  The command is the same as the normal SAVE statement. The program,
  however, gets another execution address (#AFAF inside the P-Charme).
  This effectively makes it possible to *RUN basic programs, that
  require stack, free space pointer etc. to be initialized.
  On the Atom Emulator, however, it only works if P-Charme is selected.


CASE          Case ... Of                                            CA.

  Examples: 10 CASE J-48 OF
            20 2 PRINT "THIS IS EVEN"'
            30 3 PRINT "THIS IS "
            40    PRINT "ODD"'
            50 1 PRINT "J = 49"'
            60 CEND

            10 CASE $A OF
            20"SWEET"  PRINT "NICE"'
            30"BORING" PRINT "DULL"'
            40$A      PRINT "NO IDEA"'
            50 CEND

  If a case expression does not equal a case label, program execution is
  resumed right behind CEND. In the second example, the case label at line
  40 always satisfies, and is therefore executed if the others do not.
  CASE statements may not be nested.


CAT           Catalog

  This statement shows a list with all the programs that are resident in
  the memory area #1000 to #9FFFF, starting with PROGRAM.


CONT          Continue

  May be used to resume program execution after a STOP.


COPY          Copy memory areas

  The syntaxis is as follows:

    COPY expr, expr, expr

  The first expression is the start address, the second is the end address
  of the area that is to be copied. The last expression is the destination
  memory address. If this one is within the boundaries of the source area,
  the COPY statement effectively is a FILL command. For example

    COPY #2000,#3000,#2004

  The result of this command is the the area between 32000 and 33004
  repeatedly contains the same four bytes.


COS           Casette operation system

  Example: COS 0  -  300 baud
           COS 1  - 1200 baud


DATA

  See READ and RESTORE.


DEL           Delete line

  Examples: DEL 200,300     - Delete lines 200 to 300.
            DEL /REM/,300L  - Lines 0 to 300, containing the text 'REM'.
            DEL /STOP/V     - All lines that contain the text 'STOP'.
            DEL             - Delete all lines (be careful!).

  If the Veto option (V) is selected, a line is printed on screen first
  and a query will be made Y/N? There are several possible answers:
     Y - YES       proceed with the operation,
     N - NO        do not execute the operation,
     C - CONTINUE  proceed with the operation and disable the veto option,
     L - LIST      execute the operation and go on without the veto
                   option, however, do list all the lines that are changed,
     S - SKIP      do not execute the operation and go on to the next line,
     ESC           do not proceed with the operation and go back to direct
                   mode.


ELSE

  This is the alternative for the XIF statement. The line behind ELSE is
  executed only if the expression behind XIF is false.


EVEN                                                                 EV.

  This function has the value TRUE (1) if the argument is even. Syntaxis:

    EVEN (factor)


FALSE                                                                FA.

  Always results in the value 0. 'A=0' and 'A=FALSE' are completely equal.


FEND          Function end

  This statement delimits the end of a FUNCTION block.


FUNCTION      Function declaration                                   FUNC.

  Function can be used to calculate one value, which on its turn is to be
  used in an expression. Functions begin with the FUNCTION statement and
  end with the FEND statement. Example:

    10 PROGRAM FTEST
    20
    30 FUNCTION ADD(A,B)
    40  ADD=A+B
    50 FEND
    60
    70 PRINT 2*ADD(5,6)
    80 END

  Recursive functions are allowed as well:

    FUNCTION GCD(M,N)
     XIF N=0 THEN GCD=M
     ELSE GCD=GCD(N,M%N)
    FEND

  It is NOT allowed to used DIM inside functions and procedures.


HEX           Hexadecimal / ASCII dump

  Hexdump is started from the specified address. The syntaxis is:

    HEX 


HTAB          Horizontal tabulation                                  HT.

  This statement is especially useful when creating tables. Example:

    HTAB 16


ICOPY         Intelligent copy                                       IC.

  This is almost the same as the COPY statement. However, the fill effect
  cannot occur with this statement.


INKEY         Input key                                              INK.

  The INKEY statement waits until a key is pressed, and then assigns an
  ASCII value to the specified variable. Example:

    DO
     INKEY A
     PRINT $A
    UNTIL A=CH"."


INSTR         In string                                              I.

  With this integer function a string can be saught in another string. The
  syntaxis is:

    INSTR (string var,string right)

  The brackets ( and ) are obligatory. The functions starts seaching in
  the first string for the second string. If found, INSTR is assigned the
  value of the position, otherwise it's zero. INSTR may also be used in
  a logical expression. Examples:

    P=INSTR($A,"HALLO")
    R=INSTR($B+6,$C); REM search from 6th position in $B onwards.
    IF INSTR($D,$E) THEN PRINT "FOUND"'


KEY           Single keyboard scanner                                K.

  The keyboard is scanned through once and an ASCII value is assigned to
  the specified variable.


NOT                                                                  N.

  This function equals a logical negation. The values of NOT are
  exclusively FALSE or TRUE (0 or 1).


ODD                                                                  O.

  This function has the value TRUE (1) if the argument is odd. Syntaxis:

    ODD (factor)


ON ERROR                                                             O.

  For trapping BASIC errors.


ON ... GOSUB  Gosub selector

  This statement is used to choose from a number of possibilities.
  Example:

     10 INPUT S
     20 ON S GOSUB 100,110,50,a,70
     30 PRINT"*"'
     40 GOTO 10
     50 PRINT "THREE";RETURN
     70 PRINT "FIVE";RETURN
     80aPRINT "FOUR";RETURN
    100 PRINT "ONE";RETURN
    110 PRINT "TWO";RETURN


ON ... GOTO

  This statement is the same as ON ... GOSUB, except for the fact that
  GOSUB is replaced by GOTO.


PAUSE         Delay program execution                                PA.

  PAUSE is followed by an expression. PAUSE 60 waits for one second.


PEND          Procedure end

  This statement delimits the end of a PROC block.


POP

  This statement gets one return address from the GOSUB stack. It
  cannot cause an error.


PROC          Procedure declaration

  Within a procedure there are three types of variables:
  -Local variables
  -Value parameters
  -Output variables

  Examples:  10 PROGRAM EXAMPLE
             20
             30 PROC FIX-PRINT (%A),Z,@
             40  Z=%(%A*1000+5)/10;PRINT Z/100
             50  @=0;Z=Z%100
             60  PRINT "."Z/10,Z%10
             70 PEND
             80
             90 @=11
            100 FOR I=1 TO 5
            110  READ %F
            120  FPRINT %F;FIX-PRINT(%F)
            130  PRINT'
            140 NEXT I
            150 END
            160
            170 DATA 10,1/3,2/3,10.9999,0

            Herein %A is a value parameter. Z and @ are local variables.


             10 PROGRAM EXTREME
             20
             30 PROC MINMAX (A,B:G,S)
             40  XIF A>B THEN G=A
             50  ELSE G=B
             60  XIF A <B THEN S=A
             70  ELSE S=B
             80 PEND
             90
            100 MINMAX(3,7,X,Y);PRINT X,Y'
            110 A=1;B=2;G=3;K=4
            120 MINMAX(G,12,X,Y);PRINT X,Y'
            130 PRINT A,B,G,K'
            140 END

            Herein A and B are value parameters. G and S are ouput
            variables.
            The output of the program is:

             7     3
            12     3
             1     2     3     4

  Recursion is allowed as well. Example:

            PROC STAR(N)
              IF N>1 PRINT "*";STAR(N-1)
              IF N=1 PRINT "*"
            PEND

  It is NOT allowed to used DIM inside functions and procedures.


PROGRAM       Program heading

  Behind this statement there is room for a name. The rest of the line is
  regarded as comment. Besides giving a name to a program, the following
  features are supported:
  1-Automatical RESTORE at the start of the program,
  2-Initialization of procedures and functions,
  3-Initialization of built-in functions (INSTR, EVEN etc),
  4-Initialization of error pointer routines,
  5-Initialization of multi-dimensional arrays,
  6-Initialization of WHILE loops,
  7-Recognition for the CAT statement.

  Item 2 effectively fills the area #28DD-#28FF with #00. This area is NOT
  used by the floating point ROM. For Item 3, 4 and 5 the BRKVEC is changed
  for the duration of the program.
  A correct program name begins with two different characters. Here are
  some examples:

    10 PROGRAM TEST VERSIE IV    - the name here is 'TEST'
    10 PROGRAM CRC-TEST          - the name here is 'CRC-TEST'
    10 PROGRAM QS(QUICK START)   - the name here is 'QS'
    10 PROGRAM -A Anemometer     - the name here is '-A'

  If the program is resident in the memory area #1000-#9FFF and if there's
  one space between the NOT abreviated statement PROGRAM and the line number
  the program name is automatically promoted to a statement.
  Typing a program name results in searching the memory for that program,
  initializing the labels, clearing the FOR-NEXT, DO-UNTIL and GOSUB-stacks,
  setting the value of TOP and starting the program.


READ          Read data

  With the READ statement integer, floating point variables, arrays and
  multi-dimensional arrays, and string variables can be read. Example:

    READ A,B,%A,%B,$T,DD(12),%FF(3,4)


RENUM         Renumber program                                       REN.

  This command renumbers the program accoring to the specified expressions.


RESTORE       Restore data                                           RES.

  With this statement the data-pointer can be set to a specific line.
  Examples:

    RESTORE
    RESTORE 160
    RESTORE a


STOP          Stop execution

  This statement is ment for trapping errors. If a program is stopped, the
  text 'STOPPED AT LINE ...' is printed. Execution can be resumed by typing
  CONT.


TRUE                                                                 TR.

  Always results in the value 1. 'A=1' and 'A=TRUE' are completely equal.


VAR           Variable dump

  This statement shows the values of the variables A to Z.


VTAB          Vertical tabulation                                    V.

  The syntaxis for this stament is:

    VTAB 


WEND          End of WHILE loop

  This statement delimits the end of the WHILE loop.


WHILE         WHILE loop

  A WHILE block is executed until the expression behind WHILE is FALSE.
  The WHILE statement can be nested up to 10 levels deep.


XIF           Expanded IF

  The XIF statement must be used together with ELSE. If the expression
  behind XIF is TRUE, the block behind it is executed and the line behind
  ELSE not. And vice versa, if the expression behind XIF is FALSE.
  The ELSE statement may not be abreviated and must be at the beginning of
  a line.
  XIF...THEN...ELSE constructions may be nested unlimited. Example:

    10 XIF A+9=B-2 THEN I=1
    20  Z=S?I
    30  S?I=S?J
    40  XIF %X=PI THEN PRINT '"PI="
    60   PRINT "3.1415"'
    70  ELSE PRINT'"NO PI"'
    80 ELSE I=2
    90 PRINT I'

  Note that the THEN part may be spread over more than one line, and the
  ELSE part can take no more than one line.


ZERO          Clear variables                                        Z.

  Fills the BASIC variables A to Z with the value 0.


/             Find text

  With the FIND command a certain text can be saught in a program. Line
  numbers are not a part of the text. Examples:

    /REM/        - searches for the text 'REM' in the entire program,
    /STOP/200,   - searches 'STOP' from line 200 onwards,
    /$A/,1000    - searches '$A' until line 1000.


/             Change text

  With this command text can be saught and replaced. Examples:

    /A$/$A/           - replace 'A$' by '$A',
    /STEP -1/STEP 1/V - replace 'STEP -1' by 'STEP 1' with veto,
    / //L             - remove all spaces with the list option
    /DIM/FDIM/,100V   - replace 'DIM' by 'FDIM' in the lines 0 to 100 with
                        the veto option.



Multi-dimensional arrays
------------------------
With P-Charme it is possible to use multi-dimensional arrays. Example:

   10 PROGRAM ARRAY
   20
   30 DIM TT(5,4,2)
   40 A=0
   50 FOR I=0 TO 5
   60   FOR J=0 TO 4
   70     FOR K=0 TO 2
   80       TT(I,J,K)=A
   90       A=A+1
  100     NEXT K
  110   NEXT J
  120 NEXT I
  130 PRINT TT(1,1,2)'
  140 END

All indices are checked. If, for example, line 130 is changed into

  130 PRINT TT(1,5,2)'

error 134 (Array subscript out of range) is generated. Multi-dimensional
arrays can only be used in programs, and only if it begins with the
PROGRAM header. If you would like to know the value of TT(5,3,1) in direct
mode, the following must be entered:

  PRINT TT((5*(4+1)+3)*(2+1)+1)

Herein (4+1) is one more than the second dimension and (2+1) is one more
than the third dimension of the array TT. A statement like DIM SS(7) has
(7+1) elements also.
Multi-dimensional floating point arrays are possible as well.

Note that brackets ( and ) are obligatory. The maximum number of dimensions
is 9.



String functions
----------------
With exception of INSTR, no new string-handling functions have been added.
The following examples, however, show that it is very easy to implement
them yourself:

  FUNCTION LEFT(S,L)
    IF L<1 OR LEN(S)>64 THEN ERROR
    $#140=$S;L?#141=13
    LEFT=#140
  FEND

  FUNCTION RIGHT(S,L)
    IF L<1 OR LEN(S)>64 THEN ERROR
    $#140=$S;IF L64 THEN ERROR
    ?#140=13;IF L<=LEN(S) $#140=$S+L-1;M?#140=13
    MID=#140
  FEND

Since the word ERROR is not a statement, the interpreter will produce error
94 on an attempt to interpret ERROR.
Note that, although functions (and procedures) don't "know" string variables
it is very well possible to handle strings by passing the string's address.
If the strings are no longer than 64 characters, the string buffer at #140
can safely be used. For longer strings, a buffer must be dimensioned first
outside the functions. Example:

  $S="THIS IS A STRING"
  PRINT $LEFT(S,6)        - THIS IS
  PRINT $RIGHT(S,10)      - S A STRING
  PRINT $MID(S,2,6)       - HIS IS



Expanding the P-Charme interpreter
----------------------------------
There are three ways to expand the interpreter. The first one is the easiest
and most obvious way: Just writing it in BASIC. See the PROGRAM statement.
Example:

   10 PROGRAM HELP
   20
   30 DIM S64
   40 $S=$#100
   50 K=INSTR(S,"HELP")
   60 IF K=0 THEN PRINT '"SORRY, NO HELP."';GOTO e
   70 E=VAL(#100+K+3)
   80 CASE E OF
   90<2>  PRINT "TOO MANY GOSUBS"
  100<6>  PRINT "CHECKSUM ERROR"
  110<18> PRINT "TOO MANY DO STATEMENTS"
  120<29> PRINT "UNKNOWN OR MISSING FUNCTION"
  130 REM etc.
  140 CEND
  150 PRINT '
  160e?18=#29
  170 END

Try typing

  HELP 29


The second way offers a lot more possibilities, but require more skill. It
must be written in machine code and is preceded by a table. A table must
always start on a new page (low byte #00). The P-Charme interpreter will
check the table if the second byte on the page equals #E3 and the third
byte equals #C6. It is wise to put #FF in the first byte. The rest of the
table is followed by subsequently the name of a statement and its address.
The high byte of the address comes first, and the MSB is always set. This
results is address which are always higher than or equal to #8000.
If, however, the table is in the memory area lower than #8000, the P-Charme
interpreter substracts #8000 from the address.
The table must be ended with a byte equal to #80. The table may not be
larger than 256 bytes. Example:

      3B00 FF (page extension byte)
      3B01 E3
      3B02 C6
      3B03 43 C
      3B04 4C L
      3B05 53 S
      3B06 BB (=3B+80)
      3B07 10
      3B08 53 S
      3B09 54 T
      3B0A 41 A
      3B0B 52 R
      3B0C BB (=3B+80)
      3B0D 19
      3B0E 80 (end of table)

 CLS  3B10 JSR C4E4
      3B13 JSR FD6D
      3B16 JMP C55B
 STAR 3B19 JSR C4E1
      3B1C LDX 04
      3B1E DEX
      3B1F STX 04
      3B21 LDA 16,X
      3B23 TAY
      3B24 LDA @2A
      3B26 JSR FFF4
      3B29 DEY
      3B2A BNE 3B26
      3B2C JMP C55B

 To tell the interpreter where the table is, the page number must be POKEd
 into memory address #3FE (here it is #3B). It is possible to use more than
 one table. The first byte in a table (the page extension byte) must point
 to the following page. The page extenstion byte of the last table should
 be #FF.
 Please note the following notes:
 1. Almost all the statements end with JMP #C55B
 2. Statements without parameters always begin with JSR #C4E4 to test
    whether or not the statement is followed by ';' or CR.
 3. Statements with one expression as parameter, begin with JSR #C4E1.
    The expression is read, and then the routine at #C4E4 is done.


The third way to expand the P-Charme is somewhat difficult. During program
execution, the P-Charme interpreter uses the BRK-vector. If during program
execution an error occurs and memory address #3FB contains the value #B3
and memory address #3EE is zero, the instruction

  JMP (#03EE)

is executed. This test is done before the built-in functions and multi-
dimensional arrays are handled.
This last method is for experienced programmers only.



Error messages
--------------
22  Out of data
      A read is being commited when there are no more DATA lines.


38  Stack error in PROC or FUNCTION block
      The control byte, stored during the call of the procedure or function
      in the free space, has changed on executing PEND or FEND. This could
      have been caused by a DIM statement within a procedure or function.

84  Illegal function

120 '(' expected

129 Division by zero; Missing CEND; Protected RAM

132 WEND without WHILE

133 Variable expected after KEY or INKEY

135 Out of memory; SYNtax error
      Not enough memory to execute a function or procedure. SYNtax error in
      the COS statement.

137 Error in parameterlist; paremeter expression too complicated.

163 Illegal or too many names

166 Missing PEND or FEND

182 Line not found in RESTORE

200 Malformed string
      An odd number of quotes was used, or a '/' is missing.

210 Missing CEND

222 Variable expected

237 Can't continue; Illegal STOP in direct mode

242 Too many WHILE statements

249 Missing WEND, missing ELSE



Memory usage
------------
The P-Charme interpreter only uses zero page addresses #90-#99.
The memory area #28BD-#28FF is used to keep the addresses of functions
and procedures.