diff options
| author | Joel Martin <github@martintribe.org> | 2014-04-01 22:50:55 -0500 |
|---|---|---|
| committer | Joel Martin <github@martintribe.org> | 2014-04-01 22:50:55 -0500 |
| commit | 9528bb145193159fa3e697da642e32a0877af5fb (patch) | |
| tree | 3375b4524d7c845ec33c7636fb7697ce3c1d6a42 /c | |
| parent | 950e3c765e30648de34cfc4f65fffdce06f0727f (diff) | |
| download | mal-9528bb145193159fa3e697da642e32a0877af5fb.tar.gz mal-9528bb145193159fa3e697da642e32a0877af5fb.zip | |
All: pass stepA tests, in particular with correct conj behavior.
Diffstat (limited to 'c')
| -rw-r--r-- | c/types.c | 102 |
1 files changed, 75 insertions, 27 deletions
@@ -556,44 +556,62 @@ MalVal *_hash_map(int count, ...) { return hm; } -MalVal *hash_map(MalVal *args) { - assert_type(args, MAL_LIST|MAL_VECTOR, - "hash-map called with non-sequential arguments"); - assert((args->val.array->len % 2) == 0, - "odd number of parameters to hash-map"); - GHashTable *htable = g_hash_table_new(g_str_hash, g_str_equal); - MalVal *hm = malval_new_hash_map(htable); +MalVal *_assoc_BANG(MalVal* hm, MalVal *args) { + assert((_count(args) % 2) == 0, + "odd number of parameters to assoc!"); + GHashTable *htable = hm->val.hash_table; int i; MalVal *k, *v; - for(i=0; i< args->val.array->len; i+=2) { + for (i=0; i<_count(args); i+=2) { k = g_array_index(args->val.array, MalVal*, i); assert_type(k, MAL_STRING, - "hash-map called with non-string key"); + "assoc! called with non-string key"); v = g_array_index(args->val.array, MalVal*, i+1); g_hash_table_insert(htable, k->val.string, v); } return hm; } +MalVal *_dissoc_BANG(MalVal* hm, MalVal *args) { + GHashTable *htable = hm->val.hash_table; + int i; + MalVal *k, *v; + for (i=0; i<_count(args); i++) { + k = g_array_index(args->val.array, MalVal*, i); + assert_type(k, MAL_STRING, + "dissoc! called with non-string key"); + g_hash_table_remove(htable, k->val.string); + } + return hm; +} + +MalVal *hash_map(MalVal *args) { + assert_type(args, MAL_LIST|MAL_VECTOR, + "hash-map called with non-sequential arguments"); + GHashTable *htable = g_hash_table_new(g_str_hash, g_str_equal); + MalVal *hm = malval_new_hash_map(htable); + return _assoc_BANG(hm, args); +} + int _hash_map_Q(MalVal *seq) { return seq->type & MAL_HASH_MAP; } MalVal *hash_map_Q(MalVal *seq) { return _hash_map_Q(seq) ? &mal_true : &mal_false; } -// TODO: support multiple key/values -MalVal *assoc(MalVal *hm, MalVal *key, MalVal *val) { - GHashTable *htable = g_hash_table_copy(hm->val.hash_table); - MalVal *new_hm = malval_new_hash_map(htable); - g_hash_table_insert(htable, key->val.string, val); - return new_hm; +MalVal *assoc(MalVal *args) { + assert_type(args, MAL_LIST|MAL_VECTOR, + "assoc called with non-sequential arguments"); + assert(_count(args) >= 2, + "assoc needs at least 2 arguments"); + GHashTable *htable = g_hash_table_copy(_nth(args,0)->val.hash_table); + MalVal *hm = malval_new_hash_map(htable); + return _assoc_BANG(hm, rest(args)); } -// TODO: support multiple keys -MalVal *dissoc(MalVal *hm, MalVal *key) { - GHashTable *htable = g_hash_table_copy(hm->val.hash_table); - MalVal *new_hm = malval_new_hash_map(htable); - g_hash_table_remove(htable, key->val.string); - return new_hm; +MalVal *dissoc(MalVal* args) { + GHashTable *htable = g_hash_table_copy(_nth(args,0)->val.hash_table); + MalVal *hm = malval_new_hash_map(htable); + return _dissoc_BANG(hm, rest(args)); } MalVal *keys(MalVal *obj) { @@ -849,10 +867,19 @@ MalVal *sconj(MalVal *args) { int i, len = _count(src_lst) + _count(args) - 1; GArray *new_arr = g_array_sized_new(TRUE, TRUE, sizeof(MalVal*), len); - for (i=1; i<len; i++) { - g_array_append_val(new_arr, g_array_index(args->val.array, MalVal*, i)); + // Copy in src_lst + for (i=0; i<_count(src_lst); i++) { + g_array_append_val(new_arr, g_array_index(src_lst->val.array, MalVal*, i)); } - return malval_new_list(MAL_LIST, new_arr); + // Conj extra args + for (i=1; i<_count(args); i++) { + if (src_lst->type & MAL_LIST) { + g_array_prepend_val(new_arr, g_array_index(args->val.array, MalVal*, i)); + } else { + g_array_append_val(new_arr, g_array_index(args->val.array, MalVal*, i)); + } + } + return malval_new_list(src_lst->type, new_arr); } MalVal *first(MalVal *seq) { @@ -889,6 +916,27 @@ MalVal *nth(MalVal *seq, MalVal *idx) { return _nth(seq, idx->val.intnum); } +MalVal *sapply(MalVal *args) { + assert_type(args, MAL_LIST|MAL_VECTOR, + "apply called with non-sequential"); + MalVal *f = _nth(args, 0); + MalVal *last_arg = _nth(args, _count(args)-1); + assert_type(last_arg, MAL_LIST|MAL_VECTOR, + "last argument to apply is non-sequential"); + int i, len = _count(args) - 2 + _count(last_arg); + GArray *new_arr = g_array_sized_new(TRUE, TRUE, sizeof(MalVal*), + len); + // Initial arguments + for (i=1; i<_count(args)-1; i++) { + g_array_append_val(new_arr, g_array_index(args->val.array, MalVal*, i)); + } + // Add arguments from last_arg + for (i=0; i<_count(last_arg); i++) { + g_array_append_val(new_arr, g_array_index(last_arg->val.array, MalVal*, i)); + } + return apply(f, malval_new_list(MAL_LIST, new_arr)); +} + MalVal *_map2(MalVal *(*func)(void*, void*), MalVal *lst, void *arg2) { MalVal *e, *el; assert_type(lst, MAL_LIST|MAL_VECTOR, @@ -1007,8 +1055,8 @@ types_ns_entry types_ns[49] = { {"<=", (void*(*)(void*))int_lte, 2}, {"hash-map", (void*(*)(void*))hash_map, -1}, {"map?", (void*(*)(void*))hash_map_Q, 1}, - {"assoc", (void*(*)(void*))assoc, 3}, - {"dissoc", (void*(*)(void*))dissoc, 2}, + {"assoc", (void*(*)(void*))assoc, -1}, + {"dissoc", (void*(*)(void*))dissoc, -1}, {"get", (void*(*)(void*))get, 2}, {"contains?", (void*(*)(void*))contains_Q, 2}, {"keys", (void*(*)(void*))keys, 1}, @@ -1033,6 +1081,6 @@ types_ns_entry types_ns[49] = { {"last", (void*(*)(void*))last, 1}, {"rest", (void*(*)(void*))rest, 1}, {"nth", (void*(*)(void*))nth, 2}, - {"apply", (void*(*)(void*))apply, 2}, + {"apply", (void*(*)(void*))sapply, -1}, {"map", (void*(*)(void*))map, 2}, }; |
