Introducing interp

interp is a portable programming language, a testing platform, and a development framework. It is targeted for Linux and Unix-based systems, yet remains adaptable for less powerful embedded systems that were never intended to support an interactive programming language because all you need is a serial port.

You can use interp interactively, write programs in it, or externally script your interactive sessions (e.g. through files.) You can write extensions to the language and add the missing bits you need.

Because interp is an interactive language, when you start it, you get this prompt:

interp>

If you want to add two numbers and display the result with a calculator, you would type something like this:

12+3=

To do this with interp, you would type this (at the prompt):

12 3 + .

To do the same thing in c, you would write this:

printf( "%d\n",12+3);

A function that returns the larger of two integers looks like this in c:

int max( int num1, int num2)
{
  int retval;
  
  if ( num1 > num2 )  /* is num1 greater than num2? */
    retval = num1;    /* yes, num1 will be returned */
  else
    retval = num2;    /* no, num2 will be returned */
	
  return retval;      /* return the larger number */
}

or like this in interp:

__ m ( num1 num2 -- larger )
__ This function returns the larger of the top 2 stack items.
#BUFFER
{m
#define num1=0L
#define num2=1L

   num2 !		__ the top stack item is num2
   num1 !		__ then next one down is num1

   num1 @ num2 @ > if	__ is num1 > num2 ?
      num1 @		__ yes, put num1 on the stack
   else
      num2 @		__ no, put num2 on the stack
   endif

#undefine num1
#undefine num2
}			__ return with the larger number on the stack
#EXECUTE

To invoke the c function:

printf( "%d\n", max(3,5));

To invoke the interp function:

3 5 Fm .

We can give the interp function an alias:

#define Max=Fm

Which lets us invoke it in a more memorable way:

3 5 Max .

Like any versatile programming language, there is usually more than one way to perform any given action. The preceding function that returns the larger of two integers, can also be rewritten more compactly and efficiently:

__ m ( num1 num2 -- larger )
__ This function more efficiently returns the larger of the top 2 stack items.
#BUFFER
{m
   2dup                 __ duplicate the top two stack items 
   < if swap endif   __ put the smaller item on top
   drop                 __ drop the smaller, leaving the larger
}			__ return with the larger number on the stack
#EXECUTE

This final example shows how to use a time-saving feature, the print iterator, to create a simple memory dump function by printing directly from memory:

# This example expects a memory address on top of the stack and prints 256
# bytes of memory in hex, as 16 rows of eight 16-bit values.

__ FD ( addr -- ) print 256 bytes of memory in hex,
__                as 16 rows of 8 16-bit vals
__    usage example: 8 K dump
#BUFFER
{D
    1~&                __ force address to be halfword-aligned
    255 over + swap    __ convert addr to end-addr start-addr
    loop 2dup swap <= while  __ while start-addr is <= end-addr
      dup                       __ copy the row start-addr 
      "!A @a: @h @h @h @h @h @h @h @h\n" __ print a row
      16+                       __ advance to next row start
    endloop
    2drop              __ drop start-addr end-addr from stack
}
#EXECUTE
#define dump=FD

And just to impress you, here's how great the output looks:

 0x00497b98: 0x2364 0x0040 0x2405 0x0040 0x2405 0x0040 0x2405 0x0040
 0x00497ba8: 0x2405 0x0040 0x2405 0x0040 0x2405 0x0040 0x2405 0x0040
 0x00497bb8: 0x2405 0x0040 0x2424 0x0040 0x2424 0x0040 0x2405 0x0040
 0x00497bc8: 0x2424 0x0040 0x2424 0x0040 0x2405 0x0040 0x2405 0x0040
 0x00497bd8: 0x2405 0x0040 0x2405 0x0040 0x2405 0x0040 0x2405 0x0040
 0x00497be8: 0x2405 0x0040 0x2405 0x0040 0x2405 0x0040 0x2405 0x0040
 0x00497bf8: 0x2405 0x0040 0x2405 0x0040 0x2405 0x0040 0x2405 0x0040
 0x00497c08: 0x2405 0x0040 0x2405 0x0040 0x2405 0x0040 0x2405 0x0040
 0x00497c18: 0x2424 0x0040 0x2665 0x0040 0x2cd0 0x0040 0x2405 0x0040
 0x00497c28: 0x3001 0x0040 0x2520 0x0040 0x2591 0x0040 0x2e28 0x0040
 0x00497c38: 0x2f82 0x0040 0x34f0 0x0040 0x2495 0x0040 0x2440 0x0040
 0x00497c48: 0x2ca4 0x0040 0x2474 0x0040 0x2c80 0x0040 0x24d5 0x0040
 0x00497c58: 0x3140 0x0040 0x3140 0x0040 0x3140 0x0040 0x3140 0x0040
 0x00497c68: 0x3140 0x0040 0x3140 0x0040 0x3140 0x0040 0x3140 0x0040
 0x00497c78: 0x3140 0x0040 0x3140 0x0040 0x2e00 0x0040 0x2f02 0x0040
 0x00497c88: 0x2980 0x0040 0x2c50 0x0040 0x29e2 0x0040 0x2d70 0x0040

In summary, here's the main concepts featured by this introduction: