You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
959 lines
31 KiB
959 lines
31 KiB
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
#include "ast.h"
|
|
|
|
// XXX hardcoded buffer sizes
|
|
|
|
static char *_itoa(int i) {
|
|
int n = 33;
|
|
char *s = malloc(n);
|
|
snprintf(s, n, "%d", i);
|
|
return s;
|
|
}
|
|
|
|
static char *_ftoa(double f) {
|
|
int n = 65;
|
|
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_default_cmp(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);
|
|
sol_object_t *res = sol_new_int(state, a!=b);
|
|
sol_obj_free(a);
|
|
sol_obj_free(b);
|
|
return res;
|
|
}
|
|
|
|
sol_object_t *sol_f_no_op(sol_state_t *state, sol_object_t *args) {
|
|
if(state) return sol_incref(state->None);
|
|
return NULL;
|
|
}
|
|
|
|
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;
|
|
sol_list_insert(state, fargs, 0, func);
|
|
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_clear_error(state);
|
|
sol_object_t *zero = sol_new_int(state, 0);
|
|
sol_obj_free(res);
|
|
sol_obj_free(one);
|
|
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;
|
|
}
|
|
|
|
static char *sol_TypeNames[] = {"singlet", "integer", "float", "string", "list", "listcell", "map", "mapcell", "function", "cfunction", "cdata"};
|
|
|
|
sol_object_t *sol_f_type(sol_state_t *state, sol_object_t *args) {
|
|
sol_object_t *obj = sol_list_get_index(state, args, 0);
|
|
sol_object_t *res = sol_new_string(state, sol_TypeNames[obj->type]);
|
|
sol_obj_free(obj);
|
|
return res;
|
|
}
|
|
|
|
sol_object_t *p_seen[1024] = {0};
|
|
|
|
void ob_print(sol_object_t *obj) {
|
|
sol_object_t *cur;
|
|
int i;
|
|
for(i=0; i<1024; i++) {
|
|
if(!p_seen[i]) {
|
|
p_seen[i] = obj;
|
|
break;
|
|
}
|
|
if(p_seen[i] == obj) {
|
|
printf("... (%p)", obj);
|
|
return;
|
|
}
|
|
}
|
|
switch(obj->type) {
|
|
case SOL_SINGLET:
|
|
printf("<Singlet>");
|
|
break;
|
|
|
|
case SOL_INTEGER:
|
|
printf("%ld", obj->ival);
|
|
break;
|
|
|
|
case SOL_FLOAT:
|
|
printf("%f", obj->fval);
|
|
break;
|
|
|
|
case SOL_STRING:
|
|
printf("\"%s\"", obj->str);
|
|
break;
|
|
|
|
case SOL_LCELL:
|
|
printf("<<");
|
|
/* fall through */
|
|
|
|
case SOL_LIST:
|
|
printf("[");
|
|
cur = obj;
|
|
while(cur) {
|
|
if(cur->lvalue) {
|
|
ob_print(cur->lvalue);
|
|
}
|
|
if(cur->lnext) {
|
|
printf(", ");
|
|
}
|
|
cur = cur->lnext;
|
|
}
|
|
printf("]");
|
|
break;
|
|
|
|
case SOL_MCELL:
|
|
printf("<<");
|
|
/* fall through */
|
|
|
|
case SOL_MAP:
|
|
printf("{");
|
|
cur = obj;
|
|
while(cur) {
|
|
if(cur->mkey) {
|
|
printf("[");
|
|
ob_print(cur->mkey);
|
|
printf("] = ");
|
|
ob_print(cur->mval);
|
|
}
|
|
if(cur->mnext) printf(", ");
|
|
cur = cur->mnext;
|
|
}
|
|
printf("}");
|
|
break;
|
|
|
|
case SOL_FUNCTION:
|
|
if(obj->fname) {
|
|
printf("<Function %s>", obj->fname);
|
|
} else {
|
|
printf("<Function>");
|
|
}
|
|
break;
|
|
|
|
case SOL_CFUNCTION:
|
|
printf("<CFunction>");
|
|
break;
|
|
|
|
case SOL_CDATA:
|
|
printf("<CData>");
|
|
break;
|
|
}
|
|
}
|
|
|
|
sol_object_t *sol_f_prepr(sol_state_t *state, sol_object_t *args) {
|
|
int i, sz = sol_list_len(state, args);
|
|
sol_object_t *obj;
|
|
for(i=0; i<1024; i++) p_seen[i] = NULL;
|
|
for(i=0; i<sz; i++) {
|
|
obj = sol_list_get_index(state, args, i);
|
|
ob_print(obj);
|
|
printf(" ");
|
|
sol_obj_free(obj);
|
|
}
|
|
printf("\n");
|
|
return sol_incref(state->None);
|
|
}
|
|
|
|
sol_object_t *sol_f_print(sol_state_t *state, sol_object_t *args) {
|
|
int i, sz = sol_list_len(state, args);
|
|
sol_object_t *obj;
|
|
for(i=0; i<1024; i++) p_seen[i] = NULL;
|
|
for(i=0; i<sz; i++) {
|
|
obj = sol_list_get_index(state, args, i);
|
|
if(sol_is_string(obj)) {
|
|
printf("%s", obj->str);
|
|
} else {
|
|
ob_print(obj);
|
|
}
|
|
printf(" ");
|
|
sol_obj_free(obj);
|
|
}
|
|
printf("\n");
|
|
return sol_incref(state->None);
|
|
}
|
|
|
|
sol_object_t *sol_f_rawget(sol_state_t *state, sol_object_t *args) {
|
|
sol_object_t *obj = sol_list_get_index(state, args, 0), *key, *res;
|
|
if(!sol_is_map(obj)) return sol_set_error_string(state, "Rawset of non-map");
|
|
key = sol_list_get_index(state, args, 1);
|
|
res = sol_map_get(state, obj, key);
|
|
sol_obj_free(key);
|
|
sol_obj_free(obj);
|
|
return res;
|
|
}
|
|
|
|
|
|
sol_object_t *sol_f_rawset(sol_state_t *state, sol_object_t *args) {
|
|
sol_object_t *obj = sol_list_get_index(state, args, 0), *key, *val;
|
|
if(!sol_is_map(obj)) return sol_set_error_string(state, "Rawset of non-map");
|
|
key = sol_list_get_index(state, args, 1);
|
|
val = sol_list_get_index(state, args, 2);
|
|
sol_map_set(state, obj, key, val);
|
|
sol_obj_free(val);
|
|
sol_obj_free(key);
|
|
sol_obj_free(obj);
|
|
return sol_incref(state->None);
|
|
}
|
|
|
|
sol_object_t *sol_f_range(sol_state_t *state, sol_object_t *args) {
|
|
sol_object_t *res = sol_new_list(state), *bound = sol_cast_int(state, sol_list_get_index(state, args, 0));
|
|
int i;
|
|
for(i=0; i<bound->ival; i++) {
|
|
sol_list_insert(state, res, sol_list_len(state, res), sol_new_int(state, i));
|
|
}
|
|
sol_obj_free(bound);
|
|
return res;
|
|
}
|
|
|
|
sol_object_t *sol_f_exec(sol_state_t *state, sol_object_t *args) {
|
|
sol_object_t *prg = sol_list_get_index(state, args, 0), *prgstr = sol_cast_string(state, prg);
|
|
stmt_node *program;
|
|
|
|
program = sol_compile(prgstr->str);
|
|
if(!program) {
|
|
return sol_set_error_string(state, "Compilation failure");
|
|
}
|
|
// XXX should st_free(program);
|
|
|
|
sol_exec(state, program);
|
|
return sol_incref(state->None);
|
|
}
|
|
|
|
sol_object_t *sol_f_eval(sol_state_t *state, sol_object_t *args) {
|
|
sol_object_t *prg = sol_list_get_index(state, args, 0), *prgstr = sol_cast_string(state, prg);
|
|
stmt_node *program;
|
|
|
|
program = sol_compile(prgstr->str);
|
|
if(!program) {
|
|
return sol_set_error_string(state, "Compilation failure");
|
|
}
|
|
if(program->type != ST_LIST || program->stmtlist->stmt->type != ST_EXPR) {
|
|
return sol_set_error_string(state, "Not an expression");
|
|
}
|
|
// XXX should st_free(program);
|
|
|
|
return sol_eval(state, program->stmtlist->stmt->expr);
|
|
}
|
|
|
|
sol_object_t *sol_f_execfile(sol_state_t *state, sol_object_t *args) {
|
|
sol_object_t *prg = sol_list_get_index(state, args, 0), *prgstr = sol_cast_string(state, prg);
|
|
stmt_node *program;
|
|
FILE *f = fopen(prgstr->str, "r");
|
|
char *s;
|
|
long sz;
|
|
|
|
if(!f) {
|
|
return sol_set_error_string(state, "File open failure");
|
|
}
|
|
|
|
fseek(f, 0, SEEK_END);
|
|
sz = ftell(f);
|
|
fseek(f, 0, SEEK_SET);
|
|
s = malloc(sz);
|
|
if(!s) {
|
|
fclose(f);
|
|
return sol_set_error_string(state, "File memory allocation failure");
|
|
}
|
|
fread(s, sz, 1, f);
|
|
fclose(f);
|
|
|
|
program = sol_compile(s);
|
|
free(s);
|
|
if(!program) {
|
|
return sol_set_error_string(state, "Compilation failure");
|
|
}
|
|
// XXX should st_free(program);
|
|
|
|
sol_exec(state, program);
|
|
return sol_incref(state->None);
|
|
}
|
|
|
|
sol_object_t *sol_f_debug_getref(sol_state_t *state, sol_object_t *args) {
|
|
sol_object_t *obj = sol_list_get_index(state, args, 0);
|
|
sol_object_t *res = sol_new_int(state, obj->refcnt - 2); // NB: We grabbed a reference, and there's one in the arglist, so account for them.
|
|
sol_obj_free(obj);
|
|
return res;
|
|
}
|
|
|
|
sol_object_t *sol_f_debug_setref(sol_state_t *state, sol_object_t *args) {
|
|
sol_object_t *obj = sol_list_get_index(state, args, 0), *cnt = sol_list_get_index(state, args, 1);
|
|
obj->refcnt = sol_cast_int(state, cnt)->ival + 2; // NB: As above.
|
|
sol_obj_free(cnt);
|
|
sol_obj_free(obj);
|
|
return sol_incref(state->None);
|
|
}
|
|
|
|
sol_object_t *sol_f_debug_closure(sol_state_t *state, sol_object_t *args) {
|
|
sol_object_t *func = sol_list_get_index(state, args, 0);
|
|
sol_object_t *res = sol_incref(func->closure);
|
|
sol_obj_free(func);
|
|
return res;
|
|
}
|
|
|
|
sol_object_t *sol_f_debug_globals(sol_state_t *state, sol_object_t *args) {
|
|
return sol_list_get_index(state, state->scopes, sol_list_len(state, state->scopes)-1);
|
|
}
|
|
|
|
sol_object_t *sol_f_debug_locals(sol_state_t *state, sol_object_t *args) {
|
|
return sol_list_get_index(state, state->scopes, 0);
|
|
}
|
|
|
|
sol_object_t *sol_f_iter_str(sol_state_t *state, sol_object_t *args) {
|
|
sol_object_t *obj = sol_list_get_index(state, args, 0), *local = sol_list_get_index(state, args, 1);
|
|
sol_object_t *index = sol_map_get_name(state, local, "idx"), *res;
|
|
char temp[2] = {0, 0};
|
|
if(sol_is_none(state, index)) {
|
|
sol_obj_free(index);
|
|
index = sol_new_int(state, 0);
|
|
sol_map_set_name(state, local, "idx", index);
|
|
}
|
|
if(index->ival >= strlen(obj->str)) {
|
|
sol_obj_free(index);
|
|
sol_obj_free(obj);
|
|
sol_obj_free(local);
|
|
return sol_incref(state->StopIteration);
|
|
}
|
|
temp[0] = obj->str[index->ival];
|
|
res = sol_new_string(state, temp);
|
|
index->ival++;
|
|
sol_obj_free(index);
|
|
sol_obj_free(local);
|
|
sol_obj_free(obj);
|
|
return res;
|
|
}
|
|
|
|
sol_object_t *sol_f_iter_list(sol_state_t *state, sol_object_t *args) {
|
|
sol_object_t *obj = sol_list_get_index(state, args, 0), *local = sol_list_get_index(state, args, 1);
|
|
sol_object_t *index = sol_map_get_name(state, local, "idx"), *res;
|
|
if(sol_is_none(state, index)) {
|
|
sol_obj_free(index);
|
|
index = sol_new_int(state, 0);
|
|
sol_map_set_name(state, local, "idx", index);
|
|
}
|
|
if(index->ival >= sol_list_len(state, obj)) {
|
|
sol_obj_free(index);
|
|
sol_obj_free(obj);
|
|
sol_obj_free(local);
|
|
return sol_incref(state->StopIteration);
|
|
}
|
|
res = sol_list_get_index(state, obj, index->ival);
|
|
index->ival++;
|
|
sol_obj_free(index);
|
|
sol_obj_free(local);
|
|
sol_obj_free(obj);
|
|
return res;
|
|
}
|
|
|
|
sol_object_t *sol_f_iter_map(sol_state_t *state, sol_object_t *args) {
|
|
sol_object_t *obj = sol_list_get_index(state, args, 0), *local = sol_list_get_index(state, args, 1);
|
|
sol_object_t *index = sol_map_get_name(state, local, "idx"), *res;
|
|
if(sol_is_none(state, index)) {
|
|
sol_obj_free(index);
|
|
index = obj;
|
|
sol_map_set_name(state, local, "idx", index);
|
|
}
|
|
if(!index || index == state->StopIteration) {
|
|
sol_obj_free(index);
|
|
sol_obj_free(obj);
|
|
sol_obj_free(local);
|
|
return sol_incref(state->StopIteration);
|
|
}
|
|
while(index && !index->mkey) index = index->mnext;
|
|
res = sol_incref(index->mkey);
|
|
index = index->mnext;
|
|
if(!index) index = state->StopIteration;
|
|
sol_map_set_name(state, local, "idx", index);
|
|
sol_obj_free(index);
|
|
sol_obj_free(local);
|
|
sol_obj_free(obj);
|
|
return res;
|
|
}
|
|
|
|
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_pow(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, (long) pow((double) 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_blsh(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_brsh(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_cmp(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? 0 : (a->ival<b->ival? -1 : 1));
|
|
sol_obj_free(a);
|
|
sol_obj_free(b);
|
|
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_pow(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, pow(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_cmp(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_int(state, a->fval==b->fval? 0 : (a->fval<b->fval? -1 : 1));
|
|
sol_obj_free(a);
|
|
sol_obj_free(b);
|
|
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, a->str, n), b->str, n));
|
|
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, a->str, n);
|
|
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_cmp(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));
|
|
sol_object_t *res = sol_new_int(state, strcmp(a->str, b->str));
|
|
sol_obj_free(a);
|
|
sol_obj_free(b);
|
|
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 *res = sol_new_int(state, strlen(a->str));
|
|
sol_obj_free(a);
|
|
return res;
|
|
}
|
|
|
|
sol_object_t *sol_f_str_iter(sol_state_t *state, sol_object_t *args) {
|
|
return sol_new_cfunc(state, sol_f_iter_str);
|
|
}
|
|
|
|
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 *res = 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 *res = 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_list_get_index(state, args, 1), *ival;
|
|
sol_object_t *res;
|
|
if(sol_is_string(b)) {
|
|
res = sol_map_get(state, state->ListFuncs, b);
|
|
} else {
|
|
ival = sol_cast_int(state, b);
|
|
res = sol_list_get_index(state, ls, ival->ival);
|
|
sol_obj_free(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_object_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_iter(sol_state_t *state, sol_object_t *args) {
|
|
return sol_new_cfunc(state, sol_f_iter_list);
|
|
}
|
|
|
|
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_list_copy(sol_state_t *state, sol_object_t *args) {
|
|
sol_object_t *list = sol_list_get_index(state, args, 0);
|
|
sol_object_t *res = sol_list_copy(state, list);
|
|
sol_obj_free(list);
|
|
return res;
|
|
}
|
|
|
|
sol_object_t *sol_f_list_insert(sol_state_t *state, sol_object_t *args) {
|
|
sol_object_t *list = sol_list_get_index(state, args, 0), *idx = sol_cast_int(state, sol_list_get_index(state, args, 1)), *obj = sol_list_get_index(state, args, 2);
|
|
sol_list_insert(state, list, idx->ival, obj);
|
|
sol_obj_free(list);
|
|
return sol_incref(state->None);
|
|
}
|
|
|
|
sol_object_t *sol_f_list_remove(sol_state_t *state, sol_object_t *args) {
|
|
sol_object_t *list = sol_list_get_index(state, args, 0), *idx = sol_cast_int(state, sol_list_get_index(state, args, 1));
|
|
sol_list_remove(state, list, idx->ival);
|
|
sol_obj_free(list);
|
|
return sol_incref(state->None);
|
|
}
|
|
|
|
sol_object_t *sol_f_list_truncate(sol_state_t *state, sol_object_t *args) {
|
|
sol_object_t *list = sol_list_get_index(state, args, 0), *idx = sol_list_get_index(state, args, 1);
|
|
sol_object_t *res = sol_list_truncate(state, list, idx->ival);
|
|
sol_obj_free(list);
|
|
return res;
|
|
}
|
|
|
|
sol_object_t *sol_f_list_map(sol_state_t *state, sol_object_t *args) {
|
|
sol_object_t *list = sol_list_get_index(state, args, 0), *func = sol_list_get_index(state, args, 1);
|
|
sol_object_t *fargs = sol_new_list(state), *item;
|
|
int idx=0, len = sol_list_len(state, list);
|
|
sol_list_insert(state, fargs, 0, func);
|
|
while(idx<len) {
|
|
item = sol_list_get_index(state, list, idx);
|
|
sol_list_insert(state, fargs, 1, item);
|
|
sol_obj_free(item);
|
|
item = func->ops->call(state, fargs);
|
|
if(sol_has_error(state)) return list;
|
|
sol_list_remove(state, fargs, 1);
|
|
sol_list_set_index(state, list, idx, item);
|
|
sol_obj_free(item);
|
|
idx++;
|
|
}
|
|
sol_obj_free(fargs);
|
|
sol_obj_free(func);
|
|
return list;
|
|
}
|
|
|
|
sol_object_t *sol_f_list_filter(sol_state_t *state, sol_object_t *args) {
|
|
sol_object_t *list = sol_list_get_index(state, args, 0), *func = sol_list_get_index(state, args, 1);
|
|
sol_object_t *fargs = sol_new_list(state), *item, *ival;
|
|
int idx=0, len = sol_list_len(state, list);
|
|
sol_list_insert(state, fargs, 0, func);
|
|
while(idx<len) {
|
|
item = sol_list_get_index(state, list, idx);
|
|
sol_list_insert(state, fargs, 1, item);
|
|
sol_obj_free(item);
|
|
item = func->ops->call(state, fargs);
|
|
if(sol_has_error(state)) return list;
|
|
ival = sol_cast_int(state, item);
|
|
if(ival->ival) {
|
|
idx++;
|
|
} else {
|
|
sol_list_remove(state, list, idx);
|
|
len--;
|
|
}
|
|
sol_obj_free(item);
|
|
sol_obj_free(ival);
|
|
}
|
|
sol_obj_free(fargs);
|
|
sol_obj_free(func);
|
|
return 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);
|
|
sol_object_t *indexf = sol_map_get_name(state, map, "__index");
|
|
sol_object_t *res = NULL, *newls;
|
|
if(!sol_is_none(state, indexf)) {
|
|
if(indexf->ops->call && (sol_is_func(indexf) || sol_is_cfunc(indexf)) && indexf->ops->call != sol_f_not_impl) {
|
|
newls = sol_new_list(state);
|
|
sol_list_insert(state, newls, 0, indexf);
|
|
sol_list_append(state, newls, args);
|
|
res = indexf->ops->call(state, newls);
|
|
sol_obj_free(newls);
|
|
} else if(indexf->ops->index && indexf->ops->index != sol_f_not_impl) {
|
|
newls = sol_new_list(state);
|
|
sol_list_insert(state, newls, 0, indexf);
|
|
sol_list_insert(state, newls, 1, b);
|
|
res = indexf->ops->index(state, newls);
|
|
sol_obj_free(newls);
|
|
}
|
|
}
|
|
if(!res) res = sol_map_get(state, map, b);
|
|
sol_obj_free(indexf);
|
|
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_object_t *setindexf = sol_map_get_name(state, map, "__setindex"), *newls;
|
|
if(!sol_is_none(state, setindexf)) {
|
|
if(setindexf->ops->call && (sol_is_func(setindexf) || sol_is_cfunc(setindexf)) && setindexf->ops->call != sol_f_not_impl) {
|
|
newls = sol_new_list(state);
|
|
sol_list_insert(state, newls, 0, setindexf);
|
|
sol_list_append(state, newls, args);
|
|
sol_obj_free(setindexf->ops->call(state, newls));
|
|
sol_obj_free(newls);
|
|
return sol_incref(state->None);
|
|
} else if(setindexf->ops->setindex && setindexf->ops->setindex != sol_f_not_impl) {
|
|
newls = sol_new_list(state);
|
|
sol_list_insert(state, newls, 0, setindexf);
|
|
sol_list_insert(state, newls, 1, b);
|
|
sol_list_insert(state, newls, 2, val);
|
|
sol_obj_free(setindexf->ops->index(state, newls));
|
|
sol_obj_free(newls);
|
|
return sol_incref(state->None);
|
|
}
|
|
}
|
|
sol_obj_free(setindexf);
|
|
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_call(sol_state_t *state, sol_object_t *args) {
|
|
sol_object_t *map = sol_list_get_index(state, args, 0), *fargs = sol_list_sublist(state, args, 1);
|
|
sol_object_t *callf = sol_map_get_name(state, map, "__call"), *res = NULL;
|
|
if(!sol_is_none(state, callf)) {
|
|
if(callf->ops->call) {
|
|
sol_list_insert(state, fargs, 0, callf);
|
|
sol_list_insert(state, fargs, 1, map);
|
|
res = callf->ops->call(state, fargs);
|
|
}
|
|
}
|
|
sol_obj_free(map);
|
|
sol_obj_free(fargs);
|
|
sol_obj_free(callf);
|
|
if(res) return res;
|
|
return sol_set_error_string(state, "Call map without call method");
|
|
}
|
|
|
|
sol_object_t *sol_f_map_len(sol_state_t *state, sol_object_t *args) {
|
|
sol_object_t *map = sol_list_get_index(state, 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_iter(sol_state_t *state, sol_object_t *args) {
|
|
return sol_new_cfunc(state, sol_f_iter_map);
|
|
}
|
|
|
|
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_index(sol_state_t *state, sol_object_t *args) {
|
|
sol_object_t *func = sol_list_get_index(state, args, 0), *key = sol_list_get_index(state, args, 1), *res;
|
|
res = sol_map_get(state, func->closure, key);
|
|
sol_obj_free(func);
|
|
sol_obj_free(key);
|
|
return res;
|
|
}
|
|
|
|
sol_object_t *sol_f_func_setindex(sol_state_t *state, sol_object_t *args) {
|
|
sol_object_t *func = sol_list_get_index(state, args, 0), *key = sol_list_get_index(state, args, 1), *val = sol_list_get_index(state, args, 2);
|
|
sol_map_set(state, func->closure, key, val);
|
|
sol_obj_free(func);
|
|
sol_obj_free(key);
|
|
sol_obj_free(val);
|
|
return sol_incref(state->None);
|
|
}
|
|
|
|
sol_object_t *sol_f_func_tostring(sol_state_t *state, sol_object_t *args) {
|
|
return sol_new_string(state, "<Function>");
|
|
}
|
|
|
|
sol_object_t *sol_f_cfunc_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->cfunc(state, fargs);
|
|
sol_obj_free(func);
|
|
sol_obj_free(fargs);
|
|
return res;
|
|
}
|
|
|
|
sol_object_t *sol_f_cfunc_tostring(sol_state_t *state, sol_object_t *args) {
|
|
return sol_new_string(state, "<CFunction>");
|
|
}
|