pcs/senv.asm

1052 lines
45 KiB
NASM
Raw 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.

; =====> 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