Difference between revisions of "Simple graphics language"

From ScienceZero
Jump to: navigation, search
(Interpreter)
(Interpreter)
Line 133: Line 133:
 
  again
 
  again
  
Opcodes:
+
=== Opcodes===
char dictionary[512] = "ld0,ld8,ld16,ld24,ld32,lds,end,setcolour,readcolour,setpos,readpos,load8,load16,load32,store8,store16,store32,var,unvar,ldl,stl,penup,pendown,forward,backward,left,right,for,next,do,again,if,else,endif,+,-,*,/,lsl,lsr,and,or,eor,not,drop,dup,swap,over,rot,-rot,>r,r>,nop,";
+
*char dictionary[512] = "ld0,ld8,ld16,ld24,ld32,lds,end,setcolour,readcolour,setpos,readpos,load8,load16,load32,store8,store16,store32,var,unvar,ldl,stl,penup,pendown,forward,backward,left,right,for,next,do,again,if,else,endif,+,-,*,/,lsl,lsr,and,or,eor,not,drop,dup,swap,over,rot,-rot,>r,r>,nop,";
+
*enum operands {op_ld0,op_ld8,op_ld16,op_ld24,op_ld32,op_lds,op_end,op_setcolour,op_readcolour,op_setpos,op_readpos,op_load8,op_load16,op_load32,op_store8,op_store16,op_store32,op_var,op_unvar,op_ldl,op_stl,op_penup,op_pendown,op_forward,op_backward,op_left,op_right,op_for,op_next,op_do,op_again,op_if,op_else,op_endif,op_add,op_sub,op_mul,op_div,op_lsl,op_lsr,op_and,op_or,op_eor,op_not,op_drop,op_dup,op_swap,op_over,op_rot,op_nrot,op_dtor,op_rtod,op_nop};
enum operands {op_ld0,op_ld8,op_ld16,op_ld24,op_ld32,op_lds,op_end,op_setcolour,op_readcolour,op_setpos,op_readpos,op_load8,op_load16,op_load32,op_store8,op_store16,op_store32,op_var,op_unvar,op_ldl,op_stl,op_penup,op_pendown,op_forward,op_backward,op_left,op_right,op_for,op_next,op_do,op_again,op_if,op_else,op_endif,op_add,op_sub,op_mul,op_div,op_lsl,op_lsr,op_and,op_or,op_eor,op_not,op_drop,op_dup,op_swap,op_over,op_rot,op_nrot,op_dtor,op_rtod,op_nop};
+

Revision as of 17:55, 28 April 2011

A simple graphics language for microcontrollers

We start with a very simple reverse polish notation interpreter with a preprocessor stage

Sample code:

to circle 360 for 1 forward 1 right next end

Registers:

0 X (nn.ff)
1 Y
2 Angle
3 Scale
4 Colour
5 Pen up/down
6 Nested If/For counter
7 Local variable pointer

Stack diagrams

( things read from the stack -- things written on the stack )
x - x position
y - y position
n - number
Examples:
  ( n n -- n )
  This means that two numbers were read from the stack, then one number was written back.
  For example a simple addition reads two numbers and writes back the result.

  ( a b c -- c b a )
  Reading threee values from the stack and write them back in the opposite order.

Definitions

  • Function:
    • To < function name > < code > End
  • Constant:
    • Define < constant name > < costant > End
  • Macro:
    • Macro < macro name > < code > End


Commands

Absolute commands
  setcolour     ( colour -- )
  readcolour    ( -- colour )
  setpos        ( x y -- )
  readpos       ( -- x y )
  load          ( address -- data )
  store         ( data address -- )

Variables:
  var           ( n -- )( create n variables of value 0 on the return stack ) 
  unvar         ( n -- )( delete n variables from the return stack )
  ldl           ( index -- )( load local variable )
  stl           ( n index -- )( store local variable )

Relative commands:
  penup         ( -- )
  pendown       ( -- )
  forward       ( length -- )
  backward      ( length -- )
  left          ( angle -- )
  right         ( angle -- )
 
