Monday, February 01, 2016

A Review of Tiny Languages - Part 3

Last time I explained how to add more functionality to Txtzyme to build up a more versatile language that I call SIMPL.

In this post I look at a couple of ways to perform program flow control.

The latest version of SIMPL is located at this Github Gist  - and includes the code below.

The 16 bit maths version compilese to 2268 bytes, whilst the 32 bit version, with it's more complicated 32bit maths routines adds a further 624 bytes.


Program Flow Control

So far, SIMPL lacks many of the usual program flow control constructs:

IF-THEN-ELSE

FOR-NEXT

DO-WHILE

SWITCH - CASE


1. Simple Loop

SIMPL has a simple loop construct - where a block of code can be repeated k times before exiting the loop.

10{kp_ Green Bottles_}

This initialises the loop counter k to 10, and prints it out along with the text Green Bottles, decrementing k each time it goes around the loop.

This is similar to C's    while(k)      // k>0
                                 { some task;
                                  k-- ;
                                 }

When executed, you will get this screen output:

9 Green Bottles
8 Green Bottles
7 Green Bottles
6 Green Bottles
5 Green Bottles
4 Green Bottles
3 Green Bottles
2 Green Bottles
1 Green Bottles
0 Green Bottles

ok

It is also reminiscent of the old Z80 instruction DJNZ, in which the B register was decremented and a relative jump to a label if it was non-zero.  In SIMPL we effectively have 26 labels - the capital letters A to Z so this could be quite a useful feature.   Loop can be used for any repetitive output task - such as flashing LEDs or playing musical tones.

The next construct required is the conditional jump.  Here the number on the top of the stack, x should be compared against a constant y and a call to a block of code executed whilst the comparison remains true.

We have the means to perform logical and comparison operations on the top value of the stack.

AND   &
OR      |
XOR   ^

These perform bitwise logic on the x and y operands.

AND may be used to check if  x != 0   as it returns 1 for any value of x other than zero
OR can check if x = 0
XOR  can check if x != y

Greater Than  >   if  x > y  return 1
Less Than      <   if x  < y  return 1

Any of these operations may combined with a skip operation - skipping over the next operation if the result is true.

Here's the C implementation of the  SIMPL comparison and jump operators:

// Comparison Test and conditional Group
   
      case '<':
      if(x       break;
   
      case '>':
      if(x > y){x=1;}      // If x > y x= 1 - can be combined with jump j
      else x=0;
      break;
   
      case 'j':                  // test  if x = 1 and jump next instruction  
      if(x==1){*buf++;}  
      break;


So we want to turn these simple comparisons into a more familiar IF-THEN construct.

The block of code to conditionally execute will be enclosed within square brackets  [   ]

If the result if the comparison is true - then the code withing the brackets is executed, if false, the interpreter skips the words until it finds the last bracket and then resumes execution there.

Example   If x > 10 then print "x greater than 10 "

11 10 >[_x greater than 10_]

11 assigns 11 to x 
"space" moves x to y
10 assigns 10 to x 
>  performs x >y
[   tests x for true
_x greater than 10_   prints the message
]  marks the end of the conditional execution block


Case Selection

The switch-case statement is a powerful mechanism in C, can it be easily implement in SIMPL?

We could restrict the number of cases to 26, allowing any of the capital letter words to be accessed directly.

Alternatively, we could select a phrase of code from a list of options - based on the value of x. This second methods is more general and is a lot more flexible, as it can incorporate the first method.

We need a pair of balanced characters to instruct the interpreter that we are looking at a list -  so we could use simple parentheses and comma separated elements as follows (, , ,)

We then do a selection of the elements based on the numerical value of x.  The interpreter then jumps into the array, skipping over the entries until the correct one is found.

As an example, the word M is code for _This is a test Message_

5(0p,1p,2p,3p,4p,M,6p)  should select M and print the associated message

A second example adds two integers and prints the message if the result is 3

1 2+(0p,1p,2p,M,4p,5p,6p)

The mechanism to do the skipping can be quite elegant using some simple rules:

First, the value of x is copied into the loop-counter variable k.
If k > 0 the interpreter checks each character in turn incrementing the buffer pointer. If a comma is detected, signifying the end of the first list entry , k is decremented.
If k is zero, the interpreter executes the following table entries until the next comma is detected, this also subtracts one from k forcing it to be less than zero, this condition then forces a break out of the list.  If the final ) is found - this also forces a break out of the selection statement.

This construct is derived from the SIMPL Loop method. We provide C code for two new case statements "(" and ","

// Select the xth member from the list
// Example 5(0p,1p,2p,3p,4p,5p,6p)  should select 5 and print it

 case '(':

      k = x;                                                 // copy x to use as the "phrase counter"                                                              
      while (k)
      {
      ch = *buf++;
      if (ch == ',')                                       // decrement k to see whether to interpret or not
      { k--;}    
      }  
      break;
   
      case ',':
   
      k--;                                          
      while (k<0 nbsp="" y="">

      {
      ch = *buf++;                                    // skip the remaining characters
      if (ch == ')') {break;}
      }
   
      break;

This technique could also be used as a look up table, where a given x is converted into a different value according to a list of numbers.

10(1,2,3,4,5,6,7,8,100,200,300,400)p

This will select element 10 (300) and print it. Note that the first element is zero!





1 comment:

viscomjim said...

Just found your blog. Very cool. Have you ever taken a look at mmbasic and the micromite? It is based on a PIC32 and runs a very powerful BASIC. You only need the chip, a capacitor and a 3.3v power supply. Has a built in editor and LOTS of functionality. I've been using this since its beginning and it has really grown to a very useful little machine. Take a look here...

http://geoffg.net/micromite.html

Also there is a great support forum here...

http://www.thebackshed.com/forum/forum_topics.asp?FID=16&PN=1

Have a great day!