|
|
@ -40,12 +40,13 @@ sol_object_t *sol_cast_string(sol_state_t *state, sol_object_t *obj) { |
|
|
|
|
|
|
|
// This will not fail here; error checking is done in sol_state_init(). |
|
|
|
|
|
|
|
sol_object_t *sol_new_singlet(sol_state_t *state) { |
|
|
|
sol_object_t *sol_new_singlet(sol_state_t *state, const char *name) { |
|
|
|
sol_object_t *res = malloc(sizeof(sol_object_t)); |
|
|
|
if(res) { |
|
|
|
res->type = SOL_SINGLET; |
|
|
|
res->refcnt = 0; |
|
|
|
res->ops = &(state->NullOps); |
|
|
|
res->str = strdup(name); |
|
|
|
} |
|
|
|
return sol_incref(res); |
|
|
|
} |
|
|
@ -67,6 +68,10 @@ void sol_init_object(sol_state_t *state, sol_object_t *obj) { |
|
|
|
if(obj->ops->init) obj->ops->init(state, obj); |
|
|
|
} |
|
|
|
|
|
|
|
sol_object_t *sol_obj_acquire(sol_object_t *obj) { |
|
|
|
return sol_incref(obj); |
|
|
|
} |
|
|
|
|
|
|
|
void sol_obj_free(sol_object_t *obj) { |
|
|
|
if(!obj) { |
|
|
|
printf("WARNING: Attempt to free NULL\n"); |
|
|
@ -130,6 +135,10 @@ sol_object_t *sol_new_string(sol_state_t *state, const char *s) { |
|
|
|
return res; |
|
|
|
} |
|
|
|
|
|
|
|
int sol_string_cmp(sol_state_t *state, sol_object_t *str, const char *s) { |
|
|
|
return strcmp(str->str, s); |
|
|
|
} |
|
|
|
|
|
|
|
sol_object_t *sol_f_str_free(sol_state_t *state, sol_object_t *obj) { |
|
|
|
free(obj->str); |
|
|
|
return obj; |
|
|
@ -142,256 +151,93 @@ sol_object_t *sol_new_list(sol_state_t *state) { |
|
|
|
return sol_incref(state->None); |
|
|
|
} |
|
|
|
res->type = SOL_LIST; |
|
|
|
res->lvalue = NULL; |
|
|
|
res->lnext = NULL; |
|
|
|
res->seq = dsl_seq_new_array(NULL, &(state->obfuncs)); |
|
|
|
res->ops = &(state->ListOps); |
|
|
|
sol_init_object(state, res); |
|
|
|
return res; |
|
|
|
} |
|
|
|
|
|
|
|
int sol_list_len(sol_state_t *state, sol_object_t *list) { |
|
|
|
int i = 0; |
|
|
|
sol_object_t *cur = list; |
|
|
|
if(!sol_is_list(list)) { |
|
|
|
sol_obj_free(sol_set_error_string(state, "Compute length of non-list")); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
while(cur) { |
|
|
|
if(cur->lvalue) i++; |
|
|
|
cur = cur->lnext; |
|
|
|
sol_object_t *sol_list_from_seq(sol_state_t *state, dsl_seq *seq) { |
|
|
|
sol_object_t *res = sol_alloc_object(state); |
|
|
|
if(sol_has_error(state)) { |
|
|
|
sol_obj_free(res); |
|
|
|
return sol_incref(state->None); |
|
|
|
} |
|
|
|
return i; |
|
|
|
res->type = SOL_LIST; |
|
|
|
res->seq = seq; |
|
|
|
res->ops = &(state->ListOps); |
|
|
|
sol_init_object(state, res); |
|
|
|
return res; |
|
|
|
} |
|
|
|
|
|
|
|
int sol_list_len(sol_state_t *state, sol_object_t *list) { |
|
|
|
return dsl_seq_len(list->seq); |
|
|
|
} |
|
|
|
|
|
|
|
sol_object_t *sol_list_sublist(sol_state_t *state, sol_object_t *list, int idx) { |
|
|
|
int i = 0; |
|
|
|
sol_object_t *cur = list; |
|
|
|
sol_object_t *copy, *res; |
|
|
|
dsl_seq *subl; |
|
|
|
if(idx < 0) { |
|
|
|
return sol_set_error_string(state, "Create sublist at negative index"); |
|
|
|
} |
|
|
|
while(cur && i < idx) { |
|
|
|
if(cur->lvalue) i++; |
|
|
|
cur = cur->lnext; |
|
|
|
subl = dsl_seq_copy(list->seq); |
|
|
|
for(i=0; i<idx; i++) { |
|
|
|
dsl_seq_delete(subl, 0); |
|
|
|
} |
|
|
|
copy = sol_new_list(state); |
|
|
|
res = copy; |
|
|
|
while(cur) { |
|
|
|
if(cur->lvalue) { |
|
|
|
copy->lvalue = sol_incref(cur->lvalue); |
|
|
|
if(cur->lnext) { |
|
|
|
copy->lnext = sol_alloc_object(state); |
|
|
|
copy = copy->lnext; |
|
|
|
copy->type = SOL_LCELL; |
|
|
|
copy->ops = &(state->LCellOps); |
|
|
|
copy->lnext = NULL; |
|
|
|
copy->lvalue = NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
cur = cur->lnext; |
|
|
|
} |
|
|
|
return res; |
|
|
|
return sol_list_from_seq(state, subl); |
|
|
|
} |
|
|
|
|
|
|
|
sol_object_t *sol_list_get_index(sol_state_t *state, sol_object_t *list, int idx) { |
|
|
|
sol_object_t *cur = list; |
|
|
|
int i = 0; |
|
|
|
if(!sol_is_list(list)) { |
|
|
|
return sol_set_error_string(state, "Get index of non-list"); |
|
|
|
} |
|
|
|
if(idx < 0) { |
|
|
|
return sol_set_error_string(state, "Get negative index"); |
|
|
|
} |
|
|
|
while(cur && i < idx) { |
|
|
|
if(cur->lvalue) i++; |
|
|
|
cur = cur->lnext; |
|
|
|
} |
|
|
|
while(cur && !cur->lvalue) cur = cur->lnext; |
|
|
|
if(cur) { |
|
|
|
return sol_incref(cur->lvalue); |
|
|
|
} else { |
|
|
|
return sol_set_error_string(state, "Get out-of-bounds index"); |
|
|
|
} |
|
|
|
if(idx<0 || idx>=dsl_seq_len(list->seq)) return sol_incref(state->None); |
|
|
|
return sol_incref(AS_OBJ(dsl_seq_get(list->seq, idx))); |
|
|
|
} |
|
|
|
|
|
|
|
void sol_list_set_index(sol_state_t *state, sol_object_t *list, int idx, sol_object_t *obj) { |
|
|
|
sol_object_t *cur = list, *temp; |
|
|
|
int i = 0; |
|
|
|
if(!sol_is_list(list)) { |
|
|
|
sol_obj_free(sol_set_error_string(state, "Set index of non-list")); |
|
|
|
return; |
|
|
|
} |
|
|
|
if(idx < 0) { |
|
|
|
sol_obj_free(sol_set_error_string(state, "Set negative index")); |
|
|
|
return; |
|
|
|
} |
|
|
|
while(cur && i < idx) { |
|
|
|
if(cur->lvalue) i++; |
|
|
|
cur = cur->lnext; |
|
|
|
} |
|
|
|
while(!cur->lvalue) cur = cur->lnext; |
|
|
|
if(cur) { |
|
|
|
temp = cur->lvalue; |
|
|
|
cur->lvalue = sol_incref(obj); |
|
|
|
if(temp) sol_obj_free(temp); |
|
|
|
} else { |
|
|
|
sol_obj_free(sol_set_error_string(state, "Set out-of-bounds index")); |
|
|
|
return; |
|
|
|
} |
|
|
|
if(idx<0 || idx>=dsl_seq_len(list->seq)) return; |
|
|
|
dsl_seq_set(list->seq, idx, obj); |
|
|
|
} |
|
|
|
|
|
|
|
void sol_list_insert(sol_state_t *state, sol_object_t *list, int idx, sol_object_t *obj) { |
|
|
|
sol_object_t *next = list, *prev = NULL, *temp = sol_alloc_object(state); |
|
|
|
int i = -1; |
|
|
|
if(sol_has_error(state)) return; |
|
|
|
if(!sol_is_list(list)) { |
|
|
|
sol_obj_free(sol_set_error_string(state, "Insert into non-list")); |
|
|
|
return; |
|
|
|
} |
|
|
|
if(idx < 0) { |
|
|
|
sol_obj_free(sol_set_error_string(state, "Insert at negative index")); |
|
|
|
return; |
|
|
|
} |
|
|
|
temp->type = SOL_LCELL; |
|
|
|
temp->ops = &(state->LCellOps); |
|
|
|
temp->lvalue = sol_incref(obj); |
|
|
|
while(next) { |
|
|
|
if(next->lvalue) i++; |
|
|
|
if(i >= idx) break; |
|
|
|
prev = next; |
|
|
|
next = next->lnext; |
|
|
|
} |
|
|
|
if(next) { |
|
|
|
if(prev) { |
|
|
|
prev->lnext = temp; |
|
|
|
temp->lnext = next; |
|
|
|
} else { |
|
|
|
assert(next == list); |
|
|
|
temp->lnext = sol_alloc_object(state); |
|
|
|
temp->lnext->type = SOL_LCELL; |
|
|
|
temp->lnext->ops = &(state->LCellOps); |
|
|
|
temp->lnext->lvalue = list->lvalue; |
|
|
|
temp->lnext->lnext = list->lnext; |
|
|
|
list->lnext = temp; |
|
|
|
list->lvalue = NULL; |
|
|
|
} |
|
|
|
} else { |
|
|
|
if(prev) { |
|
|
|
prev->lnext = temp; |
|
|
|
temp->lnext = NULL; |
|
|
|
} else { |
|
|
|
sol_obj_free(temp->lvalue); |
|
|
|
sol_obj_free(temp); |
|
|
|
sol_obj_free(sol_set_error_string(state, "Out-of-bounds insert")); |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
assert(!sol_validate_list(state, list)); |
|
|
|
if(idx<0 || idx>dsl_seq_len(list->seq)) return; |
|
|
|
dsl_seq_insert(list->seq, idx, obj); |
|
|
|
} |
|
|
|
|
|
|
|
sol_object_t *sol_list_remove(sol_state_t *state, sol_object_t *list, int idx) { |
|
|
|
sol_object_t *next = list, *prev = NULL, *res; |
|
|
|
int i = -1; |
|
|
|
if(sol_has_error(state)) return sol_incref(state->None); |
|
|
|
if(idx < 0) { |
|
|
|
return sol_set_error_string(state, "Remove from negative index"); |
|
|
|
} |
|
|
|
while(next) { |
|
|
|
if(next->lvalue) i++; |
|
|
|
if(i >= idx) break; |
|
|
|
prev = next; |
|
|
|
next = next->lnext; |
|
|
|
} |
|
|
|
if(next) { |
|
|
|
if(prev) { |
|
|
|
res = sol_incref(next->lvalue); |
|
|
|
prev->lnext = next->lnext; |
|
|
|
sol_obj_free(next); |
|
|
|
} else { |
|
|
|
res = sol_incref(list->lvalue); |
|
|
|
list->lvalue = NULL; |
|
|
|
} |
|
|
|
assert(!sol_validate_list(state, list)); |
|
|
|
return res; |
|
|
|
} else { |
|
|
|
return sol_set_error_string(state, "Out-of-bounds remove"); |
|
|
|
} |
|
|
|
if(idx<0 || idx>=dsl_seq_len(list->seq)) return sol_incref(state->None); |
|
|
|
return dsl_seq_remove(list->seq, idx); |
|
|
|
} |
|
|
|
|
|
|
|
sol_object_t *sol_list_copy(sol_state_t *state, sol_object_t *list) { |
|
|
|
sol_object_t *newls = sol_new_list(state), *cur = list; |
|
|
|
sol_object_t *res = newls; |
|
|
|
while(cur) { |
|
|
|
if(cur->lvalue) { |
|
|
|
newls->lvalue = sol_incref(cur->lvalue); |
|
|
|
newls->lnext = sol_alloc_object(state); |
|
|
|
if(sol_has_error(state)) return sol_incref(state->None); |
|
|
|
newls = newls->lnext; |
|
|
|
newls->type = SOL_LCELL; |
|
|
|
newls->ops = &(state->LCellOps); |
|
|
|
newls->lvalue = NULL; |
|
|
|
newls->lnext = NULL; |
|
|
|
} |
|
|
|
cur = cur->lnext; |
|
|
|
} |
|
|
|
return res; |
|
|
|
return sol_list_from_seq(state, dsl_seq_copy(list->seq)); |
|
|
|
} |
|
|
|
|
|
|
|
sol_object_t *sol_list_truncate(sol_state_t *state, sol_object_t *list, int len) { |
|
|
|
sol_object_t *newls = sol_new_list(state), *cur = list; |
|
|
|
sol_object_t *res = newls; |
|
|
|
int i = 0; |
|
|
|
while(cur && i<len) { |
|
|
|
if(cur->lvalue) { |
|
|
|
newls->lvalue = sol_incref(cur->lvalue); |
|
|
|
newls->lnext = sol_alloc_object(state); |
|
|
|
if(sol_has_error(state)) return sol_incref(state->None); |
|
|
|
newls = newls->lnext; |
|
|
|
newls->type = SOL_LCELL; |
|
|
|
newls->ops = &(state->LCellOps); |
|
|
|
newls->lvalue = NULL; |
|
|
|
newls->lnext = NULL; |
|
|
|
i++; |
|
|
|
dsl_seq *newseq = dsl_seq_copy(list->seq); |
|
|
|
dsl_seq_iter *iter = dsl_new_seq_iter(newseq); |
|
|
|
int pos = dsl_seq_iter_seek(iter, len); |
|
|
|
int sz = dsl_seq_len(newseq); |
|
|
|
int i; |
|
|
|
if(pos>=len) { |
|
|
|
for(i=0; i<sz-pos; i++) { |
|
|
|
dsl_seq_iter_delete_at(iter); |
|
|
|
} |
|
|
|
cur = cur->lnext; |
|
|
|
} |
|
|
|
return res; |
|
|
|
dsl_free_seq_iter(iter); |
|
|
|
return sol_list_from_seq(state, newseq); |
|
|
|
} |
|
|
|
|
|
|
|
void sol_list_append(sol_state_t *state, sol_object_t *dest, sol_object_t *src) { |
|
|
|
sol_object_t *curd = dest, *curs = src; |
|
|
|
while(curd->lnext) curd = curd->lnext; |
|
|
|
while(curs) { |
|
|
|
if(curs->lvalue) { |
|
|
|
curd->lvalue = sol_incref(curs->lvalue); |
|
|
|
curd->lnext = sol_alloc_object(state); |
|
|
|
if(sol_has_error(state)) return; |
|
|
|
curd = curd->lnext; |
|
|
|
curd->type = SOL_LCELL; |
|
|
|
curd->ops = &(state->LCellOps); |
|
|
|
curd->lnext = NULL; |
|
|
|
curd->lvalue = NULL; |
|
|
|
} |
|
|
|
curs = curs->lnext; |
|
|
|
} |
|
|
|
dsl_seq *oldseq = dest->seq; |
|
|
|
dest->seq = dsl_seq_append(dest->seq, src->seq); |
|
|
|
dsl_free_seq(oldseq); |
|
|
|
} |
|
|
|
|
|
|
|
sol_object_t *sol_f_list_free(sol_state_t *state, sol_object_t *list) { |
|
|
|
sol_object_t *cur = list, *prev; |
|
|
|
while(cur) { |
|
|
|
prev = cur; |
|
|
|
cur = cur->lnext; |
|
|
|
if(prev!=list) sol_obj_free(prev); |
|
|
|
} |
|
|
|
return list; |
|
|
|
dsl_free_seq(list->seq); |
|
|
|
return list; |
|
|
|
} |
|
|
|
|
|
|
|
sol_object_t *sol_f_lcell_free(sol_state_t *state, sol_object_t *lcell) { |
|
|
|
if(lcell->lvalue) sol_obj_free(lcell->lvalue); |
|
|
|
return lcell; |
|
|
|
} |
|
|
|
|
|
|
|
int sol_test_cycle(sol_state_t *state, sol_object_t *seq) { |
|
|
|
/*int sol_test_cycle(sol_state_t *state, sol_object_t *seq) { |
|
|
|
sol_object_t *seen[1024]={}; |
|
|
|
sol_object_t *cur = seq, **item; |
|
|
|
while(cur) { |
|
|
@ -424,7 +270,7 @@ int sol_validate_list(sol_state_t *state, sol_object_t *list) { |
|
|
|
snprintf(msg, 128, "Node at index %d has a next node but NULL value", i); |
|
|
|
sol_obj_free(sol_set_error_string(state, msg)); |
|
|
|
return 1; |
|
|
|
}*/ |
|
|
|
}*//* |
|
|
|
cur = cur->lnext; |
|
|
|
i++; |
|
|
|
} |
|
|
@ -434,60 +280,71 @@ int sol_validate_list(sol_state_t *state, sol_object_t *list) { |
|
|
|
return 1; |
|
|
|
} |
|
|
|
return 0; |
|
|
|
} |
|
|
|
}*/ |
|
|
|
|
|
|
|
sol_object_t *sol_new_map(sol_state_t *state) { |
|
|
|
sol_object_t *map = sol_alloc_object(state); |
|
|
|
if(sol_has_error(state)) return sol_incref(state->None); |
|
|
|
map->type = SOL_MAP; |
|
|
|
map->ops = &(state->MapOps); |
|
|
|
map->mkey = NULL; |
|
|
|
map->mval = NULL; |
|
|
|
map->mnext = NULL; |
|
|
|
map->seq = dsl_seq_new_array(NULL, &(state->obfuncs)); |
|
|
|
return map; |
|
|
|
} |
|
|
|
|
|
|
|
sol_object_t *sol_map_from_seq(sol_state_t *state, dsl_seq *seq) { |
|
|
|
sol_object_t *map = sol_alloc_object(state); |
|
|
|
if(sol_has_error(state)) return sol_incref(state->None); |
|
|
|
map->type = SOL_MAP; |
|
|
|
map->ops = &(state->MapOps); |
|
|
|
map->seq = seq; |
|
|
|
return map; |
|
|
|
} |
|
|
|
|
|
|
|
int sol_map_len(sol_state_t *state, sol_object_t *map) { |
|
|
|
int i = 0; |
|
|
|
sol_object_t *cur = map; |
|
|
|
while(cur) { |
|
|
|
if(cur->mkey) i++; |
|
|
|
cur = cur->mnext; |
|
|
|
} |
|
|
|
return i; |
|
|
|
return dsl_seq_len(map->seq); |
|
|
|
} |
|
|
|
|
|
|
|
sol_object_t *sol_map_mcell(sol_state_t *state, sol_object_t *map, sol_object_t *key) { |
|
|
|
sol_object_t *list = sol_new_list(state), *res = NULL, *cur = map, *cmp; |
|
|
|
sol_object_t *list = sol_new_list(state), *cmp, *icmp, *res = NULL; |
|
|
|
dsl_seq_iter *iter = dsl_new_seq_iter(map->seq); |
|
|
|
if(sol_has_error(state)) { |
|
|
|
dsl_free_seq_iter(iter); |
|
|
|
sol_obj_free(list); |
|
|
|
return sol_incref(state->None); |
|
|
|
} |
|
|
|
sol_list_insert(state, list, 0, key); |
|
|
|
while(cur) { |
|
|
|
if(cur->mkey) { |
|
|
|
sol_list_insert(state, list, 1, cur->mkey); |
|
|
|
cmp = sol_cast_int(state, key->ops->cmp(state, list)); |
|
|
|
sol_list_remove(state, list, 1); |
|
|
|
if(cmp->ival == 0) { |
|
|
|
res = cur; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
cur = cur->mnext; |
|
|
|
} |
|
|
|
if(res) { |
|
|
|
return sol_incref(res); |
|
|
|
} else { |
|
|
|
return sol_incref(state->None); |
|
|
|
} |
|
|
|
sol_list_insert(state, list, 1, state->None); |
|
|
|
if(!dsl_seq_iter_is_invalid(iter)) do { |
|
|
|
sol_list_set_index(state, list, 1, AS_OBJ(dsl_seq_iter_at(iter))->key); |
|
|
|
cmp = key->ops->cmp(state, list); |
|
|
|
icmp = sol_cast_int(state, cmp); |
|
|
|
sol_obj_free(cmp); |
|
|
|
if(icmp->ival == 0) { |
|
|
|
res = AS_OBJ(dsl_seq_iter_at(iter)); |
|
|
|
} |
|
|
|
sol_obj_free(icmp); |
|
|
|
} while(dsl_seq_iter_next(iter)); |
|
|
|
dsl_free_seq_iter(iter); |
|
|
|
sol_obj_free(list); |
|
|
|
if(res) { |
|
|
|
return res; |
|
|
|
} |
|
|
|
return sol_incref(state->None); |
|
|
|
} |
|
|
|
|
|
|
|
int sol_map_has(sol_state_t *state, sol_object_t *map, sol_object_t *key) { |
|
|
|
sol_object_t *mcell = sol_map_mcell(state, map, key); |
|
|
|
int res = sol_is_none(state, mcell); |
|
|
|
sol_obj_free(mcell); |
|
|
|
return res; |
|
|
|
} |
|
|
|
|
|
|
|
sol_object_t *sol_map_get(sol_state_t *state, sol_object_t *map, sol_object_t *key) { |
|
|
|
sol_object_t *submap = sol_map_mcell(state, map, key); |
|
|
|
sol_object_t *res; |
|
|
|
if(sol_is_map(submap)) { |
|
|
|
res = sol_incref(submap->mval); |
|
|
|
return res; |
|
|
|
} else { |
|
|
|
return sol_incref(state->None); |
|
|
|
} |
|
|
|
sol_object_t *mcell = sol_map_mcell(state, map, key); |
|
|
|
if(sol_is_none(state, mcell)) { |
|
|
|
return mcell; |
|
|
|
} |
|
|
|
return sol_incref(mcell->val); |
|
|
|
} |
|
|
|
|
|
|
|
sol_object_t *sol_map_get_name(sol_state_t *state, sol_object_t *map, char *name) { |
|
|
@ -498,43 +355,20 @@ sol_object_t *sol_map_get_name(sol_state_t *state, sol_object_t *map, char *name |
|
|
|
} |
|
|
|
|
|
|
|
void sol_map_set(sol_state_t *state, sol_object_t *map, sol_object_t *key, sol_object_t *val) { |
|
|
|
sol_object_t *cur = map, *prev = NULL, *list = sol_new_list(state), *cmp; |
|
|
|
sol_list_insert(state, list, 0, key); |
|
|
|
while(cur) { |
|
|
|
if(cur->mkey) { |
|
|
|
sol_list_insert(state, list, 1, cur->mkey); |
|
|
|
cmp = sol_cast_int(state, key->ops->cmp(state, list)); |
|
|
|
sol_list_remove(state, list, 1); |
|
|
|
if(cmp->ival == 0) { |
|
|
|
if(sol_is_none(state, val)) { |
|
|
|
if(prev) { |
|
|
|
prev->mnext = cur->mnext; |
|
|
|
sol_obj_free(cur); |
|
|
|
} else { |
|
|
|
sol_obj_free(cur->mkey); |
|
|
|
sol_obj_free(cur->mval); |
|
|
|
cur->mkey = NULL; |
|
|
|
cur->mval = NULL; |
|
|
|
} |
|
|
|
} else { |
|
|
|
sol_obj_free(cur->mval); |
|
|
|
cur->mval = sol_incref(val); |
|
|
|
} |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
prev = cur; |
|
|
|
cur = cur->mnext; |
|
|
|
} |
|
|
|
if(sol_is_none(state, val)) return; |
|
|
|
prev->mnext = sol_alloc_object(state); |
|
|
|
if(sol_has_error(state)) return; |
|
|
|
cur = prev->mnext; |
|
|
|
cur->type = SOL_MCELL; |
|
|
|
cur->ops = &(state->MCellOps); |
|
|
|
cur->mkey = sol_incref(key); |
|
|
|
cur->mval = sol_incref(val); |
|
|
|
cur->mnext = NULL; |
|
|
|
sol_object_t *mcell =sol_map_mcell(state, map, key), *newcell, *temp; |
|
|
|
if(sol_is_none(state, mcell)) { |
|
|
|
newcell = sol_alloc_object(state); |
|
|
|
newcell->type = SOL_MCELL; |
|
|
|
newcell->ops = &(state->MCellOps); |
|
|
|
newcell->key = sol_incref(key); |
|
|
|
newcell->val = sol_incref(val); |
|
|
|
dsl_seq_insert(map->seq, 0, newcell); |
|
|
|
sol_obj_free(newcell); |
|
|
|
} else { |
|
|
|
temp = mcell->val; |
|
|
|
mcell->val = sol_incref(val); |
|
|
|
sol_obj_free(temp); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void sol_map_set_name(sol_state_t *state, sol_object_t *map, char *name, sol_object_t *val) { |
|
|
@ -544,96 +378,46 @@ void sol_map_set_name(sol_state_t *state, sol_object_t *map, char *name, sol_obj |
|
|
|
} |
|
|
|
|
|
|
|
void sol_map_set_existing(sol_state_t *state, sol_object_t *map, sol_object_t *key, sol_object_t *val) { |
|
|
|
sol_object_t *cur = map, *prev = NULL, *list = sol_new_list(state), *cmp; |
|
|
|
sol_list_insert(state, list, 0, key); |
|
|
|
while(cur) { |
|
|
|
if(cur->mkey) { |
|
|
|
sol_list_insert(state, list, 1, cur->mkey); |
|
|
|
cmp = sol_cast_int(state, key->ops->cmp(state, list)); |
|
|
|
sol_list_remove(state, list, 1); |
|
|
|
if(cmp->ival == 0) { |
|
|
|
if(sol_is_none(state, val)) { |
|
|
|
if(prev) { |
|
|
|
prev->mnext = cur->mnext; |
|
|
|
sol_obj_free(cur); |
|
|
|
} else { |
|
|
|
sol_obj_free(cur->mkey); |
|
|
|
sol_obj_free(cur->mval); |
|
|
|
cur->mkey = NULL; |
|
|
|
cur->mval = NULL; |
|
|
|
} |
|
|
|
} else { |
|
|
|
sol_obj_free(cur->mval); |
|
|
|
cur->mval = sol_incref(val); |
|
|
|
} |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
prev = cur; |
|
|
|
cur = cur->mnext; |
|
|
|
} |
|
|
|
sol_object_t *mcell =sol_map_mcell(state, map, key), *temp; |
|
|
|
if(!sol_is_none(state, mcell)) { |
|
|
|
temp = mcell->val; |
|
|
|
mcell->val = sol_incref(val); |
|
|
|
sol_obj_free(temp); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
sol_object_t *sol_map_copy(sol_state_t *state, sol_object_t *map) { |
|
|
|
sol_object_t *newmap = sol_new_map(state), *newcur = newmap, *cur = map; |
|
|
|
while(cur) { |
|
|
|
if(cur->mkey) { |
|
|
|
newcur->mkey = sol_incref(cur->mkey); |
|
|
|
newcur->mval = sol_incref(cur->mval); |
|
|
|
newcur->mnext = sol_alloc_object(state); |
|
|
|
newcur = newcur->mnext; |
|
|
|
newcur->type = SOL_MCELL; |
|
|
|
newcur->ops = &(state->MCellOps); |
|
|
|
newcur->mkey = NULL; |
|
|
|
newcur->mval = NULL; |
|
|
|
newcur->mnext = NULL; |
|
|
|
} |
|
|
|
cur = cur->mnext; |
|
|
|
} |
|
|
|
return newmap; |
|
|
|
return sol_map_from_seq(state, dsl_seq_copy(map->seq)); |
|
|
|
} |
|
|
|
|
|
|
|
void sol_map_merge(sol_state_t *state, sol_object_t *dest, sol_object_t *src) { |
|
|
|
sol_object_t *cur = src; |
|
|
|
while(cur) { |
|
|
|
if(cur->mkey) { |
|
|
|
sol_map_set(state, dest, cur->mkey, cur->mval); |
|
|
|
} |
|
|
|
cur = cur->mnext; |
|
|
|
} |
|
|
|
dsl_seq_iter *iter = dsl_new_seq_iter(src->seq); |
|
|
|
if(!dsl_seq_iter_is_invalid(iter)) do { |
|
|
|
sol_map_set(state, dest, AS_OBJ(dsl_seq_iter_at(iter))->key, AS_OBJ(dsl_seq_iter_at(iter))->val); |
|
|
|
} while(dsl_seq_iter_next(iter)); |
|
|
|
dsl_free_seq_iter(iter); |
|
|
|
} |
|
|
|
|
|
|
|
void sol_map_merge_existing(sol_state_t *state, sol_object_t *dest, sol_object_t *src) { |
|
|
|
sol_object_t *cur = src; |
|
|
|
while(cur) { |
|
|
|
if(cur->mkey) { |
|
|
|
sol_map_set_existing(state, dest, cur->mkey, cur->mval); |
|
|
|
} |
|
|
|
cur = cur->mnext; |
|
|
|
} |
|
|
|
dsl_seq_iter *iter = dsl_new_seq_iter(src->seq); |
|
|
|
if(!dsl_seq_iter_is_invalid(iter)) do { |
|
|
|
sol_map_set_existing(state, dest, AS_OBJ(dsl_seq_iter_at(iter))->key, AS_OBJ(dsl_seq_iter_at(iter))->val); |
|
|
|
} while(dsl_seq_iter_next(iter)); |
|
|
|
dsl_free_seq_iter(iter); |
|
|
|
} |
|
|
|
|
|
|
|
sol_object_t *sol_f_map_free(sol_state_t *state, sol_object_t *map) { |
|
|
|
sol_object_t *cur = map, *prev; |
|
|
|
while(cur) { |
|
|
|
if(cur->mkey) { |
|
|
|
sol_obj_free(cur->mkey); |
|
|
|
sol_obj_free(cur->mval); |
|
|
|
} |
|
|
|
prev = cur; |
|
|
|
cur = cur->mnext; |
|
|
|
if(prev!=map) free(prev); |
|
|
|
} |
|
|
|
dsl_free_seq(map->seq); |
|
|
|
return map; |
|
|
|
} |
|
|
|
|
|
|
|
sol_object_t *sol_f_mcell_free(sol_state_t *state, sol_object_t *mcell) { |
|
|
|
if(mcell->mkey) sol_obj_free(mcell->mkey); |
|
|
|
if(mcell->mval) sol_obj_free(mcell->mval); |
|
|
|
if(mcell->key) sol_obj_free(mcell->key); |
|
|
|
if(mcell->val) sol_obj_free(mcell->val); |
|
|
|
return mcell; |
|
|
|
} |
|
|
|
|
|
|
|
int sol_validate_map(sol_state_t *state, sol_object_t *map) { |
|
|
|
/*int sol_validate_map(sol_state_t *state, sol_object_t *map) { |
|
|
|
sol_object_t *cur = map; |
|
|
|
int i = 0; |
|
|
|
char msg[128]; |
|
|
@ -652,7 +436,7 @@ int sol_validate_map(sol_state_t *state, sol_object_t *map) { |
|
|
|
i++; |
|
|
|
} |
|
|
|
return 0; |
|
|
|
} |
|
|
|
}*/ |
|
|
|
|
|
|
|
sol_object_t *sol_new_cfunc(sol_state_t *state, sol_cfunc_t cfunc) { |
|
|
|
sol_object_t *res = sol_alloc_object(state); |
|
|
@ -669,3 +453,28 @@ sol_object_t *sol_new_cdata(sol_state_t *state, void *cdata, sol_ops_t *ops) { |
|
|
|
res->cdata = cdata; |
|
|
|
return res; |
|
|
|
} |
|
|
|
|
|
|
|
sol_object_t *sol_new_buffer(sol_state_t *state, void *buffer, ssize_t sz, sol_owntype_t own, sol_freefunc_t freef, sol_movefunc_t movef) { |
|
|
|
sol_object_t *res = sol_alloc_object(state); |
|
|
|
res->type = SOL_BUFFER; |
|
|
|
res->ops = &(state->BufferOps); |
|
|
|
res->buffer = buffer; |
|
|
|
res->sz = sz; |
|
|
|
res->own = own; |
|
|
|
res->freef = freef; |
|
|
|
res->movef = movef; |
|
|
|
return res; |
|
|
|
} |
|
|
|
|
|
|
|
sol_object_t *sol_f_buffer_free(sol_state_t *state, sol_object_t *buf) { |
|
|
|
switch(buf->own) { |
|
|
|
case OWN_FREE: |
|
|
|
free(buf->buffer); |
|
|
|
break; |
|
|
|
|
|
|
|
case OWN_CALLF: |
|
|
|
buf->freef(buf->buffer, buf->sz); |
|
|
|
break; |
|
|
|
} |
|
|
|
return buf; |
|
|
|
} |