1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-04-30 03:40:34 +02:00

Add instructions for doing very late binding

Fixes the mutually-recursive toplevel definitions case. This could be
fixed by rewriting bodies as letrecs, as r6 does, but that's not really
repl-compatible.

* module/system/il/ghil.scm (ghil-lookup): Ok, if we can't locate a
  variable, mark it as unresolved.

* module/system/il/compile.scm (make-glil-var): Compile unresolved
  variables as <glil-late-bound> objects.

* module/system/il/glil.scm: Add <glil-late-bound> definition.

* module/system/vm/assemble.scm (codegen): And, finally, when we see a
  <vlate-bound> object, allocate a slot for it in the object vector,
  setting it to a symbol. Add a new pair of instructions to resolve that
  symbol to a variable at the last minute.

* src/vm_loader.c (load-number): Bugfix: the radix argument should be
  SCM_UNDEFINED in order to default to 10.
  (late-bind): Add an unresolved symbol to the object vector. Could be
  replaced with load-symbol I guess.

* src/vm_system.c (late-variable-ref, late-variable-set): New
  instructions to do late symbol binding.

* testsuite/Makefile.am (vm_test_files):
* testsuite/t-mutual-toplevel-defines.scm: New test, failing for some
  reason involving the core even? and odd? definitions.
This commit is contained in:
Andy Wingo 2008-05-19 17:46:05 +02:00
parent 1b8abe5514
commit 9cc649b880
9 changed files with 99 additions and 11 deletions

View file

