Browse Source

Incomplete work on Sol, part 1

master
Grissess 7 years ago
commit
26cebb751e
  1. 389
      builtins.c
  2. 161
      object.c
  3. 266
      sol.h
  4. 258
      state.c

389
builtins.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>");
}

161
object.c

@ -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)
}

266
sol.h

@ -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

258
state.c

@ -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);
}
Loading…
Cancel
Save