forth/twenex-forth.mid

2274 lines
37 KiB
Plaintext
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;-*-Midas-*-
Title FORTH - The FORTH Language
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Caution: This FORTH is NOT totally standard.
;;;
;;; When FORTH is started up, the file AUTO-LOAD.4TH is searched
;;; for. If it exists, it is loaded automatically. If not, a
;;; standard header is printed.
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.DECSAV
A=1 ;Used by JSYSs mostly
B=2
C=3
D=4 ;Used exclusively by colon-compiler (Addr is last word built)
E=5 ; " " " EVAL (Addr of last word evaluated)
U=6 ;# things in FORTH stack
V=7 ;Args for FORTH stack pushing/popping
L=10 ;Args for EVAL
K=11 ;Kharacter from GETCHR and such
T1=12 ;Trashy temporaries - No special purpose
T2=13
T3=14
T4=15
S=16 ;FORTH stack pointer
P=17 ;100% Pure Porpoise stack pointer
Call=PUSHJ P,
Return=POPJ P,
.PRIIN==100 ;TTY input JFN
.PRIOU==101 ;TTY output JFN
;;;
;;; Macros
;;;
Define TYPE &string
Hrroi A,[Asciz string]
PSOUT
Termin
Define DBP ac
Add ac,[70000,,0]
Skipge ac
Sub ac,[430000,,1]
Termin
;;;
;;; Storage
;;;
Loc 140
Popj1: Aos (P)
CPopj: Return
PDLen==200 ;Porpoise stack
PDList: -PDLen,,.
Block PDLen
Deep==100. ;FORTH stack
Stack: -Deep,,.
Block Deep
LogNcs: 1.0 ? 3.0 ? 5.0 ? 7.0 ? 9.0 ? 11.0 ? 13.0 ? 15.0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Start of execute-time stuff for structures.
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DOn==10. ;Maximum depth of DO loop nesting.
DOc: -1 ;Loop # we're in. -1 means not in.
DOs: Block DOn
DOtop: Block DOn ;Upper limit of DO
DOind: Block DOn ;Loop counter, what you get with I, J, etc
IFc: -1
UNTILn==10.
UNTILc: -1
UNTILs: Block UNTILn
WHILEn==10.
WHILEc: -1
WHILEs: Block WHILEn
WHILEe: Block WHILEn
BEGINp: 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Random flags, variables, constants, etc
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Level: -1 ;Level of recursion
Trace: 0
Base: 10. ;I/O number base
Echo: -1 ;True if we echo input
Width: 0 ;Terminal width
Term: 0 ;Terminal-type #
FName: Block 7 ;Filename (asciz) you're screwing with
Delim: 0 ;Delimiter for text input stuff
lsText: 0 ;Length of text read by sText
Loadp: 0 ;True when input is from a file
StoNmp: 0 ;Flag returned by StoN: Valid number?
Making: 0 ;True when we're in the middle of building a Dictionary entry
Did: 0 ;True when a DOES> was found after <BUILDS during execution.
BStart: 0 ;For run-time DOES>... the address it returns.
JCall: JSYS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; <# and #> formatting controls
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
FBufl==6 ;Room for 30. characters
Format: 0
FLeft: 0
FMinus: 0
FBuffr: Block FBufl
FBufBP: 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Instructions that are executed in the body of the two
;;; testing routines, via XCT
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2Tests: Camn V,(S) ; =
Came V,(S) ; =_
Camle V,(S) ; <
Caml V,(S) ; <=
Camge V,(S) ; >
Camg V,(S) ; >=
1Tests: Skipn (S) ; 0=
Skipe (S) ; 0=_
Skipge (S) ; 0<
Skipg (S) ; 0<=
Skiple (S) ; 0>
Skipl (S) ; 0>=
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; The ASCII strings needed to clear screen and home cursor
;;; on assorted terminals.
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Clears: 0 ? 0 ? 0 ? 0 ? 0
Asciz // ;#5 - DM2500
Asciz // ;#6 - I400
Asciz / / ;#7 - DM1520
0 ? 0 ? 0 ? 0 ? 0 ? 0 ? 0
Asciz /HJ/ ;#15 - VT52
0 ? 0 ? 0 ? 0 ? 0 ? 0 ? 0 ? 0
Asciz /v/ ;#24 - V200
0
Asciz /E/ ;#26 - H19
Homes: 0 ? 0 ? 0 ? 0 ? 0
Asciz //
Asciz //
Asciz //
0 ? 0 ? 0 ? 0 ? 0 ? 0 ? 0
Asciz /H/
0 ? 0 ? 0 ? 0 ? 0 ? 0 ? 0 ? 0
Asciz //
0
Asciz //
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Control needed to keep track of nested LOADs and iJFNs
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MaxLLs: 10
LLoad: -1
LiJFNs: Block MaxLLs
iJFN: .PRIIN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; All the rubbish used by the input processor
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
IBufln==40 ;Allowing for 160. character input lines
pInBuf: 0
InBuf: Block IBufln
nIchar: 0
IStrin: Block 3
IAddr: 0
INump: 0
Inmpos: 0
NotNum: 0
IVal: 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; The Primitive FORTH Dictionary
;;;
;;; Entries are like:
;;;
;;; +0: NAME 01-05
;;; +1: NAME 06-10
;;; +2: NAME 11-15
;;; +3: LENGTH,,CODE
;;; +4: STUFF1
;;; . .
;;; +n: STUFFi
;;;
;;; Where NAME's are ASCII words, LENGTH is the total length
;;; of this entry, CODE is a pointer to a list of STUFFs that
;;; will be executed when this word is mentioned, and a STUFF
;;; is one of:
;;;
;;; -1 ? CONSTANT
;;; -1,,SUBROUTINE
;;; 0,,DICTIONARY
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DPage==10 ;Page to load Dictionary into
Foo: Loc DPage*2000
Dict: Ascii /DUP/ ? 0 ? 0 ? 5,,0 ? -1,,Dup
Ascii /SWAP/ ? 0 ? 0 ? 5,,0 ? -1,,Swap
Ascii /ROLL/ ? 0 ? 0 ? 5,,0 ? -1,,Roll
Ascii /PICK/ ? 0 ? 0 ? 5,,0 ? -1,,Pick
Ascii /DROP/ ? 0 ? 0 ? 5,,0 ? -1,,Drop
Ascii /OVER/ ? 0 ? 0 ? 5,,0 ? -1,,Over
Ascii /ROT/ ? 0 ? 0 ? 5,,0 ? -1,,Rotate
Ascii /-DUP/ ? 0 ? 0 ? 5,,0 ? -1,,NZDup
Ascii /?DUP/ ? 0 ? 0 ? 5,,0 ? -1,,NZDup
Ascii /LEVEL/ ? 0 ? 0 ? 5,,0 ? -1,,PLevel
Ascii /DEPTH/ ? 0 ? 0 ? 5,,0 ? -1,,Depth
Ascii /FLOAT/ ? 0 ? 0 ? 5,,0 ? -1,,ItoF
Ascii /+/ ? 0 ? 0 ? 5,,0 ? -1,,Plus
Ascii /-/ ? 0 ? 0 ? 5,,0 ? -1,,Minus
Ascii /*/ ? 0 ? 0 ? 5,,0 ? -1,,Times
Ascii "/" ? 0 ? 0 ? 5,,0 ? -1,,Divide
Ascii /^/ ? 0 ? 0 ? 5,,0 ? -1,,Power
Ascii /F+/ ? 0 ? 0 ? 5,,0 ? -1,,FPlus
Ascii /F-/ ? 0 ? 0 ? 5,,0 ? -1,,FMin
Ascii /F*/ ? 0 ? 0 ? 5,,0 ? -1,,FTimes
Ascii "F/" ? 0 ? 0 ? 5,,0 ? -1,,FDiv
Ascii /FIX/ ? 0 ? 0 ? 5,,0 ? -1,,FtoI
Ascii /MOD/ ? 0 ? 0 ? 5,,0 ? -1,,Mod
Ascii "/MOD" ? 0 ? 0 ? 5,,0 ? -1,,DivMod
Ascii /0=/ ? 0 ? 0 ? 5,,0 ? -1,,EqualZ
Ascii /0=_/ ? 0 ? 0 ? 5,,0 ? -1,,NotEq0
Ascii /0</ ? 0 ? 0 ? 5,,0 ? -1,,LessZ
Ascii /0<=/ ? 0 ? 0 ? 5,,0 ? -1,,LesEq0
Ascii /0>/ ? 0 ? 0 ? 5,,0 ? -1,,GreatZ
Ascii /0>=/ ? 0 ? 0 ? 5,,0 ? -1,,GrEq0
Ascii /EXCHANGE/ ? 0 ? 5,,0 ? -1,,XChanj
Ascii /JSYS/ ? 0 ? 0 ? 5,,0 ? -1,,JSys0
Ascii /=/ ? 0 ? 0 ? 5,,0 ? -1,,Equal
Ascii /=_/ ? 0 ? 0 ? 5,,0 ? -1,,NotEqu
Ascii /</ ? 0 ? 0 ? 5,,0 ? -1,,Less
Ascii /<=/ ? 0 ? 0 ? 5,,0 ? -1,,LessEq
Ascii />/ ? 0 ? 0 ? 5,,0 ? -1,,Greatr
Ascii />=/ ? 0 ? 0 ? 5,,0 ? -1,,GretEq
Ascii /FLUSH/ ? 0 ? 0 ? 5,,0 ? -1,,Flush
Ascii /TRACE/ ? 0 ? 0 ? 5,,0 ? -1,,CTrace
Ascii /@/ ? 0 ? 0 ? 5,,0 ? -1,,Fetch
Ascii /!/ ? 0 ? 0 ? 5,,0 ? -1,,Store
Ascii /+!/ ? 0 ? 0 ? 5,,0 ? -1,,Storep
Ascii /-!/ ? 0 ? 0 ? 5,,0 ? -1,,Storem
Ascii /FILL/ ? 0 ? 0 ? 5,,0 ? -1,,Fill
Ascii /'/ ? 0 ? 0 ? 5,,0 ? -1,,Tic
Ascii /'#/ ? 0 ? 0 ? 5,,0 ? -1,,Ticnum
Ascii "]" ? 0 ? 0 ? 5,,0 ? -1,,Ticome
Ascii /QUIT/ ? 0 ? 0 ? 5,,0 ? -1,,Exit
Ascii "<#" ? 0 ? 0 ? 5,,0 ? -1,,SOutF
Ascii "#" ? 0 ? 0 ? 5,,0 ? -1,,FDigit
Ascii /HOLD/ ? 0 ? 0 ? 5,,0 ? -1,,FHold
Ascii "#N" ? 0 ? 0 ? 5,,0 ? -1,,FNDigs
Ascii /SIGN/ ? 0 ? 0 ? 5,,0 ? -1,,FSign
Ascii "#S" ? 0 ? 0 ? 5,,0 ? -1,,FDigs
Ascii "#>" ? 0 ? 0 ? 5,,0 ? -1,,EOutF
Ascii /HOME/ ? 0 ? 0 ? 5,,0 ? -1,,Home
Ascii /CR/ ? 0 ? 0 ? 5,,0 ? -1,,Terpri
Ascii /CLEAR/ ? 0 ? 0 ? 5,,0 ? -1,,CLS
Ascii /SPACE/ ? 0 ? 0 ? 5,,0 ? -1,,Space
Ascii /SPACES/ ? 0 ? 5,,0 ? -1,,Spaces
Ascii /EMIT/ ? 0 ? 0 ? 5,,0 ? -1,,Emit
Ascii /TYPE/ ? 0 ? 0 ? 5,,0 ? -1,,7TypeN
Ascii "[TYPE]" ? 0 ? 5,,0 ? -1,,7Type
Ascii /KEY/ ? 0 ? 0 ? 5,,0 ? -1,,Key
Ascii /?TERMINAL/ ? 0 ? 5,,0 ? -1,,Inputp
Ascii /EXPECT/ ? 0 ? 5,,0 ? -1,,ExpecN
Ascii "[EXPECT]" ? 0 ? 5,,0 ? -1,,Expect
Ascii /C@/ ? 0 ? 0 ? 5,,0 ? -1,,CFetch
Ascii /C!/ ? 0 ? 0 ? 5,,0 ? -1,,CStore
Ascii /C>/ ? 0 ? 0 ? 5,,0 ? -1,,CPlus
Ascii /C</ ? 0 ? 0 ? 5,,0 ? -1,,CMinus
Ascii /./ ? 0 ? 0 ? 5,,0 ? -1,,Dot
Ascii /.R/ ? 0 ? 0 ? 5,,0 ? -1,,DotR
Ascii /F./ ? 0 ? 0 ? 5,,0 ? -1,,FDot
DOTQa=.
Ascii /."/ ? 0 ? 0 ? 5,,0 ? -1,,Dotext
Ascii /:"/ ? 0 ? 0 ? 5,,0 ? -1,,ColTex
Ascii /(")/ ? 0 ? 0 ? 5,,0 ? -1,,SaveTd
Ascii /["]/ ? 0 ? 0 ? 5,,0 ? -1,,SaveTs
Ascii /VLIST/ ? 0 ? 0 ? 5,,0 ? -1,,Vlist
PARENa=.
Ascii "(" ? 0 ? 0 ? 5,,0 ? -1,,Remark
Ascii /ABS/ ? 0 ? 0 ? 5,,0 ? -1,,Abs
Ascii /MINUS/ ? 0 ? 0 ? 5,,0 ? -1,,Negate
Ascii /+-/ ? 0 ? 0 ? 5,,0 ? -1,,ApSign
Ascii /1+/ ? 0 ? 0 ? 5,,0 ? -1,,Plus1
Ascii /1-/ ? 0 ? 0 ? 5,,0 ? -1,,Minus1
Ascii /MAX/ ? 0 ? 0 ? 5,,0 ? -1,,Max
Ascii /MIN/ ? 0 ? 0 ? 5,,0 ? -1,,Min
Ascii /SINE/ ? 0 ? 0 ? 5,,0 ? -1,,Sine
Ascii /COSINE/ ? 0 ? 5,,0 ? -1,,Cosine
Ascii /ROOT/ ? 0 ? 0 ? 5,,0 ? -1,,Root
Ascii /LN/ ? 0 ? 0 ? 5,,0 ? -1,,LogN
Ascii /<-,,/ ? 0 ? 0 ? 5,,0 ? -1,,LHalf
Ascii /SW,,AP/ ? 0 ? 5,,0 ? -1,,SHalfs
Ascii /,,->/ ? 0 ? 0 ? 5,,0 ? -1,,RHalf
Ascii /AND/ ? 0 ? 0 ? 5,,0 ? -1,,LogAND
Ascii /OR/ ? 0 ? 0 ? 5,,0 ? -1,,LogOR
Ascii /NOT/ ? 0 ? 0 ? 5,,0 ? -1,,LogNOT
Ascii /XOR/ ? 0 ? 0 ? 5,,0 ? -1,,LogXOR
Ascii /EXECUTE/ ? 0 ? 5,,0 ? -1,,Execut
Ascii /FORGET/ ? 0 ? 5,,0 ? -1,,Forget
Ascii /:/ ? 0 ? 0 ? 5,,0 ? -1,,Colon
SEMIa=.
Ascii /;/ ? 0 ? 0 ? 5,,0 ? -1,,Buierr
Ascii /<BUILDS/ ? 0 ? 5,,0 ? -1,,Builds
DOESa=.
Ascii /DOES>/ ? 0 ? 0 ? 5,,0 ? -1,,Does
Ascii /,/ ? 0 ? 0 ? 5,,0 ? -1,,Comma
Ascii /ALLOT/ ? 0 ? 0 ? 5,,0 ? -1,,Allot
LOADa=.
Ascii /LOAD/ ? 0 ? 0 ? 5,,0 ? -1,,Load
Ascii "[LOAD]" ? 0 ? 5,,0 ? -1,,Loads
Ascii /UNLOAD/ ? 0 ? 5,,0 ? -1,,Unload
Ascii /DECIMAL/ ? 0 ? 5,,0 ? -1,,Base10
Ascii /OCTAL/ ? 0 ? 0 ? 5,,0 ? -1,,Base8
Ascii /BINARY/ ? 0 ? 5,,0 ? -1,,Base2
IFa=.
Ascii /IF/ ? 0 ? 0 ? 5,,-1 ? -1,,If
ELSEa=.
Ascii /ELSE/ ? 0 ? 0 ? 5,,-1 ? -1,,Else
THENa=.
Ascii /THEN/ ? 0 ? 0 ? 5,,-1 ? -1,,Then
DOa=.
Ascii /DO/ ? 0 ? 0 ? 5,,-1 ? -1,,DoLoop
LOOPa=.
Ascii /LOOP/ ? 0 ? 0 ? 5,,-1 ? -1,,Loop
LOOPPa=.
Ascii /+LOOP/ ? 0 ? 0 ? 5,,-1 ? -1,,Loopp
Ascii /I/ ? 0 ? 0 ? 5,,0 ? -1,,Aye
Ascii /J/ ? 0 ? 0 ? 5,,0 ? -1,,Jay
Ascii /IJ..N/ ? 0 ? 0 ? 5,,0 ? -1,,En
Ascii /RUNT/ ? 0 ? 0 ? 5,,0 ? -1,,Runt
REPTa=.
Ascii /REPEAT/ ? 0 ? 5,,-1 ? -1,,Rept
UNTILa=.
Ascii /UNTIL/ ? 0 ? 0 ? 5,,-1 ? -1,,Until
Ascii /CMOVE/ ? 0 ? 0 ? 5,,0 ? -1,,CMoveN
Ascii "[CMOVE]" ? 0 ? 5,,0 ? -1,,CMoves
Ascii /HERE/ ? 0 ? 0 ? 5,,0 ? -1,,Here
Ascii /LEAVE/ ? 0 ? 0 ? 5,,0 ? -1,,Leave
Ascii /ERROR/ ? 0 ? 0 ? 5,,0 ? -1,,Erret
Ascii "[NUMBER]" ? 0 ? 5,,0 ? -1,,Number
WHILEa=.
Ascii /WHILE/ ? 0 ? 0 ? 5,,-1 ? -1,,While
BEGINa=.
Ascii /BEGIN/ ? 0 ? 0 ? 5,,-1 ? -1,,Begin
ENDa=.
Ascii /END/ ? 0 ? 0 ? 5,,-1 ? -1,,FEnd
Bottom: 0
Loc Foo
Dicte: D,,Bottom
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; ;;;
;;; ;;;
;;; ;;;
;;; Start of Executable Part of FORTH ;;;
;;; ;;;
;;; ;;;
;;; ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Start: Move P,PDList
Move S,Stack
Movei A,.PRIOU
GTTYP
Movem B,Term
Movei A,.PRIIN
RFMOD
Trz B,TT%DAM
Tlz B,TT%ECO
SFMOD
Movei B,.MORLW
MTOPR
Movem C,Width
Initp: Movsi A,(GJ%SHT\GJ%OLD)
Hrroi B,[Asciz /AUTO-LOAD.4TH/]
GTJFN
Jrst Greet
Move B,[070000,,OF%RD]
OPENF
Jrst Greet
Call LSave
Jrst PRun
Greet: Type "FORTH-10 Type QUIT to exit."
Call Terpri
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; ;;;
;;; ;;;
;;; ;;;
;;; Top Level of FORTH ;;;
;;; ;;;
;;; ;;;
;;; ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PPPRun: Skipn Echo
Jrst PRun
Type " Ok"
PPRun: Call Terpri
PRun: Call FillIB
Run: Call Getwrd
Jrst PPPRun
Skipe INump
Jrst [Move V,IVal ;Constants are pushed,
Call 4SAVE
Jrst Run]
Skipn IAddr
Jrst NamErr
Move L,IAddr
Hrre A,3(L)
Skipg A ;Subroutines executed,
Move L,4(L)
Call Eval ;Words evaluated.
Jrst Run
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; ;;;
;;; ;;;
;;; ;;;
;;; Primitives ;;;
;;; ;;;
;;; ;;;
;;; ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Stack operations
;;;
Dup: Jumpe U,UFlow ; DUP
Move V,(S)
Call 4SAVE
Return
Drop: Call 4REST ; DROP
Return
Over: Caige U,2 ; OVER
Jrst UFlow
Move V,-1(S)
Call 4SAVE
Return
Rotate: Caige U,3 ; ROT
Jrst UFlow
Move T1,(S)
Exch T1,-1(S)
Exch T1,-2(S)
Movem T1,(S)
Return
Swap: Caige U,2 ; SWAP
Jrst UFlow
Move T1,(S)
Exch T1,-1(S)
Movem T1,(S)
Return
Roll: Call 4REST ; ROLL
Camle V,U
Jrst UFlow
Hrrz T1,S
Sub T1,V
Move T2,1(T1)
Movei T3,1(T1)
Hrli T3,2(T1)
BLT T3,-1(S)
Movem T2,(S)
Return
Pick: Call 4REST ; PICK
Camle V,U
Jrst UFlow
Hrrz T1,S
Sub T1,V
Move V,1(T1)
Call 4SAVE
Return
NZDup: Jumpe U,UFlow ; -DUP and ?DUP
Skipn (S)
Return
Move V,(S)
Call 4SAVE
Return
;;;
;;; Numeric changes
;;;
Negate: Jumpe U,UFlow ; MINUS
Movns (S)
Return
RHalf: Jumpe U,UFlow ; ,,->
Hrre A,(S)
Movem A,(S)
Return
LHalf: Jumpe U,UFlow ; <-,,
Hlre A,(S)
Movem A,(S)
Return
SHalfs: Jumpe U,UFlow ; SW,,AP
Movss (S)
Return
ApSign: Call 4REST ; +-
Jumpe U,UFlow
Skipge V
Movns (S)
Return
Min: Caige U,2 ; MIN
Jrst UFlow
Call 4REST
Camge V,(S)
Movem V,(S)
Return
Max: Caige U,2 ; MAX
Jrst UFlow
Call 4REST
Camle V,(S)
Movem V,(S)
Return
Abs: Jumpe U,UFlow ; ABS
Movms (S)
Return
Plus1: Jumpe U,UFlow ; 1+
Aos (S)
Return
Minus1: Jumpe U,UFlow ; 1-
Sos (S)
Return
;;;
;;; Floating-point functions
;;;
Cosine: Call 4REST ; COSINE
FADR V,[1.57079632679]
Skipa
Sine: Call 4REST ; SINE
Move A,V
Call SorC
Move V,A
Call 4SAVE
Return
SorC: Movm B,A
Camg B,[.0001761]
Return
FDVRI A,(+9.0)
Call SorC
Call .+1
FMPR B,B
FSC B,2
FADRI B,(-3.0)
FMPRB A,B
Return
Root: Call 4REST ; ROOT
Jumple V,[Setz V,
Call 4SAVE
Return]
Move T1,V
FADRI T1,(+1.0)
FDVRI T1,(+2.0)
Root1: Move T2,V
FDVR T2,T1
FADR T2,T1
FDVRI T2,(+2.0)
Move T3,T2
FSBR T3,T1
Movms T3
Camg T3,[.0000001]
Jrst Root2
Move T1,T2
Jrst Root1
Root2: Move V,T1
Call 4SAVE
Return
LogN: Call 4REST ; LN
Jumple V,[Setz V,
Call 4SAVE
Return]
Move T1,V
FSBRI T1,(+1.0)
Move T2,V
FADRI T2,(+1.0)
FDVR T1,T2
Move T2,T1
Move A,T1
Setzb C,B
LogN1: FMPR T2,T1
FMPR T2,T1
Move T3,T2
FDVR T3,LogNcs(C)
FADR A,T3
FSBR B,A
Movms B
Camg B,[.0000001]
Jrst LogN2
Move B,A
Aoja C,LogN1
LogN2: FMPRI A,(+2.0)
Move V,A
Call 4SAVE
Return
;;;
;;; System constants and toggles and stuff
;;;
Depth: Move V,U ; DEPTH
Call 4SAVE
Return
CTrace: Setcmm Trace ; TRACE
Return
Inputp: Setz V, ; ?TERMINAL
Movei A,.PRIIN
SIBE
Seto V,
Call 4SAVE
Return
PLevel: Move V,Level ; LEVEL
Call 4SAVE
Return
Runt: Movei A,.FHSLF ; RUNT
RUNTM
Move V,A
Call 4SAVE
Return
Base10: Movei A,10. ; DECIMAL
Movem A,Base
Return
Base8: Movei A,8. ; OCTAL
Movem A,Base
Return
Base2: Movei A,2 ; BINARY
Movem A,Base
Return
Aye: Skipge DOc ; I
Jrst DOerr
Move T1,DOc
Move V,DOind(T1)
Call 4SAVE
Return
Jay: Skipg DOc ; J
Jrst DOerr
Move T1,DOc
Soj T1,
Move V,DOind(T1)
Call 4SAVE
Return
En: Call 4REST ; IJ..N
Jumple V,[Type " ?Loop # <1"
Jrst Erret]
Soj V,
Camle V,DOc
Jrst DOerr
Move T1,DOc
Sub T1,V
Move V,DOind(T1)
Call 4SAVE
Return
VLIST: Movei T1,Dict
Setz T2,
Call Terpri
VL2: Skipn (T1)
Return
Move T3,[440700,,(T1)]
Setz T4,
VL3: Ildb A,T3
Skipe A
Aoja T4,VL3
Add T2,T4
Addi T2,2
Caml T2,Width
Jrst [Call Terpri
Move T2,T4
Addi T2,2
Jrst .+1]
Movei A,40
PBOUT
PBOUT
Move T3,[440700,,(T1)]
VL4: Ildb A,T3
PBOUT
Sojn T4,VL4
VL5: Hlrz T3,3(T1)
Add T1,T3
Jrst VL2
;;;
;;; Formatted number output stuff
;;;
SOutF: Skipe Format ; <#
Jrst [Type " ?Already formatting"
Jrst Erret]
Jumpe U,UFlow
Move V,(S)
Setom Format
Jumpge V,SOutFs
Movns V
Setom FMinus
SOutFs: Movem V,(S)
Move A,[010700,,FBufBP-1]
Movem A,FBufBP
Movei B,5*FBufl-1
Movem B,FLeft
Return
FSign: Skipn Format ; SIGN
Jrst NForm
Skipn FMinus
Return
Movei K,"-
Call FSave
Return
FDigit: Skipn Format ; #
Jrst NForm
Jumpe U,Unform
Move T1,(S)
Idiv T1,Base
Move K,T2
Addi K,60
Call FSave
Movem T1,(S)
Return
FNDigs: Skipn Format ; #N
Jrst NForm
Call 4REST
Skipg V
Return
Jumpe U,Unform
Move T1,(S)
FNDlop: Idiv T1,Base
Move K,T2
Addi K,60
Call FSave
Sojn V,FNDlop
Movem T1,(S)
Return
FHold: Skipn Format ; HOLD
Jrst NForm
Call 4REST
Move K,V
Call FSave
Return
FDigs: Skipn Format ; #S
Jrst NForm
Jumpe U,Unform
Move T1,(S)
FDigsl: Jumpe T1,FDigse
Idiv T1,Base
Move K,T2
Addi K,60
Call FSave
Jrst FDigsl
FDigse: Setzm (S)
Return
EOutF: Skipn Format ; #>
Jrst NForm
Call 4REST
Move V,FBufBP
Call 4SAVE
Movei V,5*FBufl-1
Sub V,FLeft
Call 4SAVE
Setzm Format
Return
FSave: Skipn FLeft
Jrst [Type " ?Formatting buffer full"
Jrst Erret]
Move A,FBufBP
DBP A
Movem A,FBufBP
Dpb K,FBufBP
Sos FLeft
Return
;;;
;;; Display hacking
;;;
Home: Skipn Term ; HOME
Return
Move T1,Term
Move A,[440700,,Homes(T1)]
PSOUT
Return
CLS: Skipn Term ; CLEAR
Return
Move T1,Term
Move A,[440700,,Clears(T1)]
PSOUT
Return
;;;
;;; Outputting words
;;;
Space: Movei A,40 ; SPACE
PBOUT
Return
Spaces: Call 4REST ; SPACES
Skipg V
Return
Movei A,40
PBOUT
Sojn V,.-1
Return
Terpri: Movei A,^M ; CR
PBOUT
Movei A,^J
PBOUT
Return
Emit: Call 4REST ; EMIT
Move A,V
PBOUT
Return
7TypeN: Call 4REST ;# Characters TYPE
Move T1,V
Call 4REST ;BP
7TNlop: Ldb A,V
PBOUT
Ibp V
Sojn T1,7TNlop
Return
7Type: Call 4REST ;BP [TYPE]
7TLoop: Ldb A,V
Skipn A
Return
PBOUT
Ibp V
Jrst 7TLoop
Dotext: Skiple Level ; ."
Jrst Dotsav
Dotxt2: Call Getchr
Call Refill
Movem K,Delim
Dotxt3: Call Getchr
Call Refill
Camn K,Delim
Return
Move A,K
PBOUT
Caie A,^M
Jrst Dotxt3
Movei A,^J
PBOUT
Jrst Dotxt3
Dotsav: Move T1,E
Hrli T1,440700
Aoj T1,
Setz T2,
Dots2: Ildb A,T1
Jumpe A,Dots3
PBOUT
Caie A,^M
Aoja T2,Dots2
Movei A,^J
PBOUT
Aoja T2,Dots2
Dots3: Idivi T2,5 ;Return # of text words to skip
Aoj T2,
Add E,T2
Return
;;;
;;; Character operations
;;;
CFetch: Jumpe U,UFlow ; C@
Ldb A,(S)
Movem A,(S)
Return
CStore: Call 4REST ;BP C!
Move T1,V
Call 4REST ;Byte
Dpb V,(T1)
Return
CPlus: Call 4REST ;Number C+
Move T1,V
Call 4REST ;BP
Idivi T1,5
Add V,T1
Jumpe T2,CPlusb
Ibp V
Sojn T2,.-1
CPlusb: Call 4SAVE
Return
CMinus: Call 4REST ;Number C-
Move T1,V
Call 4REST ;BP
IDivi T1,5
Sub V,T1
Jumpe T2,CMin2
CMin1: Dbp V
Sojn T2,CMin1
CMin2: Call 4SAVE
Return
CMoveN: Call 4REST ;Number CMOVE
Move T1,V
Call 4REST ;BP-to
Move T2,V
Call 4REST ;BP-from
CMNlop: Ldb A,V
Dpb A,T2
Ibp V
Ibp T2
Sojn T1,CMNlop
Return
CMoves: Call 4REST ;BP-to [CMOVE] Returns #chars
Move T1,V
Call 4REST ;BP-from
Setz T2,
CMSlop: Ldb A,V
Jumpe A,CMSdun
Dpb A,T1
Ibp V
Ibp T1
Aoja T2,CMSlop
CMSdun: Call 4SAVE
Return
;;;
;;; Inputting words
;;;
Key: PBIN ; KEY
Andi A,177
Move V,A
Call 4SAVE
Return
Number: Jumpe U,UFlow ; caddr [NUMBER] --> caddr n -1
Move T1,(S) ;BP-from ; --> caddr 0
Call StoN
Jrst [Movem T1,(S)
Setz V,
Call 4SAVE
Return]
Movem T1,(S)
Move V,T2
Call 4SAVE
Seto V,
Call 4SAVE
Return
ExpecN: Call 4REST ;Number EXPECT
Move T1,V
Call 4REST ;BP-to
ENLoop: PBIN
Dpb A,V
Skipe Echo
PBOUT
Ibp V
Sojn T1,ENLoop
Return
Expect: Call 4REST ;BP [EXPECT]
Setz T3,
ELoop: PBIN
Cain A,^M
Jrst ESave
Dpb A,V
Skipe Echo
PBOUT
Ibp V
Aoja T3,ELoop
ESave: Dpb V ;Make it asciz
Move V,T3
Call 4SAVE
Return
;;;
;;; Numberic output
;;;
DotR: Call 4REST ; .R
Move T4,V
Skipa
Dot: Call 4REST ; .
Dota: Setz T4,
Movm T1,V
Setz T3,
Dot1: IDiv T1,Base
Push P,T2
Aoj T3,
Jumpn T1,Dot1
Dot2: Move T1,T3
Skipge V
Aoj T1,
Camg T4,T1
Jrst DotS
Sub T4,T1
DotF: Movei A,40
PBOUT
Sojn T4,DotF
DotS: Jumpge V,Dot3
Movei A,"-
PBOUT
Dot3: Pop P,A
Addi A,60
PBOUT
Sojn T3,Dot3
Dot4: Movei A,40
PBOUT
Return
FDot: Call 4REST ; F.
Movei A,.PRIOU
Move B,V
Movei C,FL%ONE\FL%PNT
FLOUT
Jfcl
Return
;;;
;;; Text building (Dictionary)
;;;
SaveTs: Call 4REST ; ["]
Move T1,V
Movei A,^M
Movem A,Delim
Call sTextd
Move V,T2
Call 4SAVE
Return
SaveTd: Call 4REST ; (")
Move T1,V
Call sText
Move V,T2
Call 4SAVE
Return
ColTex: Call BText
Move V,lsText
Call 4SAVE
Return
;;;
;;; Miscellaneous
;;;
Exit: Call Terpri
Type "Exiting FORTH"
Call Terpri
Jrst Die
Remark: Call Getchr ; (
Call Refill
Caie K,")
Jrst Remark
Return
Here: Skipn Making ; HERE
Jrst Buierr
Move V,Dicte
Add V,D
Call 4SAVE
Return
Execut: Call 4REST ; EXECUTE
Move L,V
Call Eval
Return
Leave: Skipge DOc
Jrst DOerr
Move T1,DOc
Move T2,DOtop(T1)
Movem T2,DOind(T1)
Return
Jsys0: Call 4REST ;JSys# JSYS
Hrr V,JCall
Xct JCall
Return
Flush: Move S,Stack ; FLUSH
Setz U,
Return
;;;
;;; Stack/Memory operations
;;;
Store: Call 4REST ; !
Move T1,V
Call 4REST
Movem V,(T1)
Return
Storep: Call 4REST ; +!
Move T1,V
Call 4REST
Addm V,(T1)
Return
Storem: Call 4REST ; -!
Move T1,V
Call 4REST
Exch V,(T1)
Subm V,(T1)
Return
Fill: Call 4REST ;Value FILL
Move T1,V
Call 4REST ;Number
Move T2,V
Call 4REST ;Address
Add T2,V
Movem T1,V
Hrl V,V
Aoj V,
BLT V,-1(T2)
Return
XChanj: Call 4REST ; EXCHANGE
Move T1,V
Call 4REST
Move T2,(V)
Exch T2,(T1)
Movem T2,(V)
Return
Fetch: Jumpe U,UFlow ; @
Move T1,(S)
Move T2,(T1)
Movem T2,(S)
Return
;;;
;;; Random Dictionary stuff
;;;
Tic: Call Getwrd ; '
Call Refill
Skipn IAddr
Jrst NamErr
Move V,IAddr
Call 4SAVE
Return
Ticnum: Call Getwrd ; '#
Call Refill
Skipn INump
Jrst NamErr
Move V,IVal
Call 4SAVE
Return
Forget: Call Getwrd ; FORGET
Call Refill
Skipn IAddr
Jrst NamErr
Move T1,IAddr
Setzm (T1)
Hrl T1,T1
Aoj T1,
BLT T1,Dicte
Move A,IAddr
Hrrm A,Dicte
Return
;;;
;;; Logical operations
;;;
LogAND: Caige U,2 ; AND
Jrst UFlow
Call 4REST
Andm V,(S)
Return
LogOR: Caige U,2 ; OR
Jrst UFlow
Call 4REST
IOrm V,(S)
Return
LogNOT: Jumpe U,UFlow ; NOT
Setcmm (S)
Return
LogXOR: Caige U,2 ; XOR
Jrst UFlow
Call 4REST
XOrm V,(S)
Return
;;;
;;; Arithmetic operations
;;;
Plus: Caige U,2 ; +
Jrst UFlow
Call 4REST
Addm V,(S)
Return
FPlus: Caige U,2 ; F+
Jrst UFlow
Call 4REST
FADM V,(S)
Return
Minus: Call 4REST ; -
Jumpe U,UFlow
Exch V,(S)
Subm V,(S)
Return
FMin: Call 4REST ; F-
Jumpe U,UFlow
Exch V,(S)
FSBM V,(S)
Return
Times: Caige U,2 ; *
Jrst UFlow
Call 4REST
IMulm V,(S)
Return
FTimes: Caige U,2 ; F*
Jrst UFlow
Call 4REST
FMPM V,(S)
Return
Divide: Call 4REST ; /
Jumpe U,UFlow
Exch V,(S)
IDivm V,(S)
Return
FDiv: Call 4REST ; F/
Jumpe U,UFlow
Exch V,(S)
FDVM V,(S)
Return
Power: Call 4REST ; ^
Move T1,V
Call 4REST
Movei T2,1
P2: Jumple T1,P3
Imul T2,V
Soja T1,P2
P3: Move V,T2
Call 4SAVE
Return
Mod: Call 4REST ; MOD
Move T1,V
Call 4REST
Move T2,V
IDiv T2,T1
Move V,T3
Call 4SAVE
Return
DivMod: Call 4REST ; /MOD
Move T1,V
Call 4REST
Move T2,V
IDiv T2,T1
Move V,T3
Call 4SAVE
Move V,T2
Call 4SAVE
Return
;;;
;;; Conversions
;;;
ItoF: Jumpe U,UFlow ; FLOAT
FLTR T1,(S)
Movem T1,(S)
Return
FtoI: Jumpe U,UFlow ; FIX
FIXR T1,(S)
Movem T1,(S)
Return
;;;
;;; Single operator tests
;;;
EqualZ: Setz A, ; 0=
Jrst 1Test
NotEq0: Movei A,1 ; 0=_
Jrst 1Test
LessZ: Movei A,2 ; 0<
Jrst 1Test
LesEq0: Movei A,3 ; 0<=
Jrst 1Test
GreatZ: Movei A,4 ; 0>
Jrst 1Test
GrEq0: Movei A,5 ; 0>=
1Test: Jumpe U,UFlow
Setz T1,
Xct 1Tests(A)
Seto T1,
Movem T1,(S)
Return
;;;
;;; Two operator tests
;;;
Equal: Setz A, ; =
Jrst 2Test
NotEqu: Movei A,1 ; =_
Jrst 2Test
Less: Movei A,2 ; <
Jrst 2Test
LessEq: Movei A,3 ; <=
Jrst 2Test
Greatr: Movei A,4 ; >
Jrst 2Test
GretEq: Movei A,5 ; >=
2Test: Call 4REST
Jumpe U,UFlow
Setz T1,
Xct 2Tests(A)
Seto T1,
Movem T1,(S)
Return
;;;
;;; File-loading things
;;;
Load: Move T3,LLoad ; LOAD
Cail T3,MaxLLs
Jrst [Type " ?Can't load deeper"
Jrst Erret]
Skipg Level
Jrst L2
Movsi A,(GJ%SHT\GJ%OLD)
Hrro B,E
Aoj B,
GTJFN
Jrst NoFile
Hrrz T1,B
Sub T1,E
Move B,[070000,,OF%RD]
OPENF
Jrst NoFile
Add E,T1
Jrst LSave
L2: Call Getchr
Call Refill
Movem K,Delim
Move T1,[440700,,FName]
L3: Call Getchr
Call Refill
Camn K,Delim
Jrst L4
Idpb K,T1
Jrst L3
L4: Idpb T1 ;Make asciz
Hrroi B,FName
L5: Movsi A,(GJ%SHT\GJ%OLD)
GTJFN
Jrst NoFile
Move B,[070000,,OF%RD]
OPENF
Jrst NoFile
LSave: Move T1,iJFN
Aos T2,LLoad
Movem T1,LiJFNs(T2)
Movem A,iJFN
Setom Loadp
Setzm Echo
Return
Loads: Call 4REST ; [LOAD]
Hrro B,V
Jrst L5
Unload: Skipge LLoad ; UNLOAD
Jrst [Type " ?Not loading"
Jrst Erret]
Move A,iJFN
CLOSF
Jrst [Type " %Can't close file"
Jrst .+1]
Move T1,LLoad
Move A,LiJFNs(T1)
Movem A,iJFN
Sos LLoad
Skipl LLoad
Return
Setom Echo
Setzm Loadp
Return
;;;
;;; The infamous IF/ELSE/THEN structure
;;;
IF: Call 4REST
Skipe V
Return
IFskip: Aoj E,
Move T1,(E)
Came T1,[-1,,Then]
Camn T1,[-1,,Else]
Return
Jrst IFskip
Else: Aoj E,
Move T1,(E)
Came T1,[-1,,Then]
Jrst Else
Return
Then: Return
;;;
;;; The REPEAT/UNTIL loop
;;;
Rept: Aos T1,UNTILc
Movem E,UNTILs(T1) ;Start of REPEAT code
Return
Until: Call 4REST
Jumpe V,[Move T1,UNTILc
Move E,UNTILs(T1)
Return]
Sos UNTILc
Return
;;;
;;; The leading test WHILE/BEGIN/END loop
;;;
While: Aos T1,WHILEc
Movem E,WHILEs(T1)
Setzm WHILEe(T1)
Return
Begin: Call 4REST
Skipe V
Return
Move T1,WHILEc
Skipe WHILEe(T1)
Jrst [Move E,WHILEe(T1)
Return]
Begin2: Aoj E,
Move T1,(E)
Came T1,[-1,,FEnd]
Aoja E,Begin2
Sos WHILEc
Return
FEnd: Move T1,WHILEc
Movem E,WHILEe(T1)
Move E,WHILEs(T1)
Return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; The obligatory DO/LOOP[+] structure.
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DoLoop: Aos T1,DOc
Movem E,DOs(T1)
Call 4REST
Movem V,DOind(T1) ;Initial value
Call 4REST
Movem V,DOtop(T1) ;Upper limit
Return
Loop: Move T1,DOc
Aos V,DOind(T1)
Jrst Loopt
Loopp: Move T1,DOc
Call 4REST
Jumpl V,Looppm
Addb V,DOind(T1)
Loopt: Camge V,DOtop(T1)
Move E,DOs(T1)
Caml V,DOtop(T1)
Sos DOc
Return
Looppm: Addb V,DOtop(T1)
Camle V,DOtop(T1)
Move E,DOs(T1)
Camg V,DOtop(t1)
Sos DOc
Return
;;;
;;; The Colon (:) Compiler (Quite Hirsute)
;;;
Colon: Skipe Making
Jrst [Type " ?Can't compile :'s"
Jrst Erret]
Setom Making
Call MHead
Colon1: Call Getwrd
Call Refill
Skipe INump
Jrst [Aoj D,
Setom @Dicte
Aoj D,
Move T1,IVal
Movem T1,@Dicte
Jrst Colon1]
Skipn IAddr
Jrst [Type " ?Undefined"
Jrst Erret]
Move T1,IAddr
Cain T1,SEMIa
Jrst Coldun
Caie T1,PARENa ;Don't compile comments
Jrst Colon2
Colsr: Call Getchr
Call Refill
Caie K,")
Jrst Colsr
Colon2: Hrre A,3(T1)
Jumpg A,[Aoj D,
Movem T1,@Dicte
Jrst Colon1]
Caie T1,ELSEa
Jrst Colon3
Skipge IFc
Jrst [Type " ?ELSE without IF"
Jrst Erret]
Jrst Colis
Colon3: Caie T1,THENa
Jrst Colon4
Skipge IFc
Jrst [Type " ?THEN without IF"
Jrst Erret]
Sos IFc
Jrst Colis
Colon4: Caie T1,BEGINa
Jrst Colon5
Skipge WHILEc
Jrst [Type " ?BEGIN without WHILE"
Jrst Erret]
Setom BEGINp
Jrst Colis
Colon5: Caie T1,ENDa
Jrst Colis
Skipge WHILEc
Jrst [Type " ?END without WHILE"
Jrst Erret]
Skipn BEGINp
Jrst [Type " ?END without BEGIN"
Jrst Erret]
Pop P,BEGINp
Sos WHILEc
Colis: Move T4,4(T1)
Aoj D,
Movem T4,@Dicte
CLoad: Caie T1,DOTQa
Cain T1,LOADa
Jrst [Call BText
Jrst Colon1]
Colis1: Caie T1,UNTILa
Jrst Colis2
Skipge UNTILc
Jrst [Type " ?UNTIL without REPEAT"
Jrst Erret]
Sos UNTILc
Jrst Colon1
Colis2: Caie T1,LOOPa
Cain T1,LOOPPa
Skipa
Jrst Colis3
Skipge DOc
Jrst [Type " ?LOOP without DO"
Jrst Erret]
Sos DOc
Jrst Colon1
Colis3: Caie T1,IFa
Jrst Colis4
Aos IFc
Jrst Colon1
Colis4: Caie T1,DOa
Jrst Colis5
Move A,DOc
Cail A,DOn-1
Jrst [Type " ?DOs nested too deeply"
Jrst Erret]
Aos DOc
Jrst Colon1
Colis5: Caie T1,REPTa
Jrst Colis6
Move A,UNTILc
Cail A,UNTILn-1
Jrst [Type " ?REPEATs nested too deeply"
Jrst Erret]
Aos UNTILc
Jrst Colon1
Colis6: Caie T1,WHILEa
Jrst Colon1
Move A,WHILEc
Cail A,WHILEn-1
Jrst [Type " ?WHILEs nested too deeply"
Jrst Erret]
Aos WHILEc
Push P,BEGINp
Setzm BEGINp
Jrst Colon1
Coldun: Skipl IFc
Jrst [Type " ?Unfinished IF"
Jrst Erret]
Skipl DOc
Jrst [Type " ?Unfinished DO"
Jrst Erret]
Skipl UNTILc
Jrst [Type " ?Unfinished REPEAT"
Jrst Erret]
Skipl WHILEc
Jrst [Type " ?Unfinished WHILE"
Jrst Erret]
Hrrz T1,Dicte
Addi T1,4 ;Address of executable part
Addi D,2
Hrl T1,D
Movem T1,-1(T1) ;Length,,Address
Addm D,Dicte
Setzm Making
Return
;;;
;;; Dictionary building words
;;;
Builds: Skipe Making ; <BUILDS
Jrst [Type " ?Already building"
Jrst Erret]
Call MHead
Setom Making
Return
Does: Skipn Making ; DOES>
Jrst [Move V,BStart
Call 4SAVE
Return]
Move T1,Dicte
Move T2,E
Aoj D,
Hrl T2,D
Movem T2,3(T1)
Addm D,Dicte
Setzm Making
Setom Did
Return
Comma: Skipn Making ; ,
Jrst Buierr
Call 4REST
Aoj D,
Movem V,@Dicte
Return
Allot: Skipn Making ; ALLOT
Jrst Buierr
Call 4REST
Skiple V
Add D,V
Return
Ticome: Skipn Making ; ] --> n
Jrst Buierr
Setz V,
Ticom2: Call Getwrd
Call Refill
Skipe INump
Jrst Numer
Skipn IAddr
Jrst UDef
Move A,IAddr
Cain A,SEMIa
Jrst [Call 4SAVE
Return]
Aoj D,
Movem A,@Dicte
Aoja V,Ticom2
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; ;;;
;;; ;;;
;;; ;;;
;;; Error Messages and Handling ;;;
;;; ;;;
;;; ;;;
;;; ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
NoFile: Type " ?Can't access file"
Jrst Rerun
UFlow: Type " ?Stack underflow"
Jrst Erret
OFlow: Type " ?Stack overflow"
Jrst Erret
Buierr: Type " ?Not building"
Jrst Erret
DOerr: Type " ?Loops too shallow"
Jrst Erret
NForm: Type " ?Not formatting"
Jrst Erret
Unform: Type " ?Formatting # gone"
Setzm Format
Jrst Erret
UDef: Type " ?Undefined word"
Jrst Erret
Numer: Type " ?Numeric word"
Jrst Erret
WMode: Type " ?Immediate use disallowed"
Erret: Call Terpri
Move T1,[440700,,InBuf]
Move T2,nIchar
Soj T2,
Erret2: Ildb A,T1
PBOUT
Sojg T2,Erret2
Erret3: Type "<--"
UnMake: Skipn Making
Jrst ReRun
Call Terpri
Type "%Unbuilding"
Setzm @Dicte
Sojge D,.-1
Setzm Making
ReRun: Setzm nIchar
Setom Level
Setom DOc
Setom IFc
Setom WHILEc
Setom UNTILc
Move P,PDList
Skipn Loadp
Jrst PPRun
Call Terpri
Type "%Aborting load"
Call Unload
Jrst PPRun
NamErr: Movei A,40
PBOUT
Hrroi A,IStrin
PSOUT
Movei A,"?
PBOUT
Movei A,40
PBOUT
Jrst ReRun
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; ;;;
;;; ;;;
;;; ;;;
;;; Subroutines ;;;
;;; ;;;
;;; ;;;
;;; ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4SAVE: Cail U,Deep
Jrst OFlow
Aoj U,
Push S,V
Return
4REST: Jumpe U,UFlow
Soj U,
Pop S,V
Return
Getchr: Ildb K,pInBuf ;Returns one character in K. Skips
Skipn K ;if there's something to get.
Return
Aos nIchar
Jrst Popj1
Refill: Skipe Echo ;Does a fill-input-buffer and returns
Call Terpri ;to the instruction BEFORE the call.
Call FillIB
Sos (P)
Sos (P)
Return
FillIB: Setzb T2,nIchar ;Gets a line of input from the input
Move T4,[440700,,InBuf] ;source, with rubout handling, and
GL2: Move A,iJFN ;stores it in InBuf - Appropriate BPs
GL2a: BIN ;and character counts are reset.
Erjmp [Call Unload
Jrst GLF]
Andi B,177
Cain B,^M
Jrst GL4
Cain B,^E
Jrst [Setcmm Echo
Jrst GL2a]
Caige B,40
Jrst GL2
Cain B,177
Jrst [Jumpe T2,GL2
DBP T4
Movei A,^H
PBOUT
Movei A,40
PBOUT
Movei A,^H
PBOUT
Soja T2,GL2]
GL3: Move A,B
Skipe Echo
PBOUT
GL4: Cail T2,IBufln*5
Jrst GL2
Idpb B,T4
Aoj T2,
Caie B,^M
Jrst GL2
GLnulp: Caie T2,1 ;Ignore blank lines.
Jrst GLF
Skipe Echo
Call Terpri
Jrst FillIB
GLF: Idpb T4 ;Store the final 0 to make string ASCIZ
Move B,[440700,,InBuf]
Movem B,pInbuf
Return
Getwrd: Setzm IStrin ;Reads one word (terminated by
Move A,[IStrin,,IStrin+1] ;a blank, tab, or CR), parses
BLT A,IVal ;it, and sets flags. If INUMp
Setz T2, ;is true, it's a number, whose
Move T4,[440700,,IStrin] ;value is in IVAL. If IADDR is
GWskip: Call Getchr ;nonzero, then it is the address
Return ;in the Dictionary of the word.
Caie K,40
Cain K,^I
Jrst GWskip
Jrst GW3
GW2: Call Getchr
Jrst Check
GW3: Caie K,40
Cain K,^I
Jrst Check
Cain K,^M
Jrst Check
Cail T3,5*3 ;Only 15 characters are significant
Jrst GW2
Cail K,140
Trz K,40
Cail K,"0 ;if 0-9, or - in 1st place, or a ".", then ok.
Caile K,"9
Skipa
Jrst GW4
Cain K,"-
Skipe T2
Skipa
Jrst GW4
Caie K,".
Setom NotNum
GW4: Idpb K,T4 ;Store UPPERCASE
Aoja T2,GW2
Check: Skipn T2
Return
Move T1,[350700,,IStrin]
Call StoN
Jrst FCheck
Movem T2,IVal
Setom INump
Jrst Popj1
FCheck: Skipe NotNum
Jrst Search
Move A,[440700,,IStrin]
FLIN
Jrst Search
Movem B,IVal
Setom INump
Jrst Popj1
Search: Movei T1,Dict
S1: Move T4,IStrin
Came T4,(T1)
Jrst NFound
Move T4,IStrin+1
Came T4,1(T1)
Jrst NFound
Move T4,IStrin+2
Came T4,2(T1)
Jrst NFound
Hrrzm T1,IAddr
Jrst Popj1
NFound: Hlrz T2,3(T1)
Skipn T2
Jrst Popj1
Add T1,T2
Jrst S1
Eval: Aos Level ;The heart of FORTH. EVAL is the creature that
Skipn Trace ;evaluates *things* - It either pushes constants,
Jrst Eval1 ;calls subroutines (FORTH primitives), or EVALs
Call Terpri ;the body of a FORTH word. Note than that EVAL
Move C,Level ;is, by nature, recursive.
Jumpe C,ET1
IMuli C,2
Movei A,"=
PBOUT
Sojn C,.-1
ET1: Movei A,">
PBOUT
Eval1: Came L,[-1]
Jrst Eval2
Move V,1(E)
Call 4SAVE
Skipn Trace
Aoja E,EExit
Type " Constant"
Call SDump
Aoja E,EExit
Eval2: Skipl L
Jrst Eval3
Skipe Trace
Jrst [Movei A,40
PBOUT
Call PFind
Hrli V,350700
Call 7TLoop
Jrst .+1]
Call (L) ; -1,,Subroutine
Skipe Trace
Call SDump
Jrst EExit
Eval3: Hrrz T1,L ;T1 = Dict Addr
Push P,E
Hrrz E,3(T1) ;Code field
Movei B,4(T1)
Movem B,BStart
Skipn Trace
Jrst Eval5
Movei A,40
PBOUT
Move V,T1
Hrli V,350700
Call 7TLoop
Call SDump
Eval5: Skipe Did
Jrst EExitd
Move L,(E)
Jumpe L,EExit1
Call Eval ;Recurse!
Aoja E,Eval5
EExitd: Setzm Did
EExit1: Pop P,E
EExit: Sos Level
Return
MHead: Call Getwrd ;This starts a Dictionary entry by filling
Call Refill ;in the name field, and reserving 1 more.
Skipe INump
Jrst [Type " ?Numeric name field"
Jrst Erret]
Skipe IAddr
Jrst [Type " ?Already defined"
Jrst Erret]
Movei D,2
MH2: Move T2,IStrin(D)
Movem T2,@Dicte
Sojge D,MH2
Movei D,3
Movei A,1
Movem A,@Dicte
Return
sText: Call Getchr ;This reads text from the input buffer
Call Refill ;(delimited by 1st character) and stores
Movem K,Delim ;them using T1 as the BP. It saves the
sTextd: Hrli T1,440700 ;# of chars read in LSTEXT
Setzm lsText
BTLoop: Call Getchr
Call Refill
Camn K,Delim
Jrst BTdone
Idpb K,T1
Aos lsText
Jrst BTLoop
BTdone: Idpb T1 ;Make asciz
Return
BText: Skipn Making ;Used for ." and so on while building
Jrst Buierr ;to save the text in the Dictionary entry.
Move T1,Dicte
Aoj D,
Add T1,D
Call sText
Move T2,lsText
Idivi T2,5
Add D,T2
Return
PFind: Movei V,Dict+3 ;This finds the address of the primitive
PFind1: Hrre A,(V) ;whose machine address we know (L)
Jumpg A,[Setz V,
Return]
Came L,1(V)
Jrst [Hlrz B,(V)
Add V,B
Jrst PFind1]
Subi V,3
Return
SDump: Call Terpri ;This dumps the top 10. numbers
Type "[ " ;on the stack for TRACEing. TOS
Jumpe U,[Type "Nil ] " ;is to the right.
Return]
Move C,U
Soj C,
Caig C,10.
Jrst SDump1
Type "... "
Movei C,10.
SDump1: Move V,S
Sub V,C
Move V,(V)
Call Dota
Sojge C,SDump1
Type "] "
Return
StoN: Setzb A,B ;This is the String-to-Number routine. It
Setzb T3,StoNmp ;expects a BP to the text in T1, and returns
SN1: Ldb K,T1 ;(skipping) with T2 as the number, and T3
Caie K,40 ;the number of character read.
Cain K,^I
Aoja T3,SN1
Skipa
SN2: Ldb K,T1
Aoj A,
Caie K,40 ;String ends on "," or <space> or <cr>
Cain K,^M ;or a 0-byte
Jrst SNtest
Caie K,",
Skipn K
Jrst SNtest
Cain K,"-
Caie A,1
Jrst SN3
Setom StoNmp
Ibp T1
Jrst SN2
SN3: Subi K,60
Skipge K
Jrst SNbad
Caml K,Base
Jrst SNbad
Push P,K
Ibp T1
Aoja B,SN2
SNtest: Jumpe B,SNbad
Setz T2,
Movei T4,1
SNgood: Pop P,K
Imul K,T4
Imul T4,Base
Add T2,K
Sojn B,SNgood
SNg2: Skipe StoNmp
Movns T2
Add T3,A
Jrst Popj1
SNbad: Skipn B
Return
Pop P,K
Soja B,SNbad
Lose: Type "--Severe lossage--Dying--"
Die: HALTF
Jrst .-1
;;;
;;; The End
;;;
Variables
Constants
END Start