1
0
mirror of https://github.com/janet-lang/janet synced 2024-06-25 22:53:16 +00:00

More work on improving errors.

This commit is contained in:
Calvin Rose 2018-04-29 20:13:04 -04:00
parent 96897a0d7a
commit 53f9c18669
9 changed files with 153 additions and 299 deletions

View File

@ -29,7 +29,7 @@ BINDIR=$(PREFIX)/bin
# TODO - when api is finalized, only export public symbols instead of using rdynamic
# which exports all symbols.
CFLAGS=-std=c99 -Wall -Wextra -Isrc/include -rdynamic -s -O3
CFLAGS=-std=c99 -Wall -Wextra -Isrc/include -rdynamic -s -O2
CLIBS=-lm -ldl
PREFIX=/usr/local
DST_TARGET=dst

View File

@ -23,7 +23,7 @@
#include <dst/dst.h>
#include "gc.h"
/* Iniializes an array */
/* Initializes an array */
DstArray *dst_array_init(DstArray *array, int32_t capacity) {
Dst *data = NULL;
if (capacity > 0) {
@ -67,7 +67,7 @@ void dst_array_setcount(DstArray *array, int32_t count) {
return;
if (count > array->count) {
int32_t i;
dst_array_ensure(array, count + 1);
dst_array_ensure(array, count);
for (i = array->count; i < count; i++) {
array->data[i] = dst_wrap_nil();
}

View File

@ -62,6 +62,18 @@ void dst_buffer_ensure(DstBuffer *buffer, int32_t capacity) {
buffer->capacity = capacity;
}
/* Ensure that the buffer has enough internal capacity */
void dst_buffer_setcount(DstBuffer *buffer, int32_t count) {
if (count < 0)
return;
if (count > buffer->count) {
int32_t oldcount = buffer->count;
dst_buffer_ensure(buffer, count);
memset(buffer->data + oldcount, 0, count - oldcount);
}
buffer->count = count;
}
/* Adds capacity for enough extra bytes to the buffer. Ensures that the
* next n bytes pushed to the buffer will not cause a reallocation */
int dst_buffer_extra(DstBuffer *buffer, int32_t n) {
@ -148,11 +160,13 @@ int dst_buffer_push_u64(DstBuffer *buffer, uint64_t x) {
static int cfun_u8(DstArgs args) {
int32_t i;
DstBuffer *buffer;
if (args.n < 1 || !dst_checktype(args.v[0], DST_BUFFER)) return dst_throw(args, "expected buffer");
buffer = dst_unwrap_buffer(args.v[0]);
dst_minarity(args, 1);
dst_arg_buffer(buffer, args, 0);
for (i = 1; i < args.n; i++) {
if (!dst_checktype(args.v[i], DST_INTEGER)) return dst_throw(args, "expected integer");
if (dst_buffer_push_u8(buffer, (uint8_t) (dst_unwrap_integer(args.v[i]) & 0xFF))) return dst_throw(args, "buffer overflow");
int32_t integer;
dst_arg_integer(integer, args, i);
if (dst_buffer_push_u8(buffer, (uint8_t) (integer & 0xFF)))
return dst_throw(args, "buffer overflow");
}
return dst_return(args, args.v[0]);
}
@ -160,11 +174,13 @@ static int cfun_u8(DstArgs args) {
static int cfun_int(DstArgs args) {
int32_t i;
DstBuffer *buffer;
if (args.n < 1 || !dst_checktype(args.v[0], DST_BUFFER)) return dst_throw(args, "expected buffer");
buffer = dst_unwrap_buffer(args.v[0]);
dst_minarity(args, 1);
dst_arg_buffer(buffer, args, 0);
for (i = 1; i < args.n; i++) {
if (!dst_checktype(args.v[i], DST_INTEGER)) return dst_throw(args, "expected integer");
if (dst_buffer_push_u32(buffer, (uint32_t) dst_unwrap_integer(args.v[i]))) return dst_throw(args, "buffer overflow");
int32_t integer;
dst_arg_integer(integer, args, i);
if (dst_buffer_push_u32(buffer, (uint32_t) integer))
return dst_throw(args, "buffer overflow");
}
return dst_return(args, args.v[0]);
}
@ -172,38 +188,37 @@ static int cfun_int(DstArgs args) {
static int cfun_chars(DstArgs args) {
int32_t i;
DstBuffer *buffer;
if (args.n < 1 || !dst_checktype(args.v[0], DST_BUFFER)) return dst_throw(args, "expected buffer");
buffer = dst_unwrap_buffer(args.v[0]);
dst_minarity(args, 1);
dst_arg_buffer(buffer, args, 0);
for (i = 1; i < args.n; i++) {
int32_t len;
const uint8_t *str;
if (!dst_chararray_view(args.v[i], &str, &len)) return dst_throw(args, "expected string/buffer");
if (dst_buffer_push_bytes(buffer, str, len)) return dst_throw(args, "buffer overflow");
if (!dst_chararray_view(args.v[i], &str, &len))
return dst_throw(args, "expected string|symbol|buffer");
if (dst_buffer_push_bytes(buffer, str, len))
return dst_throw(args, "buffer overflow");
}
return dst_return(args, args.v[0]);
}
static int cfun_clear(DstArgs args) {
DstBuffer *buffer;
if (args.n < 1 || !dst_checktype(args.v[0], DST_BUFFER)) return dst_throw(args, "expected buffer");
buffer = dst_unwrap_buffer(args.v[0]);
dst_fixarity(args, 1);
dst_arg_buffer(buffer, args, 0);
buffer->count = 0;
return dst_return(args, args.v[0]);
}
static int cfun_popn(DstArgs args) {
DstBuffer *buffer;
int32_t i;
if (args.n < 2
|| !dst_checktype(args.v[0], DST_BUFFER)
|| !dst_checktype(args.v[1], DST_INTEGER)) return dst_throw(args, "expected buffer and integer");
buffer = dst_unwrap_buffer(args.v[0]);
i = dst_unwrap_integer(args.v[1]);
if (i < 0) return dst_throw(args, "expected positive integer");
if (buffer->count < i) {
int32_t n;
dst_fixarity(args, 2);
dst_arg_buffer(buffer, args, 0);
dst_arg_integer(n, args, 1);
if (buffer->count < n) {
buffer->count = 0;
} else {
buffer->count -= i;
buffer->count -= n;
}
return dst_return(args, args.v[0]);
}

View File

@ -259,17 +259,16 @@ void dst_fiber_popframe(DstFiber *fiber) {
static int cfun_fiber(DstArgs args) {
DstFiber *fiber;
if (args.n < 1) return dst_throw(args, "expected at least 1 argument");
if (!dst_checktype(args.v[0], DST_FUNCTION))
return dst_throw(args, "expected a function");
dst_fixarity(args, 1);
dst_check(args, 0, DST_FUNCTION);
fiber = dst_fiber(dst_unwrap_function(args.v[0]), 64);
return dst_return(args, dst_wrap_fiber(fiber));
}
static int cfun_status(DstArgs args) {
const char *status = "";
if (args.n != 1) return dst_throw(args, "expected 1 argument");
if (!dst_checktype(args.v[0], DST_FIBER)) return dst_throw(args, "expected fiber");
dst_fixarity(args, 1);
dst_check(args, 0, DST_FIBER);
switch(dst_unwrap_fiber(args.v[0])->status) {
case DST_FIBER_PENDING:
status = ":pending";
@ -330,8 +329,8 @@ static Dst doframe(DstStackFrame *frame) {
static int cfun_stack(DstArgs args) {
DstFiber *fiber;
DstArray *array;
if (args.n != 1) return dst_throw(args, "expected 1 argument");
if (!dst_checktype(args.v[0], DST_FIBER)) return dst_throw(args, "expected fiber");
dst_fixarity(args, 1);
dst_check(args, 0, DST_FIBER);
fiber = dst_unwrap_fiber(args.v[0]);
array = dst_array(0);
{

View File

@ -84,16 +84,16 @@ static int checkflags(const uint8_t *str, int32_t len) {
static IOFile *checkfile(DstArgs args, int32_t n) {
IOFile *iof;
if (n >= args.n) {
*args.ret = dst_cstringv("expected core.file");
*args.ret = dst_cstringv("expected core.file");
return NULL;
}
if (!dst_checktype(args.v[n], DST_ABSTRACT)) {
*args.ret = dst_cstringv("expected core.file");
*args.ret = dst_cstringv("expected core.file");
return NULL;
}
iof = (IOFile *) dst_unwrap_abstract(args.v[n]);
if (dst_abstract_type(iof) != &dst_io_filetype) {
*args.ret = dst_cstringv("expected core.file");
*args.ret = dst_cstringv("expected core.file");
return NULL;
}
return iof;
@ -105,11 +105,11 @@ static DstBuffer *checkbuffer(DstArgs args, int32_t n, int optional) {
return dst_buffer(0);
}
if (n >= args.n) {
*args.ret = dst_cstringv("expected buffer");
*args.ret = dst_cstringv("expected buffer");
return NULL;
}
if (!dst_checktype(args.v[n], DST_BUFFER)) {
*args.ret = dst_cstringv("expected buffer");
*args.ret = dst_cstringv("expected buffer");
return NULL;
}
return dst_unwrap_abstract(args.v[n]);
@ -141,8 +141,9 @@ static int dst_io_fopen(DstArgs args) {
int32_t modelen;
FILE *f;
int flags;
if (args.n < 1 || args.n > 2) return dst_throw(args, "expected 1 or 2 arguments");
if (!dst_checktype(args.v[0], DST_STRING)) return dst_throw(args, "expected string filename");
dst_minarity(args, 1);
dst_maxarity(args, 2);
dst_check(args, 0, DST_STRING);
fname = dst_unwrap_string(args.v[0]);
if (args.n == 2) {
if (!dst_checktype(args.v[1], DST_STRING) &&

View File

@ -206,13 +206,20 @@ int dst_hashtable_view(Dst tab, const DstKV **data, int32_t *len, int32_t *cap)
return 0;
}
int dst_type_err(DstArgs args, int32_t n, DstType expected) {
/* Get actual type name of a value for debugging purposes */
static const char *typestr(DstArgs args, int32_t n) {
DstType actual = n < args.n ? dst_type(args.v[n]) : DST_NIL;
return (actual == DST_ABSTRACT)
? dst_abstract_type(dst_unwrap_abstract(args.v[n]))->name
: dst_type_names[actual];
}
int dst_type_err(DstArgs args, int32_t n, DstType expected) {
const uint8_t *message = dst_formatc(
"bad argument #%d, expected %t, got %t",
"bad argument #%d, expected %t, got %s",
n,
expected,
actual);
typestr(args, n));
return dst_throwv(args, dst_wrap_string(message));
}
@ -220,7 +227,6 @@ int dst_typemany_err(DstArgs args, int32_t n, int expected) {
int i;
int first = 1;
const uint8_t *message;
DstType actual = n < args.n ? dst_type(args.v[n]) : DST_NIL;
DstBuffer buf;
dst_buffer_init(&buf, 20);
dst_buffer_push_string(&buf, dst_formatc("bad argument #%d, expected ", n));
@ -238,7 +244,7 @@ int dst_typemany_err(DstArgs args, int32_t n, int expected) {
expected >>= 1;
}
dst_buffer_push_cstring(&buf, ", got ");
dst_buffer_push_cstring(&buf, dst_type_names[actual] + 1);
dst_buffer_push_cstring(&buf, typestr(args, n));
message = dst_string(buf.data, buf.count);
dst_buffer_deinit(&buf);
return dst_throwv(args, dst_wrap_string(message));
@ -250,3 +256,10 @@ int dst_arity_err(DstArgs args, int32_t n, const char *prefix) {
"expected %s%d argument%s, got %d",
prefix, n, n == 1 ? "" : "s", args.n)));
}
int dst_typeabstract_err(DstArgs args, int32_t n, DstAbstractType *at) {
return dst_throwv(args,
dst_wrap_string(dst_formatc(
"bad argument #%d, expected %t, got %s",
n, at->name, typestr(args, n))));
}

View File

@ -151,10 +151,8 @@ int dst_compare(Dst x, Dst y) {
return dst_unwrap_string(x) > dst_unwrap_string(y) ? 1 : -1;
}
}
} else if (dst_type(x) < dst_type(y)) {
return -1;
}
return 1;
}
return (dst_type(x) < dst_type(y)) ? -1 : 1;
}
/* Get a value out af an associated data structure. For invalid
@ -200,19 +198,36 @@ Dst dst_get(Dst ds, Dst key) {
* error message, and NULL if no error. */
void dst_put(Dst ds, Dst key, Dst value) {
switch (dst_type(ds)) {
case DST_ARRAY:
if (dst_checktype(key, DST_INTEGER) &&
dst_unwrap_integer(key) >= 0 &&
dst_unwrap_integer(key) < dst_unwrap_array(ds)->count)
dst_unwrap_array(ds)->data[dst_unwrap_integer(key)] = value;
case DST_ARRAY:
{
int32_t index;
DstArray *array = dst_unwrap_array(ds);
if (!dst_checktype(key, DST_INTEGER) || dst_unwrap_integer(key) < 0)
return;
index = dst_unwrap_integer(key);
if (index == INT32_MAX) return;
if (index >= array->count) {
dst_array_setcount(array, index + 1);
}
array->data[index]= value;
return;
}
case DST_BUFFER:
if (dst_checktype(key, DST_INTEGER) &&
dst_checktype(value, DST_INTEGER) &&
dst_unwrap_integer(key) >= 0 &&
dst_unwrap_integer(key) < dst_unwrap_buffer(ds)->count)
dst_unwrap_buffer(ds)->data[dst_unwrap_integer(key)] = dst_unwrap_integer(value);
{
int32_t index;
DstBuffer *buffer = dst_unwrap_buffer(ds);
if (!dst_checktype(key, DST_INTEGER) || dst_unwrap_integer(key) < 0)
return;
index = dst_unwrap_integer(key);
if (index == INT32_MAX) return;
if (!dst_checktype(value, DST_INTEGER))
return;
if (index >= buffer->count) {
dst_buffer_setcount(buffer, index + 1);
}
buffer->data[index] = (uint8_t) (dst_unwrap_integer(value) & 0xFF);
return;
}
case DST_TABLE:
dst_table_put(dst_unwrap_table(ds), key, value);
return;

View File

@ -1,240 +0,0 @@
{
dst_array;
dst_array_init;
dst_array_deinit;
dst_array_ensure;
dst_array_setcount;
dst_array_push;
dst_array_pop;
dst_array_peek;
dst_buffer;
dst_buffer_init;
dst_buffer_deinit;
dst_buffer_ensure;
dst_buffer_extra;
dst_buffer_push_bytes;
dst_buffer_push_cstring;
dst_buffer_push_u8;
dst_buffer_push_u16;
dst_buffer_push_u32;
dst_buffer_push_u64;
dst_tuple_begin;
dst_tuple_end;
dst_tuple_n;
dst_tuple_equal;
dst_tuple_compare;
dst_string_begin;
dst_string_end;
dst_string;
dst_cstring;
dst_string_compare;
dst_string_equal;
dst_string_equalconst;
dst_string_unique;
dst_cstring_unique;
dst_description;
dst_to_string;
dst_to_zerostring;
dst_formatc;
dst_puts;
dst_symbol;
dst_symbol_from_string;
dst_csymbol;
dst_symbol_gen;
dst_struct_begin;
dst_struct_put;
dst_struct_end;
dst_struct_get;
dst_struct_next;
dst_struct_to_table;
dst_struct_equal;
dst_struct_compare;
dst_struct_find;
dst_table;
dst_table_init;
dst_table_deinit;
dst_table_get;
dst_table_rawget;
dst_table_remove;
dst_table_put;
dst_table_next;
dst_table_to_struct;
dst_table_merge_table;
dst_table_merge_struct;
dst_table_find;
dst_fiber;
dst_seq_view;
dst_chararray_view;
dst_hashtable_view;
dst_abstract;
dst_native;
dst_mark;
dst_sweep;
dst_collect;
dst_clear_memory;
dst_gcroot;
dst_gcunroot;
dst_gcunrootall;
dst_gclock;
dst_gcunlock;
dst_funcdef_alloc;
dst_thunk;
dst_verify;
dst_quick_asm;
dst_equals;
dst_hash;
dst_compare;
dst_get;
dst_put;
dst_next;
dst_length;
dst_getindex;
dst_setindex;
dst_cstrcmp;
dst_init;
dst_deinit;
dst_run;
dst_resume;
dst_env_def;
dst_env_var;
dst_env_cfuns;
dst_env_resolve;
dst_env_arg;
dst_stl_env;
dst_asm;
dst_disasm;
dst_asm_decode_instruction;
dst_asm_cfun;
dst_disasm_cfun;
dst_lib_asm;
dst_compile;
dst_compile_cfun;
dst_lib_compile;
dst_stl_env;
dst_dobytes;
dst_dostring;
dst_core_native;
dst_int;
dst_real;
dst_add;
dst_subtract;
dst_multiply;
dst_divide;
dst_modulo;
dst_rand;
dst_srand;
dst_strict_equal;
dst_strict_notequal;
dst_ascending;
dst_descending;
dst_notdescending;
dst_notascending;
dst_numeric_eq;
dst_numeric_neq;
dst_numeric_gt;
dst_numeric_lt;
dst_numeric_gte;
dst_numeric_lte;
dst_bor;
dst_band;
dst_bxor;
dst_bnot;
dst_lshift;
dst_rshift;
dst_lshiftu;
dst_not;
dst_cos;
dst_sin;
dst_tan;
dst_acos;
dst_asin;
dst_atan;
dst_exp;
dst_log;
dst_log10;
dst_sqrt;
dst_floor;
dst_ceil;
dst_pow;
dst_core_print;
dst_core_describe;
dst_core_string;
dst_core_symbol;
dst_core_buffer;
dst_core_tuple;
dst_core_array;
dst_core_table;
dst_core_struct;
dst_core_buffer;
dst_core_gensym;
dst_core_length;
dst_core_get;
dst_core_rawget;
dst_core_getproto;
dst_core_setproto;
dst_core_put;
dst_core_type;
dst_core_next;
dst_core_hash;
dst_core_string_slice;
dst_core_gccollect;
dst_core_gcsetinterval;
dst_core_gcinterval;
dst_lib_io;
dst_lib_math;
dst_lib_array;
dst_lib_tuple;
dst_lib_buffer;
dst_lib_table;
dst_lib_fiber;
dst_lib_os;
dst_ast_wrap;
dst_ast_node;
dst_ast_unwrap1;
dst_ast_unwrap;
dst_scan_number;
dst_scan_integer;
dst_scan_real;
dst_parser_init;
dst_parser_deinit;
dst_parser_consume;
dst_parser_status;
dst_parser_produce;
dst_parser_error;
dst_parse_cfun;
dst_lib_parse;
};

View File

@ -51,6 +51,7 @@ DstBuffer *dst_buffer(int32_t capacity);
DstBuffer *dst_buffer_init(DstBuffer *buffer, int32_t capacity);
void dst_buffer_deinit(DstBuffer *buffer);
void dst_buffer_ensure(DstBuffer *buffer, int32_t capacity);
void dst_buffer_setcount(DstBuffer *buffer, int32_t count);
int dst_buffer_extra(DstBuffer *buffer, int32_t n);
int dst_buffer_push_bytes(DstBuffer *buffer, const uint8_t *string, int32_t len);
int dst_buffer_push_string(DstBuffer *buffer, const uint8_t *string);
@ -195,9 +196,12 @@ DstTable *dst_stl_env(void);
int dst_arity_err(DstArgs args, int32_t n, const char *prefix);
int dst_type_err(DstArgs args, int32_t n, DstType expected);
int dst_typemany_err(DstArgs args, int32_t n, int expected);
int dst_typeabstract_err(DstArgs args, int32_t n, DstAbstractType *at);
#define dst_throw(a, e) (*((a).ret) = dst_cstringv(e), 1)
#define dst_throwv(a, v) (*((a).ret) = (v), 1)
#define dst_return(a, v) (*((a).ret) = (v), 0)
/* Early exit macros */
#define dst_maxarity(A, N) do { if ((A).n > (N))\
return dst_arity_err(A, N, "at most "); } while (0)
#define dst_minarity(A, N) do { if ((A).n < (N))\
@ -220,6 +224,53 @@ int dst_typemany_err(DstArgs args, int32_t n, int expected);
}\
} while (0)
#define dst_checkabstract(A, N, AT) do {\
if ((A).n <= (N) || !dst_checktype() {\
Dst x = (A).v[(N)];\
if (!dst_checktype(x, DST_ABSTRACT) ||\
dst_abstract_type(dst_unwrap_abstract(x)) != (AT))\
return dst_typeabstract_err(A, N, AT);\
} else {\
return dst_typeabstract_err(A, N, AT);\
}\
} while (0)
#define dst_arg_abstract(DEST, A, N, AT) do {\
dst_checkabstract(A, N, AT);\
DEST = dst_unwrap_abstract((A).v[(N)]);\
} while (0)
#define dst_arg_integer(DEST, A, N) do { \
dst_check(A, N, DST_INTEGER);\
DEST = dst_unwrap_integer((A).v[(N)]); } while (0)
#define dst_arg_real(DEST, A, N) do { \
dst_check(A, N, DST_REAL);\
DEST = dst_unwrap_real((A).v[(N)]); } while (0)
#define dst_arg_number(DEST, A, N) do { \
if ((A).n <= (N)) return dst_typemany_err(A, N, DST_TFLAG_NUMBER);\
Dst val = (A).v[(N)];\
if (dst_checktype(val, DST_REAL)) { DEST = dst_unwrap_real(val); }\
else if (dst_checktype(val, DST_INTEGER)) { DEST = (double) dst_unwrap_integer(val); }\
else dst_typemany_err(A, N, DST_TFLAG_NUMBER); } while (0)
#define dst_arg_boolean(DEST, A, N) do { \
dst_checkmany(A, N, DST_TFLAG_TRUE | DST_TFLAG_FALSE);\
DEST = dst_unwrap_boolean((A).v[(N)]); } while (0)
#define dst_arg_string(DEST, A, N) do { \
dst_check(A, N, DST_STRING);\
DEST = dst_unwrap_string((A).v[(N)]); } while (0)
#define dst_arg_symbol(DEST, A, N) do { \
dst_check(A, N, DST_SYMBOL);\
DEST = dst_unwrap_string((A).v[(N)]); } while (0)
#define dst_arg_buffer(DEST, A, N) do { \
dst_check(A, N, DST_BUFFER);\
DEST = dst_unwrap_buffer((A).v[(N)]); } while (0)
#ifdef __cplusplus
}
#endif