summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--eval.c24
-rw-r--r--share/txr/stdlib/compiler.tl33
-rw-r--r--txr.138
3 files changed, 93 insertions, 2 deletions
diff --git a/eval.c b/eval.c
index 6053c853..637ed8a6 100644
--- a/eval.c
+++ b/eval.c
@@ -202,6 +202,27 @@ val env_vbind(val env, val sym, val obj)
}
}
+static val env_vbindings(val env)
+{
+ val self = lit("env-vbindings");
+ type_check(self, env, ENV);
+ return env->e.vbindings;
+}
+
+static val env_fbindings(val env)
+{
+ val self = lit("env-fbindings");
+ type_check(self, env, ENV);
+ return env->e.fbindings;
+}
+
+static val env_next(val env)
+{
+ val self = lit("env-next");
+ type_check(self, env, ENV);
+ return env->e.up_env;
+}
+
static void env_vb_to_fb(val env)
{
if (env) {
@@ -6499,6 +6520,9 @@ void eval_init(void)
reg_fun(intern(lit("make-env"), user_package), func_n3o(make_env_intrinsic, 0));
reg_fun(intern(lit("env-fbind"), user_package), func_n3(env_fbind));
reg_fun(intern(lit("env-vbind"), user_package), func_n3(env_vbind));
+ reg_fun(intern(lit("env-vbindings"), user_package), func_n1(env_vbindings));
+ reg_fun(intern(lit("env-fbindings"), user_package), func_n1(env_fbindings));
+ reg_fun(intern(lit("env-next"), user_package), func_n1(env_next));
reg_fun(intern(lit("lexical-var-p"), user_package), func_n2(lexical_var_p));
reg_fun(intern(lit("lexical-fun-p"), user_package), func_n2(lexical_fun_p));
reg_fun(intern(lit("lexical-lisp1-binding"), user_package),
diff --git a/share/txr/stdlib/compiler.tl b/share/txr/stdlib/compiler.tl
index 51b0becd..2f27365d 100644
--- a/share/txr/stdlib/compiler.tl
+++ b/share/txr/stdlib/compiler.tl
@@ -1682,16 +1682,45 @@
(error "~s: compilation of ~s failed" 'compile-file
(stream-get-prop in-stream :name)))))))))
+(defun sys:env-to-let (env form)
+ (when env
+ (let ((vb (env-vbindings env))
+ (fb (env-fbindings env))
+ (up (env-next env)))
+ (when vb
+ (set form ^(let ,(mapcar (tb ((a . d)) ^(,a ',d)) vb) ,form)))
+ (when fb
+ (let (lbind fbind)
+ (each ((pair fb))
+ (tree-bind (a . d) pair
+ (let* ((fun-p (interp-fun-p d))
+ (fe (if fun-p (func-get-env d)))
+ (lb-p (and fe (eq fe env)))
+ (fb-p (and fe (eq fe up))))
+ (cond
+ (lb-p (push ^(,a ,(func-get-form d)) lbind))
+ (fb-p (push ^(,a ,(func-get-form d)) fbind))
+ (t (push ^(,a ',d) fbind))))))
+ (when lbind
+ (set form ^(sys:lbind ,(nreverse lbind) ,form)))
+ (when fbind
+ (set form ^(sys:fbind ,(nreverse fbind) ,form)))))
+ (if up
+ (set form (sys:env-to-let up form)))))
+ form)
+
(defun usr:compile (obj)
(typecase obj
(fun (tree-bind (indicator args . body) (func-get-form obj)
- (let* ((form ^(lambda ,args ,*body))
+ (let* ((form (sys:env-to-let (func-get-env obj)
+ ^(lambda ,args ,*body)))
(vm-desc (compile-toplevel form)))
(vm-execute-toplevel vm-desc))))
(t (condlet
(((fun (symbol-function obj)))
(tree-bind (indicator args . body) (func-get-form fun)
- (let* ((form ^(lambda ,args ,*body))
+ (let* ((form (sys:env-to-let (func-get-env fun)
+ ^(lambda ,args ,*body)))
(vm-desc (compile-toplevel form))
(comp-fun (vm-execute-toplevel vm-desc)))
(set (symbol-function obj) comp-fun))))
diff --git a/txr.1 b/txr.1
index 1aac81f8..4620b368 100644
--- a/txr.1
+++ b/txr.1
@@ -16435,6 +16435,44 @@ is specified as
.codn nil ,
then the binding takes place in the global environment.
+.coNP Functions @, env-vbindings @ env-fbindings and @ env-next
+.synb
+.mets (env-vbindings << env )
+.mets (env-fbindings << env )
+.mets (env-next << env )
+.syne
+.desc
+These function retrieve the components of
+.metn env ,
+which must be an environment. The
+.code env-vbindings
+function retrieves the the association list representing variable
+bindings. Similarly, the
+.code env-fbindings
+retrieves the association list of function bindings.
+The
+.code env-next
+function retrieves the next environment, if
+.meta env
+has one, otherwise
+.codn nil .
+
+If
+.code e
+is an environment constructed by the expression
+.codn "(make-env v f n)" ,
+then
+.code "(env-vbindings e)"
+retrieves
+.codn v ,
+.code "(env-fbindings e)"
+retrieves
+.code f
+and
+.code "(env-next e)"
+returns
+.codn n .
+
.SS* Global Environment
.coNP Accessors @, symbol-function @ symbol-macro and @ symbol-value
.synb