1052 lines
45 KiB
NASM
1052 lines
45 KiB
NASM
|
; =====> SENV.ASM
|
|||
|
;***************************************
|
|||
|
;* TIPC Scheme '84 Runtime Support *
|
|||
|
;*Interpreter -- Environment Operations*
|
|||
|
;* *
|
|||
|
;* (C) Copyright 1985 by Texas *
|
|||
|
;* Instruments Incorporated. *
|
|||
|
;* All rights reserved. *
|
|||
|
;* *
|
|||
|
;* Date Written: 5 March 1985 *
|
|||
|
;* Last Modification: 2 FEB 1987 *
|
|||
|
;***************************************
|
|||
|
;
|
|||
|
; Modification history
|
|||
|
;
|
|||
|
; tc 2/10/87 fixed define so that it will define in
|
|||
|
; to current environment if not already
|
|||
|
; there.
|
|||
|
|
|||
|
|
|||
|
|
|||
|
include scheme.equ
|
|||
|
include sinterp.mac
|
|||
|
|
|||
|
include sinterp.arg
|
|||
|
include stackf.equ
|
|||
|
|
|||
|
DGROUP group data
|
|||
|
data segment word public 'DATA'
|
|||
|
assume DS:DGROUP
|
|||
|
m_ld_en db "ld-env",0
|
|||
|
m_st_en db "st-env",0
|
|||
|
m_def_en db "define-env",0
|
|||
|
m_en_par db "environment-parent",0
|
|||
|
m_env_lu db "env-lu",0
|
|||
|
m_ld_gl db "ld-global",0
|
|||
|
m_defb db "define!",0
|
|||
|
m_st_gl db "st-global",0
|
|||
|
m_setgnv db "set-global-env!",0
|
|||
|
; Note: the following three (3) definitions are order dependent
|
|||
|
lcl_reg equ $ ; local "register"
|
|||
|
lcl_disp dw 0
|
|||
|
lcl_page dw 0
|
|||
|
; End of order dependent definitions
|
|||
|
data ends
|
|||
|
|
|||
|
PGROUP group prog
|
|||
|
prog segment byte public 'PROG'
|
|||
|
assume CS:PGROUP
|
|||
|
|
|||
|
s_env proc near
|
|||
|
|
|||
|
; Entry points defined in "sinterp.asm"
|
|||
|
extrn next:near ; Top of interpreter
|
|||
|
extrn next_PC:near ; Reload ES,SI at top of interpreter
|
|||
|
extrn next_SP:near ; All of the above, with "mov SP,BP" first
|
|||
|
extrn src_err:near ; "source operand error" message display
|
|||
|
extrn printf_c:near ; Error message print routine
|
|||
|
extrn not_yet:near ; Feature not yet implemented
|
|||
|
extrn sch_err:near ; Link to Scheme level debugger
|
|||
|
|
|||
|
; Entry point defined in "svars.asm"
|
|||
|
extrn lookup:near
|
|||
|
|
|||
|
;************************************************************************
|
|||
|
;* push environment PUSH-ENV list-of-symbols *
|
|||
|
;* *
|
|||
|
;* Purpose: Scheme interpreter support to "push" a new rib onto the *
|
|||
|
;* current heap allocated environment. *
|
|||
|
;************************************************************************
|
|||
|
public push_env
|
|||
|
push_env: lods byte ptr ES:[SI] ; load code block constant pointer
|
|||
|
; allocate new environment object
|
|||
|
mov BX,ENV_SIZE-BLK_OVHD ; load size of environment data object,
|
|||
|
mov CX,ENVTYPE ; environment type code, and
|
|||
|
mov DX,offset tmp_reg ; temporary register address
|
|||
|
pushm <BX,CX,DX> ; push arguments to 'allocate_block'
|
|||
|
C_call alloc_bl,<AX,SI>,Load_ES ; allocate new environment object
|
|||
|
|
|||
|
; fetch pointer to list-of-symbols
|
|||
|
restore <AX,ES>
|
|||
|
mov BX,AX
|
|||
|
shl AX,1
|
|||
|
add BX,AX ; BX <- constant number * 3
|
|||
|
add BX,CB_dis ; add code block displacement to BX
|
|||
|
mov AX,ES:[BX].cod_cdis ; load constant from code block
|
|||
|
mov DL,ES:[BX].cod_cpag
|
|||
|
|
|||
|
; place previous env pointer in new one; update stack frame's env pointer
|
|||
|
mov BX,tmp_page ; load pointer to new env object
|
|||
|
mov DI,tmp_disp
|
|||
|
LoadPage ES,BX
|
|||
|
;;; mov ES,pagetabl+[BX]
|
|||
|
mov SI,FP ; load current stack frame pointer
|
|||
|
xchg BL,S_stack+[SI].sf_hpage ; exchange old/new env pointers
|
|||
|
mov ES:[DI].env_ppag,BL
|
|||
|
mov CX,DI
|
|||
|
xchg CX,word ptr S_stack+[SI].sf_hdisp
|
|||
|
mov ES:[DI].env_pdis,CX
|
|||
|
|
|||
|
; put list-of-symbols pointer into new environment data object
|
|||
|
mov ES:[DI].env_npag,DL ; and store it
|
|||
|
mov ES:[DI].env_ndis,AX
|
|||
|
|
|||
|
; set tm2_reg to nil (initial empty list of values)
|
|||
|
mov byte ptr tm2_page,NIL_PAGE*2 ; set tmp_reg to nil
|
|||
|
mov tm2_disp,NIL_DISP
|
|||
|
|
|||
|
; count number of symbols in the list-of-symbols
|
|||
|
cmp DL,0 ; is list of symbols nil?
|
|||
|
je psh_end ; if empty list, jump
|
|||
|
mov ES:[DI].env_vpag,NIL_PAGE*2 ; make value list pointer in env
|
|||
|
mov ES:[DI].env_vdis,NIL_DISP ; object nil to prevent GC problems
|
|||
|
xor CX,CX ; zero the counter
|
|||
|
xor BX,BX
|
|||
|
mov BL,DL ; copy the list-of-symbols pointer
|
|||
|
mov SI,AX ; into BX:SI
|
|||
|
psh_enxt: inc CX ; increment list length counter
|
|||
|
LoadPage ES,BX ; follow the cdr field of the linked list
|
|||
|
;;; mov ES,pagetabl+[BX] ; follow the cdr field of the linked list
|
|||
|
mov BL,ES:[SI].cdr_page
|
|||
|
mov SI,ES:[SI].cdr
|
|||
|
cmp BL,0 ; end of list?
|
|||
|
jne psh_enxt
|
|||
|
|
|||
|
; set up parameters for call to cons
|
|||
|
mov DX,offset nil_reg
|
|||
|
mov AX,offset tm2_reg
|
|||
|
pushm <DX,AX,AX>
|
|||
|
mov AX,DS ; load ES for call to Lattice C routine
|
|||
|
mov ES,AX
|
|||
|
|
|||
|
; create value list of nil pointers (linked through car field)
|
|||
|
psh_cons: C_call cons,<CX> ; cons a nil value cell
|
|||
|
restore <CX> ; reload counter
|
|||
|
loop psh_cons ; decrement count, loop if not zero
|
|||
|
add SP,WORDINCR*3 ; drop arguments off TIPC's stack
|
|||
|
|
|||
|
; store pointer to list of values into environment data object
|
|||
|
mov BX,tmp_page ; reload environment object pointer (it
|
|||
|
LoadPage ES,BX ; may have been moved during the consing
|
|||
|
;;; mov ES,pagetabl+[BX] ; may have been moved during the consing
|
|||
|
mov DI,tmp_disp ; of the nil values list)
|
|||
|
psh_end: mov AL,byte ptr tm2_page ; store pointer to list-of-values
|
|||
|
mov ES:[DI].env_vpag,AL ; into env data object
|
|||
|
mov AX,tm2_disp
|
|||
|
mov ES:[DI].env_vdis,AX
|
|||
|
|
|||
|
jmp next_SP ; return to interpreter
|
|||
|
|
|||
|
;************************************************************************
|
|||
|
;* hash-environment HASH-ENV *
|
|||
|
;* *
|
|||
|
;* Purpose: Scheme interpreter support to return a hashed environment *
|
|||
|
;* *
|
|||
|
;************************************************************************
|
|||
|
public hash_env
|
|||
|
hash_env: lods byte ptr ES:[SI] ; load destination register number
|
|||
|
; allocate new environment object
|
|||
|
mov BX,(HT_SIZE*3)+BLK_OVHD ; size of hashed env
|
|||
|
mov CX,ENVTYPE ; environment type code
|
|||
|
mov DX,offset tmp_reg ; temporary register address
|
|||
|
pushm <BX,CX,DX> ; push arguments to 'allocate_block'
|
|||
|
C_call alloc_bl,<AX,SI>,Load_ES ; allocate new environment object
|
|||
|
mov SP,BP
|
|||
|
push tmp_disp ; push new environment's displacement
|
|||
|
mov BX,tmp_page ; get page offset of new env.
|
|||
|
shr BX,1 ; convert to number
|
|||
|
push BX ; push new environment's page number
|
|||
|
C_call zero_blk ; zero out the new environment
|
|||
|
mov SP,BP
|
|||
|
mov BX,tmp_page ; Now address the new environment
|
|||
|
mov DI,tmp_disp
|
|||
|
LoadPage ES,BX ; ES <= address of new environment
|
|||
|
mov BX,FP ; get current stack frame pointer
|
|||
|
mov AL,S_stack+[BX].sf_hpage ; get current env pointer from stack
|
|||
|
mov ES:[DI].env_ppag,AL ; and store in new env object
|
|||
|
mov AX,word ptr S_stack+[BX].sf_hdisp
|
|||
|
mov ES:[DI].env_pdis,AX
|
|||
|
restore <AX,SI,ES> ; restore saved regs
|
|||
|
mov DI,AX ; DI <= destination register
|
|||
|
mov BX,tmp_page ; get page number of new environment
|
|||
|
mov byte ptr reg0_pag+[DI],BL ; and place in destination reg
|
|||
|
mov BX,tmp_disp ; get disp of new environment
|
|||
|
mov reg0_dis+[DI],BX ; and place in destination
|
|||
|
jmp next
|
|||
|
|
|||
|
;************************************************************************
|
|||
|
;* drop-environment DROP-ENV I(number to drop) *
|
|||
|
;* *
|
|||
|
;* Purpose: Scheme interpreter support to drop the most recently *
|
|||
|
;* allocated rib from the current environment. *
|
|||
|
;************************************************************************
|
|||
|
public drop_env
|
|||
|
drop_env: lods byte ptr ES:[SI] ; load drop count
|
|||
|
save <SI> ; save the current location pointer
|
|||
|
mov CX,AX ; copy drop count to CX
|
|||
|
mov DI,FP ; load the current stack frame pointer
|
|||
|
xor BX,BX
|
|||
|
mov BL,S_stack+[DI].sf_hpage ; load environment pointer from
|
|||
|
mov SI,word ptr S_stack+[DI].sf_hdisp ; the current stack frame
|
|||
|
drop_lp: LoadPage ES,BX
|
|||
|
;;; mov ES,pagetabl+[BX]
|
|||
|
mov BL,ES:[SI].env_ppag ; copy parent's pointer from environment
|
|||
|
mov SI,ES:[SI].env_pdis
|
|||
|
loop drop_lp
|
|||
|
mov S_stack+[DI].sf_hpage,BL ; rib into the stack frame
|
|||
|
mov word ptr S_stack+[DI].sf_hdisp,SI
|
|||
|
jmp next_PC ; return to interpreter
|
|||
|
|
|||
|
;************************************************************************
|
|||
|
;* Macro Support for load/store-environment *
|
|||
|
;************************************************************************
|
|||
|
ld_st macro direction,text
|
|||
|
local x,y
|
|||
|
lods word ptr ES:[SI] ; load operands
|
|||
|
xor BH,BH
|
|||
|
mov BL,AL ; copy destination register number
|
|||
|
mov DI,BX ; into TIPC register DI and
|
|||
|
add DI,offset reg0 ; compute its address
|
|||
|
save <SI,DI> ; save location pointer, dest reg address
|
|||
|
mov BL,AH ; copy constant number into
|
|||
|
mov DI,BX ; TIPC register DI
|
|||
|
shl BX,1
|
|||
|
add DI,BX ; DI <- constant number * 3
|
|||
|
add DI,CB_dis ; compute address of code block constant
|
|||
|
xor BH,BH
|
|||
|
mov BL,ES:[DI].cod_cpag ; load symbol's page number
|
|||
|
cmp byte ptr ptype+[BX],SYMTYPE*2 ; it is a symbol, isn't it?
|
|||
|
jne x ; if not a symbol, error (jump)
|
|||
|
; call "srch_all" to search the current environment
|
|||
|
mov CX,BX ; copy symbol pointer into CX:DX
|
|||
|
mov DX,ES:[DI].cod_cdis
|
|||
|
mov SI,FP ; load current stack frame pointer
|
|||
|
mov BL,S_stack+[SI].sf_hpage ; load current env pointer into
|
|||
|
mov SI,word ptr S_stack+[SI].sf_hdisp ; BX:SI
|
|||
|
call srch_all ; search environment for symbol
|
|||
|
restore <DI> ; reload destination register address
|
|||
|
cmp BL,0 ; was symbol found in environment?
|
|||
|
je y ; if not found, error (jump)
|
|||
|
LoadPage ES,BX
|
|||
|
;;; mov ES,pagetabl+[BX]
|
|||
|
IFIDN <direction>,<load>
|
|||
|
; return value from cdr field of value cell returned by "srch_all"
|
|||
|
mov AL,ES:[SI].cdr_page
|
|||
|
mov byte ptr [DI].C_page,AL ; store value in destination register
|
|||
|
mov AX,ES:[SI].cdr
|
|||
|
mov [DI].C_disp,AX
|
|||
|
ELSE
|
|||
|
IFIDN <direction>,<store>
|
|||
|
; store value into cdr field of returned value cell
|
|||
|
mov AL,byte ptr [DI].C_page ; store value into cdr field
|
|||
|
mov ES:[SI].cdr_page,AL ; of cell
|
|||
|
mov AX,[DI].C_disp
|
|||
|
mov ES:[SI].cdr,AX
|
|||
|
ELSE
|
|||
|
***error*** Invalid 'direction'
|
|||
|
ENDIF
|
|||
|
ENDIF
|
|||
|
; return to the Scheme interpreter
|
|||
|
jmp next_PC
|
|||
|
; ***error-- operand is not a symbol***
|
|||
|
x: lea BX,text ; load text for instruction's name
|
|||
|
jmp src_err ; display "source operand error" message
|
|||
|
; ***error-- symbol not found in environment***
|
|||
|
y: corrpage CX
|
|||
|
IFIDN <direction>,<load>
|
|||
|
xor AX,AX ; signal current environment being used
|
|||
|
pushm <DI,AX,DX,CX> ; push arguments for call
|
|||
|
C_call sym_unde,,Load_ES ; call: sym_undefined(pg,ds,env,dest);
|
|||
|
ELSE
|
|||
|
pushm <DX,CX> ; push arguments for call
|
|||
|
C_call not_lexi,,Load_ES ; call: not_lexically_bound(pg,ds);
|
|||
|
ENDIF
|
|||
|
restore <SI> ; load next instruction's offset and
|
|||
|
sub SI,3 ; back it up to retry the ld/st
|
|||
|
jmp sch_err ; link to Scheme debugger
|
|||
|
endm
|
|||
|
|
|||
|
;************************************************************************
|
|||
|
;* Load From Environment LD-ENV R(dest),C(symbol) *
|
|||
|
;* *
|
|||
|
;* Purpose: Scheme interpreter support to load from the current *
|
|||
|
;* environment. *
|
|||
|
;************************************************************************
|
|||
|
public ld_env
|
|||
|
; load and process operands
|
|||
|
ld_env: ld_st load,m_ld_en
|
|||
|
|
|||
|
;************************************************************************
|
|||
|
;* Store Into Environment ST-ENV R(value),C(symbol) *
|
|||
|
;* *
|
|||
|
;* Purpose: Scheme interpreter support to store into the current *
|
|||
|
;* environment. *
|
|||
|
;************************************************************************
|
|||
|
public st_env
|
|||
|
; load and process operands
|
|||
|
st_env: ld_st store,m_st_en
|
|||
|
|
|||
|
purge ld_st
|
|||
|
|
|||
|
;************************************************************************
|
|||
|
;* AL AL AH *
|
|||
|
;* Define in Environment DEFINE R(d=s1),R(s2),R(s3) *
|
|||
|
;* s1=sym,s2=val,s3=env/nil *
|
|||
|
;* *
|
|||
|
;* Purpose: Scheme interpreter support to define a symbol in a given *
|
|||
|
;* environment. This routine supports the MIT Scheme construct *
|
|||
|
;* (set! (access sym env) value). In essence, the current env *
|
|||
|
;* is searched for sym. If found, then its binding is modified *
|
|||
|
;* to value. Otherwise, a new binding is added to the current *
|
|||
|
;* environment. *
|
|||
|
;************************************************************************
|
|||
|
; ***error-- invalid operand for define***
|
|||
|
def_en_x: mov BX,offset m_def_en ; load "def-env" text
|
|||
|
jmp src_err ; display "invalid source operand" message
|
|||
|
|
|||
|
public def_env
|
|||
|
def_env: lods byte ptr ES:[SI] ; load symbol operand
|
|||
|
mov DI,AX ; copy symbol register number to
|
|||
|
add DI,offset reg0 ; DI and compute the register's address
|
|||
|
lods word ptr ES:[SI] ; load value/environment operands
|
|||
|
save <SI,DI,AX> ; save loc ptr, dest reg addr, val/env opnds
|
|||
|
; validate and load the symbol operand
|
|||
|
mov BX,[DI].C_page ; fetch the symbol's page number
|
|||
|
cmp byte ptr ptype+[BX],SYMTYPE*2 ; is first operand a symbol?
|
|||
|
jne def_en_x ; if not a symbol, error (jump)
|
|||
|
mov CX,BX ; place symbol pointer into CX:DX
|
|||
|
mov DX,[DI].C_disp
|
|||
|
; validate and load environment operand
|
|||
|
mov BL,AH ; copy env register number to BX
|
|||
|
mov SI,reg0_dis+[BX] ; load environment pointer into BX:SI
|
|||
|
mov BL,byte ptr reg0_pag+[BX]
|
|||
|
cmp byte ptr ptype+[BX],ENVTYPE*2 ; is it an envirnoment object?
|
|||
|
je def_e_ok ; if an environment, jump
|
|||
|
cmp BL,0 ; is it a nil pointer?
|
|||
|
jne def_en_x ; if not nil, error (invalid operand; jump)
|
|||
|
mov SI,FP ; load pointer to current stack frame
|
|||
|
mov BL,S_stack+[SI].sf_hpage ; default environment to current
|
|||
|
mov SI,word ptr S_stack+[SI].sf_hdisp ; environment
|
|||
|
; search environment for the symbol
|
|||
|
def_e_ok: pushm <BX,SI> ; save environment pointer on stack
|
|||
|
call srch_all ; search all rib's
|
|||
|
restore <AX> ; restore 2nd and 3rd operands
|
|||
|
cmp BL,0 ; was symbol found?
|
|||
|
je def_bind ; if not found, jump
|
|||
|
LoadPage ES,BX ; load value cell page's paragraph address
|
|||
|
;;; mov ES,pagetabl+[BX] ; load value cell page's paragraph address
|
|||
|
mov BL,AL ; copy value register number to BX
|
|||
|
mov AL,byte ptr reg0_pag+[BX] ; set cdr of value cell to the
|
|||
|
mov ES:[SI].cdr_page,AL ; contents of the value register
|
|||
|
mov AX,reg0_dis+[BX]
|
|||
|
mov ES:[SI].cdr,AX
|
|||
|
jmp next_SP ; return to interpreter
|
|||
|
|
|||
|
; Symbol not found in environment -- bind it in given rib
|
|||
|
def_bind: restore <DI> ; restore symbol register address
|
|||
|
pop [BP].temp_reg.C_disp ; restore env pointer in local temp_reg
|
|||
|
pop [BP].temp_reg.C_page
|
|||
|
mov BL,AL ; compute value register address
|
|||
|
add BX,offset reg0
|
|||
|
lea SI,[BP].temp_reg ; load tmp_reg address
|
|||
|
pushm <SI,BX,DI> ; push args to bind_it
|
|||
|
call bind_it ; bind symbol in environment
|
|||
|
jmp next_SP ; return to interpreter
|
|||
|
|
|||
|
;************************************************************************
|
|||
|
;* Set Global Environment SET-GLOB-ENV! R(value) *
|
|||
|
;* *
|
|||
|
;* Purpose: Scheme interpreter support to initialize the Global *
|
|||
|
;* Environment Register (GNV_reg). *
|
|||
|
;************************************************************************
|
|||
|
public set_gnv
|
|||
|
set_gnv: lods byte ptr ES:[SI] ; load operand
|
|||
|
mov DI,AX ; copy source register number to DI and
|
|||
|
add DI,offset reg0 ; compute source/destination reg address
|
|||
|
mov AX,[DI].C_disp ; load pointer to new global environment
|
|||
|
mov BX,[DI].C_page
|
|||
|
cmp byte ptr ptype+[BX],ENVTYPE*2 ;it's an environment, isn't it?
|
|||
|
jne set_g_er ; if operand not env, error (jump)
|
|||
|
xchg byte ptr GNV_pag,BL ; copy env pointer to GNV_reg
|
|||
|
xchg GNV_dis,AX
|
|||
|
mov byte ptr [DI].C_page,BL ; store previous value of GNV_reg
|
|||
|
mov [DI].C_disp,AX ; into the destination register
|
|||
|
jmp next ; return to interpreter
|
|||
|
; ***error-- operand is not an environment object***
|
|||
|
set_g_er: save <SI> ; save the location pointer
|
|||
|
mov BX,offset m_setgnv ; load text for "set-global-env!"
|
|||
|
jmp src_err ; display "source operand error" message
|
|||
|
|
|||
|
;************************************************************************
|
|||
|
;* AL AH *
|
|||
|
;* Load from Global Environment LD-GLOBAL R(d),C(s1) *
|
|||
|
;* s1=symbol *
|
|||
|
;* *
|
|||
|
;* Purpose: Scheme interpreter support to retrieve values for symbols *
|
|||
|
;* defined in the current global environment. *
|
|||
|
;* *
|
|||
|
;* Note: This instruction is an optimization of the LD-ENV operation. *
|
|||
|
;* Here, the environment operand defaults to the current *
|
|||
|
;* global environment, which is pointer to by GNV_reg. *
|
|||
|
;************************************************************************
|
|||
|
public ld_globl
|
|||
|
ld_globl: lods word ptr ES:[SI] ; load operands
|
|||
|
mov BL,AL ; copy the destintation register
|
|||
|
mov DI,BX ; into TIPC register DI and compute
|
|||
|
add DI,offset reg0 ; the destination register's address
|
|||
|
save <SI,DI> ; save said, and the location pointer
|
|||
|
; validate the symbol operand and load symbol pointer
|
|||
|
mov BL,AH ; copy the constant number
|
|||
|
mov SI,BX ; SI <- constant number * 3
|
|||
|
shl SI,1
|
|||
|
add SI,BX
|
|||
|
add SI,CB_dis ; add in displacement of current code block
|
|||
|
mov BL,ES:[SI].cod_cpag ; load symbol's page number
|
|||
|
mov DX,ES:[SI].cod_cdis ; load symbol pointer into CX:DX
|
|||
|
ld_gl_x: cmp byte ptr ptype+[BX],SYMTYPE*2 ; it is a symbol, isn't it?
|
|||
|
jne ld_g_err ; if not a symbol, error (jump)
|
|||
|
mov CX,BX
|
|||
|
; load pointer to the global environment
|
|||
|
mov BL,byte ptr GNV_pag
|
|||
|
mov SI,GNV_dis
|
|||
|
; search the global environment for the symbol-- test to see if found
|
|||
|
pushm <CX,DX> ; save symbol pointer
|
|||
|
call srch_all ; search global environment
|
|||
|
restore <DI> ; reload destination register address
|
|||
|
cmp BL,0 ; was symbol found?
|
|||
|
je ld_g_nf ; if not found, error (jump)
|
|||
|
; copy cdr field of value cell returned into the destination register
|
|||
|
LoadPage ES,BX
|
|||
|
;;; mov ES,pagetabl+[BX]
|
|||
|
mov AL,ES:[SI].cdr_page ; copy cdr field of value cell
|
|||
|
mov byte ptr [DI].C_page,AL ; into destination register
|
|||
|
mov AX,ES:[SI].cdr
|
|||
|
mov [DI].C_disp,AX
|
|||
|
jmp next_SP ; return to interpreter
|
|||
|
; ***error-- symbol operand wasn't a symbol pointer***
|
|||
|
ld_g_err: mov BX,offset m_ld_gl ; load text for "ld-global"
|
|||
|
jmp src_err ; display "invalid source operand" message
|
|||
|
; ***error-- global symbol not found***
|
|||
|
ld_g_nf: popm <DX,CX> ; restore symbol pointer
|
|||
|
corrpage CX ; correct page number for call to C
|
|||
|
mov AX,offset GNV_reg ; load address of global env register
|
|||
|
pushm <DI,AX,DX,CX> ; push arguments for call
|
|||
|
C_call sym_unde,,Load_ES ; call: sym_undefined(pg,ds,env,dest)
|
|||
|
restore <SI> ; load next intstruction's offset and
|
|||
|
sub SI,3 ; back up location pointer to retry load
|
|||
|
jmp sch_err ; link to Scheme debugger
|
|||
|
|
|||
|
;************************************************************************
|
|||
|
;* AL AH *
|
|||
|
;* Load from Global Environment (reg operand) LD-GLOBAL-R R(d),R(s1) *
|
|||
|
;* s1=symbol *
|
|||
|
;* *
|
|||
|
;* Purpose: Scheme interpreter support to retrieve values for symbols *
|
|||
|
;* defined in the current global environment. *
|
|||
|
;* *
|
|||
|
;* Note: This instruction is an optimization of the LD-ENV operation. *
|
|||
|
;* Here, the environment operand defaults to the current *
|
|||
|
;* global environment, which is pointer to by GNV_reg. *
|
|||
|
;************************************************************************
|
|||
|
public ld_globr
|
|||
|
ld_globr: lods word ptr ES:[SI] ; load operands
|
|||
|
mov BL,AL ; copy the destintation register
|
|||
|
mov DI,BX ; into TIPC register DI and compute
|
|||
|
add DI,offset reg0 ; the destination register's address
|
|||
|
save <SI,DI> ; save said, and the location pointer
|
|||
|
; load symbol pointer
|
|||
|
mov BL,AH ; copy the symbol's register number
|
|||
|
mov DX,reg0_dis+[BX] ; load symbol's displacement
|
|||
|
mov BL,byte ptr reg0_pag+[BX] ; load symbol's page number
|
|||
|
jmp ld_gl_x ; continue process as ld-global
|
|||
|
|
|||
|
;************************************************************************
|
|||
|
;* AL AH *
|
|||
|
;* Define in Global Environment DEFINE! R(d=s1),C(s2) *
|
|||
|
;* s1=value,s2=symbol *
|
|||
|
;* *
|
|||
|
;* Purpose: Scheme interpreter support to assign a variable in the *
|
|||
|
;* current "global" environment. *
|
|||
|
;* *
|
|||
|
;* Note: This instruction is an optimization of the DEFINE-ENV *
|
|||
|
;* operation. Here, the environment operand defaults to *
|
|||
|
;* the current global environment, which is pointed to by *
|
|||
|
;* GNV_reg. *
|
|||
|
;************************************************************************
|
|||
|
public define
|
|||
|
define: lods word ptr ES:[SI] ; load operands
|
|||
|
mov BL,AH ; copy constant number to BX
|
|||
|
xor AH,AH
|
|||
|
mov DI,AX ; copy value/destination register number
|
|||
|
add DI,offset reg0 ; to DI and compute the register's address
|
|||
|
save <SI,DI> ; save location pointer, dest reg address
|
|||
|
; validate symbol operands and load it into CX:DX
|
|||
|
mov SI,BX ; copy constant number into SI
|
|||
|
shl SI,1
|
|||
|
add SI,BX ; SI <- constant number * 3
|
|||
|
add SI,CB_dis ; add starting offset of current code block
|
|||
|
mov BL,ES:[SI].cod_cpag ; load symbol's page number
|
|||
|
cmp byte ptr ptype+[BX],SYMTYPE*2 ; it is a symbol, isn't it?
|
|||
|
jne defb_err ; if not a symbol, error (jump)
|
|||
|
mov CX,BX ; put symbol pointer into CX:DX
|
|||
|
mov DX,ES:[SI].cod_cdis
|
|||
|
pushm <CX,DX> ; save pointer to symbol
|
|||
|
; load global environment pointer into BX:SI
|
|||
|
mov BL,byte ptr GNV_pag
|
|||
|
mov SI,GNV_dis
|
|||
|
; search the global environment for the symbol-- test to see if found
|
|||
|
call srch_env
|
|||
|
cmp BL,0
|
|||
|
je defb_new
|
|||
|
; symbol was found-- set cdr of field returned to the value specified
|
|||
|
restore <DI>
|
|||
|
LoadPage ES,BX
|
|||
|
;;; mov ES,pagetabl+[BX]
|
|||
|
mov AL,byte ptr [DI].C_page
|
|||
|
mov ES:[SI].cdr_page,AL
|
|||
|
mov AX,[DI].C_disp
|
|||
|
mov ES:[SI].cdr,AX
|
|||
|
jmp next_SP ; return to interpreter
|
|||
|
; symbol wasn't found-- create new binding in current global environment
|
|||
|
defb_new: mov AX,SP ; get address of symbol
|
|||
|
|
|||
|
; In case you're wondering what just went on with the above instruction,
|
|||
|
; the page and displacement of the symbol to be bound are residing in the
|
|||
|
; correct order on the top of the stack. The "mov AX,SP" captures the
|
|||
|
; address of said pointer so that it may be used as an argument to
|
|||
|
; sym_bind, below.
|
|||
|
|
|||
|
mov BX,offset GNV_reg ; load GNV_reg address (contains env ptr)
|
|||
|
pushm <BX,[BP].save_DI,AX> ; push sym,val,env register pointers
|
|||
|
call bind_it ; create binding in global environment
|
|||
|
jmp next_SP ; return to interpreter
|
|||
|
; ***error-- symbol operand wasn't a symbol***
|
|||
|
defb_err: mov BX,offset m_defb
|
|||
|
jmp src_err
|
|||
|
|
|||
|
;************************************************************************
|
|||
|
;* AL AH *
|
|||
|
;* Define in Global Environment ST-GLOBAL R(d=s1),C(s2) *
|
|||
|
;* s1=value,s2=symbol *
|
|||
|
;* *
|
|||
|
;* Purpose: Scheme interpreter support to assign a variable in the *
|
|||
|
;* current "global" environment. *
|
|||
|
;* *
|
|||
|
;* Note: This instruction is an optimization of the ST-ENV *
|
|||
|
;* operation. Here, the environment operand defaults to *
|
|||
|
;* the current global environment, which is pointed to by *
|
|||
|
;* GNV_reg. *
|
|||
|
;************************************************************************
|
|||
|
public st_globl
|
|||
|
st_globl: lods word ptr ES:[SI] ; load operands
|
|||
|
mov BL,AH ; copy constant number to BX
|
|||
|
xor AH,AH
|
|||
|
mov DI,AX ; copy value/destination register number
|
|||
|
add DI,offset reg0 ; to DI and compute the register's address
|
|||
|
save <SI,DI> ; save location pointer, dest reg address
|
|||
|
; validate symbol operands and load it into CX:DX
|
|||
|
mov SI,BX ; copy constant number into SI
|
|||
|
shl SI,1
|
|||
|
add SI,BX ; SI <- constant number * 3
|
|||
|
add SI,CB_dis ; add starting offset of current code block
|
|||
|
mov BL,ES:[SI].cod_cpag ; load symbol's page number
|
|||
|
cmp byte ptr ptype+[BX],SYMTYPE*2 ; it is a symbol, isn't it?
|
|||
|
jne st_gl_er ; if not a symbol, error (jump)
|
|||
|
mov CX,BX ; put symbol pointer into CX:DX
|
|||
|
mov DX,ES:[SI].cod_cdis
|
|||
|
pushm <CX,DX> ; save pointer to symbol
|
|||
|
; load global environment pointer into BX:SI
|
|||
|
mov BL,byte ptr GNV_pag
|
|||
|
mov SI,GNV_dis
|
|||
|
; search the global environment for the symbol-- test to see if found
|
|||
|
call srch_all
|
|||
|
restore <DI>
|
|||
|
cmp BL,0
|
|||
|
je st_gl_nf
|
|||
|
; symbol was found-- set cdr of field returned to the value specified
|
|||
|
LoadPage ES,BX
|
|||
|
;;; mov ES,pagetabl+[BX]
|
|||
|
mov AL,byte ptr [DI].C_page
|
|||
|
mov ES:[SI].cdr_page,AL
|
|||
|
mov AX,[DI].C_disp
|
|||
|
mov ES:[SI].cdr,AX
|
|||
|
jmp next_SP ; return to interpreter
|
|||
|
; symbol wasn't found-- inquire from user as to what to do
|
|||
|
st_gl_nf: popm <DX,CX> ; restore pointer to symbol
|
|||
|
corrpage CX ; adjust page number for C call
|
|||
|
pushm <DI,DX,CX> ; push page, disp, value reg address
|
|||
|
C_call not_glob,,load_ES ; resolve error situation
|
|||
|
restore <SI> ; load next instruction's offset and back
|
|||
|
sub SI,3 ; location pointer up to retry the store
|
|||
|
jmp sch_err ; link to Scheme debugger
|
|||
|
; ***error-- invalid operand to st-global***
|
|||
|
st_gl_er: mov BX,offset m_st_gl
|
|||
|
jmp src_err
|
|||
|
|
|||
|
;************************************************************************
|
|||
|
;* Environment Predicate ENV? object *
|
|||
|
;* *
|
|||
|
;* Purpose: Scheme interpreter support to test for an environment *
|
|||
|
;* data object. *
|
|||
|
;************************************************************************
|
|||
|
public env_p
|
|||
|
env_p: lods byte ptr ES:[SI] ; load the operand
|
|||
|
mov DI,AX ; and copy into TIPC register DI
|
|||
|
mov BX,reg0_pag+[DI] ; load the operand's page number
|
|||
|
cmp byte ptr ptype+[BX],ENVTYPE*2 ; is operand an environment?
|
|||
|
je env_t ; if an environment object, jump
|
|||
|
; object not an env-- return a value of nil in the destination register
|
|||
|
mov byte ptr reg0_pag+[DI],NIL_PAGE*2
|
|||
|
mov reg0_dis+[DI],NIL_DISP*2
|
|||
|
jmp next ; return to interpreter
|
|||
|
; object is an env-- return a value of 't in the destination register
|
|||
|
env_t: mov byte ptr reg0_pag+[DI],T_PAGE*2
|
|||
|
mov reg0_dis+[DI],T_DISP*2
|
|||
|
jmp next ; return to interpreter
|
|||
|
|
|||
|
;************************************************************************
|
|||
|
;* Make Environment MK-ENV dest *
|
|||
|
;* *
|
|||
|
;* Purpose: Scheme interpreter support to return a pointer to the *
|
|||
|
;* current environment. *
|
|||
|
;************************************************************************
|
|||
|
public mk_env
|
|||
|
mk_env: lods byte ptr ES:[SI] ; load destination register number
|
|||
|
mov DI,AX ; and put it in TIPC register DI
|
|||
|
mov BX,FP ; load the current stack frame pointer
|
|||
|
mov AL,S_stack+[BX].sf_hpage ; load current env pointer from stack
|
|||
|
mov byte ptr reg0_pag+[DI],AL; and put in destination register
|
|||
|
mov AX,word ptr S_stack+[BX].sf_hdisp
|
|||
|
mov reg0_dis+[DI],AX
|
|||
|
jmp next ; return to interpreter
|
|||
|
|
|||
|
;************************************************************************
|
|||
|
;* Environment Parent ENV-PARENT env *
|
|||
|
;* *
|
|||
|
;* Purpose: Scheme interpreter return the "parent" of a given *
|
|||
|
;* environment. *
|
|||
|
;************************************************************************
|
|||
|
public env_par
|
|||
|
env_par: lods byte ptr ES:[SI] ; load the environment operand
|
|||
|
save <SI> ; save the current location pointer
|
|||
|
mov DI,AX ; copy operand register number to DI
|
|||
|
mov BX,reg0_pag+[DI] ; load operand's page number
|
|||
|
cmp byte ptr ptype+[BX],ENVTYPE*2 ; is operand an environment?
|
|||
|
jne env_p_er ; if not an environment, error (jump)
|
|||
|
mov SI,reg0_dis+[DI] ; load pointer to environment object
|
|||
|
LoadPage ES,BX
|
|||
|
;;; mov ES,pagetabl+[BX]
|
|||
|
mov AL,ES:[SI].env_ppag ; load parent pointer from env object
|
|||
|
mov byte ptr reg0_pag+[DI],AL ; and put in destination register
|
|||
|
mov AX,ES:[SI].env_pdis
|
|||
|
mov reg0_dis+[DI],AX
|
|||
|
jmp next_PC ; return to interpreter
|
|||
|
; ***error-- invalid operand***
|
|||
|
env_p_er: lea BX,m_en_par ; load text addr for "environment-parent"
|
|||
|
jmp src_err ; display "invalid source operand" message
|
|||
|
|
|||
|
;************************************************************************
|
|||
|
;* Lookup In Environment ENV-LU R(d=s1),R(s2) *
|
|||
|
;* s1=symbol,s2=env *
|
|||
|
;************************************************************************
|
|||
|
public env_lu
|
|||
|
env_lu: lods word ptr ES:[SI] ; load operands
|
|||
|
; fetch and validate first operand (symbol pointer)
|
|||
|
xor BH,BH
|
|||
|
mov BL,AL
|
|||
|
mov DI,BX
|
|||
|
add DI,offset reg0
|
|||
|
save <SI,DI> ; save location pointer; dest reg address
|
|||
|
mov CX,[DI].C_page ; copy symbol pointer into CX:DX
|
|||
|
mov DX,[DI].C_disp
|
|||
|
mov BX,CX ; test to make sure that first operand
|
|||
|
cmp byte ptr ptype+[BX],SYMTYPE*2 ; is a symbol
|
|||
|
jne env_lu_x ; if not a symbol, error (jump)
|
|||
|
; fetch and validate second operand (environment pointer)
|
|||
|
mov BL,AH ; copy env register number
|
|||
|
mov SI,reg0_dis+[BX] ; copy environment pointer into BX:SI
|
|||
|
mov BL,byte ptr reg0_pag+[BX]
|
|||
|
cmp byte ptr ptype+[BX],ENVTYPE*2 ; it is an env, isn't it?
|
|||
|
jne env_lu_x ; if operand not environment, error (jump)
|
|||
|
; search the environment for the symbol
|
|||
|
call srch_all ; search all ribs
|
|||
|
; store result of search into destination register
|
|||
|
restore <DI> ; reload the destination register address
|
|||
|
mov byte ptr [DI].C_page,BL
|
|||
|
mov [DI].C_disp,SI
|
|||
|
jmp next_PC ; return to interpreter
|
|||
|
; ***error-- invalid operand***
|
|||
|
env_lu_x: mov BX,offset m_env_lu
|
|||
|
jmp src_err
|
|||
|
|
|||
|
s_env endp
|
|||
|
|
|||
|
;************************************************************************
|
|||
|
;* Local Support - Search Environment (all of it) *
|
|||
|
;* *
|
|||
|
;* Input Parameters: CX:DX - search symbol *
|
|||
|
;* BX:SI - environment chain pointer *
|
|||
|
;* *
|
|||
|
;* Output Parameters: BX:SI - value cell for symbol *
|
|||
|
;************************************************************************
|
|||
|
srch_all proc near
|
|||
|
pushm <BX,SI,CX,DX> ; save pointer to current rib
|
|||
|
call srch_env ; search rib for desired symbol
|
|||
|
cmp BX,0 ; was symbol found?
|
|||
|
jne srch_ok ; if symbol found, jump
|
|||
|
popm <DX,CX,SI,BX> ; restore pointer to current rib
|
|||
|
LoadPage ES,BX
|
|||
|
;;; mov ES,pagetabl+[BX] ; load pointer to parent rib
|
|||
|
mov BL,ES:[SI].env_ppag
|
|||
|
mov SI,ES:[SI].env_pdis
|
|||
|
cmp BX,0 ; does parent rib exist?
|
|||
|
jne srch_all ; if no parent, symbol not found (jump)
|
|||
|
jmp short srch_nok
|
|||
|
srch_ok: add SP,WORDINCR*4 ; dump env pointer off stack
|
|||
|
srch_nok: ret ; return search result to caller
|
|||
|
srch_all endp
|
|||
|
|
|||
|
;************************************************************************
|
|||
|
;* Local Support - Search Environment (one rib) *
|
|||
|
;* *
|
|||
|
;* Input Parameters: CX:DX - search symbol *
|
|||
|
;* BX:SI - environment chain pointer *
|
|||
|
;* *
|
|||
|
;* Output Parameters: BX:SI - value cell for symbol *
|
|||
|
;************************************************************************
|
|||
|
srch_env proc near
|
|||
|
LoadPage ES,BX ; load paragraph address of env chain
|
|||
|
;;; mov ES,pagetabl+[BX] ; load paragraph address of env chain
|
|||
|
cmp ES:[SI].env_len,ENV_SIZE ; hash table or "rib"?
|
|||
|
jne srch_ht ; if hash table, jump
|
|||
|
pushm <BX,SI> ; save pointer to environment
|
|||
|
;;;; pushm <ES,SI> ; save pointer to environment
|
|||
|
mov AX,1 ; initialize counter
|
|||
|
xor BX,BX
|
|||
|
mov BL,ES:[SI].env_npag ; load pointer to list of symbols
|
|||
|
mov SI,ES:[SI].env_ndis
|
|||
|
srch_mor: cmp BL,0 ; more symbols in this rib?
|
|||
|
je srch_nf ; if end of symbol list, jump
|
|||
|
LoadPage ES,BX
|
|||
|
;;; mov ES,pagetabl+[BX]
|
|||
|
cmp DX,ES:[SI].car ; is symbol disp eq to this entry?
|
|||
|
jne srch_nxt ; if no match, jump
|
|||
|
cmp CL,ES:[SI].car_page ; is page number eq?
|
|||
|
je srch_fnd ; if symbol's page number eq, jump
|
|||
|
srch_nxt: inc AX ; increment symbol count
|
|||
|
mov BL,ES:[SI].cdr_page ; follow cdr field of linked list
|
|||
|
mov SI,ES:[SI].cdr
|
|||
|
jmp short srch_mor ; loop
|
|||
|
srch_fnd: mov CX,AX ; move counter symbol counter to CX
|
|||
|
popm <SI,BX> ; recover pointer to environment chain
|
|||
|
LoadPage ES,BX
|
|||
|
;;;; popm <SI,ES> ; recover pointer to environment chain
|
|||
|
mov BL,ES:[SI].env_vpag ; load pointer to value list
|
|||
|
mov SI,ES:[SI].env_vdis
|
|||
|
jmp short srch_f1
|
|||
|
srch_lp: LoadPage ES,BX ; follow chain through car field of linked
|
|||
|
;;; mov ES,pagetabl+[BX] ; follow chain through car field of linked
|
|||
|
mov BL,ES:[SI].car_page ; list
|
|||
|
mov SI,ES:[SI].car
|
|||
|
srch_f1: loop srch_lp ; not value entry for symbol, loop (jump)
|
|||
|
ret ; return to caller
|
|||
|
; symbol not found-- return nil
|
|||
|
srch_nf: add SP,WORDINCR*2 ; drop env pointer off stack
|
|||
|
ret ; return to caller
|
|||
|
;
|
|||
|
; Hash Table Rib Format
|
|||
|
;
|
|||
|
srch_ht: pushm <BX,SI> ; save arguments to srch_env
|
|||
|
mov lcl_page,CX ; store symbol pointer in tmp_reg
|
|||
|
mov lcl_disp,DX
|
|||
|
mov AX,offset lcl_reg ; load address of lcl_reg and push
|
|||
|
push AX ; it as an argument to sym_hash
|
|||
|
call sym_hash ; get the hash value for the symbol
|
|||
|
add SP,WORDINCR ; drop the argument off the stack
|
|||
|
cmp AX,HT_SIZE ; valid hash value returned?
|
|||
|
jae srch_htx ; if not valid, error (jump)
|
|||
|
; fetch symbol chain from indicated hash table bucket
|
|||
|
popm <SI,BX> ; restore pointer to environment object
|
|||
|
add SI,AX ; env-ptr += hash-value * 3
|
|||
|
shl AX,1
|
|||
|
add SI,AX
|
|||
|
LoadPage ES,BX ; load environment page's paragraph address
|
|||
|
;;; mov ES,pagetabl+[BX] ; load environment page's paragraph address
|
|||
|
mov BL,ES:[SI].env_npag ; load pointer to hash chain
|
|||
|
cmp BL,0 ; is chain empty?
|
|||
|
je srch_nfx ; if chain is empty, symbol not found (jump)
|
|||
|
mov SI,ES:[SI].env_ndis
|
|||
|
LoadPage ES,BX
|
|||
|
;;; mov ES,pagetabl+[BX]
|
|||
|
mov DX,lcl_page ; restore symbol pointer into DX:AX
|
|||
|
mov AX,lcl_disp
|
|||
|
call lookup ; search for symbol in linked list
|
|||
|
mov SI,DI ; put pointer returned in BX:SI
|
|||
|
ret ; return to caller
|
|||
|
; ***error-- symbol operand wasn't a symbol***
|
|||
|
srch_htx: add SP,WORDINCR*2 ; drop saved arguments off stack
|
|||
|
xor BX,BX ; return a nil pointer
|
|||
|
srch_nfx: xor SI,SI
|
|||
|
ret
|
|||
|
srch_env endp
|
|||
|
|
|||
|
;************************************************************************
|
|||
|
;* Symbol Binding Routine *
|
|||
|
;* *
|
|||
|
;* Purpose: Lattice C callable routine to return the bind a value to *
|
|||
|
;* a symbol in a given environment. *
|
|||
|
;* *
|
|||
|
;* Calling Sequence: sym_bind(symbol, value, environment) *
|
|||
|
;* where symbol - register containing the symbol *
|
|||
|
;* pointer *
|
|||
|
;* value - register containing the value to *
|
|||
|
;* be assigned *
|
|||
|
;* environment - register containing a pointer to *
|
|||
|
;* the environment in which the *
|
|||
|
;* binding is to take place *
|
|||
|
;************************************************************************
|
|||
|
bind_arg struc
|
|||
|
dw ? ; caller's BP
|
|||
|
dw ? ; caller's ES
|
|||
|
dw ? ; return address
|
|||
|
bnd_sym dw ? ; address of symbol register
|
|||
|
bnd_val dw ? ; address of value register
|
|||
|
bnd_env dw ? ; address of environment register
|
|||
|
bind_arg ends
|
|||
|
|
|||
|
public sym_bind
|
|||
|
bind_it proc near
|
|||
|
push ES ; save the caller's ES register
|
|||
|
push BP ; save the caller's BP register
|
|||
|
mov BP,SP ; establish addressability for local data
|
|||
|
jmp sb_new ; bind symbol in current environment
|
|||
|
|
|||
|
sym_bind: push ES ; save the caller's ES register
|
|||
|
push BP ; save the caller's BP register
|
|||
|
mov BP,SP ; establish addressability for local data
|
|||
|
|
|||
|
; see if symbol is already present in the environment
|
|||
|
mov BX,[BP].bnd_sym ; load address of symbol register
|
|||
|
mov CX,[BX].C_page ; load symbol pointer into CX:DX
|
|||
|
mov DX,[BX].C_disp
|
|||
|
mov BX,[BP].bnd_env ; load address of environment register
|
|||
|
mov SI,[BX].C_disp ; load environment pointer into BX:SI
|
|||
|
mov BX,[BX].C_page
|
|||
|
call srch_all ; search the environment for the symbol
|
|||
|
cmp BL,0 ; was the symbol found in the environment?
|
|||
|
je sb_new ; if symbol not found, jump
|
|||
|
; store the value into the cdr field of the returned value cell
|
|||
|
LoadPage ES,BX ; load value cell's paragraph address
|
|||
|
;;; mov ES,pagetabl+[BX] ; load value cell's paragraph address
|
|||
|
mov BX,[BP].bnd_val ; load address of value register
|
|||
|
mov AL,byte ptr [BX].C_page ; copy value from value register
|
|||
|
mov ES:[SI].cdr_page,AL ; into the cdr field of the value cell
|
|||
|
mov AX,[BX].C_disp
|
|||
|
mov ES:[SI].cdr,AX
|
|||
|
jmp sb_ret ; return to caller
|
|||
|
|
|||
|
; fetch pointer to environment-- decide format of said
|
|||
|
sb_new: mov SI,[BP].bnd_env
|
|||
|
mov BX,[SI].C_page
|
|||
|
mov SI,[SI].C_disp
|
|||
|
LoadPage ES,BX
|
|||
|
;;; mov ES,pagetabl+[BX]
|
|||
|
cmp ES:[SI].env_len,ENV_SIZE
|
|||
|
jne sb_ht
|
|||
|
;
|
|||
|
; bind symbol to "rib" format environment
|
|||
|
;
|
|||
|
; cons(env[name], symbol, env[name])
|
|||
|
mov AL,ES:[SI].env_npag ; copy name list chain from environment
|
|||
|
mov byte ptr tmp_page,AL ; object to tmp_reg
|
|||
|
mov AX,ES:[SI].env_ndis
|
|||
|
mov tmp_disp,AX
|
|||
|
mov AX,offset tmp_reg
|
|||
|
pushm <AX,[BP].bnd_sym,AX> ; push arguments to "cons"
|
|||
|
call cons ; cons symbol to front of name list
|
|||
|
mov BX,[BP].bnd_env ; reload pointer to environment object
|
|||
|
mov SI,[BX].C_disp ; (it may have been relocated during the
|
|||
|
mov BX,[BX].C_page ; consing operation)
|
|||
|
LoadPage ES,BX
|
|||
|
;;; mov ES,pagetabl+[BX] ;
|
|||
|
mov AL,byte ptr tmp_page ; update name list pointer in the
|
|||
|
mov ES:[SI].env_npag,AL ; environment object
|
|||
|
mov AX,tmp_disp
|
|||
|
mov ES:[SI].env_ndis,AX
|
|||
|
; cons(env[value], env[value], value)
|
|||
|
mov AL,ES:[SI].env_vpag ; copy value list chain from environment
|
|||
|
mov byte ptr tmp_page,AL ; object to tmp_reg
|
|||
|
mov AX,ES:[SI].env_vdis
|
|||
|
mov tmp_disp,AX
|
|||
|
mov AX,offset tmp_reg
|
|||
|
pushm <[BP].bnd_val,AX,AX> ; push arguments to "cons"
|
|||
|
call cons ; cons value to front of value list
|
|||
|
mov BX,[BP].bnd_env ; reload pointer to environment object
|
|||
|
mov SI,[BX].C_disp ; (it may have been relocated during the
|
|||
|
mov BX,[BX].C_page ; consing operation)
|
|||
|
LoadPage ES,BX
|
|||
|
;;; mov ES,pagetabl+[BX] ;
|
|||
|
mov AL,byte ptr tmp_page ; update value list pointer in the
|
|||
|
mov ES:[SI].env_vpag,AL ; environment object
|
|||
|
mov AX,tmp_disp
|
|||
|
mov ES:[SI].env_vdis,AX
|
|||
|
jmp sb_ret ; return to caller
|
|||
|
;
|
|||
|
; bind symbol to "hash table" format environment
|
|||
|
;
|
|||
|
sb_ht:
|
|||
|
; cons(tmp_reg, symbol, value)
|
|||
|
mov AX,offset tmp_reg ; load address of tmp_reg
|
|||
|
mov BX,offset nil_reg ; load address of nil_reg
|
|||
|
; Note: we're pushing the arguments for both calls to "cons" in the
|
|||
|
; following statement
|
|||
|
pushm <BX,AX,AX,[BP].bnd_val,[BP].bnd_sym,AX> ; push args to cons
|
|||
|
call cons
|
|||
|
add SP,3*WORDINCR ; drop the top three arguments from the stack
|
|||
|
; cons(tmp_reg, tmp_reg, nil_reg)
|
|||
|
call cons
|
|||
|
; obtain hash value for the symbol
|
|||
|
push [BP].bnd_sym
|
|||
|
call sym_hash
|
|||
|
mov BX,AX ; multiply hash value by 3
|
|||
|
shl AX,1
|
|||
|
add BX,AX
|
|||
|
mov SI,[BP].bnd_env ; load pointer to environment object
|
|||
|
add BX,[SI].C_disp ; (which may have been moved during
|
|||
|
mov SI,[SI].C_page ; the consing operations)
|
|||
|
LoadPage ES,SI
|
|||
|
;;; mov ES,pagetabl+[SI]
|
|||
|
mov AX,tmp_page ; load pointer to second list cell
|
|||
|
mov SI,AX
|
|||
|
xchg AL,ES:[BX].env_npag ; swap list header in environment hash
|
|||
|
mov DX,tmp_disp ; table with the pointer to the second
|
|||
|
mov DI,DX ; list cell
|
|||
|
xchg DX,ES:[BX].env_ndis
|
|||
|
LoadPage ES,SI ; load pointer to second list cell
|
|||
|
;;; mov ES,pagetabl+[SI] ; load pointer to second list cell
|
|||
|
mov ES:[DI].cdr_page,AL ; update entry in environment hash table
|
|||
|
mov ES:[DI].cdr,DX
|
|||
|
|
|||
|
; return to calling procedure
|
|||
|
sb_ret: mov SP,BP ; clean up the TIPC's stack
|
|||
|
pop BP ; restore caller's BP
|
|||
|
pop ES ; restore caller's ES, too
|
|||
|
ret ; return to caller
|
|||
|
bind_it endp
|
|||
|
|
|||
|
;************************************************************************
|
|||
|
;* Symbol Lookup Routine *
|
|||
|
;* *
|
|||
|
;* Purpose: Lattice C callable routine to return the value bound to *
|
|||
|
;* a symbol in a given environment. *
|
|||
|
;* *
|
|||
|
;* Calling Sequence: sym_bind(symbol, environment) *
|
|||
|
;* where symbol - register containing the symbol *
|
|||
|
;* pointer *
|
|||
|
;* environment - register containing a pointer to *
|
|||
|
;* the environment to be searched *
|
|||
|
;************************************************************************
|
|||
|
look_arg struc
|
|||
|
dw ? ; caller's BP
|
|||
|
dw ? ; caller's ES
|
|||
|
dw ? ; return address
|
|||
|
look_sym dw ? ; address of symbol register
|
|||
|
look_env dw ? ; address of environment register
|
|||
|
look_arg ends
|
|||
|
|
|||
|
public sym_look
|
|||
|
sym_look proc near
|
|||
|
push ES ; save the caller's ES register
|
|||
|
push BP ; save the caller's BP register
|
|||
|
mov BP,SP ; establish addressability for local data
|
|||
|
|
|||
|
; see if symbol is already present in the environment
|
|||
|
mov BX,[BP].look_sym ; load address of symbol register
|
|||
|
mov CX,[BX].C_page ; load symbol pointer into CX:DX
|
|||
|
mov DX,[BX].C_disp
|
|||
|
mov BX,[BP].look_env ; load address of environment register
|
|||
|
mov SI,[BX].C_disp ; load environment pointer into BX:SI
|
|||
|
mov BX,[BX].C_page
|
|||
|
call srch_all ; search the environment for the symbol
|
|||
|
xor AX,AX ; set result to false, in case search failed
|
|||
|
cmp BL,0 ; was the symbol found in the environment?
|
|||
|
je look_ret ; if symbol not found, jump
|
|||
|
; return the value in the cdr field in the argument register
|
|||
|
LoadPage ES,BX ; load value cell's paragraph address
|
|||
|
;;; mov ES,pagetabl+[BX] ; load value cell's paragraph address
|
|||
|
mov BX,[BP].look_sym ; load address of register
|
|||
|
mov AL,ES:[SI].cdr_page ; copy current binding into the
|
|||
|
mov byte ptr [BX].C_page,AL ; argument register
|
|||
|
mov AX,ES:[SI].cdr
|
|||
|
mov [BX].C_disp,AX
|
|||
|
mov AX,1 ; set result to "TRUE"
|
|||
|
; return to calling procedure
|
|||
|
look_ret: pop BP ; restore caller's BP
|
|||
|
pop ES ; restore caller's ES, too
|
|||
|
ret ; return to caller
|
|||
|
sym_look endp
|
|||
|
|
|||
|
;************************************************************************
|
|||
|
;* Symbol Hashing Routine *
|
|||
|
;* *
|
|||
|
;* Purpose: Lattice C callable routine to return the hash value for *
|
|||
|
;* a given symbol. *
|
|||
|
;* *
|
|||
|
;* Calling Sequence: hash = sym_hash(reg) *
|
|||
|
;* reg - register containing symbol pointer *
|
|||
|
;* hash - the hash value (if page/disp don't point *
|
|||
|
;* to a symbol, -1 is returned) *
|
|||
|
;* *
|
|||
|
;* Methods Used: The hash value is computed by summing the characters *
|
|||
|
;* of the symbol and returning the remainder on division *
|
|||
|
;* by the length of the hash table (HT_SIZE). *
|
|||
|
;* *
|
|||
|
;* Note: This routine must return the same hash value as the routine *
|
|||
|
;* "hash" in SUPPORT.C. If the hashing algorithm is *
|
|||
|
;* changed, it must be changed in both routines. *
|
|||
|
;************************************************************************
|
|||
|
sh_args struc
|
|||
|
dw ? ; caller's BP
|
|||
|
dw ? ; return address
|
|||
|
sh_reg dw ? ; symbol pointer register address
|
|||
|
sh_args ends
|
|||
|
|
|||
|
public sym_hash
|
|||
|
sym_hash proc near
|
|||
|
push BP ; save caller's BP
|
|||
|
mov BP,SP
|
|||
|
; Fetch pointer to symbol-- make sure object is a symbol
|
|||
|
mov DI,[BP].sh_reg ; load register address
|
|||
|
mov BX,[DI].C_page ; load symbol's page number
|
|||
|
cmp byte ptr ptype+[BX],SYMTYPE*2 ; is object a symbol?
|
|||
|
jne sh_error ; if not a symbol, error (jump)
|
|||
|
push ES ; save caller's ES
|
|||
|
LoadPage ES,BX ; load symbol page's paragraph address
|
|||
|
;;; mov ES,pagetabl+[BX] ; load symbol page's paragraph address
|
|||
|
mov SI,[DI].C_disp ; load symbol's displacement
|
|||
|
; Fetch hash value from symbol object
|
|||
|
xor AH,AH ; clear high order byte of AX
|
|||
|
mov AL,ES:[SI].sym_hkey ; fetch hash key
|
|||
|
; Return value in TIPC register AX
|
|||
|
pop ES ; restore caller's ES
|
|||
|
sh_ret: pop BP ; restore caller's BP
|
|||
|
ret ; return
|
|||
|
; ***error-- input argument wasn't a symbol pointer***
|
|||
|
sh_error: mov AX,-1 ; return a hash value of -1
|
|||
|
jmp short sh_ret ; return invalid hash value
|
|||
|
sym_hash endp
|
|||
|
|
|||
|
prog ends
|
|||
|
end
|
|||
|
|