summaryrefslogtreecommitdiffstats
path: root/combi.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2023-12-27 15:51:53 -0800
committerKaz Kylheku <kaz@kylheku.com>2023-12-27 15:51:53 -0800
commit36fdbc7a4791ffdedf0658eb69963cffe08aaee1 (patch)
tree8b0ee66a9941acd4647d87c2dedaa4b5e51ac940 /combi.c
parent2b4dff1bc2c3274201cdda958037b9065ca974bf (diff)
downloadtxr-36fdbc7a4791ffdedf0658eb69963cffe08aaee1.tar.gz
txr-36fdbc7a4791ffdedf0658eb69963cffe08aaee1.tar.bz2
txr-36fdbc7a4791ffdedf0658eb69963cffe08aaee1.zip
rperm: support general sequences.
* combi.c (rperm_init): Take one more parameter. Allocate the state vector to three elements and put the extra value there. (rperm_list, rperm_vec, rperm_str): Pass nil for the extra value to rperm_init; these do not use it. (rperm_seq_gen_fun, rperm_seq): New functions. These use the extra value to store the original seq in the state, so that the elements of the output sequence can be converted to the same type of sequence as the input. (rperm): Replace error throw in default case with call to rperm_seq.
Diffstat (limited to 'combi.c')
-rw-r--r--combi.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/combi.c b/combi.c
index c674686d..b20555ae 100644
--- a/combi.c
+++ b/combi.c
@@ -262,12 +262,14 @@ val perm(val seq, val k)
}
}
-static val rperm_init(val list, val k)
+static val rperm_init(val list, val k, val extra)
{
val vec = vector(k, list);
- val env = vector(two, nil);
+ val env = vector(three, nil);
set(vecref_l(env, zero), list);
set(vecref_l(env, one), vec);
+ if (extra)
+ set(vecref_l(env, two), extra);
return env;
}
@@ -302,7 +304,7 @@ static val rperm_gen_fun(val env)
static val rperm_list(val list, val k)
{
- val env = rperm_init(list, k);
+ val env = rperm_init(list, k, nil);
return generate(func_f0(env, rperm_while_fun),
func_f0(env, rperm_gen_fun));
}
@@ -316,7 +318,7 @@ static val rperm_vec_gen_fun(val env)
static val rperm_vec(val ve, val k)
{
val list = list_vec(ve);
- val env = rperm_init(list, k);
+ val env = rperm_init(list, k, nil);
return generate(func_f0(env, rperm_while_fun),
func_f0(env, rperm_vec_gen_fun));
}
@@ -330,11 +332,26 @@ static val rperm_str_gen_fun(val env)
static val rperm_str(val str, val k)
{
val list = list_str(str);
- val env = rperm_init(list, k);
+ val env = rperm_init(list, k, nil);
return generate(func_f0(env, rperm_while_fun),
func_f0(env, rperm_str_gen_fun));
}
+static val rperm_seq_gen_fun(val env)
+{
+ val list = rperm_gen_fun(env);
+ val seq = env->v.vec[2];
+ return make_like(list, seq);
+}
+
+static val rperm_seq(val seq, val k)
+{
+ val list = list_seq(seq);
+ val env = rperm_init(list, k, seq);
+ return generate(func_f0(env, rperm_while_fun),
+ func_f0(env, rperm_seq_gen_fun));
+}
+
val rperm(val seq, val k)
{
if (!integerp(k))
@@ -365,7 +382,7 @@ val rperm(val seq, val k)
return cons(string(L""), nil);
return rperm_str(seq, k);
default:
- type_mismatch(lit("rperm: ~s is not a sequence"), seq, nao);
+ return rperm_seq(seq, k);
}
}