summaryrefslogtreecommitdiff
path: root/libguile/vm-i-system.c
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2008-09-18 22:49:55 +0200
committerAndy Wingo <wingo@pobox.com>2008-09-18 22:49:55 +0200
commitd51406fe875ae5040324da19459c3e867df434a3 (patch)
tree7996c92a31164bd3424c5b84e6ded8617df756f0 /libguile/vm-i-system.c
parent87e7228ff6b76d44ecf63e092fadb5754557e5eb (diff)
downloadguile-d51406fe875ae5040324da19459c3e867df434a3.tar.gz
lambda-lifting for (lambda () ...) as consumer of call-with-values
* libguile/vm-engine.c (vm_run): Add new error case, vm_error_not_enough_values. * libguile/vm-i-system.c (goto/nargs, call/nargs): So, in these cases, if we get too many values, we don't truncate the values like we do in the single-value continuation case, or in the mvbind case. What to do? I guess we either truncate them here, or only allow the correct number of values. Dunno. Mark the code as a fixme. (truncate-values): New instruction, for mv-bind: checks that the number of values on the stack is compatible with the number of bindings we have arranged for them, truncating if necessary. * module/language/scheme/translate.scm (custom-transformer-table): Compile receive as a primary form -- not so much because it is a primary form, but more to test the mv-bind machinery. Also it's more efficient, I think. * module/system/il/compile.scm (lift-variables!): New helper, factored out of `optimize'. (optimize): Add a few more cases. Adapt `lambda' optimization, which isn't much. I'm not happy with ghil as a mungeable language. Add a case for call-with-values with the second argument is a lambda: lift the lambda. Untested. (codegen): Refactor the push-bindings! code. Compile mv-bind. * module/system/il/ghil.scm (<ghil-mv-bind>): Add mv-bind construct, along with its procedures. * module/system/il/glil.scm (<glil-mv-bind>): Add mv-bind construct, different from the high-level one. It makes sense in the source, I think. * module/system/vm/assemble.scm (codegen): Assemble glil-mv-bind by pushing onto the bindings list, and actually push some code to truncate the values.
Diffstat (limited to 'libguile/vm-i-system.c')
-rw-r--r--libguile/vm-i-system.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/libguile/vm-i-system.c b/libguile/vm-i-system.c
index 05fc7476e..21d0d0821 100644
--- a/libguile/vm-i-system.c
+++ b/libguile/vm-i-system.c
@@ -713,6 +713,7 @@ VM_DEFINE_INSTRUCTION (goto_nargs, "goto/nargs", 0, 0, 1)
SCM x;
POP (x);
nargs = scm_to_int (x);
+ /* FIXME: should truncate values? */
goto vm_goto_args;
}
@@ -721,6 +722,7 @@ VM_DEFINE_INSTRUCTION (call_nargs, "call/nargs", 0, 0, 1)
SCM x;
POP (x);
nargs = scm_to_int (x);
+ /* FIXME: should truncate values? */
goto vm_call;
}
@@ -963,6 +965,29 @@ VM_DEFINE_INSTRUCTION (return_values_star, "return/values*", 1, -1, -1)
goto vm_return_values;
}
+VM_DEFINE_INSTRUCTION (truncate_values, "truncate-values", 2, -1, -1)
+{
+ SCM x;
+ int nbinds, rest;
+ POP (x);
+ nvalues = scm_to_int (x);
+ nbinds = FETCH ();
+ rest = FETCH ();
+
+ if (rest)
+ nbinds--;
+
+ if (nvalues < nbinds)
+ goto vm_error_not_enough_values;
+
+ if (rest)
+ POP_LIST (nvalues - nbinds);
+ else
+ DROPN (nvalues - nbinds);
+
+ NEXT;
+}
+
/*
Local Variables:
c-file-style: "gnu"