fixed array constructor so it doesn't require allocating a generic
container first updates and improvements to ios
This commit is contained in:
parent
9acdf313b9
commit
d6470ac62f
|
@ -332,7 +332,6 @@ value_t fl_rand32(value_t *args, u_int32_t nargs)
|
||||||
#ifdef BITS64
|
#ifdef BITS64
|
||||||
return fixnum(r);
|
return fixnum(r);
|
||||||
#else
|
#else
|
||||||
if (fits_fixnum(r)) return fixnum(r);
|
|
||||||
return mk_uint32(r);
|
return mk_uint32(r);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -340,9 +339,6 @@ value_t fl_rand64(value_t *args, u_int32_t nargs)
|
||||||
{
|
{
|
||||||
(void)args; (void)nargs;
|
(void)args; (void)nargs;
|
||||||
ulong r = (((uint64_t)random())<<32) | random();
|
ulong r = (((uint64_t)random())<<32) | random();
|
||||||
#ifdef BITS64
|
|
||||||
if (fits_fixnum(r)) return fixnum(r);
|
|
||||||
#endif
|
|
||||||
return mk_uint64(r);
|
return mk_uint64(r);
|
||||||
}
|
}
|
||||||
value_t fl_randd(value_t *args, u_int32_t nargs)
|
value_t fl_randd(value_t *args, u_int32_t nargs)
|
||||||
|
|
|
@ -16,7 +16,7 @@ static int struct_aligns[8] = {
|
||||||
sizeof(struct { char a; int64_t i; }) };
|
sizeof(struct { char a; int64_t i; }) };
|
||||||
static int ALIGN2, ALIGN4, ALIGN8, ALIGNPTR;
|
static int ALIGN2, ALIGN4, ALIGN8, ALIGNPTR;
|
||||||
|
|
||||||
typedef void (*cvinitfunc_t)(value_t*, u_int32_t, void*, void*);
|
typedef void (*cvinitfunc_t)(value_t, value_t, void*, void*);
|
||||||
|
|
||||||
value_t int8sym, uint8sym, int16sym, uint16sym, int32sym, uint32sym;
|
value_t int8sym, uint8sym, int16sym, uint16sym, int32sym, uint32sym;
|
||||||
value_t int64sym, uint64sym;
|
value_t int64sym, uint64sym;
|
||||||
|
@ -30,7 +30,7 @@ value_t unionsym;
|
||||||
|
|
||||||
value_t autoreleasesym, typeofsym, sizeofsym;
|
value_t autoreleasesym, typeofsym, sizeofsym;
|
||||||
|
|
||||||
static void cvalue_init(value_t type, value_t *vs, u_int32_t nv, void *dest);
|
static void cvalue_init(value_t type, value_t v, void *dest);
|
||||||
|
|
||||||
void cvalue_print(ios_t *f, value_t v, int princ);
|
void cvalue_print(ios_t *f, value_t v, int princ);
|
||||||
// exported guest functions
|
// exported guest functions
|
||||||
|
@ -239,14 +239,16 @@ static double strtodouble(char *str, char *fname)
|
||||||
}
|
}
|
||||||
|
|
||||||
#define num_ctor(typenam, cnvt, tag, fromstr) \
|
#define num_ctor(typenam, cnvt, tag, fromstr) \
|
||||||
static void cvalue_##typenam##_init(value_t *args, u_int32_t nargs, \
|
static void cvalue_##typenam##_init(value_t type, value_t arg, \
|
||||||
void *dest, void *data) \
|
void *dest, void *data) \
|
||||||
{ \
|
{ \
|
||||||
typenam##_t n=0; \
|
typenam##_t n=0; \
|
||||||
(void)data; \
|
(void)data; (void)type; \
|
||||||
if (nargs) { \
|
if (isfixnum(arg)) { \
|
||||||
if (iscvalue(args[0])) { \
|
n = numval(arg); \
|
||||||
cvalue_t *cv = (cvalue_t*)ptr(args[0]); \
|
} \
|
||||||
|
else if (iscvalue(arg)) { \
|
||||||
|
cvalue_t *cv = (cvalue_t*)ptr(arg); \
|
||||||
void *p = cv_data(cv); \
|
void *p = cv_data(cv); \
|
||||||
if (valid_numtype(cv_numtype(cv))) { \
|
if (valid_numtype(cv_numtype(cv))) { \
|
||||||
n = (typenam##_t)conv_to_##cnvt(p, cv_numtype(cv)); \
|
n = (typenam##_t)conv_to_##cnvt(p, cv_numtype(cv)); \
|
||||||
|
@ -258,20 +260,24 @@ static void cvalue_##typenam##_init(value_t *args, u_int32_t nargs, \
|
||||||
n = *(typenam##_t*)p; \
|
n = *(typenam##_t*)p; \
|
||||||
} \
|
} \
|
||||||
else { \
|
else { \
|
||||||
type_error(#typenam, "number", args[0]); \
|
goto cnvt_error; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
else { \
|
else { \
|
||||||
n = tofixnum(args[0], #typenam); \
|
goto cnvt_error; \
|
||||||
} \
|
|
||||||
} \
|
} \
|
||||||
*((typenam##_t*)dest) = n; \
|
*((typenam##_t*)dest) = n; \
|
||||||
|
return; \
|
||||||
|
cnvt_error: \
|
||||||
|
type_error(#typenam, "number", arg); \
|
||||||
} \
|
} \
|
||||||
value_t cvalue_##typenam(value_t *args, u_int32_t nargs) \
|
value_t cvalue_##typenam(value_t *args, u_int32_t nargs) \
|
||||||
{ \
|
{ \
|
||||||
|
if (nargs==0) { PUSH(fixnum(0)); args = &Stack[SP-1]; } \
|
||||||
value_t cv = cvalue(typenam##sym, sizeof(typenam##_t)); \
|
value_t cv = cvalue(typenam##sym, sizeof(typenam##_t)); \
|
||||||
((cprim_t*)ptr(cv))->flags.numtype = tag; \
|
((cprim_t*)ptr(cv))->flags.numtype = tag; \
|
||||||
cvalue_##typenam##_init(args, nargs, &((cprim_t*)ptr(cv))->data, 0); \
|
cvalue_##typenam##_init(typenam##sym, \
|
||||||
|
args[0], &((cprim_t*)ptr(cv))->data, 0); \
|
||||||
return cv; \
|
return cv; \
|
||||||
} \
|
} \
|
||||||
value_t mk_##typenam(typenam##_t n) \
|
value_t mk_##typenam(typenam##_t n) \
|
||||||
|
@ -332,20 +338,18 @@ value_t char_from_code(uint32_t code)
|
||||||
return cvalue_char(&ccode, 1);
|
return cvalue_char(&ccode, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cvalue_enum_init(value_t *args, u_int32_t nargs, void *dest,
|
static void cvalue_enum_init(value_t type, value_t arg, void *dest, void *data)
|
||||||
void *data)
|
|
||||||
{
|
{
|
||||||
int n=0;
|
int n=0;
|
||||||
value_t syms;
|
value_t syms;
|
||||||
|
|
||||||
(void)data;
|
(void)data;
|
||||||
argcount("enum", nargs, 2);
|
syms = car(cdr(type));
|
||||||
syms = args[0];
|
|
||||||
if (!iscons(syms))
|
if (!iscons(syms))
|
||||||
type_error("enum", "cons", syms);
|
type_error("enum", "cons", syms);
|
||||||
if (issymbol(args[1])) {
|
if (issymbol(arg)) {
|
||||||
while (iscons(syms)) {
|
while (iscons(syms)) {
|
||||||
if (car_(syms) == args[1]) {
|
if (car_(syms) == arg) {
|
||||||
*(int*)dest = n;
|
*(int*)dest = n;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -354,13 +358,13 @@ static void cvalue_enum_init(value_t *args, u_int32_t nargs, void *dest,
|
||||||
}
|
}
|
||||||
lerror(ArgError, "enum: invalid enum value");
|
lerror(ArgError, "enum: invalid enum value");
|
||||||
}
|
}
|
||||||
if (isfixnum(args[1])) {
|
if (isfixnum(arg)) {
|
||||||
n = (int)numval(args[1]);
|
n = (int)numval(arg);
|
||||||
}
|
}
|
||||||
else if (iscvalue(args[1])) {
|
else if (iscvalue(arg)) {
|
||||||
cvalue_t *cv = (cvalue_t*)ptr(args[1]);
|
cvalue_t *cv = (cvalue_t*)ptr(arg);
|
||||||
if (!valid_numtype(cv_numtype(cv)))
|
if (!valid_numtype(cv_numtype(cv)))
|
||||||
type_error("enum", "number", args[1]);
|
type_error("enum", "number", arg);
|
||||||
n = conv_to_int32(cv_data(cv), cv_numtype(cv));
|
n = conv_to_int32(cv_data(cv), cv_numtype(cv));
|
||||||
}
|
}
|
||||||
if ((unsigned)n >= llength(syms))
|
if ((unsigned)n >= llength(syms))
|
||||||
|
@ -373,105 +377,112 @@ value_t cvalue_enum(value_t *args, u_int32_t nargs)
|
||||||
argcount("enum", nargs, 2);
|
argcount("enum", nargs, 2);
|
||||||
value_t cv = cvalue(list2(enumsym, args[0]), 4);
|
value_t cv = cvalue(list2(enumsym, args[0]), 4);
|
||||||
((cvalue_t*)ptr(cv))->flags.numtype = T_INT32;
|
((cvalue_t*)ptr(cv))->flags.numtype = T_INT32;
|
||||||
cvalue_enum_init(args, nargs, cv_data((cvalue_t*)ptr(cv)), NULL);
|
cvalue_enum_init(cv_type((cvalue_t*)ptr(cv)),
|
||||||
|
args[1], cv_data((cvalue_t*)ptr(cv)), NULL);
|
||||||
return cv;
|
return cv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cvalue_array_init(value_t *args, u_int32_t nargs, void *dest,
|
static void array_init_fromargs(char *dest, value_t *vals, size_t cnt,
|
||||||
void *data)
|
value_t eltype, size_t elsize)
|
||||||
{
|
{
|
||||||
size_t cnt=0, elsize, i;
|
size_t i;
|
||||||
value_t *init = NULL;
|
for(i=0; i < cnt; i++) {
|
||||||
|
cvalue_init(eltype, vals[i], dest);
|
||||||
|
dest += elsize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int isarray(value_t v)
|
||||||
|
{
|
||||||
|
if (!iscvalue(v)) return 0;
|
||||||
|
value_t type = cv_type((cvalue_t*)ptr(v));
|
||||||
|
return (iscons(type) && car_(type)==arraysym);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t predict_arraylen(value_t arg)
|
||||||
|
{
|
||||||
|
if (isvector(arg))
|
||||||
|
return vector_size(arg);
|
||||||
|
else if (iscons(arg))
|
||||||
|
return llength(arg);
|
||||||
|
else if (arg == NIL)
|
||||||
|
return 0;
|
||||||
|
if (isarray(arg))
|
||||||
|
return cvalue_arraylen(arg);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cvalue_array_init(value_t type, value_t arg, void *dest, void *data)
|
||||||
|
{
|
||||||
|
size_t elsize, i, cnt, sz;
|
||||||
int junk;
|
int junk;
|
||||||
|
value_t eltype = car(cdr(type));
|
||||||
|
|
||||||
if (data != 0)
|
if (data != 0)
|
||||||
elsize = (size_t)data; // already computed by constructor
|
elsize = (size_t)data; // already computed by constructor
|
||||||
else
|
else
|
||||||
elsize = ctype_sizeof(args[0], &junk);
|
elsize = ctype_sizeof(eltype, &junk);
|
||||||
char *out = (char*)dest;
|
|
||||||
|
|
||||||
if (nargs == 2) {
|
cnt = predict_arraylen(arg);
|
||||||
if (isvector(args[1]) || iscons(args[1]) || args[1]==NIL)
|
|
||||||
init = &args[1];
|
if (iscons(cdr_(cdr_(type)))) {
|
||||||
else
|
size_t tc = toulong(car_(cdr_(cdr_(type))), "array");
|
||||||
cnt = toulong(args[1], "array");
|
if (tc != cnt)
|
||||||
}
|
|
||||||
else if (nargs == 3) {
|
|
||||||
cnt = toulong(args[1], "array");
|
|
||||||
init = &args[2];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
argcount("array", nargs, 2);
|
|
||||||
}
|
|
||||||
if (init) {
|
|
||||||
if (isvector(*init)) {
|
|
||||||
if (cnt && vector_size(*init) != cnt)
|
|
||||||
lerror(ArgError, "array: size mismatch");
|
lerror(ArgError, "array: size mismatch");
|
||||||
cnt = vector_size(*init);
|
|
||||||
for(i=0; i < cnt; i++) {
|
|
||||||
cvalue_init(args[0], &vector_elt(*init, i), 1, out);
|
|
||||||
out += elsize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sz = elsize * cnt;
|
||||||
|
|
||||||
|
if (isvector(arg)) {
|
||||||
|
array_init_fromargs((char*)dest, &vector_elt(arg,0), cnt,
|
||||||
|
eltype, elsize);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (iscons(*init) || *init==NIL) {
|
else if (iscons(arg) || arg==NIL) {
|
||||||
for(i=0; i < cnt || cnt==0; i++) {
|
i = 0;
|
||||||
if (!iscons(*init)) {
|
while (iscons(arg)) {
|
||||||
if (cnt != 0)
|
if (SP >= N_STACK)
|
||||||
lerror(ArgError, "array: size mismatch");
|
|
||||||
else
|
|
||||||
break;
|
break;
|
||||||
|
PUSH(car_(arg));
|
||||||
|
i++;
|
||||||
|
arg = cdr_(arg);
|
||||||
}
|
}
|
||||||
cvalue_init(args[0], &car_(*init), 1, out);
|
if (i != cnt)
|
||||||
out += elsize;
|
lerror(ArgError, "array: size mismatch");
|
||||||
*init = cdr_(*init);
|
array_init_fromargs((char*)dest, &Stack[SP-i], i, eltype, elsize);
|
||||||
}
|
POPN(i);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (iscvalue(*init)) {
|
else if (iscvalue(arg)) {
|
||||||
cvalue_t *cv = (cvalue_t*)ptr(*init);
|
cvalue_t *cv = (cvalue_t*)ptr(arg);
|
||||||
size_t tot = cnt*elsize;
|
if (isarray(arg)) {
|
||||||
if (tot == cv_len(cv)) {
|
value_t aet = car(cdr(cv_type(cv)));
|
||||||
if (tot) memcpy(out, cv_data(cv), tot);
|
if (aet == eltype) {
|
||||||
|
if (cv_len(cv) == sz)
|
||||||
|
memcpy(dest, cv_data(cv), sz);
|
||||||
|
else
|
||||||
|
lerror(ArgError, "array: size mismatch");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
type_error("array", "cons", *init);
|
// TODO: initialize array from different type elements
|
||||||
|
lerror(ArgError, "array: element type mismatch");
|
||||||
}
|
}
|
||||||
lerror(ArgError, "array: invalid size");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static size_t predict_arraylen(value_t *args, u_int32_t nargs, size_t *elsz)
|
|
||||||
{
|
|
||||||
int junk;
|
|
||||||
size_t cnt;
|
|
||||||
|
|
||||||
if (nargs < 2)
|
|
||||||
argcount("array", nargs, 2);
|
|
||||||
*elsz = ctype_sizeof(args[0], &junk);
|
|
||||||
if (isvector(args[1])) {
|
|
||||||
cnt = vector_size(args[1]);
|
|
||||||
}
|
}
|
||||||
else if (iscons(args[1])) {
|
if (cnt == 1)
|
||||||
cnt = llength(args[1]);
|
cvalue_init(eltype, arg, dest);
|
||||||
}
|
else
|
||||||
else if (args[1] == NIL) {
|
type_error("array", "sequence", arg);
|
||||||
cnt = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cnt = toulong(args[1], "array");
|
|
||||||
}
|
|
||||||
return cnt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static value_t alloc_array(value_t type, size_t sz)
|
static value_t alloc_array(value_t type, size_t sz)
|
||||||
{
|
{
|
||||||
value_t cv;
|
value_t cv;
|
||||||
if (car_(cdr_(type)) == charsym) {
|
if (car_(cdr_(type)) == charsym) {
|
||||||
|
PUSH(type);
|
||||||
cv = cvalue_string(sz);
|
cv = cvalue_string(sz);
|
||||||
((cvalue_t*)ptr(cv))->type = type;
|
((cvalue_t*)ptr(cv))->type = POP();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
cv = cvalue(type, sz);
|
cv = cvalue(type, sz);
|
||||||
|
@ -482,12 +493,18 @@ static value_t alloc_array(value_t type, size_t sz)
|
||||||
value_t cvalue_array(value_t *args, u_int32_t nargs)
|
value_t cvalue_array(value_t *args, u_int32_t nargs)
|
||||||
{
|
{
|
||||||
size_t elsize, cnt, sz;
|
size_t elsize, cnt, sz;
|
||||||
|
int junk;
|
||||||
|
|
||||||
cnt = predict_arraylen(args, nargs, &elsize);
|
if (nargs < 1)
|
||||||
|
argcount("array", nargs, 1);
|
||||||
|
|
||||||
|
cnt = nargs - 1;
|
||||||
|
elsize = ctype_sizeof(args[0], &junk);
|
||||||
sz = elsize * cnt;
|
sz = elsize * cnt;
|
||||||
|
|
||||||
value_t cv = alloc_array(listn(3, arraysym, args[0], size_wrap(cnt)), sz);
|
value_t cv = alloc_array(listn(3, arraysym, args[0], size_wrap(cnt)), sz);
|
||||||
cvalue_array_init(args, nargs, cv_data((cvalue_t*)ptr(cv)), (void*)elsize);
|
array_init_fromargs(cv_data((cvalue_t*)ptr(cv)), &args[1], cnt,
|
||||||
|
args[0], elsize);
|
||||||
return cv;
|
return cv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -683,33 +700,24 @@ value_t cvalue_copy(value_t v)
|
||||||
return tagptr(pnv, TAG_CVALUE);
|
return tagptr(pnv, TAG_CVALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cvalue_init(value_t type, value_t *vs, u_int32_t nv, void *dest)
|
static void cvalue_init(value_t type, value_t v, void *dest)
|
||||||
{
|
{
|
||||||
cvinitfunc_t f;
|
cvinitfunc_t f;
|
||||||
unsigned int i, na=0;
|
|
||||||
|
|
||||||
if (issymbol(type)) {
|
if (issymbol(type)) {
|
||||||
f = ((symbol_t*)ptr(type))->dlcache;
|
f = ((symbol_t*)ptr(type))->dlcache;
|
||||||
}
|
}
|
||||||
else if (!iscons(type)) {
|
else if (iscons(type)) {
|
||||||
f = NULL;
|
|
||||||
lerror(ArgError, "c-value: invalid c type");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
value_t head = car_(type);
|
value_t head = car_(type);
|
||||||
f = ((symbol_t*)ptr(head))->dlcache;
|
f = ((symbol_t*)ptr(head))->dlcache;
|
||||||
type = cdr_(type);
|
|
||||||
while (iscons(type)) {
|
|
||||||
PUSH(car_(type));
|
|
||||||
na++;
|
|
||||||
type = cdr_(type);
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
f = NULL;
|
||||||
}
|
}
|
||||||
for(i=0; i < nv; i++)
|
if (f == NULL)
|
||||||
PUSH(vs[i]);
|
lerror(ArgError, "c-value: invalid c type");
|
||||||
na += nv;
|
|
||||||
f(&Stack[SP-na], na, dest, NULL);
|
f(type, v, dest, NULL);
|
||||||
POPN(na);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static numerictype_t sym_to_numtype(value_t type)
|
static numerictype_t sym_to_numtype(value_t type)
|
||||||
|
@ -756,29 +764,26 @@ static numerictype_t sym_to_numtype(value_t type)
|
||||||
// type, including user-defined.
|
// type, including user-defined.
|
||||||
value_t cvalue_new(value_t *args, u_int32_t nargs)
|
value_t cvalue_new(value_t *args, u_int32_t nargs)
|
||||||
{
|
{
|
||||||
if (nargs < 1)
|
if (nargs < 1 || nargs > 2)
|
||||||
argcount("c-value", nargs, 1);
|
argcount("c-value", nargs, 2);
|
||||||
value_t type = args[0];
|
value_t type = args[0];
|
||||||
value_t cv;
|
value_t cv;
|
||||||
if (iscons(type) && car_(type) == arraysym) {
|
if (iscons(type) && car_(type) == arraysym) {
|
||||||
// special case to handle incomplete array types bla[]
|
// special case to handle incomplete array types bla[]
|
||||||
size_t elsz;
|
value_t eltype = car(cdr_(type));
|
||||||
value_t c = cdr_(type);
|
int junk;
|
||||||
int na=0;
|
size_t elsz = ctype_sizeof(eltype, &junk);
|
||||||
while (iscons(c)) {
|
size_t cnt;
|
||||||
PUSH(car_(c));
|
if (iscons(cdr_(cdr_(type))))
|
||||||
c = cdr_(c);
|
cnt = toulong(car_(cdr_(cdr_(type))), "array");
|
||||||
na++;
|
else if (nargs == 2)
|
||||||
}
|
cnt = predict_arraylen(args[1]);
|
||||||
if (nargs > 1) {
|
else
|
||||||
PUSH(args[1]);
|
cnt = 0;
|
||||||
na++;
|
|
||||||
}
|
|
||||||
size_t cnt = predict_arraylen(&Stack[SP-na], na, &elsz);
|
|
||||||
cv = alloc_array(type, elsz * cnt);
|
cv = alloc_array(type, elsz * cnt);
|
||||||
cvalue_array_init(&Stack[SP-na], na, cv_data((cvalue_t*)ptr(cv)),
|
if (nargs == 2)
|
||||||
|
cvalue_array_init(type, args[1], cv_data((cvalue_t*)ptr(cv)),
|
||||||
(void*)elsz);
|
(void*)elsz);
|
||||||
POPN(na);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int junk;
|
int junk;
|
||||||
|
@ -786,7 +791,8 @@ value_t cvalue_new(value_t *args, u_int32_t nargs)
|
||||||
if (issymbol(type)) {
|
if (issymbol(type)) {
|
||||||
((cvalue_t*)ptr(cv))->flags.numtype = sym_to_numtype(type);
|
((cvalue_t*)ptr(cv))->flags.numtype = sym_to_numtype(type);
|
||||||
}
|
}
|
||||||
cvalue_init(type, &args[1], nargs-1, cv_data((cvalue_t*)ptr(cv)));
|
if (nargs == 2)
|
||||||
|
cvalue_init(type, args[1], cv_data((cvalue_t*)ptr(cv)));
|
||||||
}
|
}
|
||||||
return cv;
|
return cv;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1433,7 +1433,7 @@ value_t load_file(char *fname)
|
||||||
FL_TRY {
|
FL_TRY {
|
||||||
while (1) {
|
while (1) {
|
||||||
e = read_sexpr(f);
|
e = read_sexpr(f);
|
||||||
//print(ios_stdout,e,0); ios_puts("\n", ios_stdout);
|
//print(ios_stdout,e,0); ios_putc('\n', ios_stdout);
|
||||||
if (ios_eof(f)) break;
|
if (ios_eof(f)) break;
|
||||||
v = toplevel_eval(e);
|
v = toplevel_eval(e);
|
||||||
}
|
}
|
||||||
|
@ -1497,6 +1497,6 @@ int main(int argc, char *argv[])
|
||||||
set(symbol("that"), v);
|
set(symbol("that"), v);
|
||||||
ios_puts("\n\n", ios_stdout);
|
ios_puts("\n\n", ios_stdout);
|
||||||
}
|
}
|
||||||
ios_puts("\n", ios_stdout);
|
ios_putc('\n', ios_stdout);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -530,18 +530,22 @@ static void cvalue_printdata(ios_t *f, void *data, size_t len, value_t type,
|
||||||
if (!weak) {
|
if (!weak) {
|
||||||
outs("#array(", f);
|
outs("#array(", f);
|
||||||
do_print(f, eltype, princ);
|
do_print(f, eltype, princ);
|
||||||
|
if (cnt > 0)
|
||||||
outc(' ', f);
|
outc(' ', f);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
outc('[', f);
|
outc('[', f);
|
||||||
|
}
|
||||||
for(i=0; i < cnt; i++) {
|
for(i=0; i < cnt; i++) {
|
||||||
cvalue_printdata(f, data, elsize, eltype, princ, 1);
|
if (i > 0)
|
||||||
if (i < cnt-1)
|
|
||||||
outc(' ', f);
|
outc(' ', f);
|
||||||
|
cvalue_printdata(f, data, elsize, eltype, princ, 1);
|
||||||
data += elsize;
|
data += elsize;
|
||||||
}
|
}
|
||||||
outc(']', f);
|
|
||||||
if (!weak)
|
if (!weak)
|
||||||
outc(')', f);
|
outc(')', f);
|
||||||
|
else
|
||||||
|
outc(']', f);
|
||||||
}
|
}
|
||||||
else if (car_(type) == enumsym) {
|
else if (car_(type) == enumsym) {
|
||||||
value_t sym = list_nth(car(cdr_(type)), *(size_t*)data);
|
value_t sym = list_nth(car(cdr_(type)), *(size_t*)data);
|
||||||
|
|
|
@ -149,15 +149,14 @@ typedef struct _cvtable_t {
|
||||||
void (*print)(struct _cvalue_t *, FILE *);
|
void (*print)(struct _cvalue_t *, FILE *);
|
||||||
} cvtable_t;
|
} cvtable_t;
|
||||||
|
|
||||||
; remember: variable-length data preferred over variable-length arglists
|
|
||||||
|
|
||||||
c type representations:
|
c type representations:
|
||||||
symbols void, [u]int[8,16,32,64], float, double, [u]char, [u]short,
|
symbols void, [u]int[8,16,32,64], float, double, [u]char, [u]short,
|
||||||
[u]int, [u]long, lispvalue
|
[u]int, [u]long, lispvalue
|
||||||
(c-function ret-type (argtype ...))
|
(c-function ret-type (argtype ...))
|
||||||
(array type N)
|
(array type[ N])
|
||||||
(struct ((name type) (name type) ...))
|
(struct ((name type) (name type) ...))
|
||||||
(union ((name type) (name type) ...))
|
(union ((name type) (name type) ...))
|
||||||
|
(mlayout ((name type offset) (name type offset) ...))
|
||||||
(enum (name1 name2 ...))
|
(enum (name1 name2 ...))
|
||||||
(pointer type)
|
(pointer type)
|
||||||
|
|
||||||
|
@ -167,8 +166,8 @@ constructors:
|
||||||
([u]int64 b3 b2 b1 b0)
|
([u]int64 b3 b2 b1 b0)
|
||||||
(float hi lo) or (float "3.14")
|
(float hi lo) or (float "3.14")
|
||||||
(double b3 b2 b1 b0) or (double "3.14")
|
(double b3 b2 b1 b0) or (double "3.14")
|
||||||
(array ctype (val ...))
|
(array ctype val ...)
|
||||||
(struct ((name type) ...) (val ...))
|
(struct ((name type) ...) val ...)
|
||||||
(pointer ctype) ; null pointer
|
(pointer ctype) ; null pointer
|
||||||
(pointer cvalue) ; constructs pointer to the given value
|
(pointer cvalue) ; constructs pointer to the given value
|
||||||
; same as (pointer (typeof x) x)
|
; same as (pointer (typeof x) x)
|
||||||
|
@ -243,11 +242,27 @@ should be related formally:
|
||||||
(if (symbolp type) (apply (eval type) ())
|
(if (symbolp type) (apply (eval type) ())
|
||||||
(apply (eval (car type)) (cdr type))))
|
(apply (eval (car type)) (cdr type))))
|
||||||
|
|
||||||
|
NOTE: this relationship is no longer true. we don't want to have to
|
||||||
|
construct 1 cvalue from 1 lisp value every time, since that could
|
||||||
|
require allocating a totally redundant list or vector. it should be
|
||||||
|
possible to make a cvalue from a series of lisp arguments. for
|
||||||
|
example there are now 2 different ways to make an array:
|
||||||
|
|
||||||
|
1) from series of arguments: (array type val0 val1 ...)
|
||||||
|
2) from 1 (optional) value: (c-value '(array int8[ size])[ V])
|
||||||
|
|
||||||
|
constructors will internally use the second form to initialize elements
|
||||||
|
of aggregates. e.g. 'array' in the first case will conceptually call
|
||||||
|
(c-value type val0)
|
||||||
|
(c-value type val1)
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
for aggregate types, you can keep a variable referring to the relevant
|
for aggregate types, you can keep a variable referring to the relevant
|
||||||
piece:
|
piece:
|
||||||
|
|
||||||
(setq point '((x int) (y int)))
|
(setq point '((x int) (y int)))
|
||||||
(struct point [2 3]) ; looks like c declaration 'struct point x;'
|
(struct point 2 3) ; looks like c declaration 'struct point x;'
|
||||||
|
|
||||||
a type is a function, so something similar to typedef is achieved by:
|
a type is a function, so something similar to typedef is achieved by:
|
||||||
|
|
||||||
|
@ -373,10 +388,10 @@ then we can write the vector clause in backquote as e.g.
|
||||||
|
|
||||||
|
|
||||||
setup plan:
|
setup plan:
|
||||||
- create source directory and svn repository, move llt sources into it
|
* create source directory and svn repository, move llt sources into it
|
||||||
* write femtolisp.h, definitions for extensions to #include
|
* write femtolisp.h, definitions for extensions to #include
|
||||||
- add fl_ prefix to all exported functions
|
- add fl_ prefix to all exported functions
|
||||||
- port read and print to jclib's iostreams
|
* port read and print to llt iostreams
|
||||||
* get rid of flutils; use ptrhash instead
|
* get rid of flutils; use ptrhash instead
|
||||||
* builtinp needs to be a builtin ;) to distinguish lisp builtins from cvalues
|
* builtinp needs to be a builtin ;) to distinguish lisp builtins from cvalues
|
||||||
* allocation and gc for cvalues
|
* allocation and gc for cvalues
|
||||||
|
@ -585,6 +600,10 @@ cvalues todo:
|
||||||
- anonymous unions
|
- anonymous unions
|
||||||
* fix princ for cvalues
|
* fix princ for cvalues
|
||||||
- make header size for primitives 8 bytes, even on 64-bit arch
|
- make header size for primitives 8 bytes, even on 64-bit arch
|
||||||
|
- more efficient read for #array(), so it doesn't need to build a pairlist
|
||||||
|
- make sure shared pieces of types, like lists of enum values, can be
|
||||||
|
printed as shared structure to avoid duplication.
|
||||||
|
- share more types, allocate less
|
||||||
|
|
||||||
- string constructor/concatenator:
|
- string constructor/concatenator:
|
||||||
(string 'sym #char(65) #wchar(945) "blah" 23)
|
(string 'sym #char(65) #wchar(945) "blah" 23)
|
||||||
|
@ -797,23 +816,30 @@ String API
|
||||||
|
|
||||||
IOStream API
|
IOStream API
|
||||||
|
|
||||||
read
|
read - (read[ stream]) ; get next sexpr from stream
|
||||||
print, sprint
|
print, sprint
|
||||||
princ, sprinc
|
princ, sprinc
|
||||||
stream - (stream cvalue-as-bytestream)
|
iostream - (stream[ cvalue-as-bytestream])
|
||||||
file
|
file
|
||||||
fifo
|
fifo
|
||||||
socket
|
socket
|
||||||
stream.eof
|
stream.eof
|
||||||
stream.write - (stream.write cvalue)
|
stream.write - (stream.write s cvalue)
|
||||||
stream.read - (stream.read ctype)
|
stream.read - (stream.read s ctype)
|
||||||
stream.copy - (stream.copy to from [nbytes])
|
stream.copy - (stream.copy to from [nbytes])
|
||||||
stream.copyuntil - (stream.copy to from byte)
|
stream.copyuntil - (stream.copy to from byte)
|
||||||
stream.flush
|
stream.flush
|
||||||
stream.pos - (stream.pos s [set-pos])
|
stream.pos - (stream.pos s [set-pos])
|
||||||
stream.seek - (stream.seek s offset)
|
stream.seek - (stream.seek s offset)
|
||||||
|
stream.seekend - move to end of stream
|
||||||
stream.trunc
|
stream.trunc
|
||||||
stream.getc - get utf8 character(s)
|
stream.getc - get utf8 character(s)
|
||||||
|
stream.tostring! - destructively convert stringstream to string
|
||||||
|
stream.readline
|
||||||
|
stream.readlines
|
||||||
|
stream.readall
|
||||||
|
print-to-string
|
||||||
|
princ-to-string
|
||||||
|
|
||||||
|
|
||||||
path.combine
|
path.combine
|
||||||
|
@ -840,9 +866,11 @@ IOStream API
|
||||||
|
|
||||||
|
|
||||||
*rand
|
*rand
|
||||||
|
*randn
|
||||||
*rand.uint32
|
*rand.uint32
|
||||||
*rand.uint64
|
*rand.uint64
|
||||||
*rand.double
|
*rand.double
|
||||||
|
*rand.float
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -880,3 +908,5 @@ switch to miser mode, otherwise default is ok, for example:
|
||||||
* *print-pretty* to control it
|
* *print-pretty* to control it
|
||||||
|
|
||||||
- if indent gets too large, dedent back to left edge
|
- if indent gets too large, dedent back to left edge
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
|
53
llt/ios.c
53
llt/ios.c
|
@ -189,7 +189,7 @@ static char *_buf_realloc(ios_t *s, size_t sz)
|
||||||
|
|
||||||
// write a block of data into the buffer at the current position, resizing
|
// write a block of data into the buffer at the current position, resizing
|
||||||
// if necessary. returns # written.
|
// if necessary. returns # written.
|
||||||
static size_t _writebuf_force(ios_t *s, char *data, size_t n)
|
static size_t _write_grow(ios_t *s, char *data, size_t n)
|
||||||
{
|
{
|
||||||
size_t amt;
|
size_t amt;
|
||||||
size_t newsize;
|
size_t newsize;
|
||||||
|
@ -249,7 +249,7 @@ static size_t _ios_read(ios_t *s, char *dest, size_t n, int all)
|
||||||
s->bpos += avail;
|
s->bpos += avail;
|
||||||
return avail;
|
return avail;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
dest += avail;
|
dest += avail;
|
||||||
n -= avail;
|
n -= avail;
|
||||||
tot += avail;
|
tot += avail;
|
||||||
|
@ -257,7 +257,6 @@ static size_t _ios_read(ios_t *s, char *dest, size_t n, int all)
|
||||||
ios_flush(s);
|
ios_flush(s);
|
||||||
s->bpos = s->size = 0;
|
s->bpos = s->size = 0;
|
||||||
s->state = bst_rd;
|
s->state = bst_rd;
|
||||||
}
|
|
||||||
|
|
||||||
if (n > MOST_OF(s->maxsize)) {
|
if (n > MOST_OF(s->maxsize)) {
|
||||||
// doesn't fit comfortably in buffer; go direct
|
// doesn't fit comfortably in buffer; go direct
|
||||||
|
@ -321,6 +320,12 @@ size_t ios_readprep(ios_t *s, size_t n)
|
||||||
return s->size - s->bpos;
|
return s->size - s->bpos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _write_update_pos(ios_t *s)
|
||||||
|
{
|
||||||
|
if (s->bpos > s->ndirty) s->ndirty = s->bpos;
|
||||||
|
if (s->bpos > s->size) s->size = s->bpos;
|
||||||
|
}
|
||||||
|
|
||||||
size_t ios_write(ios_t *s, char *data, size_t n)
|
size_t ios_write(ios_t *s, char *data, size_t n)
|
||||||
{
|
{
|
||||||
if (n == 0) return 0;
|
if (n == 0) return 0;
|
||||||
|
@ -334,7 +339,7 @@ size_t ios_write(ios_t *s, char *data, size_t n)
|
||||||
space = s->size - s->bpos;
|
space = s->size - s->bpos;
|
||||||
|
|
||||||
if (s->bm == bm_mem) {
|
if (s->bm == bm_mem) {
|
||||||
wrote = _writebuf_force(s, data, n);
|
wrote = _write_grow(s, data, n);
|
||||||
}
|
}
|
||||||
else if (s->bm == bm_none) {
|
else if (s->bm == bm_none) {
|
||||||
int result = _os_write_all(s->fd, data, n, &wrote);
|
int result = _os_write_all(s->fd, data, n, &wrote);
|
||||||
|
@ -366,10 +371,7 @@ size_t ios_write(ios_t *s, char *data, size_t n)
|
||||||
}
|
}
|
||||||
return ios_write(s, data, n);
|
return ios_write(s, data, n);
|
||||||
}
|
}
|
||||||
if (s->bpos > s->ndirty)
|
_write_update_pos(s);
|
||||||
s->ndirty = s->bpos;
|
|
||||||
if (s->bpos > s->size)
|
|
||||||
s->size = s->bpos;
|
|
||||||
return wrote;
|
return wrote;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,7 +619,7 @@ static void _ios_init(ios_t *s)
|
||||||
s->tally = 0;
|
s->tally = 0;
|
||||||
s->fd = -1;
|
s->fd = -1;
|
||||||
s->byteswap = 0;
|
s->byteswap = 0;
|
||||||
s->ownbuf = 0;
|
s->ownbuf = 1;
|
||||||
s->ownfd = 0;
|
s->ownfd = 0;
|
||||||
s->_eof = 0;
|
s->_eof = 0;
|
||||||
s->rereadable = 0;
|
s->rereadable = 0;
|
||||||
|
@ -692,6 +694,13 @@ int ios_putc(int c, ios_t *s)
|
||||||
{
|
{
|
||||||
char ch = (char)c;
|
char ch = (char)c;
|
||||||
|
|
||||||
|
if (s->state == bst_wr && s->bpos < s->maxsize && s->bm != bm_none) {
|
||||||
|
s->buf[s->bpos++] = ch;
|
||||||
|
_write_update_pos(s);
|
||||||
|
if (s->bm == bm_line && ch == '\n')
|
||||||
|
ios_flush(s);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
return (int)ios_write(s, &ch, 1);
|
return (int)ios_write(s, &ch, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -754,16 +763,30 @@ int ios_getutf8(ios_t *s, uint32_t *pwc)
|
||||||
|
|
||||||
int ios_printf(ios_t *s, char *format, ...)
|
int ios_printf(ios_t *s, char *format, ...)
|
||||||
{
|
{
|
||||||
char buf[512];
|
char *str=NULL;
|
||||||
char *str=&buf[0];
|
|
||||||
va_list args;
|
va_list args;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
|
|
||||||
// TODO: avoid copy
|
if (s->state == bst_wr && s->bpos < s->maxsize && s->bm != bm_none) {
|
||||||
c = vsnprintf(buf, sizeof(buf), format, args);
|
size_t avail = s->maxsize - s->bpos;
|
||||||
if ((size_t)c >= sizeof(buf))
|
char *start = s->buf + s->bpos;
|
||||||
|
c = vsnprintf(start, avail, format, args);
|
||||||
|
if (c < 0) {
|
||||||
|
va_end(args);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
if (c < avail) {
|
||||||
|
va_end(args);
|
||||||
|
s->bpos += (size_t)c;
|
||||||
|
_write_update_pos(s);
|
||||||
|
// TODO: only works right if newline is at end
|
||||||
|
if (s->bm == bm_line && memrchr(start, '\n', (size_t)c))
|
||||||
|
ios_flush(s);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
c = vasprintf(&str, format, args);
|
c = vasprintf(&str, format, args);
|
||||||
|
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
@ -772,6 +795,6 @@ int ios_printf(ios_t *s, char *format, ...)
|
||||||
|
|
||||||
ios_write(s, str, c);
|
ios_write(s, str, c);
|
||||||
|
|
||||||
if (str != &buf[0]) free(str);
|
free(str);
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue