diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2016-06-01 07:05:35 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2016-06-01 07:05:35 -0700 |
commit | cd8cf4f8fd827e428c53f2e6d7fcce5cd9727e7f (patch) | |
tree | 5acb1cb50e758409457f971d3e2fefa484ed9890 /lib.c | |
parent | 8a443d67ef95021529db7eb451479e79fb39b272 (diff) | |
download | txr-cd8cf4f8fd827e428c53f2e6d7fcce5cd9727e7f.tar.gz txr-cd8cf4f8fd827e428c53f2e6d7fcce5cd9727e7f.tar.bz2 txr-cd8cf4f8fd827e428c53f2e6d7fcce5cd9727e7f.zip |
Methods for turning objects into sequences.
Struct objects can now define methods car, cdr and nullify.
With these, they can participate in operations on sequences.
* eval.h (car_s, cdr_s): Declared.
* lib.c (nullify_s): New symbol variable.
(car, cdr): Implement for struct objects via, respectively,
their car and cdr methods.
(tolist): Handle objects by mapping through identity.
(nullify): Implement for objects optionally: if an object
is a struct with a nullify method, use it, otherwise go
through default case of just returning the object.
(empty): Implement for objects that have nullify method.
(obj_init): Initialize nullify_s.
* struct.c (maybe_slot): New function.
* struct.h (maybe_slot): Declared.
* txr.1: Documented car, cdr and nullify method
convention.
Diffstat (limited to 'lib.c')
-rw-r--r-- | lib.c | 22 |
1 files changed, 20 insertions, 2 deletions
@@ -101,7 +101,7 @@ val error_s, type_error_s, internal_error_s, panic_s; val numeric_error_s, range_error_s; val query_error_s, file_error_s, process_error_s, syntax_error_s; val timeout_error_s, system_error_s; -val gensym_counter_s; +val gensym_counter_s, nullify_s; val nothrow_k, args_k, colon_k, auto_k, fun_k; val wrap_k, reflect_k; @@ -305,6 +305,9 @@ val car(val cons) if (zerop(length_str(cons))) return nil; return chr_str(cons, zero); + case COBJ: + if (structp(cons)) + return funcall1(slot(cons, car_s), cons); default: type_mismatch(lit("~s is not a cons"), cons, nao); } @@ -333,6 +336,9 @@ val cdr(val cons) if (le(length(cons), one)) return nil; return sub(cons, one, t); + case COBJ: + if (structp(cons)) + return funcall1(slot(cons, cdr_s), cons); default: type_mismatch(lit("~s is not a cons"), cons, nao); } @@ -692,6 +698,8 @@ val tolist(val seq) case LIT: case LSTR: return list_str(seq); + case COBJ: + return mapcar(identity_f, seq); case NIL: case CONS: case LCONS: @@ -715,6 +723,12 @@ val nullify(val seq) return if3(length_str_gt(seq, zero), seq, nil); case VEC: return if3(length_vec(seq) != zero, seq, nil); + case COBJ: + if (structp(seq)) { + val nullify_meth = maybe_slot(seq, nullify_s); + if (nullify_meth) + return funcall1(nullify_meth, seq); + } default: return seq; } @@ -8041,7 +8055,10 @@ val empty(val seq) case COBJ: if (seq->co.cls == hash_s) return eq(hash_count(seq), zero); - /* fallthrough */ + if (structp(seq)) { + val nullify_meth = maybe_slot(seq, nullify_s); + return if3(nullify_meth && funcall1(nullify_meth, seq), nil, seq); + } default: type_mismatch(lit("empty: ~s is not a sequence"), seq, nao); } @@ -8635,6 +8652,7 @@ static void obj_init(void) timeout_error_s = intern(lit("timeout-error"), user_package); assert_s = intern(lit("assert"), user_package); name_s = intern(lit("name"), user_package); + nullify_s = intern(lit("nullify"), user_package); args_k = intern(lit("args"), keyword_package); nothrow_k = intern(lit("nothrow"), keyword_package); |