@ -103,6 +103,8 @@
(let ((env (ghil-var-env var)))
(make-glil-module op (and env (ghil-mod-module (ghil-env-mod env)))
(ghil-var-name var))))
((unresolved)
(make-glil-late-bound op (ghil-var-name var)))
(else (error "Unknown kind of variable:" var))))
(define (codegen ghil)

View file

@ -224,12 +224,10 @@
(make-ghil-var found-env sym 'module)))
(else
;; a free variable that we have not resolved
(if (not (module-locally-bound? module sym))
;; For the benefit of repl compilation, that
;; doesn't compile modules all-at-once, don't warn
;; if we find the symbol locally.
(warn "unresolved variable during compilation:" sym))
(make-ghil-var #f sym 'module))))
(warn "unresolved variable during compilation:" sym)
(let ((var (make-ghil-var #f sym 'unresolved)))
(apush! sym var table)
var))))
((<ghil-env> mod parent table variables)
(let ((found (assq-ref table sym)))
(if found

View file

@ -54,6 +54,9 @@
<glil-module> make-glil-module glil-module?
glil-module-op glil-module-module glil-module-index
<glil-late-bound> make-glil-late-bound glil-late-bound?
glil-late-bound-op glil-late-bound-name
<glil-label> make-glil-label glil-label?
glil-label-label
@ -80,6 +83,7 @@
(<glil-local> op index)
(<glil-external> op depth index)
(<glil-module> op module name)
(<glil-late-bound> op name)
;; Controls
(<glil-label> label)
(<glil-branch> inst label)

View file

@ -44,6 +44,7 @@
(define-record (<venv> parent nexts closure?))
(define-record (<vmod> id))
(define-record (<vlink> module name))
(define-record (<vlate-bound> name))
(define-record (<vdefine> module name))
(define-record (<bytespec> vars bytes meta objs closure?))
@ -158,6 +159,20 @@
(push-object! (make-vdefine :module module :name name))
(push-code! '(variable-set)))))
((<glil-late-bound> op name)
(let* ((var (make-vlate-bound :name name))
(i (cond ((object-assoc var object-alist) => cdr)
(else
(let ((i (length object-alist)))
(set! object-alist (acons var i object-alist))
i)))))
(case op
((ref)
(push-code! `(late-variable-ref ,i)))
((set)
(push-code! `(late-variable-set ,i)))
(else (error "unknown late bound" op name)))))
((<glil-label> label)
(set! label-alist (assq-set! label-alist label (current-address))))
@ -263,6 +278,8 @@
((<vdefine> module name)
;; FIXME: dump module
(push-code! `(define ,(symbol->string name))))
((<vlate-bound> name)
(push-code! `(late-bind ,(symbol->string name))))
((<vmod> id)
(push-code! `(load-module ,id)))
(else

View file

@ -64,7 +64,7 @@ VM_DEFINE_LOADER (load_number, "load-number")
FETCH_LENGTH (len);
PUSH (scm_string_to_number (scm_from_locale_stringn ((char *)ip, len),
SCM_UNSPECIFIED /* radix = 10 */));
SCM_UNDEFINED /* radix = 10 */));
/* Was: scm_istring2number (ip, len, 10)); */
ip += len;
NEXT;
@ -215,6 +215,19 @@ VM_DEFINE_LOADER (define, "define")
NEXT;
}
VM_DEFINE_LOADER (late_bind, "late-bind")
{
SCM sym;
size_t len;
FETCH_LENGTH (len);
sym = scm_from_locale_symboln ((char *)ip, len);
ip += len;
PUSH (sym);
NEXT;
}
/*
Local Variables:
c-file-style: "gnu"

View file

@ -257,6 +257,28 @@ VM_DEFINE_INSTRUCTION (variable_ref, "variable-ref", 0, 0, 1)
NEXT;
}
VM_DEFINE_INSTRUCTION (late_variable_ref, "late-variable-ref", 1, 0, 1)
{
register unsigned objnum = FETCH ();
SCM x;
CHECK_OBJECT (objnum);
x = OBJECT_REF (objnum);
if (!SCM_VARIABLEP (x))
{
x = scm_lookup (x); /* might longjmp */
OBJECT_SET (objnum, x);
if (!VARIABLE_BOUNDP (x))
{
err_args = SCM_LIST1 (x);
goto vm_error_unbound;
}
}
PUSH (VARIABLE_REF (x));
NEXT;
}
/* set */
VM_DEFINE_INSTRUCTION (local_set, "local-set", 1, 1, 0)
@ -289,6 +311,29 @@ VM_DEFINE_INSTRUCTION (variable_set, "variable-set", 0, 1, 0)
NEXT;
}
VM_DEFINE_INSTRUCTION (late_variable_set, "late-variable-set", 1, 1, 0)
{
register unsigned objnum = FETCH ();
SCM x;
CHECK_OBJECT (objnum);
x = OBJECT_REF (objnum);
if (!SCM_VARIABLEP (x))
{
x = scm_lookup (x); /* might longjmp */
OBJECT_SET (objnum, x);
if (!VARIABLE_BOUNDP (x))
{
err_args = SCM_LIST1 (x);
goto vm_error_unbound;
}
}
VARIABLE_SET (x, *sp);
DROP ();
NEXT;
}
/*
* branch and jump

View file

@ -15,7 +15,8 @@ vm_test_files = \
t-proc-with-setter.scm \
t-values.scm \
t-records.scm \
t-match.scm
t-match.scm \
t-mutual-toplevel-defines.scm
EXTRA_DIST = run-vm-tests.scm $(vm_test_files)

View file

@ -74,9 +74,9 @@ equal in the sense of @var{equal?}."
(format #t "running `~a'... " file)
(if (catch #t
(lambda ()
(equal? (compile/run-test-from-file file)
(eval (fetch-sexp-from-file file)
(interaction-environment))))
(equal? (pk (compile/run-test-from-file file))
(pk (eval (fetch-sexp-from-file file)
(interaction-environment)))))
(lambda (key . args)
(format #t "[~a/~a] " key args)
#f))

View file

@ -0,0 +1,8 @@
(define (even? x)
(or (zero? x)
(not (odd? (1- x)))))
(define (odd? x)
(not (even? (1- x))))
(even? 20)