diff options
-rw-r--r-- | combi.c | 91 | ||||
-rw-r--r-- | combi.h | 1 | ||||
-rw-r--r-- | eval.c | 1 | ||||
-rw-r--r-- | lib.c | 23 | ||||
-rw-r--r-- | lib.h | 11 |
5 files changed, 117 insertions, 10 deletions
@@ -35,6 +35,7 @@ #include "unwind.h" #include "eval.h" #include "hash.h" +#include "gc.h" #include "combi.h" static void check_k(val k, val self) @@ -266,6 +267,96 @@ val perm(val seq, val k) } } +static int permi_get(struct seq_iter *it, val *pval) +{ + val state = it->inf.obj; + + if (it->ul.next) { + if (it->ui.iter || perm_while_fun(state)) { + it->ui.iter = nil; + *pval = perm_seq_gen_fun(state); + return 1; + } + } + + it->ul.next = nil; + return 0; +} + +static int permi_peek(struct seq_iter *it, val *pval) +{ + val state = it->inf.obj; + + if (it->ul.next) { + if (it->ui.iter || perm_while_fun(state)) { + it->ui.iter = t; + *pval = state; + *pval = perm_seq_gen_fun(state); + return 1; + } + } + + it->ul.next = nil; + return 0; +} + +static void permi_clone(const struct seq_iter *sit, struct seq_iter *dit) +{ + val state = sit->inf.obj; + val c = vecref(state, two); + val state_copy = copy_vec(state); + + *dit = *sit; + dit->inf.obj = state_copy; + set(vecref_l(state_copy, two), copy_vec(c)); +} + +struct seq_iter_ops permi_ops = seq_iter_ops_init_clone(permi_get, + permi_peek, + permi_clone); + +static val permi_iter(val state) +{ + val obj; + struct seq_iter *it = coerce(struct seq_iter *, chk_calloc(1, sizeof *it)); + + it->inf.obj = state; + it->inf.type = NIL; + it->inf.kind = SEQ_NOTSEQ; + + it->ui.iter = nil; + it->ul.next = t; + it->ops = &permi_ops; + + obj = cobj(coerce(mem_t *, it), seq_iter_cls, &seq_iter_cobj_ops); + + gc_hint(obj); + gc_hint(state); + + return obj; +} + +val permi(val seq, val k) +{ + val self = lit("permi"); + + if (null_or_missing_p(k)) { + k = nil; + } else { + check_k(k, self); + } + + if (k == zero) { + return cons(make_like(nil, seq), nil); + } else { + val vec = vec_seq(seq); + val state = perm_init(vec, k, seq); + if (!state) + return nil; + return permi_iter(state); + } +} + static val rperm_init(val list, val k, val extra) { val vec = vector(k, list); @@ -27,6 +27,7 @@ */ val perm(val seq, val k); +val permi(val seq, val k); val rperm(val seq, val k); val comb(val seq, val k); val rcomb(val seq, val k); @@ -7898,6 +7898,7 @@ void eval_init(void) reg_fun(intern(lit("promisep"), user_package), func_n1(promisep)); reg_fun(intern(lit("rperm"), user_package), func_n2(rperm)); reg_fun(intern(lit("perm"), user_package), func_n2o(perm, 1)); + reg_fun(intern(lit("permi"), user_package), func_n2o(permi, 1)); reg_fun(intern(lit("comb"), user_package), func_n2(comb)); reg_fun(intern(lit("rcomb"), user_package), func_n2(rcomb)); @@ -910,7 +910,7 @@ static int seq_iter_peek_cat(seq_iter_t *it, val *pval) } } -static void seq_iter_mark_op(struct seq_iter *it) +void seq_iter_mark_op(struct seq_iter *it) { gc_mark(it->ui.iter); } @@ -977,6 +977,14 @@ struct seq_iter_ops si_fast_oop_ops = seq_iter_ops_init(seq_iter_get_fast_oop, struct seq_iter_ops si_cat_ops = seq_iter_ops_init(seq_iter_get_cat, seq_iter_peek_cat); +static void seq_iter_clone(seq_iter_t *dit, const seq_iter_t *sit) +{ + if (sit->ops->clone) + sit->ops->clone(sit, dit); + else + *dit = *sit; +} + void seq_iter_init_with_info(val self, seq_iter_t *it, seq_info_t si, int support_rewind) { @@ -1128,7 +1136,7 @@ void seq_iter_init_with_info(val self, seq_iter_t *it, } if (it->inf.obj->co.cls == seq_iter_cls) { - *it = *coerce(struct seq_iter *, it->inf.obj->co.handle); + seq_iter_clone(it, coerce(struct seq_iter *, it->inf.obj->co.handle)); break; } if (it->inf.obj->co.cls == tree_iter_cls) @@ -1224,12 +1232,11 @@ static void seq_iter_mark(val seq_iter) si->ops->mark(si); } -static struct cobj_ops - seq_iter_cobj_ops = cobj_ops_init(eq, - cobj_print_op, - cobj_destroy_free_op, - seq_iter_mark, - cobj_eq_hash_op); +struct cobj_ops seq_iter_cobj_ops = cobj_ops_init(eq, + cobj_print_op, + cobj_destroy_free_op, + seq_iter_mark, + cobj_eq_hash_op); val seq_begin(val obj) { @@ -465,10 +465,13 @@ struct seq_iter_ops { int (*get)(struct seq_iter *, val *pval); int (*peek)(struct seq_iter *, val *pval); void (*mark)(struct seq_iter *); + void (*clone)(const struct seq_iter *, struct seq_iter *); }; -#define seq_iter_ops_init(get, peek) { get, peek, seq_iter_mark_op } -#define seq_iter_ops_init_nomark(get, peek) { get, peek, 0 } +#define seq_iter_ops_init(get, peek) { get, peek, seq_iter_mark_op, 0 } +#define seq_iter_ops_init_nomark(get, peek) { get, peek, 0, 0 } +#define seq_iter_ops_init_clone(get, peek, clone) \ + { get, peek, seq_iter_mark_op, clone } typedef struct seq_build { val obj; @@ -745,12 +748,16 @@ typedef unsigned long alloc_bytes_t; extern alloc_bytes_t malloc_bytes; extern alloc_bytes_t gc_bytes; +extern struct cobj_class *seq_iter_cls; +extern struct cobj_ops seq_iter_cobj_ops; + val identity(val obj); val built_in_type_p(val sym); val typeof(val obj); val subtypep(val sub, val sup); val typep(val obj, val type); seq_info_t seq_info(val cobj); +void seq_iter_mark_op(struct seq_iter *it); void seq_iter_init_with_info(val self, seq_iter_t *it, seq_info_t si, int support_rewind); void seq_iter_init(val self, seq_iter_t *it, val obj); |