Special Feature: ColorForth Commentary

COLOR.ASM: Dictionary

Original file

NOTICE: This is a work in progress. Parts of my commentary are still very rough. However, I have it up on the web because even in this rough form it may be useful to ColorForth enthusiasts. Expect the contents of these files to change frequently.

Adding temporary definitions

mark:
;Set beginning of definitions that will be removed by empty.
;[Refs: forth2]
	mov	ecx, macros    ; Save # words in MACRO wordlist.
	mov	mk, ecx
	mov	ecx, forths    ; Save # words in FORTH wordlist.
	mov	mk+4, ecx
	mov	ecx, h         ; Save end-of-dictionary pointer.
	mov	mk+2*4, ecx
	ret

empty: ;"empt"
;[Refs: forth2]
	mov	ecx, mk+2*4    ; Restore end-of-dictionary pointer.
	mov	h, ecx
	mov	ecx, mk+4      ; Restore # words in FORTH wordlist.
	mov	forths, ecx
	mov	ecx, mk        ; Restore # words in MACRO wordlist.
	mov	macros, ecx
	mov	class, 0       ; (?)
	ret

Finding words

These routines return with ECX = offset into wordlist to word if zero flag set(?) -- [note how instructions affect zero flag]

mfind:
;Look up word in MACRO wordlist.
;[Refs: qcompile, compile]
	mov	ecx, macros
	push	edi
	lea	edi, [macro0-4+ecx*4]
	jmp	@f

find:
;Look up word in FORTH wordlist.
;[Refs: ex1, ex2, qcompile]
	mov	ecx, forths
	push	edi
	lea	edi, [forth0-4+ecx*4]
@@:	std
	repne	scasd
	cld
	pop	edi
	ret

Executing words

ex1:
;[Refs: ex1, aword, eout]
	dec	words ; from keyboard
	jz	@f
	drop
	jmp	ex1
@@:	call	find
	jnz	abort1
	drop
	jmp	[forth2+ecx*4]

execute:
;Used by inter to handle yellow (color=1, execute) words.
;[Refs: spaces]
	mov	lit, offset alit
	dup_
	mov	eax, [-4+edi*4]            ; Grab the next pre-parsed word.

ex2:
;[Refs: none]
	and	eax, -20o                  ; Mask out color bits (bits 0..3).
	call	find                       ; Look up word in FORTH wordlist.
	jnz	abort                      ; If not found, abort.
	drop
	jmp	[forth2+ecx*4]             ; Run the word's definition.

Canceling execution

abort:
;[Refs: ex2, qcompile (qring, insert1) ]
	mov	curs, edi
	shr	edi, 10-2
	mov	blk, edi

abort1:
;[Refs: ex1, copy]
	mov	esp, gods ; [RST]
	mov	spaces+3*4, offset forthd
	mov	spaces+4*4, offset qcompile
	mov	spaces+5*4, offset cnum
	mov	spaces+6*4, offset cshort
	mov	eax, 57o ; ?       ; (57o = value for '?' in encoding scheme)
	call	echo_
	jmp	accept

Adding words to the dictionary

ColorForth offers two routines to add a word to the dictionary — one routine for each wordlist. The address of the routine to use is stored in adefine, the word-definition vector. Macro_ uses sdefine to store the address of macrod into this vector, while forth uses sdefine to store the address of forthd.

Sdefine takes the address of a word-definition routine, but it takes the address off the return stack. This allows the caller to pass the address simply by calling sdefine (as long as the address is intended to be the address of the instruction following the call). This leads to simpler code than would be required to pass an address on the data stack. Of course this means that (1) the code after the call is not run when sdefine returns, and (2) sdefine returns not to its caller but to its caller's caller.

sdefine:
;Sets word-definition vector. Called when current wordlist changes.
;[Refs: macro_, forth]
	pop	adefine ; [RST]
	ret

macro_: ;"macro"
;Points word-definition vector at macrod.
;[Refs: adefine, forth2]
	call	sdefine
	; Does NOT fall through to macrod.

macrod:
;Defines new word and adds it to the MACRO wordlist.
;Used by inter to handle red (color=3, define) words
;  (if the current wordlist is MACRO).
;[Refs: variable (adefine)]
	mov	ecx, macros
	inc	macros
	lea	ecx, [macro0+ecx*4]
	jmp	@f

forth:
;Points word-definition vector at forthd.
;[Refs: forth2]
	call	sdefine
	; Does NOT fall through to forthd.

forthd:
;Defines new word and adds it to the FORTH wordlist.
;Used by inter to handle red (color=3, define) words
;  (if the current wordlist is FORTH).
;[Refs: abort1, variable]
	mov	ecx, forths              ; Increment number of words in the
	inc	forths                   ;   FORTH wordlist.
	lea	ecx, [forth0+ecx*4]      ; Make offset into FORTH word array.
@@:	mov	edx, [-4+edi*4]          ; Grab pre-parsed word.
	and	edx, -20o                ; Clear color bits (bits 0..3).
	mov	[ecx], edx               ; Store result at end of word array.
	mov	edx, h                   ; Store end-of-dictionary pointer
	mov	[forth2-forth0+ecx], edx ;   into wordlist's address array.
	lea	edx, [forth2-forth0+ecx] ; Get address of address-array cell.
	shr	edx, 2                   ; Convert it into DWORD address.
	mov	last, edx                ; Store it (to allow optimization).
	mov	list, esp                ; -- ???? --
	mov	lit, offset adup         ; -- ???? --
	test	class, -1                ; Call custom routine only if
	jz	@f                       ;   vector is non-zero.
	jmp	[class]
@@:	ret	                         ; Otherwise simply return.
;;;;;;;;;;;;;;;;;;NOTE--TEMP
			; ECX = byte pointer to word within word array.
			; EDX = DWORD pointer to addr within addr array.
;;;;;;;;;;;;;;;;;;NOTE--TEMP

Check the index for other entries.