diff options
-rw-r--r-- | eval.c | 3 | ||||
-rw-r--r-- | lib.c | 57 | ||||
-rw-r--r-- | lib.h | 3 |
3 files changed, 61 insertions, 2 deletions
@@ -6073,7 +6073,8 @@ void eval_init(void) reg_fun(intern(lit("copy-list"), user_package), func_n1(copy_list)); reg_fun(intern(lit("nreverse"), user_package), func_n1(nreverse)); reg_fun(intern(lit("reverse"), user_package), func_n1(reverse)); - reg_fun(intern(lit("ldiff"), user_package), func_n2(ldiff)); + reg_fun(intern(lit("ldiff"), user_package), + func_n2(if3(opt_compat && opt_compat <= 190, ldiff_old, ldiff))); reg_fun(intern(lit("last"), user_package), func_n2o(last, 1)); reg_fun(intern(lit("butlast"), user_package), func_n2o(butlast, 1)); reg_fun(intern(lit("nthlast"), user_package), func_n2(nthlast)); @@ -1447,7 +1447,62 @@ val lazy_appendl(val lists) return lazy_appendv(args); } -val ldiff(val list1, val list2) +val ldiff(val seq1_in, val seq2) +{ + val seq1 = seq1_in; + list_collect_decl (out, ptail); + +loop: + if (seq1 == seq2) + return out; + + { + seq_info_t si1 = seq_info(seq1); + seq_info_t si2 = seq_info(seq2); + + switch (SEQ_KIND_PAIR(si1.kind, si2.kind)) { + case SEQ_KIND_PAIR(SEQ_NIL, SEQ_NIL): + case SEQ_KIND_PAIR(SEQ_NIL, SEQ_LISTLIKE): + case SEQ_KIND_PAIR(SEQ_NIL, SEQ_VECLIKE): + case SEQ_KIND_PAIR(SEQ_NIL, SEQ_HASHLIKE): + case SEQ_KIND_PAIR(SEQ_NIL, SEQ_NOTSEQ): + break; + case SEQ_KIND_PAIR(SEQ_LISTLIKE, SEQ_NIL): + case SEQ_KIND_PAIR(SEQ_VECLIKE, SEQ_NIL): + case SEQ_KIND_PAIR(SEQ_HASHLIKE, SEQ_NIL): + case SEQ_KIND_PAIR(SEQ_NOTSEQ, SEQ_NIL): + return seq1; + case SEQ_KIND_PAIR(SEQ_LISTLIKE, SEQ_LISTLIKE): + ptail = list_collect(ptail, car(si1.obj)); + seq1 = cdr(si1.obj); + goto loop; + case SEQ_KIND_PAIR(SEQ_LISTLIKE, SEQ_VECLIKE): + case SEQ_KIND_PAIR(SEQ_LISTLIKE, SEQ_HASHLIKE): + case SEQ_KIND_PAIR(SEQ_LISTLIKE, SEQ_NOTSEQ): + ptail = list_collect(ptail, car(si1.obj)); + seq1 = cdr(si1.obj); + goto loop; + case SEQ_KIND_PAIR(SEQ_VECLIKE, SEQ_VECLIKE): + if (equal(seq1, seq2) || zerop(length(seq1))) + break; + ptail = list_collect(ptail, ref(seq1, zero)); + seq1 = sub(seq1, one, t); + goto loop; + case SEQ_KIND_PAIR(SEQ_HASHLIKE, SEQ_HASHLIKE): + case SEQ_KIND_PAIR(SEQ_NOTSEQ, SEQ_NOTSEQ): + if (!equal(seq1, seq2)) + ptail = list_collect_append(ptail, seq1); + break; + default: + ptail = list_collect_append(ptail, seq1); + break; + } + } + + return make_like(out, seq1_in); +} + +val ldiff_old(val list1, val list2) { val list_orig = list1; list_collect_decl (out, ptail); @@ -359,6 +359,8 @@ typedef struct seq_info { extern const seq_kind_t seq_kind_tab[MAXTYPE+1]; +#define SEQ_KIND_PAIR(A, B) ((A) << 3 | (B)) + INLINE cnum tag(val obj) { return coerce(cnum, obj) & TAG_MASK; } INLINE int is_ptr(val obj) { return obj && tag(obj) == TAG_PTR; } INLINE int is_num(val obj) { return tag(obj) == TAG_NUM; } @@ -566,6 +568,7 @@ val replace_list(val list, val items, val from, val to); val lazy_appendl(val lists); val lazy_appendv(struct args *lists); val ldiff(val list1, val list2); +val ldiff_old(val list1, val list2); val flatten(val list); val lazy_flatten(val list); val flatcar(val list); |