commit
26cebb751e
4 changed files with 1074 additions and 0 deletions
-
389builtins.c
-
161object.c
-
266sol.h
-
258state.c
@ -0,0 +1,389 @@ |
|||
#include <string.h> |
|||
#include <stdlib.h> |
|||
#include "sol.h" |
|||
|
|||
// This is supposedly a C99 trick. |
|||
|
|||
static char *_itoa(int i) { |
|||
int n = sprintf(NULL, "%d", i) + 1; |
|||
char *s = malloc(n) |
|||
snprintf(s, n, "%d", i); |
|||
return s; |
|||
} |
|||
|
|||
static char *_ftoa(double f) { |
|||
int n = sprintf(NULL, "%f", f) + 1; |
|||
char *s = malloc(n) |
|||
snprintf(s, n, "%f", f); |
|||
return s; |
|||
} |
|||
|
|||
sol_object_t *sol_f_not_impl(sol_state_t *state, sol_object_t *args) { |
|||
return sol_set_error_string(state, "Undefined method"); |
|||
} |
|||
|
|||
sol_object_t *sol_f_no_op(sol_state_t *state, sol_object *args) { |
|||
return sol_incref(state->None); |
|||
} |
|||
|
|||
sol_object_t *sol_f_toint(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *obj = sol_list_get_index(state, args, 0); |
|||
sol_object_t *res = obj->ops->toint(state, args); |
|||
sol_obj_free(obj); |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_tofloat(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *obj = sol_list_get_index(state, args, 0); |
|||
sol_object_t *res = obj->ops->tofloat(state, args); |
|||
sol_obj_free(obj); |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_tostring(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *obj = sol_list_get_index(state, args, 0); |
|||
sol_object_t *res = obj->ops->tostring(state, args); |
|||
sol_obj_free(obj); |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_try(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *func = sol_list_get_index(state, args, 0), fargs = sol_list_sublist(state, args, 1); |
|||
sol_object_t *ls = sol_new_list(state), *one = sol_new_int(state, 1); |
|||
sol_object_t *res = func->ops->call(state, fargs); |
|||
sol_obj_free(func); |
|||
sol_obj_free(fargs); |
|||
if(sol_has_error(state)) { |
|||
sol_object_t *err = sol_get_error(state); |
|||
sol_object_t *zero = sol_new_int(state, 0); |
|||
sol_object_free(res); |
|||
sol_object_free(one); |
|||
sol_clear_error(state); |
|||
sol_list_insert(state, ls, 0, err); |
|||
sol_obj_free(err); |
|||
sol_list_insert(state, ls, 0, zero); |
|||
sol_obj_free(zero); |
|||
return ls; |
|||
} |
|||
sol_list_insert(state, ls, 0, res); |
|||
sol_obj_free(res); |
|||
sol_list_insert(state, ls, 0, one); |
|||
sol_obj_free(one); |
|||
return ls; |
|||
} |
|||
|
|||
sol_object_t *sol_f_int_add(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_int(state, sol_list_get_index(state, args, 1)); |
|||
sol_object_t *res = sol_new_int(state, a->ival + b->ival); |
|||
sol_obj_free(a); |
|||
sol_obj_free(b); |
|||
if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);} |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_int_sub(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_int(state, sol_list_get_index(state, args, 1)); |
|||
sol_object_t *res = sol_new_int(state, a->ival - b->ival); |
|||
sol_obj_free(a); |
|||
sol_obj_free(b); |
|||
if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);} |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_int_mul(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_int(state, sol_list_get_index(state, args, 1)); |
|||
sol_object_t *res = sol_new_int(state, a->ival * b->ival); |
|||
sol_obj_free(a); |
|||
sol_obj_free(b); |
|||
if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);} |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_int_div(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_int(state, sol_list_get_index(state, args, 1)); |
|||
sol_object_t *res = sol_new_int(state, a->ival / b->ival); |
|||
sol_obj_free(a); |
|||
sol_obj_free(b); |
|||
if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);} |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_int_band(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_int(state, sol_list_get_index(state, args, 1)); |
|||
sol_object_t *res = sol_new_int(state, a->ival & b->ival); |
|||
sol_obj_free(a); |
|||
sol_obj_free(b); |
|||
if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);} |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_int_bor(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_int(state, sol_list_get_index(state, args, 1))); |
|||
sol_object_t *res = sol_new_int(state, a->ival | b->ival); |
|||
sol_obj_free(a); |
|||
sol_obj_free(b); |
|||
if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);} |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_int_bxor(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_int(state, sol_list_get_index(state, args, 1)); |
|||
sol_object_t *res = sol_new_int(state, a->ival ^ b->ival); |
|||
sol_obj_free(a); |
|||
sol_obj_free(b); |
|||
if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);} |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_int_bnot(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *a = sol_list_get_index(state, args, 0); |
|||
sol_object_t *res = sol_new_int(state, ~a->ival); |
|||
sol_obj_free(a); |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_int_toint(sol_state_t *state, sol_object_t *args) { |
|||
return sol_list_get_index(state, args, 0); |
|||
} |
|||
|
|||
sol_object_t *sol_f_int_tofloat(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *a = sol_list_get_index(state, args, 0); |
|||
sol_object_t *res = sol_new_float(state, (double) a->ival); |
|||
sol_obj_free(a); |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_int_tostring(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *a = sol_list_get_index(state, args, 0); |
|||
char *s = _itoa(a->ival); |
|||
sol_object_t *res = sol_new_string(state, s); |
|||
sol_obj_free(a); |
|||
free(s); |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_float_add(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_float(state, sol_list_get_index(state, args, 1)); |
|||
sol_object_t *res = sol_new_float(state, a->fval + b->fval); |
|||
sol_obj_free(a); |
|||
sol_obj_free(b); |
|||
if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);} |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_float_sub(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_float(state, sol_list_get_index(state, args, 1)); |
|||
sol_object_t *res = sol_new_float(state, a->fval - b->fval); |
|||
sol_obj_free(a); |
|||
sol_obj_free(b); |
|||
if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);} |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_float_mul(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_float(state, sol_list_get_index(state, args, 1))); |
|||
sol_object_t *res = sol_new_float(state, a->fval * b->fval); |
|||
sol_obj_free(a); |
|||
sol_obj_free(b); |
|||
if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);} |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_float_div(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_float(state, sol_list_get_index(state, args, 1)); |
|||
sol_object_t *res = sol_new_float(state, a->fval / b->fval); |
|||
sol_obj_free(a); |
|||
sol_obj_free(b); |
|||
if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);} |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_float_toint(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *a = sol_list_get_index(state, args, 0); |
|||
sol_object_t *res = sol_new_int(state, (int) a->fval); |
|||
sol_obj_free(a); |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_float_tofloat(sol_state_t *state, sol_object_t *args) { |
|||
return sol_list_get_index(state, args, 0) |
|||
} |
|||
|
|||
sol_object_t *sol_f_float_tostring(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *a = sol_list_get_index(state, args, 0); |
|||
char *s = _ftoa(a->fval); |
|||
sol_object_t *res = sol_new_string(state, s); |
|||
sol_obj_free(a); |
|||
free(s); |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_str_add(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_string(state, sol_list_get_index(state, args, 1))); |
|||
int n = strlen(a->str) + strlen(b->str) + 1; |
|||
char *s = malloc(n); |
|||
sol_object_t *res = sol_new_string(state, strncat(strncpy(s, n, a->str), n, b->str)); |
|||
sol_obj_free(a); |
|||
sol_obj_free(b); |
|||
free(s); |
|||
if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);} |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_str_mul(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_int(state, sol_list_get_index(state, args, 1)); |
|||
int n = strlen(a->str) * b->ival + 1; |
|||
char *s = malloc(n); |
|||
int i; |
|||
s[0]='\0'; |
|||
for(i = 0; i < b->ival; i++) strncat(s, n, a->str); |
|||
sol_object_t *res = sol_new_string(state, s); |
|||
sol_obj_free(a); |
|||
sol_obj_free(b); |
|||
free(s); |
|||
if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);} |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_str_len(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *a = sol_list_get_index(state, args, 0); |
|||
sol_object_t *ret = sol_new_int(state, strlen(a->str)); |
|||
sol_obj_free(a); |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_str_toint(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *a = sol_list_get_index(state, args, 0); |
|||
sol_object_t *ret = sol_new_int(state, atoi(a->str)); |
|||
sol_obj_free(a); |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_str_tofloat(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *a = sol_list_get_index(state, args, 0); |
|||
sol_object_t *ret = sol_new_float(state, atof(a->str)); |
|||
sol_obj_free(a); |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_str_tostring(sol_state_t *state, sol_object_t *args) { |
|||
return sol_list_get_index(state, args, 0) |
|||
} |
|||
|
|||
sol_object_t *sol_f_list_add(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *ls; |
|||
if(!sol_is_list(b)) { |
|||
sol_obj_free(a); |
|||
sol_obj_free(b); |
|||
return sol_set_error_string(state, "Adding list to non-list"); |
|||
} |
|||
ls = sol_list_copy(state, a); |
|||
sol_list_append(state, ls, b); |
|||
sol_obj_free(a); |
|||
sol_obj_free(b); |
|||
return ls; |
|||
} |
|||
|
|||
sol_object_t *sol_f_list_mul(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_int(state, sol_list_get_index(state, args, 1)), *ls; |
|||
int i; |
|||
if(sol_has_error(state)) { |
|||
sol_obj_free(a); |
|||
sol_obj_free(b); |
|||
return sol_incref(state->None); |
|||
} |
|||
ls = sol_new_list(state); |
|||
for(i = 0; i < b->ival; i++) { |
|||
sol_list_append(state, ls, a); |
|||
if(sol_has_error(state)) { |
|||
sol_obj_free(a); |
|||
sol_obj_free(b); |
|||
return sol_incref(state->None); |
|||
} |
|||
} |
|||
return ls; |
|||
} |
|||
|
|||
sol_object_t *sol_f_list_index(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *ls = sol_list_get_index(state, args, 0), *b = sol_cast_int(state, sol_list_get_index(state, args, 1)); |
|||
sol_object_t *res = sol_list_get_index(state, ls, b->ival); |
|||
sol_obj_free(ls); |
|||
sol_obj_free(b); |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_list_setindex(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *ls = sol_list_get_index(state, args, 0), *b = sol_cast_int(state, sol_list_get_index(state, args ,1)); |
|||
sol_objcet_t *val = sol_list_get_index(state, args, 2); |
|||
sol_list_set_index(state, ls, b->ival, val); |
|||
sol_obj_free(ls); |
|||
sol_obj_free(b); |
|||
sol_obj_free(val); |
|||
return sol_incref(state->None); |
|||
} |
|||
|
|||
sol_object_t *sol_f_list_len(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *ls = sol_list_get_index(state, args, 0); |
|||
sol_object_t *res = sol_new_int(state, sol_list_len(state, ls)); |
|||
sol_obj_free(ls); |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_list_tostring(sol_state_t *state, sol_object_t *args) { |
|||
return sol_new_string(state, "<List>"); |
|||
} |
|||
|
|||
sol_object_t *sol_f_map_add(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *map; |
|||
if(!sol_is_map(b)) { |
|||
sol_obj_free(a); |
|||
sol_obj_free(b); |
|||
return sol_set_error_string(state, "Adding map to non-map"); |
|||
} |
|||
map = sol_map_copy(state, a); |
|||
sol_map_merge(state, map, b); |
|||
sol_obj_free(a); |
|||
sol_obj_free(b); |
|||
return map; |
|||
} |
|||
|
|||
sol_object_t *sol_f_map_index(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *map = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1); |
|||
sel_object_t *res = sol_map_get(state, map, b); |
|||
sol_obj_free(map); |
|||
sol_obj_free(b); |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_map_setindex(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *map = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1); |
|||
sol_object_t *val = sol_list_get_index(state, args, 2); |
|||
sol_map_set(state, map, b, val); |
|||
sol_obj_free(map); |
|||
sol_obj_free(b); |
|||
sol_obj_free(val); |
|||
return sol_incref(state->None); |
|||
} |
|||
|
|||
sol_object_t *sol_f_map_len(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *map = sol_list_get_index(sate, args, 0); |
|||
sol_object_t *res = sol_new_int(state, sol_map_len(state, map)); |
|||
sol_obj_free(map); |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_map_tostring(sol_state_t *state, sol_object_t *args) { |
|||
return sol_new_string(state, "<Map>"); |
|||
} |
|||
|
|||
sol_object_t *sol_f_func_call(sol_state_t *state, sol_object_t *args) { |
|||
sol_object_t *func = sol_list_get_index(state, args, 0), *fargs = sol_list_sublist(state, args, 1); |
|||
sol_object_t *res = func->func(state, fargs); |
|||
sol_obj_free(func); |
|||
sol_obj_free(fargs); |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_func_tostring(sol_state_t *state, sol_object_t *args) { |
|||
return sol_new_string(state, "<Function>"); |
|||
} |
@ -0,0 +1,161 @@ |
|||
#include "sol.h" |
|||
|
|||
sol_object_t *sol_cast_int(sol_state_t *state, sol_object_t *obj) { |
|||
sol_object_t *res, *ls; |
|||
if(sol_is_int(obj)) return obj; |
|||
ls = sol_new_list(state); |
|||
sol_list_insert(state, ls, 0, obj); |
|||
res = obj->ops->toint(state, ls); |
|||
sol_obj_free(ls); |
|||
sol_obj_free(obj); |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_cast_float(sol_state_t *state, sol_object_t *obj) { |
|||
sol_object_t *res, *ls; |
|||
if(sol_is_float(obj)) return obj; |
|||
ls = sol_new_list(state); |
|||
sol_list_insert(state, ls, 0, obj); |
|||
res = obj->ops->tofloat(state, ls); |
|||
sol_obj_free(ls); |
|||
sol_obj_free(obj); |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_cast_string(sol_state_t *state, sol_object_t *obj) { |
|||
sol_object_t *res, *ls; |
|||
if(sol_is_string(obj)) return obj; |
|||
ls = sol_new_list(state); |
|||
sol_list_insert(state, ls, 0, obj); |
|||
res = obj->ops->tostring(state, ls); |
|||
sol_obj_free(ls); |
|||
sol_obj_free(obj); |
|||
return res; |
|||
} |
|||
|
|||
// 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 *res = malloc(sizeof(sol_object_t)); |
|||
if(res) { |
|||
res->type = SOL_SINGLET; |
|||
res->refcnt = 0; |
|||
res->ops = &(state->NullOps); |
|||
} |
|||
return sol_incref(res); |
|||
} |
|||
|
|||
// And, now, for the rest of the checked stuff... |
|||
|
|||
sol_object_t *sol_alloc_object(sol_state_t *state) { |
|||
sol_object_t *res = malloc(sizeof(sol_object_t)); |
|||
if(!res) { |
|||
sol_set_error(state, state->OutOfMemory); |
|||
return sol_incref(state->None); |
|||
} |
|||
res->refcnt = 0; |
|||
res->ops = &(state->NullOps); |
|||
return sol_incref(res); |
|||
} |
|||
|
|||
void sol_init_object(sol_state_t *state, sol_object_t *obj) { |
|||
obj->ops->init(state, obj); |
|||
} |
|||
|
|||
void sol_obj_free(sol_object_t *obj) { |
|||
if(sol_decref(obj) <= 0) { |
|||
obj->ops->free(state, obj); |
|||
free(obj); |
|||
} |
|||
} |
|||
|
|||
sol_object_t *sol_new_int(sol_state_t *state, int i) { |
|||
sol_object_t *res = sol_alloc_object(state); |
|||
if(sol_has_error(state)) { |
|||
sol_obj_free(res); |
|||
return sol_incref(state->None); |
|||
} |
|||
res->type = SOL_INTEGER; |
|||
res->ival = i; |
|||
res->ops = &(state->IntOps); |
|||
sol_init_object(state, res); |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_new_float(sol_state_t *state, double f) { |
|||
sol_object_t *res = sol_alloc_object(state); |
|||
if(sol_has_error(state)) { |
|||
sol_obj_free(res); |
|||
return sol_incref(state->None); |
|||
} |
|||
res->type = SOL_FLOAT; |
|||
res->fval = f; |
|||
res->ops = &(state->FloatOps); |
|||
sol_init_object(state, res); |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_new_string(state, const char *s) { |
|||
sol_object_t *res = sol_alloc_object(state); |
|||
if(sol_has_error(state)) { |
|||
sol_obj_free(res); |
|||
return sol_incref(state->None); |
|||
} |
|||
res->type = SOL_STRING; |
|||
res->str = strdup(s); |
|||
if(!res->str) { |
|||
sol_obj_free(res); |
|||
sol_set_error(state, state->OutOfMemory); |
|||
return sol_incref(state->None); |
|||
} |
|||
res->ops = &(state->StringOps); |
|||
sol_init_object(state, res); |
|||
return res; |
|||
} |
|||
|
|||
sol_object_t *sol_f_str_free(sol_state_t *state, sol_object_t *obj) { |
|||
free(obj->str); |
|||
return obj; |
|||
} |
|||
|
|||
sol_object_t *sol_new_list(sol_state_t *) { |
|||
sol_object_t *res = sol_alloc_object(state); |
|||
if(sol_has_error(state)) { |
|||
sol_obj_free(res); |
|||
return sol_incref(state->None); |
|||
} |
|||
res->type = SOL_LIST; |
|||
res->lvalue = NULL; |
|||
res->lnext = NULL; |
|||
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)) { |
|||
return sol_set_error_string("Compute length of non-list"); |
|||
} |
|||
while(cur.lvalue) { |
|||
i++; |
|||
cur = cur.lnext; |
|||
} |
|||
return i; |
|||
} |
|||
|
|||
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; |
|||
if(idx < 0) { |
|||
return sol_set_error_string("Create sublist at negative index"); |
|||
} |
|||
while(cur && i < idx) { |
|||
i++; |
|||
cur = cur.lnext; |
|||
} |
|||
copy = sol_new_list(state); |
|||
while(cur) |
|||
} |
@ -0,0 +1,266 @@ |
|||
#ifndef SOL_H |
|||
#define SOL_H |
|||
|
|||
#define NULL 0 |
|||
|
|||
typedef enum { |
|||
SOL_IDENT, |
|||
SOL_KEYWORD, |
|||
SOL_INTEGER, |
|||
SOL_FLOAT, |
|||
SOL_STRING, |
|||
SOL_LPAREN, |
|||
SOL_RPAREN, |
|||
SOL_LBRACKET, |
|||
SOL_RBRACKET, |
|||
SOL_PLUS, |
|||
SOL_MINUS, |
|||
SOL_STAR, |
|||
SOL_SLASH, |
|||
SOL_EQUAL, |
|||
SOL_LESS, |
|||
SOL_GREATER, |
|||
SOL_LESSEQ, |
|||
SOL_GREATEREQ, |
|||
SOL_LOGICAND, |
|||
SOL_LOGICOR, |
|||
SOL_LOGICNOT, |
|||
SOL_BITAND, |
|||
SOL_BITOR, |
|||
SOL_BITNOT, |
|||
SOL_ASSIGN, |
|||
SOL_ASSIGNADD, |
|||
SOL_ASSIGNSUBTRACT, |
|||
SOL_ASSIGNMULTIPLY, |
|||
SOL_ASSIGNDIVIDE, |
|||
SOL_ASSIGNBITAND, |
|||
SOL_ASSIGNBITOR, |
|||
SOL_ASSIGNBITNOT, |
|||
SOL_DOT, |
|||
SOL_COLON; |
|||
} sol_toktype_t; |
|||
|
|||
extern const char *sol_Keywords[]={ |
|||
"if", "else", |
|||
"while", "for", |
|||
"end", |
|||
"break", "continue", |
|||
"return", |
|||
"func", |
|||
"local", |
|||
}; |
|||
|
|||
typedef struct { |
|||
sol_toktype_t type; |
|||
char *data; |
|||
} sol_token_t; |
|||
|
|||
typedef struct { |
|||
const char *p; |
|||
int lineno; |
|||
} sol_tokstream_t; |
|||
|
|||
// Forward declarations: |
|||
struct sol_tag_object_t; |
|||
typedef struct sol_tag_object_t sol_object_t; |
|||
|
|||
typedef sol_object_t *(*sol_cfunc_t)(sol_state_t *, sol_object_t *); |
|||
|
|||
typedef struct { |
|||
sol_cfunc_t add; |
|||
sol_cfunc_t sub; |
|||
sol_cfunc_t mul; |
|||
sol_cfunc_t div; |
|||
sol_cfunc_t band; |
|||
sol_cfunc_t bor; |
|||
sol_cfunc_t bxor; |
|||
sol_cfunc_t bnot; |
|||
sol_cfunc_t call; |
|||
sol_cfunc_t index; |
|||
sol_cfunc_t setindex; |
|||
sol_cfunc_t len; |
|||
sol_cfunc_t toint; |
|||
sol_cfunc_t tofloat; |
|||
sol_cfunc_t tostring; |
|||
sol_cfunc_t init; |
|||
sol_cfunc_t free; |
|||
} sol_ops_t; |
|||
|
|||
typedef enum { |
|||
SOL_SINGLET, |
|||
SOL_INTEGER, |
|||
SOL_FLOAT, |
|||
SOL_STRING, |
|||
SOL_LIST, |
|||
SOL_MAP, |
|||
SOL_FUNCTION, |
|||
} sol_objtype_t; |
|||
|
|||
typedef struct sol_tag_object_t { |
|||
sol_objtype_t type; |
|||
int refcnt; |
|||
sol_ops_t *ops; |
|||
union { |
|||
int ival; |
|||
double fval; |
|||
const char *str; |
|||
struct { |
|||
struct sol_tag_object_t *lvalue; |
|||
struct sol_tag_object_t *lnext; |
|||
}; |
|||
struct { |
|||
struct sol_tag_object_t *mkey; |
|||
struct sol_tag_object_t *mval; |
|||
struct sol_tag_object_t *mnext; |
|||
}; |
|||
sol_cfunc_t func; |
|||
}; |
|||
} sol_object_t; |
|||
|
|||
typedef struct { |
|||
sol_object_t *scopes; // A list of scope maps, innermost out, ending at the global scope |
|||
sol_object_t *error; // Some arbitrary error descriptor, sol_None if no error |
|||
sol_object_t *None; |
|||
sol_object_t *OutOfMemory; |
|||
sol_ops_t NullOps; |
|||
sol_ops_t IntOps; |
|||
sol_ops_t FloatOps; |
|||
sol_ops_t StringOps; |
|||
sol_ops_t ListOps; |
|||
sol_ops_t MapOps; |
|||
sol_ops_t FuncOps; |
|||
} sol_state_t; |
|||
|
|||
// state.c |
|||
|
|||
int sol_state_init(sol_state_t *); |
|||
void sol_state_cleanup(sol_state_t *) |
|||
|
|||
sol_object_t *sol_state_resolve(sol_state_t *, sol_object_t *); |
|||
sol_object_t *sol_state_resolve_name(sol_state_t *, const char *); |
|||
void sol_state_assign(sol_state_t *, sol_object_t *, sol_object_t *); |
|||
void sol_state_assign_name(sol_state_t *, const char *, sol_object_t *); |
|||
void sol_state_assign_l(sol_state_t *, sol_object_t *, sol_object_t *); |
|||
void sol_state_assign_l_name(sol_state_t *, const char *, sol_object_t *); |
|||
|
|||
sol_object_t *sol_get_error(sol_state_t *); |
|||
sol_object_t *sol_set_error(sol_state_t *, sol_object_t *); |
|||
sol_object_t *sol_set_error_string(sol_state_t *, const char *); |
|||
void sol_clear_error(sol_state_t *); |
|||
|
|||
// builtins.c |
|||
|
|||
extern sol_cfunc_t sol_f_not_impl; |
|||
extern sol_cfunc_t sol_f_no_op; |
|||
|
|||
extern sol_cfunc_t sol_f_toint; |
|||
extern sol_cfunc_t sol_f_tofloat; |
|||
extern sol_cfunc_t sol_f_tostring; |
|||
extern sol_cfunc_t sol_f_try; |
|||
|
|||
extern sol_cfunc_t sol_f_int_add; |
|||
extern sol_cfunc_t sol_f_int_sub; |
|||
extern sol_cfunc_t sol_f_int_mul; |
|||
extern sol_cfunc_t sol_f_int_div; |
|||
extern sol_cfunc_t sol_f_int_band; |
|||
extern sol_cfunc_t sol_f_int_bor; |
|||
extern sol_cfunc_t sol_f_int_bxor; |
|||
extern sol_cfunc_t sol_f_int_bnot; |
|||
extern sol_cfunc_t sol_f_int_toint; |
|||
extern sol_cfunc_t sol_f_int_tofloat; |
|||
extern sol_cfunc_t sol_f_int_tostring; |
|||
|
|||
extern sol_cfunc_t sol_f_float_add; |
|||
extern sol_cfunc_t sol_f_float_sub; |
|||
extern sol_cfunc_t sol_f_float_mul; |
|||
extern sol_cfunc_t sol_f_float_div; |
|||
extern sol_cfunc_t sol_f_float_toint; |
|||
extern sol_cfunc_t sol_f_float_tofloat; |
|||
extern sol_cfunc_t sol_f_float_tostring; |
|||
|
|||
extern sol_cfunc_t sol_f_str_add; |
|||
extern sol_cfunc_t sol_f_str_mul; |
|||
extern sol_cfunc_t sol_f_str_len; |
|||
extern sol_cfunc_t sol_f_str_toint; |
|||
extern sol_cfunc_t sol_f_str_tofloat; |
|||
extern sol_cfunc_t sol_f_str_tostring; |
|||
|
|||
extern sol_cfunc_t sol_f_list_add; |
|||
extern sol_cfunc_t sol_f_list_mul; |
|||
extern sol_cfunc_t sol_f_list_index; |
|||
extern sol_cfunc_t sol_f_list_setindex; |
|||
extern sol_cfunc_t sol_f_list_len; |
|||
extern sol_cfunc_t sol_f_list_tostring; |
|||
|
|||
extern sol_cfunc_t sol_f_map_add; |
|||
extern sol_cfunc_t sol_f_map_index; |
|||
extern sol_cfunc_t sol_f_map_setindex; |
|||
extern sol_cfunc_t sol_f_map_len; |
|||
extern sol_cfunc_t sol_f_map_tostring; |
|||
|
|||
extern sol_cfunc_t sol_f_func_call; |
|||
extern sol_cfunc_t sol_f_func_tostring; |
|||
|
|||
// object.c |
|||
|
|||
#define sol_incref(obj) (++((obj)->refcnt), obj) |
|||
#define sol_decref(obj) (--((obj)->refcnt)) |
|||
|
|||
void sol_obj_free(sol_object_t *); |
|||
void sol_obj_release(sol_object_t *); |
|||
|
|||
#define sol_is_singlet(obj) ((obj)->type == SOL_SINGLET) |
|||
#define sol_is_none(state, obj) ((obj) == state->sol_None) |
|||
#define sol_is_oom(state, obj) ((obj) == state->sol_OutOfMemory) |
|||
#define sol_is_int(obj) ((obj)-> type == SOL_INTEGER) |
|||
#define sol_is_float(obj) ((obj)->type == SOL_FLOAT) |
|||
#define sol_is_string(obj) ((obj)->type == SOL_STRING) |
|||
#define sol_is_list(obj) ((obj)->type == SOL_LIST) |
|||
#define sol_is_map(obj) ((obj)->type == SOL_MAP) |
|||
#define sol_is_func(obj) ((obj)->type == SOL_FUNCTION) |
|||
|
|||
#define sol_has_error(state) (!sol_is_none((state), (state)->error)) |
|||
|
|||
sol_object_t *sol_new_singlet(sol_state_t *); |
|||
sol_object_t *sol_new_int(sol_state_t *, int); |
|||
sol_object_t *sol_new_float(sol_state_t *, double); |
|||
sol_object_t *sol_new_string(sol_state_t *, const char *); |
|||
|
|||
sol_object_t *sol_new_list(sol_state_t *); |
|||
int sol_list_len(sol_state_t *, sol_object_t *); |
|||
sol_object_t *sol_list_sublist(sol_state_t *, sol_object_t *, int); |
|||
sol_object_t *sol_list_next(sol_state_t *, sol_object_t *); |
|||
sol_object_t *sol_list_get_index(sol_state_t *, sol_object_t *, int); |
|||
void sol_list_set_index(sol_state_t *, sol_object_t *, int, sol_object_t *); |
|||
void sol_list_insert(sol_state_t *, sol_object_t *, int, sol_object_t *); |
|||
void sol_list_remove(sol_state_t *, sol_object_t *, int); |
|||
sol_object_t *sol_list_copy(sol_state_t *, sol_object_t *); |
|||
void sol_list_append(sol_state_t *, sol_object_t *, sol_object_t *); |
|||
|
|||
sol_object_t *sol_new_map(sol_state_t *); |
|||
int sol_map_len(sol_state_t *, sol_object_t *); |
|||
sol_object_t *sol_map_submap(sol_state_t *, sol_object_t *, sol_object_t *); |
|||
sol_object_t *sol_map_get(sol_state_t *, sol_object_t *, sol_object_t *); |
|||
void sol_map_set(sol_state-t *, sol_object_t *, sol_object_t *, sol_object_t *); |
|||
sol_object_t *sol_map_copy(sol_state_t *, sol_object_t *); |
|||
void sol_map_merge(sol_state_t *, sol_object_t *, sol_object_t *); |
|||
|
|||
sol_object_t *sol_new_func(sol_state_t *, sol_cfunc_t); |
|||
|
|||
sol_object_t *sol_cast_int(sol_state_t *, sol_object_t *); |
|||
sol_object_t *sol_cast_float(sol_state_t *, sol_object_t *); |
|||
sol_object_t *sol_cast_string(sol_state_t *, sol_object_t *); |
|||
|
|||
extern sol_cfunc_t sol_f_str_free; |
|||
extern sol_cfunc_t sol_f_list_free; |
|||
extern sol_cfunc_t sol_f_map_free; |
|||
|
|||
// tokenizer.c |
|||
|
|||
sol_tokstream_t *sol_tokst_new(const char *); |
|||
void sol_tokst_free(sol_tokstream_t *); |
|||
|
|||
sol_token_t *sol_tokst_peek(sol_tokstream_t *); |
|||
sol_token_t *sol_tokst_next(sol_tokstream_t *); |
|||
|
|||
#endif |
@ -0,0 +1,258 @@ |
|||
#include "sol.h" |
|||
|
|||
int sol_state_init(sol_state_t *state) { |
|||
sol_object_t *globals; |
|||
|
|||
state->None = NULL; |
|||
state->OutOfMemory = NULL; |
|||
state->scopes = NULL; |
|||
state->error = NULL; |
|||
|
|||
// If any of the following fail, some very weird things are happening. |
|||
if(!(state->None = sol_new_singlet(state))) goto cleanup; |
|||
if(!(state->OutOfMemory = sol_new_singlet(state))) goto cleanup; |
|||
|
|||
// We can now use the normal error reporting mechanism, now |
|||
// that errors are distinguishable. Set that up now. |
|||
state->error = state->None; |
|||
state->scopes = sol_new_list(state); |
|||
if(sol_has_error(state)) goto cleanup; |
|||
globals = sol_new_map(); |
|||
if(sol_has_error(state)) goto cleanup; |
|||
sol_list_insert(state, state->scopes, 0, globals); |
|||
if(sol_has_error(state)) goto cleanup; |
|||
// I'm going to buffer all of these together because I can. |
|||
sol_map_set(state, globals, sol_new_string(state, "toint"), sol_new_func(state, sol_f_toint)); |
|||
sol_map_set(state, globals, sol_new_string(state, "tofloat"), sol_new_func(state, sol_f_tofloat)); |
|||
sol_map_set(state, globals, sol_new_string(state, "tostring"), sol_new_func(state, sol_f_tostring)); |
|||
sol_map_set(state, globals, sol_new_string(state, "try"), sol_new_func(state, sol_f_try)); |
|||
if(sol_has_error(state)) goto cleanup; |
|||
|
|||
//Initialize all of the builtin operations |
|||
//(these ones are technically already pointed to by None/OOM) |
|||
state->NullOps.add = sol_f_not_impl; |
|||
state->NullOps.sub = sol_f_not_impl; |
|||
state->NullOps.mul = sol_f_not_impl; |
|||
state->NullOps.div = sol_f_not_impl; |
|||
state->NullOps.band = sol_f_not_impl; |
|||
state->NullOps.bor = sol_f_not_impl; |
|||
state->NullOps.bxor = sol_f_not_impl; |
|||
state->NullOps.bnot = sol_f_not_impl; |
|||
state->NullOps.call = sol_f_not_impl; |
|||
state->NullOps.index = sol_f_not_impl; |
|||
state->NullOps.setindex = sol_f_not_impl; |
|||
state->NullOps.len = sol_f_not_impl; |
|||
state->NullOps.toint = sol_f_not_impl; |
|||
state->NullOps.tofloat = sol_not_impl |
|||
state->NullOps.tostring = sol_f_not_impl; |
|||
state->NullOps.init = sol_f_no_op; |
|||
state->NullOps.free = sol_f_no_op; |
|||
|
|||
state->IntOps.add = sol_f_int_add; |
|||
state->IntOps.sub = sol_f_int_sub; |
|||
state->IntOps.mul = sol_f_int_mul; |
|||
state->IntOps.div = sol_f_int_div; |
|||
state->IntOps.band = sol_f_int_band; |
|||
state->IntOps.bor = sol_f_int_bor; |
|||
state->IntOps.bxor = sol_f_int_bxor; |
|||
state->IntOps.bnot = sol_f_int_bnot; |
|||
state->IntOps.call = sol_f_not_impl; |
|||
state->IntOps.index = sol_f_not_impl; |
|||
state->IntOps.setindex = sol_f_not_impl; |
|||
state->IntOps.len = sol_f_not_impl; |
|||
state->IntOps.toint = sol_f_int_toint; |
|||
state->IntOps.tofloat = sol_f_int_tofloat; |
|||
state->IntOps.tostring = sol_f_int_tostring; |
|||
state->IntOps.init = sol_f_no_op; |
|||
state->IntOps.free = sol_f_no_op; |
|||
|
|||
state->FloatOps.add = sol_f_float_add; |
|||
state->FloatOps.sub = sol_f_float_sub; |
|||
state->FloatOps.mul = sol_f_float_mul; |
|||
state->FloatOps.div = sol_f_float_div; |
|||
state->FloatOps.band = sol_f_not_impl; |
|||
state->FloatOps.bor = sol_f_not_impl; |
|||
state->FloatOps.bxor = sol_f_not_impl; |
|||
state->FloatOps.bnot = sol_f_not_impl; |
|||
state->FloatOps.call = sol_f_not_impl; |
|||
state->FloatOps.index = sol_f_not_impl; |
|||
state->FloatOps.setindex = sol_f_not_impl; |
|||
state->FloatOps.len = sol_f_not_impl; |
|||
state->FloatOps.toint = sol_f_float_toint; |
|||
state->FloatOps.tofloat = sol_f_float_tofloat; |
|||
state->FloatOps.tostring = sol_f_float_tostring; |
|||
state->FloatOps.init = sol_f_no_op; |
|||
state->FloatOps.free = sol_f_no_op; |
|||
|
|||
state->StringOps.add = sol_f_str_add; |
|||
state->StringOps.sub = sol_f_not_impl; |
|||
state->StringOps.mul = sol_f_str_mul; |
|||
state->StringOps.div = sol_f_not_impl; |
|||
state->StringOps.band = sol_f_not_impl |
|||
state->StringOps.bor = sol_f_not_impl; |
|||
state->StringOps.bxor = sol_f_not_impl; |
|||
state->StringOps.bnot = sol_f_not_impl; |
|||
state->StringOps.call = sol_f_not_impl; |
|||
state->StringOps.index = sol_f_not_impl; |
|||
state->StringOps.setindex = sol_f_not_impl; |
|||
state->StringOps.len = sol_f_str_len; |
|||
state->StringOps.toint = sol_f_str_toint; |
|||
state->StringOps.tofloat = sol_f_str_tofloat; |
|||
state->StringOps.tostring = sol_f_str_tostring; |
|||
state->StringOps.init = sol_f_no_op; |
|||
state->StringOps.free = sol_f_str_free; |
|||
|
|||
state->ListOps.add = sol_f_list_add; |
|||
state->ListOps.sub = sol_f_not_impl; |
|||
state->ListOps.mul = sol_f_list_mul; |
|||
state->ListOps.div = sol_f_not_impl; |
|||
state->ListOps.band = sol_f_not_impl; |
|||
state->ListOps.bor = sol_f_not_impl; |
|||
state->ListOps.bxor = sol_f_not_impl; |
|||
state->ListOps.bnot = sol_f_not_impl; |
|||
state->ListOps.call = sol_f_not_impl; |
|||
state->ListOps.index = sol_f_list_index; |
|||
state->ListOps.setindex = sol_f_list_setindex; |
|||
state->ListOps.len = sol_f_list_len; |
|||
state->ListOps.toint = sol_f_not_impl; |
|||
state->ListOps.tofloat = sol_f_not_impl; |
|||
state->ListOps.tostring = sol_f_list_tostring; |
|||
state->ListOps.init = sol_f_no_op; |
|||
state->ListOps.free = sol_f_list_free; |
|||
|
|||
state->MapOps.add = sol_f_map_add; |
|||
state->MapOps.sub = sol_f_not_impl; |
|||
state->MapOps.mul = sol_f_not_impl; |
|||
state->MapOps.div = sol_f_not_impl; |
|||
state->MapOps.band = sol_f_not_impl; |
|||
state->MapOps.bor = sol_f_not_impl; |
|||
state->MapOps.bxor = sol_f_not_impl; |
|||
state->MapOps.bnot = sol_f_not_impl; |
|||
state->MapOps.call = sol_f_not_impl; |
|||
state->MapOps.index = sol_f_map_index; |
|||
state->MapOps.setindex = sol_f_map_setindex; |
|||
state->MapOps.len = sol_f_map_len; |
|||
state->MapOps.toint = sol_f_not_impl; |
|||
state->MapOps.tofloat = sol_f_not_impl; |
|||
state->MapOps.tostring = sol_f_map_tostring; |
|||
state->MapOps.init = sol_f_no_op; |
|||
state->MapOps.free = sol_f_map_free; |
|||
|
|||
state->FuncOps.add = sol_f_not_impl; |
|||
state->FuncOps.sub = sol_f_not_impl; |
|||
state->FuncOps.mul = sol_f_not_impl; |
|||
state->FuncOps.div = sol_f_not_impl; |
|||
state->FuncOps.band = sol_f_not_impl; |
|||
state->FuncOps.bor = sol_f_not_impl; |
|||
state->FuncOps.bxor = sol_f_not_impl; |
|||
state->FuncOps.bnot = sol_f_not_impl; |
|||
state->FuncOps.call = sol_f_float_call; |
|||
state->FuncOps.index = sol_f_not_impl; |
|||
state->FuncOps.setindex = sol_f_not_impl; |
|||
state->FuncOps.len = sol_f_not_impl; |
|||
state->FuncOps.toint = sol_f_not_impl; |
|||
state->FuncOps.tofloat = sol_not_impl |
|||
state->FuncOps.tostring = sol_f_float_tostring; |
|||
state->FuncOps.init = sol_f_no_op; |
|||
state->FuncOps.free = sol_f_no_op; |
|||
|
|||
// We're all set! |
|||
return 1; |
|||
|
|||
_cleanup: |
|||
sol_obj_free(state->None); |
|||
sol_obj_free(state->OutOfMemory); |
|||
return 0; |
|||
} |
|||
|
|||
sol_object_t *sol_state_resolve(sol_state_t *state, sol_object_t *key) { |
|||
sol_object_t *cur = state->scopes, *temp; |
|||
while(cur.lvalue) { |
|||
temp = sol_map_get(state, cur.lvalue, key); |
|||
if(!sol_is_none(temp)) return sol_incref(temp); |
|||
cur = cur.lnext; |
|||
} |
|||
|
|||
return sol_incref(state->None); |
|||
} |
|||
|
|||
sol_object_t *sol_state_resolve_name(sol_state_t *state, const char *name) { |
|||
sol_object_t *key = sol_new_string(state, name), *temp; |
|||
|
|||
if(sol_has_error(state)) return sol_incref(state->None); |
|||
|
|||
temp = sol_state_resolve(state, key); |
|||
sol_obj_free(key); |
|||
return temp; |
|||
} |
|||
|
|||
void sol_state_assign(sol_state_t *state, sol_object_t *key, sol_object_t *val) { |
|||
sol_object_t *cur = state->scopes, *next; |
|||
|
|||
if(!cur) { |
|||
sol_set_error_string(state, "Global state does not exist"); |
|||
return; |
|||
} |
|||
|
|||
next = cur.lnext; |
|||
while(next) { |
|||
cur = next; |
|||
next = cur.lnext; |
|||
} |
|||
|
|||
sol_map_set(state, cur.lvalue, key, val); |
|||
} |
|||
|
|||
void sol_state_assign_name(sol_state_t *state, const char *name, sol_object_t *val) { |
|||
sol_object_t *key = sol_new_string(name); |
|||
|
|||
if(sol_has_error(state)) return; |
|||
|
|||
sol_state_assign(state, key, val); |
|||
sol_obj_free(key); |
|||
} |
|||
|
|||
void sol_state_assign_l(sol_state_t *state, sol_object_t *key, sol_object_t *val) { |
|||
sol_object_t *cur = state->scopes; |
|||
|
|||
if(!cur) { |
|||
sol_set_error_string(state, "Local state does not exist"); |
|||
return; |
|||
} |
|||
|
|||
sol_map_set(state, cur.lvalue, key, val); |
|||
} |
|||
|
|||
void sol_state_assign_l_name(sol_state_t *state, const char *name, sol_object_t *val) { |
|||
sol_object_t *key = sol_new_string(name); |
|||
|
|||
if(sol_has_error(state)) return; |
|||
|
|||
sol_state_assign_l(state, key, val); |
|||
sol_obj_free(key); |
|||
} |
|||
|
|||
sol_object_t *sol_get_error(sol_state_t *state) { |
|||
return sol_incref(state->error); |
|||
} |
|||
|
|||
sol_object_t *sol_set_error(sol_state_t *state, sol_object_t *err) { |
|||
state->error = sol_incref(err); |
|||
return sol_incref(state->None); |
|||
} |
|||
|
|||
sol_object_t *sol_set_error_string(sol_state_t *state, const char *serr) { |
|||
sol_object_t *err = sol_new_string(serr); |
|||
|
|||
if(sol_has_error(state)) return sol_incref(state->None); |
|||
|
|||
sol_set_error(state, err); |
|||
sol_obj_free(err); |
|||
} |
|||
|
|||
void sol_clear_error(sol_state_t *state) { |
|||
// This silliness ensures we don't accidentally free None. |
|||
sol_object_t *olderr = state->error; |
|||
state->error = sol_incref(state->None); |
|||
sol_obj_free(olderr); |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue