diff options
-rw-r--r-- | combi.c | 252 | ||||
-rw-r--r-- | combi.h | 2 | ||||
-rw-r--r-- | eval.c | 2 | ||||
-rw-r--r-- | tests/015/comb.tl | 41 |
4 files changed, 265 insertions, 32 deletions
@@ -271,15 +271,17 @@ 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; - } + if (it->ul.next != nao) { + *pval = it->ul.next; + it->ul.next = nao; + return 1; + } + + if (perm_while_fun(state)) { + *pval = perm_seq_gen_fun(state); + return 1; } - it->ul.next = nil; return 0; } @@ -287,19 +289,25 @@ 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; - } + if (it->ul.next != nao) { + *pval = it->ul.next; + return 1; + } + + if (perm_while_fun(state)) { + it->ul.next = *pval = perm_seq_gen_fun(state); + return 1; } - it->ul.next = nil; return 0; } +static void permi_mark(struct seq_iter *it) +{ + if (it->ul.next != nao) + gc_mark(it->ul.next); +} + static void permi_clone(const struct seq_iter *sit, struct seq_iter *dit) { val state = sit->inf.obj; @@ -311,9 +319,10 @@ static void permi_clone(const struct seq_iter *sit, struct seq_iter *dit) set(vecref_l(state_copy, two), copy_vec(c)); } -static struct seq_iter_ops permi_ops = seq_iter_ops_init_clone(permi_get, - permi_peek, - permi_clone); +static struct seq_iter_ops permi_ops = seq_iter_ops_init_full(permi_get, + permi_peek, + permi_mark, + permi_clone); static val permi_iter(val state) { @@ -324,8 +333,8 @@ static val permi_iter(val state) it->inf.type = NIL; it->inf.kind = SEQ_NOTSEQ; - it->ui.iter = nil; - it->ul.next = t; + it->ul.next = nao; + it->ops = &permi_ops; obj = cobj(coerce(mem_t *, it), seq_iter_cls, &seq_iter_cobj_ops); @@ -481,10 +490,9 @@ static int rpermi_get(struct seq_iter *it, val *pval) { val env = it->inf.obj; - if (it->ul.next) { - *pval = it->ui.iter; - it->ui.iter = nil; - it->ul.next = 0; + if (it->ul.next != nao) { + *pval = it->ul.next; + it->ul.next = nao; return 1; } @@ -500,21 +508,25 @@ static int rpermi_peek(struct seq_iter *it, val *pval) { val env = it->inf.obj; - if (it->ul.next) { - *pval = it->ui.iter; - it->ui.iter = nil; + if (it->ul.next != nao) { + *pval = it->ul.next; return 1; } if (rperm_while_fun(env)) { - it->ui.iter = *pval = rperm_seq_gen_fun(env); - it->ul.next = t; + it->ul.next = *pval = rperm_seq_gen_fun(env); return 1; } return 0; } +static void rpermi_mark(struct seq_iter *it) +{ + if (it->ul.next != nao) + gc_mark(it->ul.next); +} + static void rpermi_clone(const struct seq_iter *sit, struct seq_iter *dit) { val env = sit->inf.obj; @@ -532,9 +544,10 @@ static void rpermi_clone(const struct seq_iter *sit, struct seq_iter *dit) dit->inf.obj = nenv; } -static struct seq_iter_ops rpermi_ops = seq_iter_ops_init_clone(rpermi_get, - rpermi_peek, - rpermi_clone); +static struct seq_iter_ops rpermi_ops = seq_iter_ops_init_full(rpermi_get, + rpermi_peek, + rpermi_mark, + rpermi_clone); val rpermi(val seq, val k) { @@ -551,6 +564,8 @@ val rpermi(val seq, val k) it->inf.obj = env; it->inf.kind = SEQ_NOTSEQ; + it->ul.next = nao; + it->ops = &rpermi_ops; obj = cobj(coerce(mem_t *, it), seq_iter_cls, &seq_iter_cobj_ops); @@ -758,6 +773,92 @@ val comb(val seq, val k) } } +static int combi_get(struct seq_iter *it, val *pval) +{ + val state = it->inf.obj; + val seq = it->ui.iter; + + if (it->ul.next != nao) { + *pval = it->ul.next; + it->ul.next = nao; + return 1; + } + + if (comb_while_fun(state)) { + val item = comb_list_gen_fun(state); + *pval = make_like(item, seq); + return 1; + } + + return 0; +} + +static int combi_peek(struct seq_iter *it, val *pval) +{ + val state = it->inf.obj; + val seq = it->ui.iter; + + if (it->ul.next != nao) { + *pval = it->ul.next; + return 1; + } + + if (comb_while_fun(state)) { + val item = comb_list_gen_fun(state); + it->ul.next = *pval = make_like(item, seq); + return 1; + } + + return 0; +} + +static void combi_mark(struct seq_iter *it) +{ + gc_mark(it->ui.iter); + if (it->ul.next != nao) + gc_mark(it->ul.next); +} + +static void combi_clone(const struct seq_iter *sit, struct seq_iter *dit) +{ + *dit = *sit; + dit->inf.obj = copy_vec(sit->inf.obj); +} + +static struct seq_iter_ops combi_ops = seq_iter_ops_init_full(combi_get, + combi_peek, + combi_mark, + combi_clone); + + +val combi(val seq, val k) +{ + check_k(k, lit("combi")); + + if (k == zero) { + return cons(make_like(nil, seq), nil); + } else if (gt(k, length(seq))) { + return nil; + } else { + val state = comb_init(list_seq(seq), k); + struct seq_iter *it = coerce(struct seq_iter *, chk_calloc(1, sizeof *it)); + val obj; + + it->inf.obj = state; + it->inf.kind = SEQ_NOTSEQ; + it->ui.iter = seq; + it->ul.next = nao; + + it->ops = &combi_ops; + + obj = cobj(coerce(mem_t *, it), seq_iter_cls, &seq_iter_cobj_ops); + + gc_hint(seq); + + return obj; + } +} + static val rcomb_while_fun(val state) { return car(state); @@ -890,3 +991,90 @@ val rcomb(val seq, val k) return rcomb_seq(seq, k); } } + +static int rcombi_get(struct seq_iter *it, val *pval) +{ + val state = it->inf.obj; + val seq = it->ui.iter; + + if (it->ul.next != nao) { + *pval = it->ul.next; + it->ul.next = nao; + return 1; + } + + if (rcomb_while_fun(state)) { + val item = rcomb_list_gen_fun(state); + *pval = make_like(item, seq); + return 1; + } + + return 0; +} + +static int rcombi_peek(struct seq_iter *it, val *pval) +{ + val state = it->inf.obj; + val seq = it->ui.iter; + + if (it->ul.next != nao) { + *pval = it->ul.next; + return 1; + } + + if (rcomb_while_fun(state)) { + val item = rcomb_list_gen_fun(state); + it->ul.next = *pval = make_like(item, seq); + return 1; + } + + return 0; +} + +static void rcombi_mark(struct seq_iter *it) +{ + gc_mark(it->ui.iter); + if (it->ul.next != nao) + gc_mark(it->ul.next); +} + +static void rcombi_clone(const struct seq_iter *sit, struct seq_iter *dit) +{ + *dit = *sit; + dit->inf.obj = copy_list(sit->inf.obj); +} + +static struct seq_iter_ops rcombi_ops = seq_iter_ops_init_full(rcombi_get, + rcombi_peek, + rcombi_mark, + rcombi_clone); + + +val rcombi(val seq, val k) +{ + check_k(k, lit("rcombi")); + + if (k == zero) { + return cons(make_like(nil, seq), nil); + } else if (gt(k, length(seq))) { + return nil; + } else { + val state = nreverse(list_vec(vector(k, list_seq(seq)))); + struct seq_iter *it = coerce(struct seq_iter *, chk_calloc(1, sizeof *it)); + val obj; + + it->inf.obj = state; + it->inf.kind = SEQ_NOTSEQ; + it->ui.iter = seq; + it->ul.next = nao; + + it->ops = &rcombi_ops; + + obj = cobj(coerce(mem_t *, it), seq_iter_cls, &seq_iter_cobj_ops); + + gc_hint(seq); + + return obj; + } +} + @@ -31,4 +31,6 @@ val permi(val seq, val k); val rperm(val seq, val k); val rpermi(val seq, val k); val comb(val seq, val k); +val combi(val seq, val k); val rcomb(val seq, val k); +val rcombi(val seq, val k); @@ -7902,7 +7902,9 @@ void eval_init(void) 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("combi"), user_package), func_n2(combi)); reg_fun(intern(lit("rcomb"), user_package), func_n2(rcomb)); + reg_fun(intern(lit("rcombi"), user_package), func_n2(rcombi)); reg_fun(intern(lit("return*"), user_package), func_n2o(return_star, 1)); reg_fun(intern(lit("abscond*"), system_package), func_n2o(abscond_star, 1)); diff --git a/tests/015/comb.tl b/tests/015/comb.tl index 70aa9dd3..8b9208e9 100644 --- a/tests/015/comb.tl +++ b/tests/015/comb.tl @@ -451,3 +451,44 @@ (rperm 1..4 0) (nil) (comb 1..4 0) (nil) (rcomb 1..4 0) (nil)) + +(mtest + (combi #() -1) :error + (combi #(1) -1) :error + (combi () -1) :error + (combi '(1) -1) :error + (combi "" -1) :error + (combi "a" -1) :error) + +(mtest + (rcombi #() -1) :error + (rcombi #(1) -1) :error + (rcombi () -1) :error + (rcombi '(1) -1) :error + (rcombi "" -1) :error + (rcombi "a" -1) :error) + +(mtest + (permi #() -1) :error + (permi #(1) -1) :error + (permi () -1) :error + (permi '(1) -1) :error + (permi "" -1) :error + (permi "a" -1) :error) + +(mtest + (rpermi #() -1) :error + (rpermi #(1) -1) :error + (rpermi () -1) :error + (rpermi '(1) -1) :error + (rpermi "" -1) :error + (rpermi "a" -1) :error) + +(let ((s "abcdef") + (v #(0 1 2 3 4)) + (l '(0 1 2 3 4))) + (each ((fn [list comb rcomb perm rperm]) + (fi [list combi rcombi permi rpermi])) + (each ((i 0..6)) + (each ((o [list s v l])) + (vtest (list-seq [fi o i]) [fn o i]))))) |