Browse Source

Sol Part 64.1: YOU DIVIDED BY ZERO DIDN'T YOU

master
Graham Northup 4 years ago
parent
commit
563077defa
Signed by: grissess GPG Key ID: 5D000E6F539376FB
  1. 2
      .gitignore
  2. 1
      ast.h
  3. 97
      builtins.c
  4. 27
      lex.yy.c
  5. 485
      parser.tab.c
  6. 4
      parser.y
  7. 11
      programs/solid_run.sol
  8. 8
      programs/test.sol
  9. 6
      sol.h
  10. 4
      state.c
  11. 6
      tests/crasher_apply_noargs.sol
  12. 5
      tests/crasher_range_noargs.sol
  13. 27
      tokenizer.lex

2
.gitignore

@ -15,4 +15,4 @@ doxyxml
valgrind.log
*_INFO
prof
/afl
/afl*

1
ast.h

@ -301,6 +301,7 @@ sol_object_t *sol_new_exprnode(sol_state_t *, expr_node *);
// runtime.c
stmt_node *sol_compile(const char *);
stmt_node *sol_compile_buffer(const char *, size_t);
stmt_node *sol_compile_file(FILE *);
expr_node *sol_comp_as_expr(stmt_node *);
void sol_compile_free(stmt_node *);

97
builtins.c

