Whilst I have discussed some of the wider aspects of SIMPL , I thought that it might be beneficial to take it back to its roots, as a simple sketch running on an Arduino Uno.
SIMPL was inspired by Ward Cunningham's Txtzyme and it was his compact interpreter that provides an essential part of the evolution.
Ward Cunningham's Txtzyme made good use of the lowercase alpha characters as a series of inbuilt commands designed to allow the hardware peripherals to be exercised.
This has been well documented in Ward's Txtzyme Github so won't be repeated here, needless to say that SIMPL has incorporated these commands and uses the same convention of lowercase alpha characters for inbuilt hardware functions.
Deconstructing SIMPL
SIMPL can be broken down into a few basic routines:
Read a character from RAM txtRead
Compare against colon character txtChk
Look up the character and execute associated code block txtEval
These 3 routines are enclosed in a tight loop and provide the Read-Evaluate-Print Loop
In Arduino the code is as follows:
void loop() // This is the endless while loop which implements the interpreter
{
txtRead(buf, 64); // Get the next "instruction" character from the buffer
txtChk(buf); // check if it is a : character for beginning a colon definition
txtEval(buf); // evaluate and execute the instruction
}
Supporting these routines, are four others for handling the serial input and output and numerical conversion
u_getchar Get a character from the UART
u_putchar Send a character to the UART
number Read in a decimal numeric string and convert it into a 16-bit integer stored into a variable x
printnum16 Print out the 16-bit decimal integer stored in x via the UART
With just these 7 routines you have the fundamental building blocks to build the SIMPL kernel, and with this kernel create a framework from which the remainder of the application can be built.
To keep the kernel codesize to a minimum, I have avoided the Arduino serial library. Instead I have used very compact UART code borrowed from AVR Freaks.
As such, the 16-bit kernel fits into 1500 bytes. With a change to printnum16 it can be modified to accept 32-bit integers. This pushes the code up to 1688 bytes.
I have placed the 32-bit SIMPL kernel code in my SIMPL Github repository.
Extending the Kernel
At this point, the kernel is very basic, - purposefully with very few functions.
- You can enter a 32-bit decimal number, which is stored in a variable x eg. 1234567890 enter
- You can enter a 2nd decimal number separated by a space and it will be stored in variable y eg. 123456789 54321 enter
- You can print out the value of x as a 32-bit decimal number using the p command 9876543210p
- You can assign a 32-bit number to any of the user functions A-Z, using the colon command :A2468013579 and print it later using the p command Ap
- You can use the ? command to list all of the User Commands A-Z and see if any value or code has been allocated to them.
Maths Operations
The obvious extension to the kernel is to add the maths functions, addition, subtraction, multiplication and division.
It is necessary to provide the means for a second parameter, y. Txtzyme only allows one parameter x.
Providing a second variable to hold the y parameter makes arithmetic and logic operations possible.
When a number is entered, it automatically is placed in the x variable. By inserting an ascii space invokes a transfer of the first number from x into y, and allows a second number to be entered.
123 456 this puts 123 into x, transfers it to y and then places 456 into x.
We can then add the + operator to make addition possible:
123 456+p ADD 123 to 456 and print it out as a decimal number.
We can now add the four common maths operations to the code.
case '+': x = x+y; break; // ADD
case '-': x = x-y; break; // SUB
case '*': x = x*y; break; // MUL
case '/': x = x/y; break; // DIV
This effectively forms the basis of a very simple 4 function calculator, but the printnum routine will have to be modified to handle negative numbers. Adding these 4 functions pushes the codesize up to 1940 bytes.
So building upon the basic numerical input and output routines we add the maths functions and this makes simple calculations possible.
We can also add the logic operations: AND, OR, XOR and INV:
case '&': x = x&y; break; // AND
case '|': x = x|y; break; // OR
case '^': x = x^y; break; // XOR
case '~': x = ~x ; break; // INV
Looping
One of the principle functions borrowed from Txtzyme is the looping structure.
This introduces a new parameter k which is equal to the loop index counter. k is used to initiate the loop function and is decremented each time the interpreter executes the loop.
The loop terminates when k=0. The code to be executed in the loop is contained within curly braces {...........}. If the loop counter k is set to zero, the code within the braces will never be executed - and this can be used to create inline comments, eg. 0{This is a comment}
Adding the looping control code increases the codesize to 2124 bytes
// Looping and program control group
case '{':
k = x;
loop = buf;
while ((ch = *buf++) && ch != '}') {
}
case '}':
if (k) {
k--;
buf = loop;
}
break;
case 'k': x = k; break;
SIMPL follows a subtley different approach to Txtzyme, whilst retaining basic functional compatibility. SIMPL has been designed to provide an executable symbolic language for virtual machines - as an alternative to their native assembly language.
With arithmetic commands and the loop structure that allows conditional flow there is the basis of a simple virtual machine instruction set.
In the next log we will look at the options for implementing a virtual machine.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.
Ah. Thanks for expanding this. I didn't understand the x y syntax before.
I don't have an application right now but SIMPL looks like a tool that will find a use.
Are you sure? yes | no
Adding a second variable makes arithmetic and logic functions possible. It's a simplification of having a data stack, where one value is pushed down the stack to make room for a new value to be input. It's effectively a two level stack, which is about as simple as you can get. If it were a full Forth, it would have many more levels. The next log will add further functions to take it from a four function desktop calculator to the equivalent of a small programmable cpu.
For the moment I will be using a standard Arduino Uno to illustrate the code. If it can be written for an 8-bit microcontroller such as the ATmega328, it can be written for any other mcu. Thanks for following.
Are you sure? yes | no