mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-02 21:10:27 +02:00
Got the VM up and running! Augmented the documentation.
* src/*.[ch]: Replaced the remaining `SCM_MAKINUM', and changed `SCM_VELTS' into `scm_vector_elements ()'. * src/vm_loader.c (link): Fixed so that it pushed a variable object on the stack. * src/vm_system.c (variable-ref): Fixed so that it uses `scm_variable_ref ()' and friends. * module/system/vm/assemble.scm (dump-object!): Fixed the string case. * src/vm_engine.h (CONS): Use `scm_cons' instead of `SCM_NEWCELL'. * doc/guile-vm.texi: Added actual instruction definitions, explanations of the program invocation mechanism, programs' object tables, etc., in the `Instruction Set' chapter. git-archimport-id: lcourtes@laas.fr--2004-libre/guile-vm--revival--0.6--patch-5
This commit is contained in:
parent
fa19602c28
commit
238e7a11a8
8 changed files with 213 additions and 40 deletions
|
@ -10,15 +10,21 @@
|
||||||
@set VERSION 0.6
|
@set VERSION 0.6
|
||||||
@set UPDATED 2005-04-26
|
@set UPDATED 2005-04-26
|
||||||
|
|
||||||
|
@c Macro for instruction definitions.
|
||||||
|
@macro insn{}
|
||||||
|
Instruction
|
||||||
|
@end macro
|
||||||
|
|
||||||
@ifinfo
|
@ifinfo
|
||||||
@dircategory Scheme Programming
|
@dircategory Scheme Programming
|
||||||
@direntry
|
@direntry
|
||||||
* Guile VM: (guile-vm). Guile Virtual Machine.
|
* Guile VM: (guile-vm). Guile's Virtual Machine.
|
||||||
@end direntry
|
@end direntry
|
||||||
|
|
||||||
This file documents Guile VM.
|
This file documents Guile VM.
|
||||||
|
|
||||||
Copyright @copyright{} 2000 Keisuke Nishida
|
Copyright @copyright{} 2000 Keisuke Nishida
|
||||||
|
Copyright @copyright{} 2005 Ludovic Court`es
|
||||||
|
|
||||||
Permission is granted to make and distribute verbatim copies of this
|
Permission is granted to make and distribute verbatim copies of this
|
||||||
manual provided the copyright notice and this permission notice are
|
manual provided the copyright notice and this permission notice are
|
||||||
|
@ -54,6 +60,7 @@ Updated for Guile VM @value{VERSION} @*
|
||||||
@value{UPDATED} @*
|
@value{UPDATED} @*
|
||||||
|
|
||||||
Copyright @copyright{} 2000 Keisuke Nishida
|
Copyright @copyright{} 2000 Keisuke Nishida
|
||||||
|
Copyright @copyright{} 2005 Ludovic Court`es
|
||||||
|
|
||||||
Permission is granted to make and distribute verbatim copies of this
|
Permission is granted to make and distribute verbatim copies of this
|
||||||
manual provided the copyright notice and this permission notice are
|
manual provided the copyright notice and this permission notice are
|
||||||
|
@ -76,7 +83,9 @@ approved by the Free Software Foundation.
|
||||||
@node Top, Introduction, (dir), (dir)
|
@node Top, Introduction, (dir), (dir)
|
||||||
@top Guile VM Specification
|
@top Guile VM Specification
|
||||||
|
|
||||||
This document corresponds to Guile VM @value{VERSION}.
|
This document would like to correspond to Guile VM @value{VERSION}.
|
||||||
|
However, be warned that important parts still correspond to version
|
||||||
|
0.0 and are not valid anymore.
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
* Introduction::
|
* Introduction::
|
||||||
|
@ -457,10 +466,49 @@ External function:
|
||||||
The Guile VM instruction set is roughly divided two groups: system
|
The Guile VM instruction set is roughly divided two groups: system
|
||||||
instructions and functional instructions. System instructions control
|
instructions and functional instructions. System instructions control
|
||||||
the execution of programs, while functional instructions provide many
|
the execution of programs, while functional instructions provide many
|
||||||
useful calculations. By convention, system instructions begin with a
|
useful calculations.
|
||||||
letter `%'.
|
|
||||||
|
|
||||||
@section Environment control instructions
|
@menu
|
||||||
|
* Environment Control Instructions::
|
||||||
|
* Subprogram Control Instructions::
|
||||||
|
* Data Control Instructions::
|
||||||
|
@end menu
|
||||||
|
|
||||||
|
@node Environment Control Instructions, Subprogram Control Instructions, Instruction Set, Instruction Set
|
||||||
|
@section Environment Control Instructions
|
||||||
|
|
||||||
|
@deffn @insn{} link binding-name
|
||||||
|
Look up @var{binding-name} (a string) in the current environment and
|
||||||
|
push the corresponding variable object onto the stack. If
|
||||||
|
@var{binding-name} is not bound yet, then create a new binding and
|
||||||
|
push its variable object.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn @insn{} variable-ref
|
||||||
|
Dereference the variable object which is on top of the stack and
|
||||||
|
replace it by the value of the variable it represents.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn @insn{} variable-set
|
||||||
|
Set the value of the variable on top of the stack (at @code{sp[0]}) to
|
||||||
|
the object located immediately before (at @code{sp[-1]}).
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
As an example, let us look at what a simple function call looks like:
|
||||||
|
|
||||||
|
@example
|
||||||
|
(+ 2 3)
|
||||||
|
@end example
|
||||||
|
|
||||||
|
This call yields the following sequence of instructions:
|
||||||
|
|
||||||
|
@example
|
||||||
|
(link "+") ;; lookup binding "x"
|
||||||
|
(variable-ref) ;; dereference it
|
||||||
|
(make-int8 2) ;; push immediate value `2'
|
||||||
|
(make-int8 3) ;; push immediate value `3'
|
||||||
|
(tail-call 2) ;; call the proc at sp[-3] with two args
|
||||||
|
@end example
|
||||||
|
|
||||||
@itemize
|
@itemize
|
||||||
@item %alloc
|
@item %alloc
|
||||||
|
@ -469,15 +517,125 @@ letter `%'.
|
||||||
@item %unbind
|
@item %unbind
|
||||||
@end itemize
|
@end itemize
|
||||||
|
|
||||||
@section Subprogram control instructions
|
@node Subprogram Control Instructions, Data Control Instructions, Environment Control Instructions, Instruction Set
|
||||||
|
@section Subprogram Control Instructions
|
||||||
|
|
||||||
|
Programs (read: ``compiled procedure'') may refer to external
|
||||||
|
bindings, like variables or functions defined outside the program
|
||||||
|
itself, in the environment in which it will evaluate at run-time. In
|
||||||
|
a sense, a program's environment and its bindings are an implicit
|
||||||
|
parameter of every program.
|
||||||
|
|
||||||
|
@cindex Object table
|
||||||
|
In order to handle such bindings, each program has an @dfn{object
|
||||||
|
table} associated to it. This table (actually a vector) contains all
|
||||||
|
the variable objects corresponding to the external bindings referenced
|
||||||
|
by the program. The object table of a program is initialized right
|
||||||
|
before a program is loaded and run with @var{load-program}.
|
||||||
|
|
||||||
|
Therefore, external bindings only need to be looked up once before the
|
||||||
|
program is loaded. References to the corresponding external variables
|
||||||
|
from within the program are then performed via the @var{object-ref}
|
||||||
|
instruction and are almost as fast as local variable references.
|
||||||
|
|
||||||
|
Let us consider the following program (procedure) which references
|
||||||
|
external bindings @code{frob} and @var{%magic}:
|
||||||
|
|
||||||
|
@example
|
||||||
|
(lambda (x)
|
||||||
|
(frob x %magic))
|
||||||
|
@end example
|
||||||
|
|
||||||
|
This yields the following assembly code:
|
||||||
|
|
||||||
|
@example
|
||||||
|
(make-int8 64) ;; number of args, vars, etc. (see below)
|
||||||
|
(link "frob")
|
||||||
|
(link "%magic")
|
||||||
|
(vector 2)
|
||||||
|
...
|
||||||
|
(load-program #u8(20 0 23 21 0 20 1 23 36 2))
|
||||||
|
(return)
|
||||||
|
@end example
|
||||||
|
|
||||||
|
All the instructions occurring before @var{load-program} (some were
|
||||||
|
omitted for simplicity) form a @dfn{prologue} which, among other
|
||||||
|
things, pushed an object table (a vector) that contains the variable
|
||||||
|
objects for the variables bound to @var{frob} and @var{%magic}. This
|
||||||
|
vector and other data pushed onto the stack are then popped by the
|
||||||
|
@var{load-program} instruction.
|
||||||
|
|
||||||
|
Besides, the @var{load-program} instruction takes one explicit
|
||||||
|
argument which is the bytecode of the program itself. Disassembled,
|
||||||
|
this bytecode looks like:
|
||||||
|
|
||||||
|
@example
|
||||||
|
(object-ref 0) ;; push the variable object of `frob'
|
||||||
|
(variable-ref) ;; dereference it
|
||||||
|
(local-ref 0) ;; push the value of `x'
|
||||||
|
(object-ref 1) ;; push the variable object of `%magic'
|
||||||
|
(variable-ref) ;; dereference it
|
||||||
|
(tail-call 2) ;; call `frob' with two parameters
|
||||||
|
@end example
|
||||||
|
|
||||||
|
This clearly shows that there is little difference between references
|
||||||
|
to local variables and references to externally bound variables.
|
||||||
|
|
||||||
|
@deffn @insn{} load-program bytecode
|
||||||
|
Load the program whose bytecode is @var{bytecode} (a u8vector) and pop
|
||||||
|
its meta-information from the stack. The program's meta-information
|
||||||
|
may consist of (in the order in which it should be pushed onto the
|
||||||
|
stack):
|
||||||
|
|
||||||
@itemize
|
@itemize
|
||||||
@item %make-program
|
@item optionally, a pair representing meta-data (see the
|
||||||
@item %call
|
@var{program-meta} procedure); [FIXME: explain their meaning]
|
||||||
@item %return
|
@item optionally, a vector which is the program's object table (a
|
||||||
|
program that does not reference external bindings does not need an
|
||||||
|
object table);
|
||||||
|
@item either one integer or four integers representing respectively
|
||||||
|
the number of arguments taken by the function (@var{nargs}), the
|
||||||
|
number of @dfn{rest arguments} (@var{nrest}, 0 or 1), the number of
|
||||||
|
local variables (@var{nlocs}) and the number of external variables
|
||||||
|
(@var{nexts}) (see the example above).
|
||||||
@end itemize
|
@end itemize
|
||||||
|
|
||||||
@section Data control instructinos
|
In the end, push a program object onto the stack.
|
||||||
|
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn @insn{} object-ref offset
|
||||||
|
Push the variable object for the external variable located at
|
||||||
|
@var{offset} within the program's object table.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn @insn{} return
|
||||||
|
Free the program's frame.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
|
@node Data Control Instructions, , Subprogram Control Instructions, Instruction Set
|
||||||
|
@section Data Control Instructions
|
||||||
|
|
||||||
|
@deffn @insn{} make-int8 value
|
||||||
|
Push @var{value}, an 8-bit integer, onto the stack.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn @insn{} make-int8:0
|
||||||
|
Push the immediate value @code{0} onto the stack.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn @insn{} make-int8:1
|
||||||
|
Push the immediate value @code{1} onto the stack.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn @insn{} make-false
|
||||||
|
Push @code{#f} onto the stack.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn @insn{} make-true
|
||||||
|
Push @code{#t} onto the stack.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
@itemize
|
@itemize
|
||||||
@item %push
|
@item %push
|
||||||
|
@ -558,3 +716,5 @@ letter `%'.
|
||||||
@c mode:outline-minor
|
@c mode:outline-minor
|
||||||
@c outline-regexp:"@\\(ch\\|sec\\|subs\\)"
|
@c outline-regexp:"@\\(ch\\|sec\\|subs\\)"
|
||||||
@c End:
|
@c End:
|
||||||
|
|
||||||
|
@c LocalWords: bytecode
|
||||||
|
|
|
@ -258,7 +258,7 @@
|
||||||
(($ number)
|
(($ number)
|
||||||
(push-code! `(load-number ,(number->string x))))
|
(push-code! `(load-number ,(number->string x))))
|
||||||
(($ string)
|
(($ string)
|
||||||
(push-code! `(load-string ,(string->string x))))
|
(push-code! `(load-string ,x)))
|
||||||
(($ symbol)
|
(($ symbol)
|
||||||
(push-code! `(load-symbol ,(symbol->string x))))
|
(push-code! `(load-symbol ,(symbol->string x))))
|
||||||
(($ keyword)
|
(($ keyword)
|
||||||
|
|
|
@ -149,10 +149,10 @@ SCM_DEFINE (scm_program_arity, "program-arity", 1, 0, 0,
|
||||||
SCM_VALIDATE_PROGRAM (1, program);
|
SCM_VALIDATE_PROGRAM (1, program);
|
||||||
|
|
||||||
p = SCM_PROGRAM_DATA (program);
|
p = SCM_PROGRAM_DATA (program);
|
||||||
return SCM_LIST4 (SCM_MAKINUM (p->nargs),
|
return SCM_LIST4 (scm_from_uchar (p->nargs),
|
||||||
SCM_MAKINUM (p->nrest),
|
scm_from_uchar (p->nrest),
|
||||||
SCM_MAKINUM (p->nlocs),
|
scm_from_uchar (p->nlocs),
|
||||||
SCM_MAKINUM (p->nexts));
|
scm_from_uchar (p->nexts));
|
||||||
}
|
}
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
|
|
||||||
|
|
4
src/vm.c
4
src/vm.c
|
@ -369,7 +369,7 @@ SCM_DEFINE (scm_vm_fp, "vm:fp", 1, 0, 0,
|
||||||
SCM_VALIDATE_VM (1, vm); \
|
SCM_VALIDATE_VM (1, vm); \
|
||||||
vp = SCM_VM_DATA (vm); \
|
vp = SCM_VM_DATA (vm); \
|
||||||
if (SCM_FALSEP (vp->hooks[n])) \
|
if (SCM_FALSEP (vp->hooks[n])) \
|
||||||
vp->hooks[n] = scm_make_hook (SCM_MAKINUM (1)); \
|
vp->hooks[n] = scm_make_hook (SCM_I_MAKINUM (1)); \
|
||||||
return vp->hooks[n]; \
|
return vp->hooks[n]; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -528,7 +528,7 @@ SCM_DEFINE (scm_vm_fetch_code, "vm-fetch-code", 1, 0, 0,
|
||||||
|
|
||||||
list = SCM_LIST1 (scm_str2symbol (p->name));
|
list = SCM_LIST1 (scm_str2symbol (p->name));
|
||||||
for (i = 1; i <= p->len; i++)
|
for (i = 1; i <= p->len; i++)
|
||||||
list = scm_cons (SCM_MAKINUM (ip[i]), list);
|
list = scm_cons (scm_from_uint8 (ip[i]), list);
|
||||||
return scm_reverse_x (list, SCM_EOL);
|
return scm_reverse_x (list, SCM_EOL);
|
||||||
}
|
}
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
|
|
||||||
#include "vm_engine.h"
|
#include "vm_engine.h"
|
||||||
|
|
||||||
|
|
||||||
static SCM
|
static SCM
|
||||||
vm_run (SCM vm, SCM program, SCM args)
|
vm_run (SCM vm, SCM program, SCM args)
|
||||||
#define FUNC_NAME "vm-engine"
|
#define FUNC_NAME "vm-engine"
|
||||||
|
|
|
@ -130,10 +130,20 @@
|
||||||
vp->fp = fp; \
|
vp->fp = fp; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get a local copy of the program's "object table" (i.e. the vector of
|
||||||
|
external bindings that are referenced by the program), initialized by
|
||||||
|
`load-program'. */
|
||||||
#define CACHE_PROGRAM() \
|
#define CACHE_PROGRAM() \
|
||||||
{ \
|
{ \
|
||||||
|
size_t _vsize; \
|
||||||
|
ssize_t _vincr; \
|
||||||
|
scm_t_array_handle _vhandle; \
|
||||||
|
\
|
||||||
bp = SCM_PROGRAM_DATA (program); \
|
bp = SCM_PROGRAM_DATA (program); \
|
||||||
objects = SCM_VELTS (bp->objs); \
|
/* Was: objects = SCM_VELTS (bp->objs); */ \
|
||||||
|
objects = scm_vector_elements (bp->objs, &_vhandle, \
|
||||||
|
&_vsize, &_vincr); \
|
||||||
|
scm_array_handle_release (&_vhandle); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SYNC_BEFORE_GC() \
|
#define SYNC_BEFORE_GC() \
|
||||||
|
@ -208,12 +218,8 @@
|
||||||
|
|
||||||
#define CONS(x,y,z) \
|
#define CONS(x,y,z) \
|
||||||
{ \
|
{ \
|
||||||
SCM cell; \
|
|
||||||
SYNC_BEFORE_GC (); \
|
SYNC_BEFORE_GC (); \
|
||||||
SCM_NEWCELL (cell); \
|
x = scm_cons (y, z); \
|
||||||
SCM_SET_CELL_OBJECT_0 (cell, y); \
|
|
||||||
SCM_SET_CELL_OBJECT_1 (cell, z); \
|
|
||||||
x = cell; \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define POP_LIST(n) \
|
#define POP_LIST(n) \
|
||||||
|
|
|
@ -130,7 +130,7 @@ VM_DEFINE_LOADER (load_program, "load-program")
|
||||||
}
|
}
|
||||||
|
|
||||||
/* init object table */
|
/* init object table */
|
||||||
if (SCM_VECTORP (x))
|
if (scm_is_vector (x))
|
||||||
{
|
{
|
||||||
p->objs = x;
|
p->objs = x;
|
||||||
POP (x);
|
POP (x);
|
||||||
|
@ -178,7 +178,7 @@ VM_DEFINE_LOADER (link, "link")
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
FETCH_LENGTH (len);
|
FETCH_LENGTH (len);
|
||||||
sym = scm_mem2symbol (ip, len);
|
sym = scm_from_locale_symboln (ip, len);
|
||||||
ip += len;
|
ip += len;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -193,7 +193,7 @@ VM_DEFINE_LOADER (link, "link")
|
||||||
/* Create a new variable if not defined yet */
|
/* Create a new variable if not defined yet */
|
||||||
var = scm_eval_closure_lookup (scm_standard_eval_closure (mod),
|
var = scm_eval_closure_lookup (scm_standard_eval_closure (mod),
|
||||||
sym, SCM_BOOL_T);
|
sym, SCM_BOOL_T);
|
||||||
PUSH (scm_variable_ref (var));
|
PUSH (var);
|
||||||
/* Was: SCM_VARVCELL (var)); */
|
/* Was: SCM_VARVCELL (var)); */
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,19 +119,19 @@ VM_DEFINE_INSTRUCTION (make_eol, "make-eol", 0, 0, 1)
|
||||||
|
|
||||||
VM_DEFINE_INSTRUCTION (make_int8, "make-int8", 1, 0, 1)
|
VM_DEFINE_INSTRUCTION (make_int8, "make-int8", 1, 0, 1)
|
||||||
{
|
{
|
||||||
PUSH (SCM_MAKINUM ((signed char) FETCH ()));
|
PUSH (scm_from_schar ((signed char) FETCH ()));
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
VM_DEFINE_INSTRUCTION (make_int8_0, "make-int8:0", 0, 0, 1)
|
VM_DEFINE_INSTRUCTION (make_int8_0, "make-int8:0", 0, 0, 1)
|
||||||
{
|
{
|
||||||
PUSH (SCM_MAKINUM (0));
|
PUSH (SCM_INUM0);
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
VM_DEFINE_INSTRUCTION (make_int8_1, "make-int8:1", 0, 0, 1)
|
VM_DEFINE_INSTRUCTION (make_int8_1, "make-int8:1", 0, 0, 1)
|
||||||
{
|
{
|
||||||
PUSH (SCM_MAKINUM (1));
|
PUSH (SCM_I_MAKINUM (1));
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ VM_DEFINE_INSTRUCTION (make_int16, "make-int16", 2, 0, 1)
|
||||||
{
|
{
|
||||||
int h = FETCH ();
|
int h = FETCH ();
|
||||||
int l = FETCH ();
|
int l = FETCH ();
|
||||||
PUSH (SCM_MAKINUM ((signed short) (h << 8) + l));
|
PUSH (scm_from_short ((signed short) (h << 8) + l));
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,8 +197,8 @@ VM_DEFINE_INSTRUCTION (list_break, "list-break", 0, 0, 0)
|
||||||
#define LOCAL_REF(i) SCM_FRAME_VARIABLE (fp, i)
|
#define LOCAL_REF(i) SCM_FRAME_VARIABLE (fp, i)
|
||||||
#define LOCAL_SET(i,o) SCM_FRAME_VARIABLE (fp, i) = o
|
#define LOCAL_SET(i,o) SCM_FRAME_VARIABLE (fp, i) = o
|
||||||
|
|
||||||
#define VARIABLE_REF(v) SCM_CDR (v)
|
/* #define VARIABLE_REF(v) SCM_CDR (v) */
|
||||||
#define VARIABLE_SET(v,o) SCM_SETCDR (v, o)
|
/* #define VARIABLE_SET(v,o) SCM_SETCDR (v, o) */
|
||||||
|
|
||||||
/* ref */
|
/* ref */
|
||||||
|
|
||||||
|
@ -231,13 +231,19 @@ VM_DEFINE_INSTRUCTION (external_ref, "external-ref", 1, 0, 1)
|
||||||
VM_DEFINE_INSTRUCTION (variable_ref, "variable-ref", 0, 0, 1)
|
VM_DEFINE_INSTRUCTION (variable_ref, "variable-ref", 0, 0, 1)
|
||||||
{
|
{
|
||||||
SCM x = *sp;
|
SCM x = *sp;
|
||||||
SCM o = VARIABLE_REF (x);
|
|
||||||
if (SCM_UNBNDP (o))
|
if (SCM_FALSEP (scm_variable_bound_p (x)))
|
||||||
{
|
{
|
||||||
err_args = SCM_LIST1 (SCM_CAR (x));
|
err_args = SCM_LIST1 (x);
|
||||||
|
/* Was: err_args = SCM_LIST1 (SCM_CAR (x)); */
|
||||||
goto vm_error_unbound;
|
goto vm_error_unbound;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SCM o = scm_variable_ref (x);
|
||||||
*sp = o;
|
*sp = o;
|
||||||
|
}
|
||||||
|
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +273,7 @@ VM_DEFINE_INSTRUCTION (external_set, "external-set", 1, 1, 0)
|
||||||
|
|
||||||
VM_DEFINE_INSTRUCTION (variable_set, "variable-set", 0, 1, 0)
|
VM_DEFINE_INSTRUCTION (variable_set, "variable-set", 0, 1, 0)
|
||||||
{
|
{
|
||||||
VARIABLE_SET (sp[0], sp[-1]);
|
scm_variable_set_x (sp[0], sp[-1]);
|
||||||
scm_set_object_property_x (sp[-1], scm_sym_name, SCM_CAR (sp[0]));
|
scm_set_object_property_x (sp[-1], scm_sym_name, SCM_CAR (sp[0]));
|
||||||
sp -= 2;
|
sp -= 2;
|
||||||
NEXT;
|
NEXT;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue