Browse Source

Sol Part 2: It's Almost a Parser Edition\!

master
Graham Northup 7 years ago
parent
commit
fa5c124970
  1. 174
      ast.h
  2. BIN
      astprint
  3. 287
      astprint.c
  4. 506
      builtins.c
  5. 2107
      lex.yy.c
  6. 364
      object.c
  7. 7531
      parser.output
  8. 2547
      parser.tab.c
  9. 125
      parser.tab.h
  10. 399
      parser.y
  11. 224
      sol.h
  12. 422
      state.c
  13. 27
      test.sol
  14. 6
      testbuild.sh
  15. 169
      tokenizer.lex

174
ast.h

@ -0,0 +1,174 @@
#ifndef AST_H
#define AST_H
#include "sol.h"
struct tag_expr_node;
typedef struct tag_expr_node expr_node;
struct tag_stmt_node;
typedef struct tag_stmt_node stmt_node;
typedef enum {LIT_INT, LIT_FLOAT, LIT_STRING} lit_t;
typedef struct {
lit_t type;
union {
int ival;
double fval;
char *str;
};
} lit_node;
typedef enum {OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_POW, OP_BAND, OP_BOR, OP_BXOR, OP_LAND, OP_LOR, OP_EQUAL, OP_LESS, OP_GREATER, OP_LESSEQ, OP_GREATEREQ} binop_t;
typedef struct {
binop_t type;
expr_node *left;
expr_node *right;
} binop_node;
typedef enum {OP_NEG, OP_BNOT, OP_LNOT} unop_t;
typedef struct {
unop_t type;
expr_node *expr;
} unop_node;
typedef struct {
expr_node *expr;
expr_node *index;
} index_node;
typedef struct {
expr_node *expr;
expr_node *index;
expr_node *value;
} setindex_node;
typedef struct {
char *ident;
expr_node *value;
} assign_node;
typedef struct {
char *ident;
} ref_node;
typedef struct tag_exprlist_node {
expr_node *expr;
struct tag_exprlist_node *next;
} exprlist_node;
typedef struct {
expr_node *key;
expr_node *value;
} associtem_node;
typedef struct tag_assoclist_node {
associtem_node *item;
struct tag_assoclist_node *next;
} assoclist_node;
typedef struct {
exprlist_node *list;
} listgen_node;
typedef struct {
assoclist_node *map;
} mapgen_node;
typedef struct {
expr_node *expr;
exprlist_node *args;
} call_node;
typedef struct tag_identlist_node {
char *ident;
struct tag_identlist_node *next;
} identlist_node;
typedef struct {
char *name;
identlist_node *args;
stmt_node *body;
} funcdecl_node;
typedef enum {EX_LIT, EX_LISTGEN, EX_MAPGEN, EX_BINOP, EX_UNOP, EX_INDEX, EX_SETINDEX, EX_ASSIGN, EX_REF, EX_CALL, EX_FUNCDECL} expr_t;
typedef struct tag_expr_node {
expr_t type;
union {
lit_node *lit;
listgen_node *listgen;
mapgen_node *mapgen;
binop_node *binop;
unop_node *unop;
index_node *index;
setindex_node *setindex;
assign_node *assign;
ref_node *ref;
call_node *call;
funcdecl_node *funcdecl;
};
} expr_node;
typedef struct {
expr_node *cond;
stmt_node *iftrue;
stmt_node *iffalse;
} ifelse_node;
typedef struct {
expr_node *cond;
stmt_node *loop;
} loop_node;
typedef struct {
char *var;
expr_node *iter;
stmt_node *loop;
} iter_node;
typedef struct tag_stmtlist_node {
stmt_node *stmt;
struct tag_stmtlist_node *next;
} stmtlist_node;
typedef enum {ST_EXPR, ST_IFELSE, ST_LOOP, ST_ITER, ST_LIST} stmt_t;
typedef struct tag_stmt_node {
stmt_t type;
union {
expr_node *expr;
ifelse_node *ifelse;
loop_node *loop;
iter_node *iter;
stmtlist_node *stmtlist;
};
} stmt_node;
#define AS_ST(arg) ((stmt_node *) (arg))
#define AS_EX(arg) ((expr_node *) (arg))
#define AS(arg, tp) ((tp *) (arg))
#define NEW_ST() malloc(sizeof(stmt_node))
#define NEW_EX() malloc(sizeof(expr_node))
#define NEW(arg) malloc(sizeof(arg))
#define MAKE_REF_BINOP(nd, tp, name, val) nd = NEW_EX(); \
nd->type = EX_BINOP; \
nd->binop = NEW(binop_node); \
nd->binop->type = tp; \
nd->binop->left = NEW_EX(); \
nd->binop->left->type = EX_REF; \
nd->binop->left->ref = NEW(ref_node); \
nd->binop->left->ref->ident = name; \
nd->binop->right = val
#define MAKE_IDX_BINOP(nd, tp, obj, idx, val) nd = NEW_EX(); \
nd->type = EX_BINOP; \
nd->binop = NEW(binop_node); \
nd->binop->type = tp; \
nd->binop->left = NEW_EX(); \
nd->binop->left->type = EX_INDEX; \
nd->binop->left->index = NEW(index_node); \
nd->binop->left->index->expr = obj; \
nd->binop->left->index->index = idx; \
nd->binop->right = val
sol_object_t *sol_new_func(sol_state_t *, identlist_node *, stmt_node *);
#endif

BIN
astprint

287
astprint.c

@ -0,0 +1,287 @@
#include "ast.h"
#include "parser.tab.h"
#include <stdarg.h>
#include <stdio.h>
void prlev(int lev, const char *fmt, ...) {
va_list vl;
int i;
for(i = 0; i < lev; i++) putchar(' ');
va_start(vl, fmt);
vprintf(fmt, vl);
va_end(vl);
putchar('\n');
}
void prex(expr_node *, int);
void prst(stmt_node *node, int lev) {
if(!node) {
prlev(lev, "<NULL>");
return;
}
switch(node->type) {
case ST_EXPR:
prlev(lev, "Stmt<Expr>:");
prex(node->expr, lev+1);
break;
case ST_IFELSE:
prlev(lev, "Stmt<IfElse>:");
lev++;
prlev(lev, "Cond:");
prex(node->ifelse->cond, lev+1);
prlev(lev, "IfTrue:");
prst(node->ifelse->iftrue, lev+1);
prlev(lev, "IfFalse:");
prst(node->ifelse->iffalse, lev+1);
break;
case ST_LOOP:
prlev(lev, "Stmt<Loop>:");
lev++;
prlev(lev, "Cond:");
prex(node->loop->cond, lev+1);
prlev(lev, "Loop:");
prst(node->loop->loop, lev+1);
break;
case ST_ITER:
prlev(lev, "Stmt<Iter>:");
lev++;
prlev(lev, "Var: %s", node->iter->var);
prlev(lev, "Iter:");
prex(node->iter->iter, lev+1);
prlev(lev, "Loop:");
prst(node->iter->loop, lev+1);
break;
case ST_LIST:
prlev(lev, "Stmt<List>:");
stmtlist_node *cur = node->stmtlist;
while(cur && cur->stmt) {
prst(cur->stmt, lev+1);
cur = cur->next;
}
break;
}
}
void prex(expr_node *node, int lev) {
assoclist_node *cura;
exprlist_node *cure;
identlist_node *curi;
if(!node) {
prlev(lev, "<NULL>");
return;
}
switch(node->type) {
case EX_LIT:
prlev(lev, "Literal:");
lev++;
switch(node->lit->type) {
case LIT_INT:
prlev(lev, "Int: %ld", node->lit->ival);
break;
case LIT_FLOAT:
prlev(lev, "Float: %f", node->lit->fval);
break;
case LIT_STRING:
prlev(lev, "String: %s", node->lit->str);
break;
}
break;
case EX_LISTGEN:
prlev(lev, "ListGen:");
cure = node->listgen->list;
while(cure && cure->expr) {
prex(cure->expr, lev+1);
cure = cure->next;
}
break;
case EX_MAPGEN:
prlev(lev, "MapGen:");
lev++;
cura = node->mapgen->map;
while(cura && cura->item) {
prlev(lev, "<Key>:");
prex(cura->item->key, lev+1);
prlev(lev, "<Value>:");
prex(cura->item->value, lev+1);
cura = cura->next;
}
break;
case EX_BINOP:
prlev(lev, "BinOp:");
lev++;
switch(node->binop->type) {
case OP_ADD:
prlev(lev, "Op: +");
break;
case OP_SUB:
prlev(lev, "Op: -");
break;
case OP_MUL:
prlev(lev, "Op: *");
break;
case OP_DIV:
prlev(lev, "Op: /");
break;
case OP_POW:
prlev(lev, "Op: **");
break;
case OP_BAND:
prlev(lev, "Op: &");
break;
case OP_BOR:
prlev(lev, "Op: |");
break;
case OP_BXOR:
prlev(lev, "Op: ^");
break;
case OP_LAND:
prlev(lev, "Op: &&");
break;
case OP_LOR:
prlev(lev, "Op: ||");
break;
case OP_EQUAL:
prlev(lev, "Op: ==");
break;
case OP_LESS:
prlev(lev, "Op: <");
break;
case OP_GREATER:
prlev(lev, "Op: >");
break;
case OP_LESSEQ:
prlev(lev, "Op: <=");
break;
case OP_GREATEREQ:
prlev(lev, "Op: >=");
break;
}
prlev(lev, "Left:");
prex(node->binop->left, lev+1);
prlev(lev, "Right:");
prex(node->binop->right, lev+1);
break;
case EX_UNOP:
prlev(lev, "UnOp:");
lev++;
switch(node->unop->type) {
case OP_NEG:
prlev(lev, "Op: -");
break;
case OP_BNOT:
prlev(lev, "Op: ~");
break;
case OP_LNOT:
prlev(lev, "Op: !");
break;
}
prlev(lev, "Expr:");
prex(node->unop->expr, lev+1);
break;
case EX_INDEX:
prlev(lev, "Index:");
lev++;
prlev(lev, "Expr:");
prex(node->index->expr, lev+1);
prlev(lev, "Index:");
prex(node->index->index, lev+1);
break;
case EX_SETINDEX:
prlev(lev, "SetIndex:");
lev++;
prlev(lev, "Expr:");
prex(node->setindex->expr, lev+1);
prlev(lev, "Index:");
prex(node->setindex->index, lev+1);
prlev(lev, "Value:");
prex(node->setindex->value, lev+1);
break;
case EX_ASSIGN:
prlev(lev, "Assign:");
lev++;
prlev(lev, "Ident: %s", node->assign->ident);
prlev(lev, "Value:");
prex(node->assign->value, lev+1);
break;
case EX_REF:
prlev(lev, "Ref: %s", node->ref->ident);
break;
case EX_CALL:
prlev(lev, "Call:");
lev++;
prlev(lev, "Expr:");
prex(node->call->expr, lev+1);
prlev(lev, "Args:");
cure = node->call->args;
while(cure && cure->expr) {
prex(cure->expr, lev+1);
cure = cure->next;
}
break;
case EX_FUNCDECL:
prlev(lev, "FuncDecl:");
lev++;
prlev(lev, "Name: %s", node->funcdecl->name);
prlev(lev, "Args:");
curi = node->funcdecl->args;
while(curi && curi->ident) {
prlev(lev+1, curi->ident);
curi = curi->next;
}
prlev(lev, "Body:");
prst(node->funcdecl->body, lev+1);
break;
}
}
int main(int argc, char **argv) {
stmt_node *program = NULL;
if(argc>1) yydebug = 1;
if(yyparse(&program)) {
printf("Syntax error (somewhere)\n");
printf("Partial tree:\n");
prst(program, 0);
return 1;
}
prst(program, 0);
return 0;
}

506
builtins.c

@ -5,385 +5,389 @@
// 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;
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;
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");
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);
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 *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 *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 *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 *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 *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 *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 *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 *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 *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 *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 *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 *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);
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 *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 *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 *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 *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 *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 *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 *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)
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 *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 *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 *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 *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 *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 *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)
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 *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 *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 *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 *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 *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>");
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 *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 *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 *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 *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>");
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>");
}
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>");
}

2107
lex.yy.c
File diff suppressed because it is too large
View File

364
object.c

@ -1,161 +1,289 @@
#include "sol.h"
#include <stdlib.h>
#include <string.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 *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 *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;
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);
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);
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);
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);
}
if(sol_decref(obj) <= 0) {
obj->ops->free(NULL, 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 *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 *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(sol_state_t *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;
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;
sol_object_t *sol_new_list(sol_state_t *state) {
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;
int i = 0;
sol_object_t *cur = list;
if(!sol_is_list(list)) {
return sol_set_error_string(state, "Compute length of non-list");
}
while(cur && 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)
int i = 0;
sol_object_t *cur = list;
sol_object_t *copy;
if(idx < 0) {
return sol_set_error_string(state, "Create sublist at negative index");
}
while(cur && cur->lvalue && i < idx) {
i++;
cur = cur->lnext;
}
copy = sol_new_list(state);
while(cur && cur->lvalue) {
copy->lvalue = sol_incref(cur->lvalue);
if(cur->lnext) {
copy->lnext = sol_alloc_object(state);
copy = copy->lnext;
copy->type = SOL_LIST;
copy->ops = &(state->ListOps);
}
cur = cur->lnext;
}
return copy;
}
sol_object_t *sol_list_get_index(sol_state_t *state, sol_object_t *list, int idx) {
sol_object_t *cur = list;
int i = 0;
if(idx < 0) {
return sol_set_error_string(state, "Get negative index");
}
while(cur && cur->lvalue && i < idx) {
i++;
cur = cur->lnext;
}
if(cur) {
return sol_incref(cur->lvalue);
} else {
return sol_set_error_string(state, "Get out-of-bounds index");
}
}
void sol_list_set_index(sol_state_t *state, sol_object_t *list, int idx, sol_object_t *obj) {
sol_object_t *cur = list;
int i = 0;
if(idx < 0) {
sol_obj_free(sol_set_error_string(state, "Set negative index"));
return;
}
while(cur && cur->lvalue && i < idx) {
i++;
cur = cur->lnext;
}
if(cur) {
sol_obj_free(cur->lvalue);
cur->lvalue = sol_incref(obj);
} else {