home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 June
/
SIMTEL_0692.cdr
/
msdos
/
forth
/
fifth.arc
/
ASSIGN.FIV
< prev
next >
Wrap
Text File
|
1986-03-18
|
13KB
|
412 lines
CREATE X
CREATE ^
EDIT
\ This exponent program does not work well on numbers close to zero.
\ For example, .01 2. ^ yields: .0000709 (It should be .0001)
\
\ We wrote a ^ module that works fine, but I don't have it. Put yours
\ in instead of this one.
: ^
swap flog f* fexp
;
~UP
CREATE STACK
CREATE BUFF
EDIT
create buff 1024 allot
~UP
CREATE TOP
EDIT
variable top
~UP
CREATE WORDST
EDIT
variable wordst
~UP
EDIT
: stack
\ This is a universal stack word. I will explain by example:
\ stack A|AA \ is the same as DUP
\ stack abc|bca \ is the same as ROT
\ stack ABCD| \ is the same as 2DROP 2DROP
\ stack ab|ababba \ is the same as 2DUP 2DUP SWAP
\ stack ABCD|CDBA \ is the same as 3 ROLL 3 ROLL SWAP
\ stack abc|abcabc \ is the same as 2 PICK 2 PICK 2 PICK
\ Notice that the stack expects the Specification of action to be in all
\ caps or all lower case. Mixing the cases is not checked for, and will
\ likely crash your system. Also on the left of the `|', number the stack
\ ABCD... where A is the deepest element on the stack. On the right, you
\ get to do whatever you want. The left side is limited to 26 characters,
\ the right is not really limited at all. (You can overflow the stack...)
state c@ 0= if
124 word
dup c@ 0= if 0 23 gotoxy ." You got an error with stack!" abort endif
dup c@ 64 + top !
c@ 4 * 0 do
r@ buff + !
4 +loop
32 word dup 1+ wordst !
dup c@ 1 = if drop else
c@ 1 do
wordst @ i + c@ top @ - abs 2 shl \ get offset
buff + \ Abs addr
@
loop
endif
else
124 word
dup c@ 0= if 0 23 gotoxy ." You got an error with stack!" abort endif
dup c@ 64 + top !
[compile] buff [compile] drop \ insure buff's compilation.
c@ 4 * 0 do
i buff + ['] literal execute [compile] !
4 +loop
32 word dup 1+ wordst !
dup c@ 1 = if drop else
c@ 1 do
wordst @ i + c@ top @ - abs 2 shl \ get offset
buff + ['] literal execute \ Abs addr
[compile] @
loop
endif
endif
;
immediate
~UP
CREATE :=
CREATE PP
EDIT
\ This is a debugging print routine.
: pp 1 \ <<<--- If this is a 1, run time trace occurs on expressions.
\ is a 2, the postfix expression is printed.
\ is none of the above, nothing happens.
dup 1 = if \ Run time debugging.
drop
['] literal execute [compile] count [compile] type
[compile] key [compile] drop
else
2 = if \ Compile time debugging
count type
else
drop \ No debugging.
endif
endif
;
~UP
CREATE BUFF
EDIT
create buff 200 allot
~UP
CREATE OPLIST
CREATE DEFINE
CREATE STR=
EDIT
( str1 str2 -> flag )
\ flag = -1 if str1 = str2
\ otherwise flag = 0
: str=
over c@ 1+ 0 do \ For 0 to character count do:
over c@ over c@ =
if else 2drop 0 exit endif
1+ swap 1+
loop
2drop -1
;
~UP
EDIT
: define
create \ Create the module.
here \ Address of number of entries.
0 , \ Number of entries spot.
here \ Addr of beginning of list.
" +" , ['] f+ , \ All arithmetic is done in floating point.
" -" , ['] f- ,
" *" , ['] f* ,
" /" , ['] f/ ,
" (" , ['] abort , \ Left paren.
" )" , ['] abort , \ Right paren.
" ;" , ['] abort , \ End of statement marker.
" [" , ['] abort , \ Begin subscript (or function) marker.
" ]" , ['] abort , \ Close subscript (or function) marker.
" ^" , ['] ^ , \ You must supply exponent routine.
here swap - \ Compute length of list.
swap ! \ Save this away. (Number of entries = length/8)
does>
dup 4 + swap @ 0 do
2dup @ str= if
swap drop 4 + @ i 16 + exit
endif
8 +
8 +loop
drop dup find
dup -1 = if drop swap drop 8 exit endif
dup 2 = if drop swap drop 0 exit endif
3 = if swap drop 0 exit endif
0 24 gotoxy cr cr buff count type cr
." Token Not Found error in := statement: " count type cr cr abort
;
~UP
EDIT
\ ( string -> addr num )
\ Returns the address and number of the operator or identifier.
\ Operator Num
\ --------------
\ constant 0
\ variable 8
\ + 16
\ - 24
\ * 32
\ / 40
\ ( 48
\ ) 56
\ ; 64
\ [ 72
\ ] 80
\ ^ 88
define oplist
~UP
CREATE PREC
CREATE DEFINE
EDIT
: define
create
\ 0 8 16 24 32 40 48 56 64 72 80 88
\ lit var + - * / ( ) ; [ ] ^
\ +----------------------------------------------------------------------
( lit) 15 c, 15 c, 0 c, 0 c, 0 c, 0 c, 15 c, 1 c, 1 c, 15 c, 1 c, 0 c,
( var) 15 c, 15 c, 0 c, 0 c, 0 c, 0 c, 15 c, 1 c, 1 c, 15 c, 1 c, 0 c,
( + ) 1 c, 1 c, 1 c, 1 c, 0 c, 0 c, 15 c, 1 c, 1 c, 15 c, 1 c, 0 c,
( - ) 1 c, 1 c, 1 c, 1 c, 0 c, 0 c, 15 c, 1 c, 1 c, 15 c, 1 c, 0 c,
( * ) 1 c, 1 c, 1 c, 1 c, 1 c, 1 c, 15 c, 1 c, 1 c, 15 c, 1 c, 0 c,
( / ) 1 c, 1 c, 1 c, 1 c, 1 c, 1 c, 15 c, 1 c, 1 c, 15 c, 1 c, 0 c,
( { ) 1 c, 1 c, 0 c, 0 c, 0 c, 0 c, 0 c, 2 c, 15 c, 15 c, 15 c, 0 c,
( } ) 15 c, 15 c, 15 c, 15 c, 15 c, 15 c, 15 c, 15 c, 15 c, 15 c, 15 c, 15 c,
( ; ) 0 c, 0 c, 0 c, 0 c, 0 c, 0 c, 0 c, 15 c, 3 c, 15 c, 15 c, 0 c,
( [ ) 1 c, 1 c, 0 c, 0 c, 0 c, 0 c, 0 c, 15 c, 15 c, 15 c, 4 c, 0 c,
( ] ) 15 c, 15 c, 15 c, 15 c, 15 c, 15 c, 15 c, 15 c, 15 c, 15 c, 15 c, 15 c,
( ^ ) 1 c, 1 c, 1 c, 1 c, 1 c, 1 c, 0 c, 1 c, 1 c, 15 c, 1 c, 0 c,
does>
rot 8 / rot 8 /
swap 12 * + dup 144 u< if else
0 24 gotoxy cr
buff count type
." You have an ill eagle in your := statement " abort
endif
+ c@
;
~UP
EDIT
define prec
~UP
CREATE EXPRESS
CREATE ARRAY?
EDIT
\ Check to see if we are dealing with an array. If so, evaluate the subscripts.
: array?
>in @ 32 word oplist dup 72 = if \ Is it an array?
" [" pp
rot drop \ If so, get rid of the text pointer.
express \ Evaluate the subscript expression.
else
2drop >in ! \ Restore the text pointer if it's not
endif \ an array.
;
~UP
CREATE REDUCE
EDIT
\ Reduces an operator.
: reduce
stack ABCD|ABCDBD
prec \ Get precedence code.
dup 1 = if \ 1 = Reduce an operator.
stack ABCDE|CDA
" &" pp
['] literal execute [compile] execute
reduce exit
endif
dup 4 = if \ End a subscript.
" ]" pp
drop 2drop 2drop \ Drop brackets, and
array? exit \ check for more subscripts.
endif
dup 2 = if drop 2drop 2drop exit endif \ Remove paren's from stack.
dup 15 = if \ An ill eagle state found.
0 24 gotoxy cr cr buff count type cr
." I can't figure out your := statement. Sorry." cr cr abort
endif
3 = if exit endif \ End of statement found.
express
;
~UP
EDIT
\ ( -> ) Compiles an expression pointed to by >in.
: express
32 word oplist \ Get a token.
dup 0 = if drop " c" pp ['] literal execute else \ Compile a constant.
dup 8 = if drop \ This is a variable or array.
array? \ Compile subscripts if an array.
" a" pp
['] literal execute \ Compile execution address.
[compile] execute [compile] @ else \ Compile an EXECUTE and a Fetch.
dup 48 = if express else
dup 56 = if reduce express else \ End of parenthesis?
0 24 gotoxy cr cr buff count type cr
." Something is out of order in your := statement! " cr cr abort
endif
endif
endif
endif
32 word oplist reduce \ Reduce operators.
;
~UP
EDIT
( addr -> )
\ Compiles the following expression storing the results at addr. The expression
\ is terminated by a semicolon. If any thing is not in the operator list, it is
\ considered a variable. You can easily die if you mess up and put a module in
\ as a variable.
: :=
state c@ 0 = if
0 24 gotoxy cr cr
." Assignment statments are only allowed in compile mode."
cr abort
endif
>in @ 10 text >in !
pad 1- buff 150 cmove \ Save the expression for error messages.
['] abort 64
express
2drop 2drop
[compile] swap [compile] !
1 >in +!
; immediate
~UP
CREATE README
CREATE A
EDIT
variable a
~UP
CREATE B
EDIT
variable b
~UP
CREATE C
EDIT
variable c
~UP
CREATE D
CREATE DEFINE
EDIT
\ The execution of this module will create a array which takes a subscript
\ from the stack and returns the address of that element.
: define
create \ Create a module.
10 4 * allot \ Allot room for 10 elements, 4 bytes each.
does> \ Define this module's run time behavior.
\ ( Remember that the address of beginning of the 10
\ elements allotted above has been pushed on the
\ stack prior to this code. )
swap dup 10 u< if else \ Do range checking.
." Out of range" abort
endif
4 * + \ Multiply the subscript by 4, add to beginning address.
;
~UP
EDIT
( subscript -> address )
\ D is a 10 element array. See DEFINE below for D's definition.
\ Takes the subscript and returns the address of that element.
define d
~UP
CREATE E
CREATE DEFINE
EDIT
\ The execution of this module will create a array which takes two subscripts
\ from the stack and returns the address of that element.
: define
create \ Create a module.
5 4 * dup * allot \ Allot room for a 5x5 array, each element is 4 bytes.
does> \ Define this module's run time behavior.
\ ( Remember that the address of beginning of the
\ first element has been pushed on the stack
\ on top of the subscripts prior to the execution
\ of this code. )
stack abc|cabab \ Put subscripts on top of stack, address on bottom.
5 u< swap 5 u< and \ Are both subscripts under 5?
if else \ If not, you have an error.
." Out of range" abort
endif
4 * + \ Multiply the subscript by 4, add to beginning address.
;
~UP
EDIT
( subscript subscript -> address )
\ Expects two subscripts, returns address of the specified element.
\ E is a 5x5 array. See DEFINE for the defintion.
define e
~UP
CREATE K
EDIT
variable k
~UP
EDIT
: readme
\ These are some examples of expressions.
a := 3.5 + 1.0 + -6.7 - 8.001 * 3.5 + 7.6 ;
\ Every token ( a number, operator, variable ) MUST be seperated by a space.
\ Notice that the numbers MUST be real if they are to be used in
\ arithmetic. (i.e. must have a decimal point.) This could be changed by
\ going into OPLIST under :=, and doing a conversion to floating point if
\ OPLIST finds an integer. The reason I didn't do the conversion is
\ illistrated in the next example.
5 0 do
i k !
3 d := 7.5 ;
2 k @ e := 9.6 ;
3 d := d [ 3 ] + e [ 2 ] [ k ] ;
loop
\ Notice that to the left of the := you use Fifth code to get the address
\ the results of the expression are to be stored at. On the right, notice
\ the subscript of the array must be an integer. (The overhead of converting
\ real subscripts to integers is a bit too much overhead, speed wise.)
\ Notice how pairs of subscripts can be specified. This is the same as
\ Basic's e(2,5). This is the same notation C uses. The subscripts are
\ handled by the array, NOT by :=. See E ad D's definition.
\ Another limitation is that I can not be used as a subscript. Store I in
\ a convienent variable, then use the variable.
a := 5. + 2. * 0. ; \ Same as a := 5. + ( 2. * 0. ) ;
c := a + a * 2. ^ 3. ^ 2. ; \ Same as a := a + ( a * ( 2. ^ ( 3. ^ 2. ) ) ) ;
\ The order of operations between operators hold. A little "behind the scenes"
\ explaination is in order now. What does the := module do? Given the
\ following:
\
\ := 4. + 3. * 7.
\
\ The := module compiles the code to do:
\
\ 4. 3. 7. f* f+ swap !
\
\ Thus If you neglect to leave a valid address on the stack, := is going to
\ blow up. Also, if you specify a procedure instead of a variable, your
\ system will most likely crash.
;
~UP
EDIT
~UP
ABORT