mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-03 13:20:26 +02:00
* libguile/frames.c (scm_init_frames): No need to bootstrap the VM here, it should be already bootstrapped by init.c. (scm_bootstrap_frames): No need to register an extension, as scm_init_frames is called by init.c. * module/system/vm/frame.scm: Don't load the scm_init_frames extension, as the primitives from frames.c are loaded by Guile's init. (frame-bindings): Change to return bindings, as can be accessed by the binding: accessors from program.scm. (frame-lookup-binding): Revive and make this one work with current code. (frame-binding-set!): (frame-binding-ref): Use the new frame-lookup-binding. Perhaps these should handle boxing and unboxing, though. (frame-source): New accessor, returns a source object. (frame-call-representation): Change to return a full list, as truncated-print can truncate for us. (frame-environment, frame-object-binding, frame-object-name): Update not to take an address, as the address is part of the frame. (frame-variable-exists?, frame-variable-ref, frame-variable-set!) (frame-local-variables, frame-program-name, print-frame) (print-frame-chain-as-backtrace, frame-file, frame-line-number) (make-frame-chain, bootstrap-frame?, frame-number, frame-address): Remove these outdated functions. * module/system/vm/debug.scm (debugger-repl): Use frame-call-representation, and ~@y. (locals): New command, prints local variables in a frame.
126 lines
4.4 KiB
Scheme
126 lines
4.4 KiB
Scheme
;;; Guile VM frame functions
|
||
|
||
;;; Copyright (C) 2001, 2005, 2009 Free Software Foundation, Inc.
|
||
;;;
|
||
;;; This library is free software; you can redistribute it and/or
|
||
;;; modify it under the terms of the GNU Lesser General Public
|
||
;;; License as published by the Free Software Foundation; either
|
||
;;; version 3 of the License, or (at your option) any later version.
|
||
;;;
|
||
;;; This library is distributed in the hope that it will be useful,
|
||
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
;;; Lesser General Public License for more details.
|
||
;;;
|
||
;;; You should have received a copy of the GNU Lesser General Public
|
||
;;; License along with this library; if not, write to the Free Software
|
||
;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||
|
||
;;; Code:
|
||
|
||
(define-module (system vm frame)
|
||
#:use-module (system base pmatch)
|
||
#:use-module (system vm program)
|
||
#:use-module (system vm instruction)
|
||
#:use-module (system vm objcode)
|
||
#:use-module ((srfi srfi-1) #:select (fold))
|
||
#:export (frame-bindings
|
||
frame-lookup-binding
|
||
frame-binding-ref frame-binding-set!
|
||
frame-source frame-call-representation
|
||
frame-environment
|
||
frame-object-binding frame-object-name))
|
||
|
||
(define (frame-bindings frame)
|
||
(program-bindings-for-ip (frame-procedure frame)
|
||
(frame-instruction-pointer frame)))
|
||
|
||
(define (frame-lookup-binding frame var)
|
||
(let lp ((bindings (frame-bindings frame)))
|
||
(cond ((null? bindings)
|
||
(error "variable not bound in frame" var frame))
|
||
((eq? (binding:name (car bindings)) var)
|
||
(car bindings))
|
||
(else
|
||
(lp (cdr bindings))))))
|
||
|
||
(define (frame-binding-set! frame var val)
|
||
(frame-local-set! frame
|
||
(binding:index (frame-lookup-binding frame var))
|
||
val))
|
||
|
||
(define (frame-binding-ref frame var)
|
||
(frame-local-ref frame
|
||
(binding:index (frame-lookup-binding frame var))))
|
||
|
||
|
||
;; Basically there are two cases to deal with here:
|
||
;;
|
||
;; 1. We've already parsed the arguments, and bound them to local
|
||
;; variables. In a standard (lambda (a b c) ...) call, this doesn't
|
||
;; involve any argument shuffling; but with rest, optional, or
|
||
;; keyword arguments, the arguments as given to the procedure may
|
||
;; not correspond to what's on the stack. We reconstruct the
|
||
;; arguments using e.g. for the case above: `(,a ,b ,c). This works
|
||
;; for rest arguments too: (a b . c) => `(,a ,b . ,c)
|
||
;;
|
||
;; 2. We have failed to parse the arguments. Perhaps it's the wrong
|
||
;; number of arguments, or perhaps we're doing a typed dispatch and
|
||
;; the types don't match. In that case the arguments are all on the
|
||
;; stack, and nothing else is on the stack.
|
||
(define (frame-arguments frame)
|
||
(cond
|
||
((program-lambda-list (frame-procedure frame)
|
||
(frame-instruction-pointer frame))
|
||
;; case 1
|
||
=> (lambda (formals)
|
||
(let lp ((formals formals))
|
||
(pmatch formals
|
||
(() '())
|
||
((,x . ,rest) (guard (symbol? x))
|
||
(cons (frame-binding-ref frame x) (lp rest)))
|
||
((,x . ,rest)
|
||
;; could be a keyword
|
||
(cons x (lp rest)))
|
||
(,rest (guard (symbol? rest))
|
||
(frame-binding-ref frame rest))
|
||
;; let's not error here, as we are called during
|
||
;; backtraces...
|
||
(else '???)))))
|
||
(else
|
||
;; case 2
|
||
(map (lambda (i)
|
||
(frame-local-ref frame i))
|
||
(iota (frame-num-locals frame))))))
|
||
|
||
|
||
;;;
|
||
;;; Pretty printing
|
||
;;;
|
||
|
||
(define (frame-source frame)
|
||
(program-source (frame-procedure frame)
|
||
(frame-instruction-pointer frame)))
|
||
|
||
(define (frame-call-representation frame)
|
||
(let ((p (frame-procedure frame)))
|
||
(cons (or (procedure-name p) p) (frame-arguments frame))))
|
||
|
||
|
||
|
||
;;; Misc
|
||
;;;
|
||
|
||
(define (frame-environment frame)
|
||
(map (lambda (binding)
|
||
(cons (binding:name binding) (frame-binding-ref frame binding)))
|
||
(frame-bindings frame)))
|
||
|
||
(define (frame-object-binding frame obj)
|
||
(do ((bs (frame-bindings frame) (cdr bs)))
|
||
((or (null? bs) (eq? obj (frame-binding-ref frame (car bs))))
|
||
(and (pair? bs) (car bs)))))
|
||
|
||
(define (frame-object-name frame obj)
|
||
(cond ((frame-object-binding frame obj) => binding:name)
|
||
(else #f)))
|