summaryrefslogtreecommitdiffstats
path: root/lib.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2016-06-01 07:05:35 -0700
committerKaz Kylheku <kaz@kylheku.com>2016-06-01 07:05:35 -0700
commitcd8cf4f8fd827e428c53f2e6d7fcce5cd9727e7f (patch)
tree5acb1cb50e758409457f971d3e2fefa484ed9890 /lib.c
parent8a443d67ef95021529db7eb451479e79fb39b272 (diff)
downloadtxr-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.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/lib.c b/lib.c
index 31301b6d..92d218a6 100644
--- a/lib.c
+++ b/lib.c
@@ -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);