commit c8dd66263abdb1fdbc3d477ddad15eb212abbc21
parent 1407b2adf81afc9a066f41da46a8ec330d6ce42f
Author: Andres Navarro <canavarro82@gmail.com>
Date: Wed, 16 Mar 2011 03:34:05 -0300
Added force and $lazy to the ground environment. Promises & Encapsulations completed.
Diffstat:
4 files changed, 73 insertions(+), 12 deletions(-)
diff --git a/src/kgpromises.c b/src/kgpromises.c
@@ -21,14 +21,79 @@
#include "kghelpers.h"
#include "kgpromises.h"
+/* SOURCE_NOTE: this is mostly an adaptation of the library derivation
+ in the report */
+
/* 9.1.1 promise? */
/* uses typep */
+/* Helper for force */
+void handle_result(klisp_State *K, TValue *xparams, TValue obj)
+{
+ /*
+ ** xparams[0]: promise
+ */
+ TValue prom = xparams[0];
+
+ /* check to see if promise was determined before the eval completed */
+ if (ttisnil(kpromise_maybe_env(prom))) {
+ /* discard obj, return previous result */
+ kapply_cc(K, kpromise_exp(prom));
+ } else if (ttispromise(obj)) {
+ /* force iteratively, by sharing pairs so that when obj
+ determines a value, prom also does */
+ TValue node = kpromise_node(obj);
+ kpromise_node(prom) = node;
+ TValue expr = kpromise_exp(prom);
+ TValue maybe_env = kpromise_maybe_env(prom);
+ if (ttisnil(maybe_env)) {
+ /* promise was already determined */
+ kapply_cc(K, expr);
+ } else {
+ TValue new_cont = kmake_continuation(K, kget_cc(K), KNIL, KNIL,
+ handle_result, 1, prom);
+ kset_cc(K, new_cont);
+ ktail_eval(K, expr, maybe_env);
+ }
+ } else {
+ /* memoize result */
+ TValue node = kpromise_node(prom);
+ kset_car(node, obj);
+ kset_cdr(node, KNIL);
+ }
+}
+
/* 9.1.2 force */
-/* TODO */
+void force(klisp_State *K, TValue *xparams, TValue ptree, TValue denv)
+{
+ UNUSED(xparams);
+ UNUSED(denv);
+ bind_1p(K, "force", ptree, obj);
+ if (!ttispromise(obj)) {
+ /* non promises force to themselves */
+ kapply_cc(K, obj);
+ } else if (ttisnil(kpromise_maybe_env(obj))) {
+ /* promise was already determined */
+ kapply_cc(K, kpromise_exp(obj));
+ } else {
+ TValue expr = kpromise_exp(obj);
+ TValue env = kpromise_maybe_env(obj);
+ TValue new_cont = kmake_continuation(K, kget_cc(K), KNIL, KNIL,
+ handle_result, 1, obj);
+ kset_cc(K, new_cont);
+ ktail_eval(K, expr, env);
+ }
+}
/* 9.1.3 $lazy */
-/* TODO */
+void Slazy(klisp_State *K, TValue *xparams, TValue ptree, TValue denv)
+{
+ UNUSED(xparams);
+
+ bind_1p(K, "$lazy", ptree, exp);
+ TValue new_prom = kmake_promise(K, KNIL, KNIL, exp, denv);
+ kapply_cc(K, new_prom);
+}
/* 9.1.4 memoize */
void memoize(klisp_State *K, TValue *xparams, TValue ptree, TValue denv)
diff --git a/src/kgpromises.h b/src/kgpromises.h
@@ -22,10 +22,10 @@
/* uses typep */
/* 9.1.2 force */
-/* TODO */
+void force(klisp_State *K, TValue *xparams, TValue ptree, TValue denv);
/* 9.1.3 $lazy */
-/* TODO */
+void Slazy(klisp_State *K, TValue *xparams, TValue ptree, TValue denv);
/* 9.1.4 memoize */
void memoize(klisp_State *K, TValue *xparams, TValue ptree, TValue denv);
diff --git a/src/kground.c b/src/kground.c
@@ -431,10 +431,10 @@ void kinit_ground_env(klisp_State *K)
i2tv(K_TPROMISE));
/* 9.1.2 force */
- /* TODO */
+ add_applicative(K, ground_env, "force", force, 0);
/* 9.1.3 $lazy */
- /* TODO */
+ add_operative(K, ground_env, "$lazy", Slazy, 0);
/* 9.1.4 memoize */
add_applicative(K, ground_env, "memoize", memoize, 0);
diff --git a/src/kpromise.h b/src/kpromise.h
@@ -15,11 +15,7 @@ TValue kmake_promise(klisp_State *K, TValue name, TValue si,
TValue exp, TValue maybe_env);
#define kpromise_node(p_) (tv2prom(p_)->node)
-inline void kdetermine_promise(TValue p, TValue obj)
-{
- TValue node = kpromise_node(p);
- kset_car(node, obj);
- kset_cdr(node, KNIL);
-}
+#define kpromise_exp(p_) (kcar(kpromise_node(p_)))
+#define kpromise_maybe_env(p_) (kcdr(kpromise_node(p_)))
#endif