pcs/newpcs/pdebug.s

411 lines
14 KiB
Common Lisp
Raw Permalink Blame History

This file contains invisible Unicode characters

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

; -*- Mode: Lisp -*- Filename: pdebug.s
;--------------------------------------------------------------------------;
; ;
; TI SCHEME -- PCS Compiler ;
; Copyright 1985 (c) Texas Instruments ;
; ;
; David Bartley ;
; ;
; System Debugger and Error Handlers ;
; ;
;--------------------------------------------------------------------------;
; Revision history:
; db 10/18/85 - ??
; tc 03/13/87 - Extended errors for DOS I/O errors
; The following definitions are used only at compile time for readability
; and understanding. They will not be written out to the .so file.
; See pboot.s and compile.all.
(compile-time-alias IO-ERRORS-START 21)
(compile-time-alias IO-ERRORS-END 108)
(compile-time-alias DOS-IO-ERROR 21)
(compile-time-alias FILE-NOT-FOUND 22)
(compile-time-alias PATH-NOT-FOUND 23)
(compile-time-alias TOO-MANY-FILES 24)
(define assert-procedure)
(define breakpoint-procedure)
(define error-procedure)
(define *error-handler*)
(letrec
((uv-msg
'(1 2 3 4))
(msg-codes
'((0 . "Unspecified VM error")
(1 . "Variable not defined in current environment")
(2 . "SET! of an unbound variable")
(3 . "Variable not defined in lexical environment")
(4 . "SET! of an unbound lexical variable")
(5 . "Variable not defined in fluid environment")
(6 . "SET-FLUID! of an unbound fluid variable")
(7 . "Vector index out of range")
(8 . "String index out of range")
(9 . "Invalid substring range") ; not generated
(10 . "Invalid operand to VM instruction")
(11 . "User keyboard interrupt")
(12 . "Attempt to call a non-procedural object")
;; (13 . "Engine Timer Interrupt")
(14 . "I/O attempted to a de-exposed window")
;; 14 is a trap for a window handler, not a real error
(15 . "FLONUM overflow or underflow")
(16 . "Divide by zero")
(17 . "Non-numeric operand to arithmetic operation")
(18 . "Register overflow--Too many arguments to closure")
(19 . "MAKE-VECTOR size limit exceeded")
(20 . "MAKE-STRING size limit exceeded")
(21 . "DOS I/O error number ")
(22 . "DOS I/O error - File not found")
(23 . "DOS I/O error - Path not found")
(24 . "DOS I/O error - Too many open files")
(25 . "DOS I/O error - Access denied")
(32 . "DOS I/O error - Invalid access")
(36 . "DOS I/O error - Invalid disk drive")
(39 . "DOS I/O error - Disk write protected")
(41 . "DOS I/O error - Drive not ready")
(48 . "DOS I/O error - Printer out of paper")
(200 . "DOS I/O error - Disk Full")
))
(oops
(lambda (msg irritant env stk-index kind error-code)
(fluid-let ((input-port standard-input)
(output-port standard-output))
(let* ((si (if (negative? stk-index)
(%reify-stack (+ (%reify-stack -1) 6))
stk-index))
(env (if (null? env)
(%reify-stack (+ si 9))
env)))
(newline)
(display kind)
(when msg (display msg))
(newline)
(write irritant)
(newline)
(pcs-kill-engine)
(if (unbound? compile)
;; see if compiler auto-loadable
(when (not (pcs-autoload-binding 'compile))
;; Cant find compiler, punt
(display (integer->char 7)) ;beep
(display "Press a key to return to toplevel, escape to exit to DOS")
(let ((ch (read-char)))
(if (char=? ch #\escape)
(exit)
(scheme-reset))))
;else
(if (null? (%env-lu '%inspector user-initial-environment))
;; check to see if we can load the inspector
(when (or (eqv? *error-message* TOO-MANY-FILES)
(null? (pcs-autoload-binding '%inspector)))
(display "Unable to autoload the inspector - file PINSPECT.FSL")
(reset))))
(%inspector msg kind irritant env si error-code)
))))
(envoke-handler
(lambda (number msg irritant stk-index err-code)
(let ((handler (lambda ()
(oops msg
irritant
'()
stk-index
"[VM ERROR encountered!] "
err-code))))
(if (closure? *user-error-handler*)
(*user-error-handler* number
msg
irritant
handler)
(handler)))))
(decipher-error
(lambda (stk-index)
(let ((err-code *error-code*)
(irritant *irritant*)
(err-num (and (number? *error-message*) *error-message*))
(msg (apply-if (assv *error-message* msg-codes)
cdr
*error-message*)))
(cond ((eqv? err-num 11) ; Shift Break
(set! err-num 100))
((and err-num ; I/O Errors
(>= err-num IO-ERRORS-START)
(<= err-num IO-ERRORS-END))
(if (and (or (=? err-num FILE-NOT-FOUND)
(=? err-num PATH-NOT-FOUND))
(fluid-bound? *file-exists-open*))
((fluid *file-exists-open*) #!false)) ; error continuation
(set! err-num (- err-num (-1+ DOS-IO-ERROR)))
(if (number? msg)
(set! msg (string-append (cdr (assv DOS-IO-ERROR msg-codes))
(integer->string err-num 10))))))
(envoke-handler err-num msg irritant stk-index err-code))))
) ; letrec vars
(begin
(set! assert-procedure ; ASSERT-PROCEDURE
(lambda (msgs env)
(oops '() (cons 'ASSERT (cons '() msgs)) env -1 "[ASSERT failure!] " 0)))
(set! breakpoint-procedure ; BREAKPOINT-PROCEDURE
(lambda (msg irritant env . rest)
(let* ((stk-index (if (or (null? rest)
(not (integer? (car rest))))
-1
(car rest))))
(oops msg irritant env stk-index "[BKPT encountered!] " 0))))
(set! error-procedure ; ERROR-PROCEDURE
(lambda (msg irritant env)
(let ((system-error-handler
(lambda ()
(oops msg irritant env -1 "[ERROR encountered!] " 0))))
(if (closure? *user-error-handler*)
(begin
(*user-error-handler* '() msg irritant system-error-handler))
;else
(system-error-handler)))))
(set! *error-handler* ; *ERROR-HANDLER*
(lambda ()
(cond ((and (zero? *error-code*) ; resumable
(memv *error-message* uv-msg)) ; unbound symbol
(if (pcs-autoload-binding *irritant*)
'() ; autoload worked!
;else
(let ((info (getprop *irritant* 'PCS*PRIMOP-HANDLER))
(compiler-present (or (not (unbound? compile))
(pcs-autoload-binding 'compile))))
(cond ((and compiler-present
(integer? info)
(getprop *irritant* 'PCS*OPCODE))
(let* ((vars '(J I H G F E D C B A))
(bvl (list-tail vars (- (length vars) info)))
(form `(define ,*irritant*
(lambda ,bvl
(,*irritant* . ,bvl))))
(dw pcs-display-warnings)
(ip pcs-integrate-primitives))
(set! pcs-display-warnings #!false)
(set! pcs-integrate-primitives #!true)
(eval form user-global-environment)
(set! pcs-display-warnings dw)
(set! pcs-integrate-primitives ip)
'()))
((and compiler-present
(pair? info)
(eq? (car info) 'DEFINE-INTEGRABLE))
(let ((form `(define ,*irritant* ,(cdr info)))
(dw pcs-display-warnings)
(ip pcs-integrate-primitives))
(set! pcs-display-warnings #!false)
(set! pcs-integrate-primitives #!true)
(eval form user-initial-environment)
(set! pcs-display-warnings dw)
(set! pcs-integrate-primitives ip)
'()))
(else
(set! *error-message*
(cdr (assv *error-message* msg-codes)))
(*error-handler*))))))
((eqv? *error-message* 13)
(pcs-engine-timeout)) ; Engine Timeout
(else
(decipher-error (%reify-stack
(+ (%reify-stack
(+ (%reify-stack -1) 6)) 6)))))
) ;lambda
) ;set!
) ;begin
) ;letrec
(define autoload-from-file ; AUTOLOAD-FROM-FILE
(lambda (file names . rest)
(let ((env (if rest (car rest) user-initial-environment)))
(putprop 'PCS-AUTOLOAD-INFO
(cons (list file names env)
(getprop 'PCS-AUTOLOAD-INFO
'PCS-AUTOLOAD-INFO))
'PCS-AUTOLOAD-INFO)
'())))
(define pcs-autoload-binding '()) ; PCS-AUTOLOAD-BINDING
(define remove-autoload-info '()) ; REMOVE-AUTOLOAD-INFO
(letrec
((find-entry
(lambda (name info)
(and info
(or (symbol? name) (string? name))
(find-item name (caar info)(cadar info) info))))
(find-item
(lambda (name file symbols info)
(cond ((string? name)
(if (string-ci=? name file)
(car info)
(find-entry name (cdr info))))
((null? symbols)
(find-entry name (cdr info)))
((eq? name (car symbols))
(car info))
(else
(find-item name file (cdr symbols) info))))))
(set! pcs-autoload-binding
(lambda (name)
(let* ((info (getprop 'PCS-AUTOLOAD-INFO 'PCS-AUTOLOAD-INFO))
(entry (find-entry name info)))
(and entry
(let ((file (car entry))
(env (caddr entry)))
(and (string? file)
(file-exists? file)
(let ((saved-env (%set-global-environment env)))
(load file)
(%set-global-environment saved-env)
(not (null? (%env-lu name env)))
)))))))
(set! remove-autoload-info
(lambda (filename)
(let* ((info (getprop 'PCS-AUTOLOAD-INFO 'PCS-AUTOLOAD-INFO))
(entry (find-entry (%system-file-name filename) info)))
(and entry
(putprop 'PCS-AUTOLOAD-INFO
(delq! entry
(getprop 'PCS-AUTOLOAD-INFO
'PCS-AUTOLOAD-INFO))
'PCS-AUTOLOAD-INFO)))))
)
(define environment-bindings ; ENVIRONMENT-BINDINGS
(letrec
((linked-bindings
(lambda (a-list names values)
(if (null? names)
(reverse! a-list)
(linked-bindings (cons (cons (car names)(cdr values))
a-list)
(cdr names)
(car values)))))
(hashed-bindings
(lambda (a-list index env)
(if (zero? index)
a-list
(let ((bucket (%reify env index)))
(hashed-bindings (if (null? bucket)
a-list
(bucket-bindings a-list bucket))
(- index 1)
env)))))
(bucket-bindings
(lambda (a-list bucket)
(if (null? bucket)
a-list
(bucket-bindings (cons (car bucket) a-list)
(cdr bucket))))))
(lambda (obj)
(if (null? obj)
obj
(let* ((env (cond ((environment? obj) ; environment?
obj)
((or (closure? obj) ; closure?
(delayed-object? obj)) ; delayed object?
(procedure-environment obj))
(else
(%error-invalid-operand 'ENVIRONMENT-BINDINGS
obj))))
(size (%reify env -1)))
(if (= size 12)
(linked-bindings '() (%reify env 1) (%reify env 2))
(hashed-bindings '() (- (quotient size 3) 2) env)))))))
;;;
;;; UNBIND is a function which will remove a variable's binding from a given
;;; environment. It will work for either of the 2 global environments
;;; (USER-GLOBAL-ENVIRONMENT and USER-INITIAL-ENVIRONMENT) or for any other
;;; heap allocated environments. Removing the binding from the environment
;;; will allow the garbage collector to reclaim that space. Also, once
;;; unbound, the autoloader may reload the variable whenever that variable
;;; is referenced again.
;;;
(define unbind
(letrec
((remove-hashed-binding!
(lambda (key alist)
(cond ((null? (cadr alist))
'())
((eq? key (caadr alist))
(set-cdr! alist (cddr alist)))
(else
(remove-hashed-binding! key (cdr alist))))))
(modify-hashed-env!
(lambda (symbol env)
(let* ((hash-val (1+ (%esc2 9 (symbol->string symbol))))
(sym-list (%reify env hash-val)))
(if (null? sym-list)
'()
;else
(begin
(if (eq? symbol (caar sym-list))
(set! sym-list (cdr sym-list))
;else
(remove-hashed-binding! symbol sym-list))
(%reify! env hash-val sym-list)
env)))))
(remove-linked-binding!
(lambda (key names values)
(cond ((null? (cadr names))
'())
((eq? key (cadr names))
(set-cdr! names (cddr names))
(set-car! values (caar values)))
(else
(remove-linked-binding! key (cdr names) (car values))))))
(modify-linked-env!
(lambda (symbol env names values)
(if (eq? symbol (car names))
(begin
(set! names (cdr names))
(set! values (car values)))
;else
(remove-linked-binding! symbol names values))
(%reify! env 1 names)
(%reify! env 2 values)))
)
(lambda (symbol env)
(cond ((not (symbol? symbol))
(%error-invalid-operand 'UNBIND symbol))
((not (environment? env))
(%error-invalid-operand 'UNBIND env))
(else
(if (= (%reify env -1) 12)
(modify-linked-env! symbol env (%reify env 1) (%reify env 2))
;
(modify-hashed-env! symbol env)))))))
(define (procedure-environment obj) ; PROCEDURE-ENVIRONMENT
(cond ((closure? obj)
(%reify obj 1))
((delayed-object? obj)
(procedure-environment (vector-ref obj 1)))
(else
(%error-invalid-operand 'PROCEDURE-ENVIRONMENT obj))))