@ -148,6 +148,12 @@ sol_object_t *sol_f_try(sol_state_t *state, sol_object_t *args) {
sol_object_t *sol_f_apply(sol_state_t *state, sol_object_t *args) {
sol_object_t *func = sol_list_get_index(state, args, 0), *arglist = sol_list_get_index(state, args, 1), *rest = sol_list_sublist(state, args, 2);
if(!sol_is_list(arglist)) {
sol_obj_free(func);
sol_obj_free(arglist);
sol_obj_free(rest);
return sol_set_error_string(state, "apply with non-list");
}
sol_list_append(state, rest, arglist);
sol_obj_free(arglist);
sol_list_insert(state, rest, 0, func);
@ -354,15 +360,23 @@ sol_object_t *sol_f_rawset(sol_state_t *state, sol_object_t *args) {
}
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));
sol_object_t *res = sol_new_list(state), *bound = sol_list_get_index(state, args, 0);
sol_object_t *boundi = sol_cast_int(state, bound);
int i;
for(i = 0; i < bound->ival; i++) {
sol_obj_free(bound);
if(sol_has_error(state)) {
sol_obj_free(boundi);
sol_obj_free(res);
return sol_incref(state->None);
}
for(i = 0; i < boundi->ival; i++) {
sol_list_insert(state, res, sol_list_len(state, res), sol_new_int(state, i));
}
sol_obj_free(bound);
sol_obj_free(boundi);
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;
@ -392,6 +406,7 @@ sol_object_t *sol_f_eval(sol_state_t *state, sol_object_t *args) {
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);
@ -421,17 +436,28 @@ sol_object_t *sol_f_execfile(sol_state_t *state, sol_object_t *args) {
if(!program) {
return sol_set_error_string(state, "Compilation failure");
}
// XXX should st_free(program);
sol_exec(state, program);
st_free(program);
return sol_incref(state->None);
}
sol_object_t *sol_f_parse(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 = sol_compile(prgstr->str);
sol_object_t *prg = sol_list_get_index(state, args, 0), *prgstr;
stmt_node *program;
if(sol_is_buffer(prg)) {
if(prg->sz >= 0) {
program = sol_compile_buffer(prg->buffer, prg->sz);
} else {
sol_obj_free(prg);
return sol_set_error_string(state, "parse unsized buffer");
}
} else {
prgstr = sol_cast_string(state, prg);
program = sol_compile(prgstr->str);
sol_obj_free(prgstr);
}
sol_obj_free(prg);
sol_obj_free(prgstr);
if(!program) {
return sol_set_error_string(state, "Compilation failure");
}
@ -698,6 +724,7 @@ sol_object_t *sol_f_int_add(sol_state_t *state, sol_object_t *args) {
sol_object_t *res = sol_new_int(state, a->ival + bint->ival);
sol_obj_free(a);
sol_obj_free(b);
sol_obj_free(bint);
if(sol_has_error(state)) {
sol_obj_free(res);
return sol_incref(state->None);
@ -710,6 +737,7 @@ sol_object_t *sol_f_int_sub(sol_state_t *state, sol_object_t *args) {
sol_object_t *res = sol_new_int(state, a->ival - bint->ival);
sol_obj_free(a);
sol_obj_free(b);
sol_obj_free(bint);
if(sol_has_error(state)) {
sol_obj_free(res);
return sol_incref(state->None);
@ -722,6 +750,7 @@ sol_object_t *sol_f_int_mul(sol_state_t *state, sol_object_t *args) {
sol_object_t *res = sol_new_int(state, a->ival * bint->ival);
sol_obj_free(a);
sol_obj_free(b);
sol_obj_free(bint);
if(sol_has_error(state)) {
sol_obj_free(res);
return sol_incref(state->None);
@ -731,9 +760,16 @@ sol_object_t *sol_f_int_mul(sol_state_t *state, sol_object_t *args) {
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_list_get_index(state, args, 1), *bint = sol_cast_int(state, b);
sol_object_t *res = sol_new_int(state, a->ival / bint->ival);
sol_obj_free(a);
sol_object_t *res;
sol_obj_free(b);
if(bint->ival == 0) {
sol_obj_free(a);
sol_obj_free(bint);
return sol_set_error_string(state, "integer divide by zero");
}
res = sol_new_int(state, a->ival / bint->ival);
sol_obj_free(a);
sol_obj_free(bint);
if(sol_has_error(state)) {
sol_obj_free(res);
return sol_incref(state->None);
@ -743,9 +779,16 @@ sol_object_t *sol_f_int_div(sol_state_t *state, sol_object_t *args) {
sol_object_t *sol_f_int_mod(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), *bint = sol_cast_int(state, b);
sol_object_t *res = sol_new_int(state, a->ival % bint->ival);
sol_obj_free(a);
sol_object_t *res;
sol_obj_free(b);
if(bint->ival == 0) {
sol_obj_free(a);
sol_obj_free(bint);
return sol_set_error_string(state, "integer modulus by zero");
}
res = sol_new_int(state, a->ival % bint->ival);
sol_obj_free(a);
sol_obj_free(bint);
if(sol_has_error(state)) {
sol_obj_free(res);
return sol_incref(state->None);
@ -758,6 +801,7 @@ sol_object_t *sol_f_int_pow(sol_state_t *state, sol_object_t *args) {
sol_object_t *res = sol_new_int(state, (long) pow((double) a->ival, bint->ival));
sol_obj_free(a);
sol_obj_free(b);
sol_obj_free(bint);
if(sol_has_error(state)) {
sol_obj_free(res);
return sol_incref(state->None);
@ -770,6 +814,7 @@ sol_object_t *sol_f_int_band(sol_state_t *state, sol_object_t *args) {
sol_object_t *res = sol_new_int(state, a->ival & bint->ival);
sol_obj_free(a);
sol_obj_free(b);
sol_obj_free(bint);
if(sol_has_error(state)) {
sol_obj_free(res);
return sol_incref(state->None);
@ -782,6 +827,7 @@ sol_object_t *sol_f_int_bor(sol_state_t *state, sol_object_t *args) {
sol_object_t *res = sol_new_int(state, a->ival | bint->ival);
sol_obj_free(a);
sol_obj_free(b);
sol_obj_free(bint);
if(sol_has_error(state)) {
sol_obj_free(res);
return sol_incref(state->None);
@ -794,6 +840,7 @@ sol_object_t *sol_f_int_bxor(sol_state_t *state, sol_object_t *args) {
sol_object_t *res = sol_new_int(state, a->ival ^ bint->ival);
sol_obj_free(a);
sol_obj_free(b);
sol_obj_free(bint);
if(sol_has_error(state)) {
sol_obj_free(res);
return sol_incref(state->None);
@ -806,6 +853,7 @@ sol_object_t *sol_f_int_blsh(sol_state_t *state, sol_object_t *args) {
sol_object_t *res = sol_new_int(state, a->ival << bint->ival);
sol_obj_free(a);
sol_obj_free(b);
sol_obj_free(bint);
if(sol_has_error(state)) {
sol_obj_free(res);
return sol_incref(state->None);
@ -818,6 +866,7 @@ sol_object_t *sol_f_int_brsh(sol_state_t *state, sol_object_t *args) {
sol_object_t *res = sol_new_int(state, a->ival >> bint->ival);
sol_obj_free(a);
sol_obj_free(b);
sol_obj_free(bint);
if(sol_has_error(state)) {
sol_obj_free(res);
return sol_incref(state->None);
@ -870,6 +919,7 @@ sol_object_t *sol_f_float_add(sol_state_t *state, sol_object_t *args) {
sol_object_t *res = sol_new_float(state, a->fval + bflt->fval);
sol_obj_free(a);
sol_obj_free(b);
sol_obj_free(bflt);
if(sol_has_error(state)) {
sol_obj_free(res);
return sol_incref(state->None);
@ -882,6 +932,7 @@ sol_object_t *sol_f_float_sub(sol_state_t *state, sol_object_t *args) {
sol_object_t *res = sol_new_float(state, a->fval - bflt->fval);
sol_obj_free(a);
sol_obj_free(b);
sol_obj_free(bflt);
if(sol_has_error(state)) {
sol_obj_free(res);
return sol_incref(state->None);
@ -894,6 +945,7 @@ sol_object_t *sol_f_float_mul(sol_state_t *state, sol_object_t *args) {
sol_object_t *res = sol_new_float(state, a->fval * bflt->fval);
sol_obj_free(a);
sol_obj_free(b);
sol_obj_free(bflt);
if(sol_has_error(state)) {
sol_obj_free(res);
return sol_incref(state->None);
@ -903,9 +955,16 @@ sol_object_t *sol_f_float_mul(sol_state_t *state, sol_object_t *args) {
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_list_get_index(state, args, 1), *bflt = sol_cast_float(state, b);
sol_object_t *res = sol_new_float(state, a->fval / bflt->fval);
sol_obj_free(a);
sol_object_t *res;
sol_obj_free(b);
if(bflt->fval == 0.0) {
sol_obj_free(a);
sol_obj_free(bflt);
return sol_set_error_string(state, "floating division by zero");
}
res = sol_new_float(state, a->fval / bflt->fval);
sol_obj_free(a);
sol_obj_free(bflt);
if(sol_has_error(state)) {
sol_obj_free(res);
return sol_incref(state->None);
@ -916,8 +975,9 @@ sol_object_t *sol_f_float_div(sol_state_t *state, sol_object_t *args) {
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_list_get_index(state, args, 1), *bflt = sol_cast_float(state, b);
sol_object_t *res = sol_new_float(state, pow(a->fval, bflt->fval));
sol_obj_free(a);
sol_obj_free(b);
sol_obj_free(a);
sol_obj_free(bflt);
if(sol_has_error(state)) {
sol_obj_free(res);
return sol_incref(state->None);
@ -963,6 +1023,7 @@ sol_object_t *sol_f_str_add(sol_state_t *state, sol_object_t *args) {
sol_object_t *res = sol_string_concat(state, a, bstr);
sol_obj_free(a);
sol_obj_free(b);
sol_obj_free(bstr);
if(sol_has_error(state)) {
sol_obj_free(res);
return sol_incref(state->None);
@ -2415,7 +2476,7 @@ sol_object_t *sol_f_buffer_index(sol_state_t *state, sol_object_t *args) {
if(sol_is_name(key)) {
res = sol_map_get(state, funcs, key);
} else if(sol_is_int(key)) {
res = sol_new_buffer(state, a->buffer, (a->sz < 0) ? a->sz : (a->sz - key->ival), OWN_NONE, NULL, NULL);
res = sol_new_buffer(state, ((char *) a->buffer) + key->ival, (a->sz < 0) ? a->sz : (a->sz - key->ival), OWN_NONE, NULL, NULL);
} else {
res = sol_f_not_impl(state, args);
}
@ -2545,14 +2606,14 @@ sol_object_t *sol_f_buffer_repr(sol_state_t *state, sol_object_t *args) {
sol_object_t *sol_f_buffer_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->buffer));
sol_object_t *res = sol_new_int(state, a->buffer ? atoi(a->buffer) : 0);
sol_obj_free(a);
return res;
}
sol_object_t *sol_f_buffer_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->buffer));
sol_object_t *res = sol_new_float(state, a->buffer ? atof(a->buffer) : 0.0);
sol_obj_free(a);
return res;
}
@ -2864,7 +2925,7 @@ sol_object_t *sol_f_buffer_sub(sol_state_t *state, sol_object_t *args) {
return sol_new_buffer(state, NULL, 0, OWN_NONE, NULL, NULL);
}
b = malloc(sizeof(char) * (h - l));
memcpy(b, buf->buffer, h - l);
memcpy(b, ((char *) buf->buffer) + l, h - l);
sol_obj_free(buf);
return sol_new_buffer(state, b, h - l, OWN_FREE, NULL, NULL);
}

27
lex.yy.c

@ -572,7 +572,7 @@ char *yytext;
#include <string.h>
#include <stdio.h>
void yyerror(YYLTYPE *, char *);
void yyerror(YYLTYPE *, stmt_node **, char *);
int yywrap(void);
char *str, *curptr;
@ -600,11 +600,11 @@ void str_putc(char c) {
/* Many thanks to hugomg and David Elson! */
static void update_loc(YYLTYPE *yylloc, char *yytext){
static int curr_line = 1;
static int curr_col = 1;
int curr_line;
int curr_col;
yylloc->first_line = curr_line;
yylloc->first_column = curr_col;
curr_line = yylloc->first_line = yylloc->last_line;
curr_col = yylloc->first_column = yylloc->last_column;
{char * s; for(s = yytext; *s != '\0'; s++){
if(*s == '\n'){
@ -2322,9 +2322,12 @@ int yywrap(void) {
return 1;
}
void yyerror(YYLTYPE *locp, char *err) {
puts(err);
printf("(at lines %d-%d, cols %d-%d)\n", locp->first_line, locp->last_line, locp->first_column, locp->last_column);
void yyerror(YYLTYPE *locp, stmt_node **prog, char *err) {
fputs(err, stderr);
fprintf(stderr, "\n(at lines %d-%d, cols %d-%d)\n", locp->first_line, locp->last_line, locp->first_column, locp->last_column);
if(prog && *prog) {
fprintf(stderr, "(while building a stmt of type %d)\n", (*prog)->type);
}
}
stmt_node *sol_compile(const char *prgstr) {
@ -2335,6 +2338,14 @@ stmt_node *sol_compile(const char *prgstr) {
return program;
}
stmt_node *sol_compile_buffer(const char *prgbuf, size_t sz) {
stmt_node *program = NULL;
YY_BUFFER_STATE buf = yy_scan_bytes(prgbuf, sz);
yyparse(&program);
yy_delete_buffer(buf);
return program;
}
stmt_node *sol_compile_file(FILE *prgfile) {
stmt_node *program = NULL;
YY_BUFFER_STATE buf = yy_create_buffer(prgfile, YY_BUF_SIZE);

485
parser.tab.c
File diff suppressed because it is too large
View File

4
parser.y

@ -37,6 +37,10 @@ void yyerror(loc_t *, stmt_node **, char *);
%debug
%locations
%initial-action {
@$.first_line = 1; @$.first_column = 0;
@$.last_line = 1; @$.last_column = 1;
}
%%

11
programs/solid_run.sol

@ -0,0 +1,11 @@
execfile('solid.sol')
io.stdout:write('Enter filename to run: ')
__fname = io.stdin:read(io.LINE):sub(0, -1)
__result = try(execfile, __fname)
if __result[0] then
print('Subprogram exited successfully')
else
print('Subprogram terminated with an error: ', __result[1])
__debst = new_debug_state(__result)
postmortem(__debst)
end

8
programs/test.sol

@ -182,10 +182,10 @@ print('--- Map/filter chain')
print([1 2 3 4 5]:map(func (i) return i * 3 end):filter(func (i) return i & 1 end))
print('--- Exec/eval')
exec('print("Hello from exec!")')
print(eval('5 + 3'))
execfile('programs/subtest.sol')
print('(removed from core language)')
--exec('print("Hello from exec!")')
--print(eval('5 + 3'))
--execfile('programs/subtest.sol')
print('--- Modulus')

6
sol.h

@ -10,7 +10,7 @@
#include "dsl/dsl.h"
/** The version of the project, as made available through `debug.version`. */
#define SOL_VERSION "0.4a0"
#define SOL_VERSION "0.4a1"
/** The hexadecimal version of the project, formatted 0xAAIIRPP where:
*
* - AA is the two-digit major version
@ -739,9 +739,9 @@ sol_object_t *sol_f_rawset(sol_state_t *, sol_object_t *);
/// Built-in function range
sol_object_t *sol_f_range(sol_state_t *, sol_object_t *);
/// Built-in function exec
sol_object_t *sol_f_exec(sol_state_t *, sol_object_t *);
//sol_object_t *sol_f_exec(sol_state_t *, sol_object_t *);
/// Built-in function eval
sol_object_t *sol_f_eval(sol_state_t *, sol_object_t *);
//sol_object_t *sol_f_eval(sol_state_t *, sol_object_t *);
/// Built-in function execfile
sol_object_t *sol_f_execfile(sol_state_t *, sol_object_t *);
/// Built-in function parse

4
state.c

@ -263,8 +263,8 @@ int sol_state_init(sol_state_t *state) {
sol_map_borrow_name(state, globals, "rawget", sol_new_cfunc(state, sol_f_rawget, "rawget"));
sol_map_borrow_name(state, globals, "rawset", sol_new_cfunc(state, sol_f_rawset, "rawset"));
sol_map_borrow_name(state, globals, "range", sol_new_cfunc(state, sol_f_range, "range"));
sol_map_borrow_name(state, globals, "exec", sol_new_cfunc(state, sol_f_exec, "exec"));
sol_map_borrow_name(state, globals, "eval", sol_new_cfunc(state, sol_f_eval, "eval"));
//sol_map_borrow_name(state, globals, "exec", sol_new_cfunc(state, sol_f_exec, "exec"));
//sol_map_borrow_name(state, globals, "eval", sol_new_cfunc(state, sol_f_eval, "eval"));
sol_map_borrow_name(state, globals, "execfile", sol_new_cfunc(state, sol_f_execfile, "execfile"));
sol_map_borrow_name(state, globals, "parse", sol_new_cfunc(state, sol_f_parse, "parse"));
sol_map_borrow_name(state, globals, "ord", sol_new_cfunc(state, sol_f_ord, "ord"));

6
tests/crasher_apply_noargs.sol

@ -0,0 +1,6 @@
execfile("tests/_lib.sol")
assert_eq(try(apply)[0], 0, "apply with no args causes error")
assert_eq(try(apply, print, 7)[0], 0, "apply with non-list (int) causes error")
assert_eq(try(apply, print, {})[0], 0, "apply with non-list (map) causes error")
assert_eq(try(apply, print, "foo")[0], 0, "apply with non-list (strbuf) causes error")

5
tests/crasher_range_noargs.sol

@ -0,0 +1,5 @@
execfile('tests/_lib.sol')
assert_eq(try(range)[0], 0, "range with no args causes error")
assert_eq(try(range, [])[0], 0, "range with list arg causes error")
assert_eq(try(range, {})[0], 0, "range with map arg causes error")

27
tokenizer.lex

@ -8,7 +8,7 @@
#include <string.h>
#include <stdio.h>
void yyerror(YYLTYPE *, char *);
void yyerror(YYLTYPE *, stmt_node **, char *);
int yywrap(void);
char *str, *curptr;
@ -36,11 +36,11 @@ void str_putc(char c) {
/* Many thanks to hugomg and David Elson! */
static void update_loc(YYLTYPE *yylloc, char *yytext){
static int curr_line = 1;
static int curr_col = 1;
int curr_line;
int curr_col;
yylloc->first_line = curr_line;
yylloc->first_column = curr_col;
curr_line = yylloc->first_line = yylloc->last_line;
curr_col = yylloc->first_column = yylloc->last_column;
{char * s; for(s = yytext; *s != '\0'; s++){
if(*s == '\n'){
@ -235,9 +235,12 @@ int yywrap(void) {
return 1;
}
void yyerror(YYLTYPE *locp, char *err) {
puts(err);
printf("(at lines %d-%d, cols %d-%d)\n", locp->first_line, locp->last_line, locp->first_column, locp->last_column);
void yyerror(YYLTYPE *locp, stmt_node **prog, char *err) {
fputs(err, stderr);
fprintf(stderr, "\n(at lines %d-%d, cols %d-%d)\n", locp->first_line, locp->last_line, locp->first_column, locp->last_column);
if(prog && *prog) {
fprintf(stderr, "(while building a stmt of type %d)\n", (*prog)->type);
}
}
stmt_node *sol_compile(const char *prgstr) {
@ -248,6 +251,14 @@ stmt_node *sol_compile(const char *prgstr) {
return program;
}
stmt_node *sol_compile_buffer(const char *prgbuf, size_t sz) {
stmt_node *program = NULL;
YY_BUFFER_STATE buf = yy_scan_bytes(prgbuf, sz);
yyparse(&program);
yy_delete_buffer(buf);
return program;
}
stmt_node *sol_compile_file(FILE *prgfile) {
stmt_node *program = NULL;
YY_BUFFER_STATE buf = yy_create_buffer(prgfile, YY_BUF_SIZE);

Loading…
Cancel
Save