Difference between revisions of "Forth parser"
From ScienceZero
(→How to encode numbers) |
(→Variable inference) |
||
Line 16: | Line 16: | ||
Emit '''LDL #<index in the ordered list>''' | Emit '''LDL #<index in the ordered list>''' | ||
− | + | If there are more than 0 variables emit '''DIM #<largest index>''' as the first instruction of the function. | |
+ | This can be skipped if the function calls no other functions or do not use the stack for any or purpose. | ||
TODO: Check if every variable is read and eliminate the ones that are not in use and emit a warning. | TODO: Check if every variable is read and eliminate the ones that are not in use and emit a warning. |
Revision as of 13:40, 25 April 2018
Contents
String
When you reach ", start copying characters into a string dictionary until the matching " Emit LDC ... LEA instructions to point to where the string is located in the final binary The length of the string is stored in front of it.
Variable inference
Variables are stored locally on the return stack. Any word that starts with ">" is a write to a variable. For each word in function If word starts with ">" Add the word to an ordered list of unique words that starts with ">", remove the leading ">" If there are more than 16 variables emit error Emit STL #<index in the ordered list> If word is in the list but does not start with ">" Emit LDL #<index in the ordered list> If there are more than 0 variables emit DIM #<largest index> as the first instruction of the function. This can be skipped if the function calls no other functions or do not use the stack for any or purpose. TODO: Check if every variable is read and eliminate the ones that are not in use and emit a warning. This can be done with a simple bitmask to make sure a variable is written and then read.
How to encode constants
if number = 0 then emit LDC #0 else find the leftmost hex digit n that is not 0 emit LDC #n zero out that digit for each remaining digit n, zero or not emit LDE #n #0x1230 can be encoded as: LDC #0x1 LDE #0x2 LDE #0x3 LDE #0x0 More efficient code can sometimes be achieved by using LDN LSL INC DEC DUP OVER and other opcodes.
Example 1
: lsl for dup + next ; ( Simple complete function that implements left shift by repeated addition ) ":" this tells the parser to define a new function "lsl" is the name of the function Adr Value 0 0xF0 ( for ) 1 0xE0 ( dup ) 2 0xC0 ( add ) 3 0xF1 ( next ) ";" tells the parser that it has reached the end of the definition The parser should create an "object" in memory like: "lsl",0xF0,0xE0,0xC0,0xF1 ( the return opcode is implied )
Example 2
: xorpattern 0 >yval 1080 for 0 >xval 1920 for xval dup 1 + >xval yval eor xval yval plotpixel next yval 1 + >yval next ; Unique variable names being written to 0 "yval" 1 "xval" DIM #1 ( Largest index of a variable is 1 ) LDC #0 ( 0 ) STL #0 ( >yval ) LDC #0x4 ( 1080 = 0x483 ) LDE #0x8 LDE #0x3 FOR ( for ) LDC #0 ( 0 ) STL #1 ( >xval ) LDC #0x7 ( 1920 = 0x780 ) LDE #0x8 LDE #0x0 FOR ( for ) LDC #1 ( xval ) LDC #0 ( yval ) LDC #<off> ( Load offset to the function plotpixel ) ... CALL NEXT LDC #0 ( yval ) INC STC #0 ( yval ) NEXT RETURN
Default opcode equivalency for forth words
Forth string - opcode + - add - - sub * - mul / - div