diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-06-16 20:41:25 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-06-16 20:41:25 -0700 |
commit | 9435f6a3ed7b211c92810d3e6470677d2b03c319 (patch) | |
tree | 49a6fbbad527734ad9f6a09df11e626bae287b6b | |
parent | 6ef95aee02b53e3bba0778ef2a94291c33c21cfb (diff) | |
download | txr-9435f6a3ed7b211c92810d3e6470677d2b03c319.tar.gz txr-9435f6a3ed7b211c92810d3e6470677d2b03c319.tar.bz2 txr-9435f6a3ed7b211c92810d3e6470677d2b03c319.zip |
New sequence classification system.
This will help simplify writing generic sequence code, while
allowing lists and vectors to be handled specially.
* lib.h (enum seq_kind, seq_kind_t): New enum and typedef.
(struct seq_info, seq_info_t): New struct and typedef.
(seq_kind_tab, seq_info): Declared.
* lib.c (seq_kind_tab): New global array.
(seq_info): New function.
-rw-r--r-- | lib.c | 60 | ||||
-rw-r--r-- | lib.h | 13 |
2 files changed, 73 insertions, 0 deletions
@@ -150,6 +150,28 @@ int null_or_missing_p(val v); val default_null_arg(val arg); #endif +const seq_kind_t seq_kind_tab[MAXTYPE+1] = { + SEQ_NIL, /* NIL */ + SEQ_NOTSEQ, /* NUM */ + SEQ_NOTSEQ, /* CHR */ + SEQ_VECLIKE, /* LIT */ + SEQ_LISTLIKE, /* CONS */ + SEQ_VECLIKE, /* STR */ + SEQ_NOTSEQ, /* SYM */ + SEQ_NOTSEQ, /* PKG */ + SEQ_NOTSEQ, /* FUN */ + SEQ_VECLIKE, /* VEC */ + SEQ_LISTLIKE, /* LCONS */ + SEQ_VECLIKE, /* LSTR */ + SEQ_NOTSEQ, /* COBJ */ + SEQ_NOTSEQ, /* CPTR */ + SEQ_NOTSEQ, /* ENV */ + SEQ_NOTSEQ, /* BGNUM */ + SEQ_NOTSEQ, /* FLNUM */ + SEQ_NOTSEQ, /* RNG */ + SEQ_VECLIKE, /* BUF */ +}; + val identity(val obj) { return obj; @@ -257,6 +279,44 @@ val typep(val obj, val type) return subtypep(typeof(obj), type); } +seq_info_t seq_info(val obj) +{ + seq_info_t ret; + type_t to = type(obj); + + if (to != COBJ) { + ret.obj = obj; + ret.type = to; + ret.kind = seq_kind_tab[to]; + return ret; + } + + ret.obj = obj = nullify(obj); + + if (!obj || (ret.type = to = type(obj)) != COBJ) { + ret.kind = seq_kind_tab[to]; + } else { + val cls = obj->co.cls; + + if (cls == hash_s) { + ret.kind = SEQ_HASHLIKE; + } else if (cls == carray_s) { + ret.kind = SEQ_VECLIKE; + } else if (structp(cls)) { + if (maybe_slot(obj, length_s)) + ret.kind = SEQ_VECLIKE; + if (maybe_slot(obj, car_s)) + ret.kind = SEQ_LISTLIKE; + else + ret.kind = SEQ_NOTSEQ; + } else { + ret.kind = SEQ_NOTSEQ; + } + } + + return ret; +} + val throw_mismatch(val obj, type_t t) { type_mismatch(lit("~s is not of type ~s"), obj, code2type(t), nao); @@ -345,6 +345,18 @@ typedef val *loc; #define mpush(val, lo) (push(val, lo)) #endif +typedef enum seq_kind { + SEQ_NIL, SEQ_LISTLIKE, SEQ_VECLIKE, SEQ_HASHLIKE, SEQ_NOTSEQ +} seq_kind_t; + +typedef struct seq_info { + val obj; + type_t type; + seq_kind_t kind; +} seq_info_t; + +extern const seq_kind_t seq_kind_tab[MAXTYPE+1]; + 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; } @@ -486,6 +498,7 @@ val identity(val obj); val typeof(val obj); val subtypep(val sub, val sup); val typep(val obj, val type); +seq_info_t seq_info(val cobj); val throw_mismatch(val obj, type_t); INLINE val type_check(val obj, type_t typecode) { |