Loops:
  for           ( n -- )
  next          ( -- )
  do            ( -- )
  again         ( -- )

Conditionals:
  if            ( n -- )
  else          ( -- )
  endif         ( --  )

Data processing:
  +             ( n n -- n )        ( to +  >r 0 r> - - end )
  -             ( n n -- n )        ( fundamental )
  *             ( n n -- n )        ( to * 0 do over 1 and if rot dup >r -rot r> + endif rot 1 lsl rot 1 lsr rot over if again endif >r drop -rot drop drop end ) 
  /             ( n n -- n )
  lsl           ( n n -- n )        ( to lsl for dup + next end )
  lsr           ( n n -- n )        ( to lsr for 31 for dup 0x80000000 and swap 1 lsl swap if 1 + endif next 0x7fffffff and next end )
  and           ( n n -- n )        ( fundamental )
  or            ( n n -- n )        ( to or over not and + end )
  eor           ( n n -- n )        ( to eor over over or -rot and not and end )
  not           ( n -- n )          ( to not >r -1 r> - end )

Stack manipulation:
 drop           ( n -- )           ( to drop if endif end )
 dup            ( n -- n n )       ( fundamental )
 swap           ( a b -- b a )     ( to swap dup >r >r dup r> eor dup >r eor r> r> eor end )
 over           ( a b -- a b a )   ( to over >r dup r> swap end ) 
 rot            ( a b c -- b c a ) ( to rot >r swap r> swap end ) 
 -rot           ( a b c -- c a b ) ( to -rot swap >r swap r> end )
 >r             ( n -- )           ( fundamental )
 r>             ( -- n )           ( fundamental )

Optimal stack reordering in Forth

Compiler

Stage 1

  • Definitions are expanded

Stage 2

  • Macros are executed

Stage 3

  • Functions are added to the dictionary

Stage 4

  1. All words are looked up in the dictionary and the opcode stored in the program array
  2. The address of each function is stored in the function jump table

The dictionary

The dictionary used to convert a command into an opcode. It is a zero terminated string like "setcolour readcolour setpos readpos ",0 that is searched linearly from start to end. A space marks the end of a word. The first compiler pass adds all functions to the end of this table.

The function jump table

This table contains the address of each function, in the same order as the functions appear in the dictionary. It is filled in during the second pass when the code position is known.

Interpreter

The opcode pointer always ppoints to the next byte to be processed.

do
  read opcode
  switch opcode
    case 0
      push 0
    case 1-4
      read byte(s)
      value = byte0 or (byte1<<8) or (byte2<<16) or (byte3<<24) 
      push value
    case command
      execute command
    case function
      pushr localpointer
      pushr opcodepointer
      opcodepointer = jumptable(function)
   end switch
again

Opcodes

  • char dictionary[512] = "ld0,ld8,ld16,ld24,ld32,lds,end,setcolour,readcolour,setpos,readpos,load8,load16,load32,store8,store16,store32,var,unvar,ldl,stl,penup,pendown,forward,backward,left,right,for,next,do,again,if,else,endif,+,-,*,/,lsl,lsr,and,or,eor,not,drop,dup,swap,over,rot,-rot,>r,r>,nop,";
  • enum operands {op_ld0,op_ld8,op_ld16,op_ld24,op_ld32,op_lds,op_end,op_setcolour,op_readcolour,op_setpos,op_readpos,op_load8,op_load16,op_load32,op_store8,op_store16,op_store32,op_var,op_unvar,op_ldl,op_stl,op_penup,op_pendown,op_forward,op_backward,op_left,op_right,op_for,op_next,op_do,op_again,op_if,op_else,op_endif,op_add,op_sub,op_mul,op_div,op_lsl,op_lsr,op_and,op_or,op_eor,op_not,op_drop,op_dup,op_swap,op_over,op_rot,op_nrot,op_dtor,op_rtod,op_nop};