ref: 20488fc4915662e0ec50bb8c4ebc2609d6e110b4
parent: 1b00536fd5957d70dfde3a67fece862dbb879492
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Fri Nov 15 19:30:55 EST 2024
refactor (mostly arithmetic) Make fixnum<->bignum arithmetic correct and more seamless when it comes to possible overflows of underlying types. Fixnums will transition to bignums (vice versa) when needed. C-specific types are no longer considered as preferred numerical types.
--- a/3rd/mp/mpaux.c
+++ b/3rd/mp/mpaux.c
@@ -75,13 +75,13 @@
return;
} else {
if(b->p == (mpdigit*)&b[1]){
- b->p = (mpdigit*)LLT_ALLOC(n*Dbytes);
+ b->p = (mpdigit*)MEM_ALLOC(n*Dbytes);
if(b->p == nil)
sysfatal("mpbits: %r");
memmove(b->p, &b[1], Dbytes*b->top);
memset(&b[1], 0, Dbytes*b->size);
} else {
- b->p = (mpdigit*)LLT_REALLOC(b->p, n*Dbytes);
+ b->p = (mpdigit*)MEM_REALLOC(b->p, n*Dbytes);
if(b->p == nil)
sysfatal("mpbits: %r");
}
@@ -101,8 +101,8 @@
sysfatal("freeing mp constant");
memset(b->p, 0, b->size*Dbytes);
if(b->p != (mpdigit*)&b[1])
- LLT_FREE(b->p);
- LLT_FREE(b);
+ MEM_FREE(b->p);
+ MEM_FREE(b);
}
mpint*
--- a/3rd/mp/mpfmt.c
+++ b/3rd/mp/mpfmt.c
@@ -143,7 +143,7 @@
for(rv=1; (base >> rv) > 1; rv++)
;
len = 10 + (b->top*Dbits / rv);
- buf = LLT_ALLOC(len);
+ buf = MEM_ALLOC(len);
if(buf == nil)
return nil;
alloced = 1;
@@ -179,7 +179,7 @@
}
if(rv < 0){
if(alloced)
- LLT_FREE(buf);
+ MEM_FREE(buf);
return nil;
}
return buf;
--- a/3rd/mp/mpmul.c
+++ b/3rd/mp/mpmul.c
@@ -90,7 +90,7 @@
mpvecadd(res+n, reslen-n, diffprod, u0len+v0len, res+n);
memmove(p, res, (alen+blen)*Dbytes);
- LLT_FREE(t);
+ MEM_FREE(t);
}
#define KARATSUBAMIN 32
--- a/3rd/mp/mptobe.c
+++ b/3rd/mp/mptobe.c
@@ -13,7 +13,7 @@
m++;
if(p == nil){
n = m;
- p = LLT_ALLOC(n);
+ p = MEM_ALLOC(n);
if(p == nil)
sysfatal("mptobe: %r");
} else {
--- a/3rd/spooky.c
+++ b/3rd/spooky.c
@@ -26,7 +26,7 @@
#include "platform.h"
#include "spooky.h"
-#define ALLOW_UNALIGNED_READS 1
+#define ALLOW_UNALIGNED_READS 0
//
// SC_CONST: a constant which:
@@ -369,9 +369,18 @@
} u;
size_t left;
- h[0] = h[3] = h[6] = h[9] = *hash1;
- h[1] = h[4] = h[7] = h[10] = *hash2;
- h[2] = h[5] = h[8] = h[11] = SC_CONST;
+ h[0] = *hash1;
+ h[1] = *hash2;
+ h[2] = SC_CONST;
+ h[3] = *hash1;
+ h[4] = *hash2;
+ h[5] = SC_CONST;
+ h[6] = *hash1;
+ h[7] = *hash2;
+ h[8] = SC_CONST;
+ h[9] = *hash1;
+ h[10] = *hash2;
+ h[11] = SC_CONST;
u.p8 = (const uint8_t *) message;
end = u.p64 + (length / SC_BLOCKSIZE) * SC_NUMVARS;
--- a/3rd/wcwidth.c
+++ b/3rd/wcwidth.c
@@ -15,7 +15,7 @@
* https://github.com/termux/termux-packages/tree/master/packages/libandroid-support
*/
-#include "../llt.h"
+#include "flisp.h"
struct width_interval {
int start;
--- a/bitvector.c
+++ b/bitvector.c
@@ -1,4 +1,4 @@
-#include "llt.h"
+#include "flisp.h"
uint32_t *
bitvector_resize(uint32_t *b, uint64_t oldsz, uint64_t newsz, int initzero)
@@ -5,7 +5,7 @@
{
uint32_t *p;
size_t sz = ((newsz+31)>>5) * sizeof(uint32_t);
- p = LLT_REALLOC(b, sz);
+ p = MEM_REALLOC(b, sz);
if(p == nil)
return nil;
if(initzero && newsz>oldsz){
--- a/builtins.c
+++ b/builtins.c
@@ -2,7 +2,6 @@
Extra femtoLisp builtin functions
*/
-#include "llt.h"
#include "flisp.h"
#include "operators.h"
#include "cvalues.h"
@@ -9,6 +8,9 @@
#include "timefuncs.h"
#include "random.h"
+#define DBL_MAXINT (1LL<<53)
+#define FLT_MAXINT (1<<24)
+
size_t
llength(value_t v)
{
@@ -131,7 +133,7 @@
BUILTIN("symbol", symbol)
{
argcount(nargs, 1);
- if(!fl_isstring(args[0]))
+ if(__unlikely(!fl_isstring(args[0])))
type_error("string", args[0]);
return symbol(cvalue_data(args[0]));
}
@@ -245,13 +247,15 @@
BUILTIN("fixnum", fixnum)
{
argcount(nargs, 1);
- if(isfixnum(args[0]))
- return args[0];
- if(iscprim(args[0])){
- cprim_t *cp = (cprim_t*)ptr(args[0]);
- return fixnum(conv_to_long(cp_data(cp), cp_numtype(cp)));
- }
- type_error("number", args[0]);
+ value_t v = args[0];
+ if(isfixnum(v))
+ return v;
+ void *p = ptr(v);
+ if(iscprim(v))
+ return fixnum(conv_to_int64(cp_data(p), cp_numtype(p)));
+ if(iscvalue(v) && cp_numtype(p) == T_MPINT)
+ return fixnum(mptov(*(mpint**)cv_data(p)));
+ type_error("number", v);
}
BUILTIN("truncate", truncate)
@@ -285,11 +289,11 @@
BUILTIN("vector-alloc", vector_alloc)
{
- uint32_t i, k, a;
+ size_t i, k, a;
value_t f, v;
if(nargs < 1)
argcount(nargs, 1);
- i = toulong(args[0]);
+ i = tosize(args[0]);
v = alloc_vector(i, 0);
a = 1;
for(k = 0; k < i; k++){
@@ -394,14 +398,12 @@
BUILTIN("rand", rand)
{
USED(args); USED(nargs);
- uint64_t x = genrand_int63();
- fixnum_t r;
#ifdef BITS64
- r = x >> 3;
+ uint64_t x = genrand_uint64();
#else
- r = x >> (32+3);
+ uint32_t x = genrand_uint32();
#endif
- return fixnum(r);
+ return fixnum(x >> 3);
}
BUILTIN("rand-uint32", rand_uint32)
--- a/cvalues.c
+++ b/cvalues.c
@@ -1,9 +1,7 @@
-#include "llt.h"
#include "flisp.h"
#include "operators.h"
#include "cvalues.h"
#include "types.h"
-#include "overflows.h"
#include "iostream.h"
// trigger unconditional GC after this many bytes are allocated
@@ -16,7 +14,7 @@
{
if(FL(nfinalizers) == FL(maxfinalizers)){
size_t nn = FL(maxfinalizers) == 0 ? 256 : FL(maxfinalizers)*2;
- cvalue_t **temp = LLT_REALLOC(FL(finalizers), nn*sizeof(cvalue_t*));
+ cvalue_t **temp = MEM_REALLOC(FL(finalizers), nn*sizeof(cvalue_t*));
if(temp == nil)
lerrorf(FL(MemoryError), "out of memory");
FL(finalizers) = temp;
@@ -47,7 +45,7 @@
t->vtable->finalize(tagptr(tmp, TAG_CVALUE));
if(!isinlined(tmp) && owned(tmp) && !FL(exiting)){
memset(cv_data(tmp), 0xbb, cv_len(tmp));
- LLT_FREE(cv_data(tmp));
+ MEM_FREE(cv_data(tmp));
}
ndel++;
}
@@ -54,7 +52,7 @@
}while((n < l-ndel) && SWAP_sf(lst[n], lst[n+ndel]));
FL(nfinalizers) -= ndel;
-#ifdef VERBOSEGC
+#if defined(VERBOSEGC)
if(ndel > 0)
printf("GC: finalized %d objects\n", ndel);
#endif
@@ -125,7 +123,7 @@
gc(0);
pcv = alloc_words(CVALUE_NWORDS);
pcv->type = type;
- pcv->data = LLT_ALLOC(sz);
+ pcv->data = MEM_ALLOC(sz);
autorelease(pcv);
FL(malloc_pressure) += sz;
}
@@ -211,7 +209,7 @@
size_t sz = cv_len(cv);
if(cv_isstr(cv))
sz++;
- void *data = LLT_ALLOC(sz);
+ void *data = MEM_ALLOC(sz);
memcpy(data, cv_data(cv), sz);
cv->data = data;
autorelease(cv);
@@ -226,9 +224,13 @@
if(isfixnum(arg)) \
n = (ctype)numval(arg); \
else if(iscprim(arg)){ \
- cprim_t *cp = (cprim_t*)ptr(arg); \
+ cprim_t *cp = ptr(arg); \
void *p = cp_data(cp); \
n = (ctype)conv_to_##cnvt(p, cp_numtype(cp)); \
+ }else if(iscvalue(arg) && cp_numtype(ptr(arg)) == T_MPINT){ \
+ cvalue_t *cv = ptr(arg); \
+ void *p = cv_data(cv); \
+ n = (ctype)conv_to_##cnvt(p, T_MPINT); \
}else \
return 1; \
*((ctype*)dest) = n; \
@@ -281,20 +283,9 @@
num_ctor(int64, int64_t, T_INT64)
num_ctor(uint64, uint64_t, T_UINT64)
num_ctor_init(byte, uint8_t, T_UINT8)
-#if defined(ULONG64)
-num_ctor_init(long, int64_t, T_INT64)
-num_ctor(ulong, uint64_t, T_UINT64)
-#else
-num_ctor_init(long, int32_t, T_INT32)
-num_ctor(ulong, uint32_t, T_UINT32)
-#endif
num_ctor(float, float, T_FLOAT)
num_ctor(double, double, T_DOUBLE)
-#if defined(__plan9__)
num_ctor(rune, uint32_t, T_UINT32)
-#else
-num_ctor(rune, int32_t, T_INT32)
-#endif
static int
cvalue_mpint_init(fltype_t *type, value_t arg, void *dest)
@@ -303,6 +294,10 @@
USED(type);
if(isfixnum(arg)){
n = vtomp(numval(arg), nil);
+ }else if(iscvalue(arg)){
+ cvalue_t *cv = ptr(arg);
+ void *p = cv_data(cv);
+ n = conv_to_mpint(p, cp_numtype(cv));
}else if(iscprim(arg)){
cprim_t *cp = (cprim_t*)ptr(arg);
void *p = cp_data(cp);
@@ -348,20 +343,22 @@
value_t
size_wrap(size_t sz)
{
- if(fits_fixnum(sz))
- return fixnum(sz);
- assert(sizeof(void*) == sizeof(size_t));
- return mk_ulong(sz);
+ if(sizeof(size_t) == 8)
+ return fits_fixnum(sz) ? fixnum(sz): mk_uint64(sz);
+ else
+ return fits_fixnum(sz) ? fixnum(sz): mk_uint32(sz);
}
size_t
-toulong(value_t n)
+tosize(value_t n)
{
if(isfixnum(n))
return (size_t)numval(n);
if(iscprim(n)){
cprim_t *cp = (cprim_t*)ptr(n);
- return conv_to_ulong(cp_data(cp), cp_numtype(cp));
+ if(sizeof(size_t) == 8)
+ return conv_to_uint64(cp_data(cp), cp_numtype(cp));
+ return conv_to_uint32(cp_data(cp), cp_numtype(cp));
}
type_error("number", n);
}
@@ -451,7 +448,7 @@
cnt = predict_arraylen(arg);
if(iscons(cdr_(cdr_(type)))){
- size_t tc = toulong(car_(cdr_(cdr_(type))));
+ size_t tc = tosize(car_(cdr_(cdr_(type))));
if(tc != cnt)
lerrorf(FL(ArgError), "size mismatch");
}
@@ -533,7 +530,7 @@
if(nargs < 3)
argcount(nargs, 3);
- cnt = toulong(args[1]);
+ cnt = tosize(args[1]);
if(cnt < 0)
lerrorf(FL(ArgError), "invalid size: %d", cnt);
@@ -572,7 +569,7 @@
while(iscons(fld)){
fsz = ctype_sizeof(car(cdr(car_(fld))), &al);
- ssz = LLT_ALIGN(ssz, al);
+ ssz = ALIGNED(ssz, al);
if(al > *palign)
*palign = al;
@@ -582,7 +579,7 @@
ssz += fsz;
fld = cdr_(fld);
}
- return LLT_ALIGN(ssz, *palign);
+ return ALIGNED(ssz, *palign);
}
static size_t
@@ -601,7 +598,7 @@
usz = fsz;
fld = cdr_(fld);
}
- return LLT_ALIGN(usz, *palign);
+ return ALIGNED(usz, *palign);
}
// *palign is an output argument giving the alignment required by type
@@ -630,7 +627,7 @@
if(!iscons(cdr_(cdr_(type))))
lerrorf(FL(ArgError), "incomplete type");
value_t n = car_(cdr_(cdr_(type)));
- size_t sz = toulong(n);
+ size_t sz = tosize(n);
return sz * ctype_sizeof(t, palign);
}
if(hed == FL(enumsym)){
@@ -741,7 +738,7 @@
size_t len = cv_len(cv);
if(cv_isstr(cv))
len++;
- ncv->data = LLT_ALLOC(len);
+ ncv->data = MEM_ALLOC(len);
memcpy(ncv->data, cv_data(cv), len);
autorelease(ncv);
if(hasparent(cv)){
@@ -801,7 +798,7 @@
size_t cnt;
if(iscons(cdr_(cdr_(type))))
- cnt = toulong(car_(cdr_(cdr_(type))));
+ cnt = tosize(car_(cdr_(cdr_(type))));
else if(nargs == 2)
cnt = predict_arraylen(args[1]);
else
@@ -845,7 +842,7 @@
cvalue_t *cv = ptr(arr);
*data = cv_data(cv);
numel = cv_len(cv)/cv_class(cv)->elsz;
- *index = toulong(ind);
+ *index = tosize(ind);
if(*index < 0 || *index >= numel)
bounds_error(arr, ind);
}
@@ -967,149 +964,33 @@
{
if(fits_fixnum(Saccum))
return fixnum((fixnum_t)Saccum);
- if(Saccum > (int64_t)UINT32_MAX || Saccum < (int64_t)INT32_MIN)
- RETURN_NUM_AS(Saccum, int64);
- if(Saccum > (int64_t)INT32_MAX)
- RETURN_NUM_AS(Saccum, uint32);
- RETURN_NUM_AS(Saccum, int32);
+ RETURN_NUM_AS(vtomp(Saccum, nil), mpint);
}
+#define ACCUM_DEFAULT 0
+#define ARITH_OP(a, b) (a)+(b)
+#define MP_OP mpadd
+#define ARITH_OVERFLOW sadd_overflow_64
value_t
-fl_add_any(value_t *args, uint32_t nargs, fixnum_t carryIn)
+fl_add_any(value_t *args, uint32_t nargs)
{
- uint64_t Uaccum = 0;
- uint64_t Uresult = 0;
- int64_t Saccum = carryIn;
- int64_t Sresult;
- double Faccum = 0;
- bool inexact = false;
- uint32_t i;
- int64_t i64;
- value_t arg;
- mpint *Maccum = nil, *x;
- numerictype_t pt;
- fixnum_t pi;
- void *a;
+#include "fl_arith_any.inc"
+}
- FOR_ARGS(i, 0, arg, args){
- if(isfixnum(arg)){
- Saccum += numval(arg);
- continue;
- }
- if(num_to_ptr(arg, &pi, &pt, &a)){
- switch(pt){
- case T_INT8: Saccum += *(int8_t*)a; break;
- case T_UINT8: Uaccum += *(uint8_t*)a; break;
- case T_INT16: Saccum += *(int16_t*)a; break;
- case T_UINT16: Uaccum += *(uint16_t*)a; break;
- case T_INT32: Saccum += *(int32_t*)a; break;
- case T_UINT32: Uaccum += *(uint32_t*)a; break;
- case T_INT64:
- i64 = *(int64_t*)a;
- if(i64 >= 0){
- if(addof_uint64(Uresult, Uaccum, (uint64_t)i64)){
- if(Maccum == nil)
- Maccum = mpnew(0);
- x = uvtomp((uint64_t)i64, nil);
- mpadd(Maccum, x, Maccum);
- mpfree(x);
- }else
- Uaccum = Uresult;
- }else{
- if(subof_int64(Sresult, Saccum, i64)){
- if(Maccum == nil)
- Maccum = mpnew(0);
- x = uvtomp(-(uint64_t)i64, nil);
- x->sign = -1;
- mpadd(Maccum, x, Maccum);
- mpfree(x);
- }else{
- USED(Sresult);
- Saccum += i64;
- }
- }
- break;
- case T_UINT64:
- if(addof_uint64(Uresult, Uaccum, *(uint64_t*)a)){
- if(Maccum == nil)
- Maccum = mpnew(0);
- x = uvtomp(*(uint64_t*)a, nil);
- mpadd(Maccum, x, Maccum);
- mpfree(x);
- }else
- Uaccum = Uresult;
- break;
- case T_MPINT:
- if(Maccum == nil)
- Maccum = mpnew(0);
- mpadd(Maccum, *(mpint**)a, Maccum);
- break;
- case T_FLOAT: Faccum += *(float*)a; inexact = true; break;
- case T_DOUBLE: Faccum += *(double*)a; inexact = true; break;
- default:
- goto add_type_error;
- }
- continue;
- }
-
-add_type_error:
- mpfree(Maccum);
- type_error("number", arg);
- }
- if(inexact){
- Faccum += Uaccum;
- Faccum += Saccum;
- if(Maccum != nil){
- Faccum += mptod(Maccum);
- mpfree(Maccum);
- }
- return mk_double(Faccum);
- }
- if(Maccum != nil){
- /* FIXME - check if it fits into fixnum first, etc */
- x = vtomp(Saccum, nil);
- mpadd(Maccum, x, Maccum);
- x = uvtomp(Uaccum, x);
- mpadd(Maccum, x, Maccum);
- mpfree(x);
- return mk_mpint(Maccum);
- }
- if(Saccum < 0){
- uint64_t negpart = -(uint64_t)Saccum;
- if(negpart > Uaccum){
- Saccum += (int64_t)Uaccum;
- // return value in Saccum
- if(Saccum >= INT32_MIN){
- if(fits_fixnum(Saccum)){
- return fixnum((fixnum_t)Saccum);
- }
- RETURN_NUM_AS(Saccum, int32);
- }
- RETURN_NUM_AS(Saccum, int64);
- }
- Uaccum -= negpart;
- }else{
- if(addof_uint64(Uresult, Uaccum, (uint64_t)Saccum)){
- if(Maccum == nil)
- Maccum = mpnew(0);
- x = vtomp(Saccum, nil);
- mpadd(Maccum, x, Maccum);
- x = uvtomp(Uaccum, x);
- mpadd(Maccum, x, Maccum);
- mpfree(x);
- return mk_mpint(Maccum);
- }else
- Uaccum = Uresult;
- }
- return return_from_uint64(Uaccum);
+#define ACCUM_DEFAULT 1
+#define ARITH_OP(a, b) (a)*(b)
+#define MP_OP mpmul
+#define ARITH_OVERFLOW smul_overflow_64
+value_t
+fl_mul_any(value_t *args, uint32_t nargs)
+{
+#include "fl_arith_any.inc"
}
value_t
fl_neg(value_t n)
{
- int32_t i32;
int64_t i64;
- uint32_t ui32;
uint64_t ui64;
mpint *mp;
numerictype_t pt;
@@ -1117,46 +998,45 @@
void *a;
if(isfixnum(n)){
- fixnum_t s = fixnum(-numval(n));
- if(__unlikely((value_t)s == n))
- return mk_xlong(-numval(n));
- return s;
+ i64 = -(int64_t)numval(n);
+i64neg:
+ return fits_fixnum(i64) ? fixnum(i64) : mk_mpint(vtomp(i64, nil));
}
if(num_to_ptr(n, &pi, &pt, &a)){
switch(pt){
- case T_INT8: return fixnum(-(int32_t)*(int8_t*)a);
- case T_UINT8: return fixnum(-(int32_t)*(uint8_t*)a);
- case T_INT16: return fixnum(-(int32_t)*(int16_t*)a);
- case T_UINT16: return fixnum(-(int32_t)*(uint16_t*)a);
- case T_INT32:
- i32 = *(int32_t*)a;
- if(i32 == (int32_t)BIT31)
- return mk_uint32((uint32_t)BIT31);
- return mk_int32(-i32);
+ case T_DOUBLE: return mk_double(-*(double*)a);
+ case T_FLOAT: return mk_float(-*(float*)a);
+ case T_INT8: return fixnum(-(fixnum_t)*(int8_t*)a);
+ case T_UINT8: return fixnum(-(fixnum_t)*(uint8_t*)a);
+ case T_INT16: return fixnum(-(fixnum_t)*(int16_t*)a);
+ case T_UINT16: return fixnum(-(fixnum_t)*(uint16_t*)a);
case T_UINT32:
- ui32 = *(uint32_t*)a;
- if(ui32 <= (uint32_t)INT32_MAX+1)
- return mk_int32(-(uint32_t)ui32);
- return mk_int64(-(int64_t)ui32);
+ i64 = -(int64_t)*(uint32_t*)a;
+ if(0){
+ case T_INT32:
+ i64 = -(int64_t)*(int32_t*)a;
+ }
+ goto i64neg;
case T_INT64:
i64 = *(int64_t*)a;
- if(i64 == (int64_t)BIT63)
- return mk_uint64((uint64_t)BIT63);
- return mk_int64(-i64);
+ if(i64 == INT64_MIN)
+ return mk_mpint(uvtomp((uint64_t)INT64_MAX+1, nil));
+ i64 = -i64;
+ goto i64neg;
case T_UINT64:
ui64 = *(uint64_t*)a;
- if(ui64 <= (uint64_t)INT64_MAX+1)
- return mk_int64(-(uint64_t)ui64);
- mp = uvtomp(ui64, nil);
- mp->sign = -1;
- return mk_mpint(mp);
+ if(ui64 >= (uint64_t)INT64_MAX+1){
+ mp = uvtomp(ui64, nil);
+ mp->sign = -1;
+ return mk_mpint(mp);
+ }
+ i64 = -(int64_t)ui64;
+ goto i64neg;
case T_MPINT:
mp = mpcopy(*(mpint**)a);
- mpsub(mpzero, mp, mp);
+ mp->sign = -mp->sign;
return mk_mpint(mp);
- case T_FLOAT: return mk_float(-*(float*)a);
- case T_DOUBLE: return mk_double(-*(double*)a);
}
}
@@ -1163,91 +1043,6 @@
type_error("number", n);
}
-value_t
-fl_mul_any(value_t *args, uint32_t nargs)
-{
- int64_t Saccum = 1;
- uint64_t Uaccum = 1;
- double Faccum = 1;
- bool inexact = false;
- int64_t i64;
- uint32_t i;
- value_t arg;
- mpint *Maccum = nil, *x;
- numerictype_t pt;
- fixnum_t pi;
- void *a;
-
- FOR_ARGS(i, 0, arg, args){
- if(isfixnum(arg)){
- Saccum *= numval(arg);
- continue;
- }
- if(num_to_ptr(arg, &pi, &pt, &a)){
- switch(pt){
- case T_INT8: Saccum *= *(int8_t*)a; break;
- case T_UINT8: Uaccum *= *(uint8_t*)a; break;
- case T_INT16: Saccum *= *(int16_t*)a; break;
- case T_UINT16: Uaccum *= *(uint16_t*)a; break;
- case T_INT32: Saccum *= *(int32_t*)a; break;
- case T_UINT32: Uaccum *= *(uint32_t*)a; break;
- case T_INT64:
- i64 = *(int64_t*)a;
- if(i64 > 0)
- Uaccum *= (uint64_t)i64;
- else
- Saccum *= i64;
- break;
- case T_UINT64: Uaccum *= *(uint64_t*)a; break;
- case T_MPINT:
- if(Maccum == nil)
- Maccum = mpcopy(mpone);
- mpmul(Maccum, *(mpint**)a, Maccum);
- break;
- case T_FLOAT: Faccum *= *(float*)a; inexact = true; break;
- case T_DOUBLE: Faccum *= *(double*)a; inexact = true; break;
- default:
- goto mul_type_error;
- }
- continue;
- }
-
-mul_type_error:
- type_error("number", arg);
- }
- if(inexact){
- Faccum *= Uaccum;
- Faccum *= Saccum;
- if(Maccum != nil){
- Faccum *= mptod(Maccum);
- mpfree(Maccum);
- }
- return mk_double(Faccum);
- }
- if(Maccum != nil){
- /* FIXME might still fit into a fixnum */
- x = vtomp(Saccum, nil);
- mpmul(Maccum, x, Maccum);
- x = uvtomp(Uaccum, x);
- mpmul(Maccum, x, Maccum);
- mpfree(x);
- return mk_mpint(Maccum);
- }
- if(Saccum < 0){
- Saccum *= (int64_t)Uaccum;
- if(Saccum >= INT32_MIN){
- if(fits_fixnum(Saccum)){
- return fixnum((fixnum_t)Saccum);
- }
- RETURN_NUM_AS(Saccum, int32);
- }
- RETURN_NUM_AS(Saccum, int64);
- }else{
- Uaccum *= (uint64_t)Saccum;
- }
- return return_from_uint64(Uaccum);
-}
-
int
num_to_ptr(value_t a, fixnum_t *pi, numerictype_t *pt, void **pp)
{
@@ -1283,7 +1078,7 @@
int
numeric_compare(value_t a, value_t b, int eq, int eqnans, int typeerr)
{
- lltint_t ai, bi;
+ fixnum_t ai, bi;
numerictype_t ta, tb;
void *aptr, *bptr;
@@ -1325,7 +1120,7 @@
fl_div2(value_t a, value_t b)
{
double da, db;
- lltint_t ai, bi;
+ fixnum_t ai, bi;
numerictype_t ta, tb;
void *aptr, *bptr;
@@ -1350,7 +1145,7 @@
value_t
fl_idiv2(value_t a, value_t b)
{
- lltint_t ai, bi;
+ fixnum_t ai, bi;
numerictype_t ta, tb;
void *aptr, *bptr;
int64_t a64, b64;
@@ -1411,7 +1206,7 @@
static value_t
fl_bitwise_op(value_t a, value_t b, int opcode)
{
- lltint_t ai, bi;
+ fixnum_t ai, bi;
numerictype_t ta, tb, itmp;
void *aptr = nil, *bptr = nil, *ptmp;
mpint *bmp = nil, *resmp = nil;
@@ -1561,6 +1356,16 @@
case T_UINT64: return mk_uint64(~*(uint64_t*)aptr);
}
}
+ if(iscvalue(a)){
+ cvalue_t *cv = ptr(a);
+ ta = cp_numtype(cv);
+ aptr = cv_data(cv);
+ if(ta == T_MPINT){
+ mpint *m = mpnew(0);
+ mpnot(*(mpint**)aptr, m);
+ return mk_mpint(m);
+ }
+ }
type_error("integer", a);
}
@@ -1637,13 +1442,6 @@
ctor_cv_intern(int64, T_INT64, int64_t);
ctor_cv_intern(uint64, T_UINT64, uint64_t);
ctor_cv_intern(byte, T_UINT8, uint8_t);
-#if defined(ULONG64)
- ctor_cv_intern(long, T_INT64, int64_t);
- ctor_cv_intern(ulong, T_UINT64, uint64_t);
-#else
- ctor_cv_intern(long, T_INT32, int32_t);
- ctor_cv_intern(ulong, T_UINT32, uint32_t);
-#endif
ctor_cv_intern(rune, T_UINT32, uint32_t);
ctor_cv_intern(float, T_FLOAT, float);
ctor_cv_intern(double, T_DOUBLE, double);
@@ -1670,13 +1468,6 @@
mk_primtype(uint32, uint32_t);
mk_primtype(int64, int64_t);
mk_primtype(uint64, uint64_t);
-#if defined(ULONG64)
- mk_primtype(long, int64_t);
- mk_primtype(ulong, uint64_t);
-#else
- mk_primtype(long, int32_t);
- mk_primtype(ulong, uint32_t);
-#endif
mk_primtype(byte, uint8_t);
mk_primtype(rune, uint32_t);
mk_primtype(float, float);
--- a/cvalues.h
+++ b/cvalues.h
@@ -1,11 +1,10 @@
#pragma once
-#ifdef BITS64
+#if defined(BITS64)
#define NWORDS(sz) (((sz)+7)>>3)
#else
#define NWORDS(sz) (((sz)+3)>>2)
#endif
-
#define CVALUE_NWORDS 4
#define MAX_INL_SIZE 384
#define CV_OWNED_BIT 0x1
@@ -30,7 +29,7 @@
void cv_pin(cvalue_t *cv);
value_t mk_mpint(mpint *n);
value_t size_wrap(size_t sz);
-size_t toulong(value_t n);
+size_t tosize(value_t n);
off_t tooffset(value_t n);
int cvalue_enum_init(fltype_t *ft, value_t arg, void *dest);
int isarray(value_t v);
@@ -46,7 +45,7 @@
value_t cbuiltin(char *name, builtin_t f);
value_t return_from_uint64(uint64_t Uaccum);
value_t return_from_int64(int64_t Saccum);
-value_t fl_add_any(value_t *args, uint32_t nargs, fixnum_t carryIn);
+value_t fl_add_any(value_t *args, uint32_t nargs);
value_t fl_neg(value_t n);
value_t fl_mul_any(value_t *args, uint32_t nargs);
int num_to_ptr(value_t a, fixnum_t *pi, numerictype_t *pt, void **pp);
@@ -63,11 +62,6 @@
value_t mk_int64(int64_t n);
value_t mk_uint64(uint64_t n);
value_t mk_rune(Rune n);
-#if defined(ULONG64)
-value_t mk_ulong(uint64_t n);
-#else
-value_t mk_ulong(uint32_t n);
-#endif
/* builtins.c */
size_t llength(value_t v);
--- a/equal.c
+++ b/equal.c
@@ -1,4 +1,3 @@
-#include "llt.h"
#include "flisp.h"
#include "operators.h"
#include "opcodes.h"
@@ -9,10 +8,14 @@
#define BOUNDED_COMPARE_BOUND 128
#define BOUNDED_HASH_BOUND 16384
-#ifdef BITS64
+#if defined(BITS64)
#define inthash int64hash
+#define MIX(a, b) int64hash((uint64_t)(a) ^ (uint64_t)(b));
+#define doublehash(a) int64hash(a)
#else
#define inthash int32hash
+#define MIX(a, b) int64to32hash((uint64_t)(a)<<32 | (uint64_t)(b));
+#define doublehash(a) int64to32hash(a)
#endif
// comparable tag
@@ -327,14 +330,6 @@
* less redundant tag checking, 3-bit tags
*/
-#ifdef BITS64
-#define MIX(a, b) int64hash((uint64_t)(a) ^ (uint64_t)(b));
-#define doublehash(a) int64hash(a)
-#else
-#define MIX(a, b) int64to32hash(((uint64_t)(a))<<32 | ((uint64_t)(b)))
-#define doublehash(a) int64to32hash(a)
-#endif
-
// *oob: output argument, means we hit the limit specified by 'bound'
static uintptr_t
bounded_hash(value_t a, int bound, int *oob)
@@ -377,7 +372,7 @@
if(cv->type == FL(mpinttype)){
len = mptobe(*(mpint**)data, nil, 0, (uint8_t**)&data);
h = memhash(data, len);
- LLT_FREE(data);
+ MEM_FREE(data);
}else{
h = memhash(data, cv_len(cv));
}
--- a/equalhash.c
+++ b/equalhash.c
@@ -1,4 +1,3 @@
-#include "llt.h"
#include "flisp.h"
#include "equalhash.h"
#include "equal.h"
--- /dev/null
+++ b/fl_arith_any.inc
@@ -1,0 +1,164 @@
+//value_t
+//fl_*_any(value_t *args, uint32_t nargs)
+// input: ACCUM_DEFAULT ARITH_OP(a,b) MP_OP ARITH_OVERFLOW
+// add: 0 a+b mpadd sadd_overflow_64
+// mul: 1 a*b mpmul smul_overflow_64
+
+ mpint *Maccum = nil, *m = nil;
+ int64_t Saccum = ACCUM_DEFAULT, x;
+ uint64_t u64;
+ double Faccum = ACCUM_DEFAULT;
+ bool inexact = false;
+ value_t arg;
+ numerictype_t pt;
+ void *a;
+ cprim_t *cp;
+ cvalue_t *cv;
+
+ uint32_t i, j;
+ FOR_ARGS(i, 0, arg, args){
+ if(isfixnum(arg))
+ x = numval(arg);
+ else{
+ if(iscprim(arg)){
+ cp = ptr(arg);
+ a = cp_data(cp);
+ pt = cp_numtype(cp);
+ }else if(iscvalue(arg)){
+ cv = ptr(arg);
+ a = cv_data(cv);
+ pt = cv_class(cv)->numtype;
+ }else{
+typeerr:
+ mpfree(Maccum);
+ mpfree(m);
+ type_error("number", arg);
+ }
+ switch(pt){
+ case T_DOUBLE: Faccum = ARITH_OP(Faccum, *(double*)a); inexact = true; continue;
+ case T_FLOAT: Faccum = ARITH_OP(Faccum, *(float*)a); inexact = true; continue;
+ case T_INT8: x = *(int8_t*)a; break;
+ case T_UINT8: x = *(uint8_t*)a; break;
+ case T_INT16: x = *(int16_t*)a; break;
+ case T_UINT16: x = *(uint16_t*)a; break;
+ case T_INT32: x = *(int32_t*)a; break;
+ case T_UINT32: x = *(uint32_t*)a; break;
+ case T_INT64: x = *(int64_t*)a; break;
+ case T_UINT64:
+ u64 = *(uint64_t*)a;
+ if(u64 > INT64_MAX){
+ x = ACCUM_DEFAULT;
+ goto overflow;
+ }
+ x = u64;
+ break;
+ case T_MPINT:
+ x = ACCUM_DEFAULT;
+ u64 = ACCUM_DEFAULT;
+ m = mpcopy(*(mpint**)a);
+ goto overflow;
+ default:
+ goto typeerr;
+ }
+ }
+
+ int64_t accu;
+ if(ARITH_OVERFLOW(Saccum, x, &accu)){
+ u64 = ACCUM_DEFAULT;
+ goto overflow;
+ }
+ Saccum = accu;
+ }
+
+ if(inexact)
+ return mk_double(ARITH_OP(Faccum, Saccum));
+ if(fits_fixnum(Saccum))
+ return fixnum((fixnum_t)Saccum);
+ u64 = ACCUM_DEFAULT;
+ x = ACCUM_DEFAULT;
+
+overflow:
+ i++;
+ if(Maccum == nil)
+ Maccum = vtomp(Saccum, nil);
+ if(m == nil){
+ if(u64 != ACCUM_DEFAULT)
+ m = uvtomp(u64, nil);
+ else if(x != ACCUM_DEFAULT)
+ m = vtomp(x, nil);
+ else
+ m = mpnew(ACCUM_DEFAULT);
+ }
+
+ MP_OP(Maccum, m, Maccum);
+
+ FOR_ARGS(j, i, arg, args){
+ if(isfixnum(arg)){
+ vtomp(numval(arg), m);
+ MP_OP(Maccum, m, Maccum);
+ continue;
+ }
+
+ if(iscprim(arg)){
+ cp = ptr(arg);
+ a = cp_data(cp);
+ pt = cp_numtype(cp);
+ }else if(iscvalue(arg)){
+ cv = ptr(arg);
+ a = cv_data(cv);
+ pt = cv_class(cv)->numtype;
+ }else{
+ goto typeerr;
+ }
+ switch(pt){
+ case T_DOUBLE: Faccum = ARITH_OP(Faccum, *(double*)a); inexact = true; continue;
+ case T_FLOAT: Faccum = ARITH_OP(Faccum, *(float*)a); inexact = true; continue;
+ case T_INT8: x = *(int8_t*)a; break;
+ case T_UINT8: x = *(uint8_t*)a; break;
+ case T_INT16: x = *(int16_t*)a; break;
+ case T_UINT16: x = *(uint16_t*)a; break;
+ case T_INT32: x = *(int32_t*)a; break;
+ case T_UINT32: x = *(uint32_t*)a; break;
+ case T_INT64: x = *(int64_t*)a; break;
+ case T_UINT64:
+ uvtomp(*(uint64_t*)a, m);
+ MP_OP(Maccum, m, Maccum);
+ continue;
+ case T_MPINT:
+ MP_OP(Maccum, *(mpint**)a, Maccum);
+ continue;
+ default:
+ goto typeerr;
+ }
+ vtomp(x, m);
+ MP_OP(Maccum, m, Maccum);
+ }
+
+ int n = mpsignif(Maccum);
+ if(n >= FIXNUM_BITS){
+ if(inexact){
+ dtomp(Faccum, m);
+ MP_OP(Maccum, m, Maccum);
+ n = mpsignif(Maccum);
+ if(n < FIXNUM_BITS){
+ inexact = false;
+ goto down;
+ }
+ }
+ mpfree(m);
+ return mk_mpint(Maccum);
+ }
+
+down:
+ mpfree(m);
+ Saccum = mptov(Maccum);
+ mpfree(Maccum);
+ if(inexact)
+ return mk_double(ARITH_OP(Faccum, Saccum));
+ assert(fits_fixnum(Saccum));
+ return fixnum((fixnum_t)Saccum);
+
+#undef ACCUM_DEFAULT
+#undef ARITH_OP
+#undef MP_OP
+#undef ARITH_OVERFLOW
--- a/flisp.c
+++ b/flisp.c
@@ -5,7 +5,6 @@
Distributed under the BSD License
*/
-#include "llt.h"
#include "flisp.h"
#include "operators.h"
#include "cvalues.h"
@@ -286,7 +285,7 @@
value_t *first;
assert(n > 0);
- n = LLT_ALIGN(n, 2); // only allocate multiples of 2 words
+ n = ALIGNED(n, 2); // only allocate multiples of 2 words
if(__unlikely((value_t*)FL(curheap) > (value_t*)FL(lim)+2-n)){
gc(0);
while((value_t*)FL(curheap) > ((value_t*)FL(lim))+2-n)
@@ -497,7 +496,7 @@
sweep_finalizers();
-#ifdef VERBOSEGC
+#if defined(VERBOSEGC)
printf("GC: found %d/%d live conses\n",
(FL(curheap)-FL(tospace))/sizeof(cons_t), FL(heapsize)/sizeof(cons_t));
#endif
@@ -509,7 +508,7 @@
// more space to fill next time. if we grew tospace last time,
// grow the other half of the heap this time to catch up.
if(FL(grew) || ((FL(lim)-FL(curheap)) < (int)(FL(heapsize)/5)) || mustgrow){
- temp = LLT_REALLOC(FL(tospace), FL(heapsize)*2);
+ temp = MEM_REALLOC(FL(tospace), FL(heapsize)*2);
if(__unlikely(temp == nil))
fl_raise(FL(memory_exception_value));
FL(tospace) = temp;
@@ -534,7 +533,7 @@
grow_stack(void)
{
size_t newsz = FL(nstack) * 2;
- value_t *ns = LLT_REALLOC(FL(stack), newsz*sizeof(value_t));
+ value_t *ns = MEM_REALLOC(FL(stack), newsz*sizeof(value_t));
if(__unlikely(ns == nil))
lerrorf(FL(MemoryError), "stack overflow");
FL(stack) = ns;
@@ -786,7 +785,7 @@
if(__unlikely(i >= nargs))
lerrorf(FL(ArgError), "keyword %s requires an argument", symbol_name(v));
value_t hv = fixnum(((symbol_t*)ptr(v))->hash);
- lltint_t lx = numval(hv);
+ fixnum_t lx = numval(hv);
uintptr_t x = 2*((lx < 0 ? -lx : lx) % n);
if(__likely(vector_elt(kwtable, x) == v)){
uintptr_t idx = numval(vector_elt(kwtable, x+1));
@@ -866,7 +865,9 @@
int tail, x;
// temporary variables (not necessary to preserve across calls)
- uint32_t op, i, ipd;
+ size_t isz;
+ uint8_t op;
+ uint32_t i, ipd;
symbol_t *sym;
cons_t *c;
value_t *pv;
@@ -895,7 +896,7 @@
PUSH(0); // captured?
FL(curr_frame) = FL(sp);
-#ifdef COMPUTED_GOTO
+#if defined(COMPUTED_GOTO)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
#define OP(x) op_##x:
@@ -1060,9 +1061,9 @@
if(isbuiltin(func)){
s = builtins[i].nargs;
if(s >= 0)
- argcount(n, s);
+ argcount(n, (unsigned)s);
else if(s != ANYARGS && (signed)n < -s)
- argcount(n, -s);
+ argcount(n, (unsigned)-s);
// remove function arg
for(s = FL(sp)-n-1; s < (int)FL(sp)-1; s++)
FL(stack)[s] = FL(stack)[s+1];
@@ -1077,7 +1078,7 @@
case OP_DIV: goto apply_div;
default:
op = i;
-#ifdef COMPUTED_GOTO
+#if defined(COMPUTED_GOTO)
goto *((uint8_t*)&&op_OP_LOADA0 + ops[i]);
#else
continue;
@@ -1259,10 +1260,10 @@
v = FL(stack)[FL(sp)-2];
if(isvector(v)){
e = FL(stack)[FL(sp)-1];
- i = isfixnum(e) ? numval(e) : (uint32_t)toulong(e);
- if(__unlikely(i >= vector_size(v)))
+ isz = tosize(e);
+ if(__unlikely(isz >= vector_size(v)))
bounds_error(v, e);
- v = vector_elt(v, i);
+ v = vector_elt(v, isz);
}else if(__likely(isarray(v))){
v = cvalue_array_aref(&FL(stack)[FL(sp)-2]);
}else{
@@ -1297,13 +1298,24 @@
NEXT_OP;
OP(OP_ADD2)
+ do_add2:
FL(stack)[ipd] = (uintptr_t)ip;
- if(bothfixnums(FL(stack)[FL(sp)-1], FL(stack)[FL(sp)-2])){
- s = numval(FL(stack)[FL(sp)-1]) + numval(FL(stack)[FL(sp)-2]);
- v = fits_fixnum(s) ? fixnum(s) : mk_xlong(s);
- }else{
- v = fl_add_any(&FL(stack)[FL(sp)-2], 2, 0);
+ if(0){
+ OP(OP_SUB2)
+ do_sub2:
+ FL(stack)[ipd] = (uintptr_t)ip;
+ FL(stack)[FL(sp)-1] = fl_neg(FL(stack)[FL(sp)-1]);
}
+ {
+ fixnum_t a, b, c;
+ a = FL(stack)[FL(sp)-2];
+ b = FL(stack)[FL(sp)-1];
+ if(bothfixnums(a, b) && !sadd_overflow(numval(a), numval(b), &c) && fits_fixnum(c)){
+ v = fixnum(c);
+ }else{
+ v = fl_add_any(&FL(stack)[FL(sp)-2], 2);
+ }
+ }
POPN(1);
FL(stack)[FL(sp)-1] = v;
NEXT_OP;
@@ -1499,25 +1511,11 @@
OP(OP_ADD)
n = *ip++;
+ if(n == 2)
+ goto do_add2;
apply_add:
- s = 0;
- i = FL(sp)-n;
- for(; i < FL(sp); i++){
- if(isfixnum(FL(stack)[i])){
- s += numval(FL(stack)[i]);
- if(__unlikely(!fits_fixnum(s))){
- i++;
- goto add_ovf;
- }
- }else{
- add_ovf:
- FL(stack)[ipd] = (uintptr_t)ip;
- v = fl_add_any(&FL(stack)[i], FL(sp)-i, s);
- break;
- }
- }
- if(i == FL(sp))
- v = fixnum(s);
+ FL(stack)[ipd] = (uintptr_t)ip;
+ v = fl_add_any(&FL(stack)[FL(sp)-n], n);
POPN(n);
PUSH(v);
NEXT_OP;
@@ -1535,27 +1533,13 @@
// so it can handle rest args properly
PUSH(FL(stack)[i]);
FL(stack)[i] = fixnum(0);
- FL(stack)[i+1] = fl_neg(fl_add_any(&FL(stack)[i], n, 0));
+ FL(stack)[i+1] = fl_neg(fl_add_any(&FL(stack)[i], n));
FL(stack)[i] = POP();
- v = fl_add_any(&FL(stack)[i], 2, 0);
+ v = fl_add_any(&FL(stack)[i], 2);
POPN(n);
PUSH(v);
NEXT_OP;
- OP(OP_SUB2)
- do_sub2:
- if(bothfixnums(FL(stack)[FL(sp)-2], FL(stack)[FL(sp)-1])){
- s = numval(FL(stack)[FL(sp)-2]) - numval(FL(stack)[FL(sp)-1]);
- v = fits_fixnum(s) ? fixnum(s) : mk_xlong(s);
- }else{
- FL(stack)[ipd] = (uintptr_t)ip;
- FL(stack)[FL(sp)-1] = fl_neg(FL(stack)[FL(sp)-1]);
- v = fl_add_any(&FL(stack)[FL(sp)-2], 2, 0);
- }
- POPN(1);
- FL(stack)[FL(sp)-1] = v;
- NEXT_OP;
-
OP(OP_MUL)
n = *ip++;
apply_mul:
@@ -1857,7 +1841,7 @@
OP(OP_NOP)
NEXT_OP;
-#ifdef COMPUTED_GOTO
+#if defined(COMPUTED_GOTO)
#pragma GCC diagnostic pop
#else
}
@@ -2184,8 +2168,8 @@
FL(heapsize) = initial_heapsize;
- FL(fromspace) = LLT_ALLOC(FL(heapsize));
- FL(tospace) = LLT_ALLOC(FL(heapsize));
+ FL(fromspace) = MEM_ALLOC(FL(heapsize));
+ FL(tospace) = MEM_ALLOC(FL(heapsize));
FL(curheap) = FL(fromspace);
FL(lim) = FL(curheap)+FL(heapsize)-sizeof(cons_t);
FL(consflags) = bitvector_new(FL(heapsize)/sizeof(cons_t), 1);
@@ -2192,7 +2176,7 @@
htable_new(&FL(printconses), 32);
comparehash_init();
FL(nstack) = 262144;
- FL(stack) = LLT_ALLOC(FL(nstack)*sizeof(value_t));
+ FL(stack) = MEM_ALLOC(FL(nstack)*sizeof(value_t));
FL(Nil) = builtin(OP_THE_EMPTY_LIST);
FL(t) = builtin(OP_BOOL_CONST_T);
@@ -2262,21 +2246,7 @@
setc(symbol("procedure?"), builtin(OP_FUNCTIONP));
setc(symbol("top-level-bound?"), builtin(OP_BOUNDP));
-#if defined(__linux__)
- set(symbol("*os-name*"), symbol("linux"));
-#elif defined(__OpenBSD__)
- set(symbol("*os-name*"), symbol("openbsd"));
-#elif defined(__FreeBSD__)
- set(symbol("*os-name*"), symbol("freebsd"));
-#elif defined(__NetBSD__)
- set(symbol("*os-name*"), symbol("netbsd"));
-#elif defined(__DragonFly__)
- set(symbol("*os-name*"), symbol("dragonflybsd"));
-#elif defined(__plan9__)
- set(symbol("*os-name*"), symbol("plan9"));
-#else
- set(symbol("*os-name*"), symbol("unknown"));
-#endif
+ set(symbol("*os-name*"), symbol(__os_name__));
FL(the_empty_vector) = tagptr(alloc_words(1), TAG_VECTOR);
vector_setsize(FL(the_empty_vector), 0);
--- a/flisp.h
+++ b/flisp.h
@@ -1,5 +1,12 @@
#pragma once
+#include "platform.h"
+#include "utf8.h"
+#include "ios.h"
+#include "bitvector.h"
+#include "htableh.inc"
+HTPROT(ptrhash)
+
enum {
TAG_NUM,
TAG_CPRIM,
@@ -26,9 +33,22 @@
T_DOUBLE,
}numerictype_t;
-typedef uintptr_t value_t;
-typedef lltint_t fixnum_t;
+#ifdef BITS64
+typedef uint64_t value_t;
+typedef int64_t fixnum_t;
+#define FIXNUM_BITS 62
+#define TOP_BIT (1ULL<<63)
+#define T_FIXNUM T_INT64
+#else
+typedef uint32_t value_t;
+typedef int32_t fixnum_t;
+#define FIXNUM_BITS 30
+#define TOP_BIT (1U<<31)
+#define T_FIXNUM T_INT32
+#endif
+#define ALIGNED(x, sz) (((x) + (sz-1)) & (-sz))
+
typedef struct {
value_t car;
value_t cdr;
@@ -68,15 +88,8 @@
typedef value_t (*builtin_t)(value_t*, uint32_t);
-#ifdef BITS64
-#define T_FIXNUM T_INT64
-#define fits_fixnum(x) (((x)>>61) == 0 || (~((x)>>61)) == 0)
-#define mk_xlong mk_int64
-#else
-#define T_FIXNUM T_INT32
-#define fits_fixnum(x) (((x)>>29) == 0 || (~((x)>>29)) == 0)
-#define mk_xlong mk_int32
-#endif
+#define fits_bits(x, b) (((x)>>(b-1)) == 0 || (~((x)>>(b-1))) == 0)
+#define fits_fixnum(x) fits_bits(x, FIXNUM_BITS)
#define ANYARGS -10000
#define NONNUMERIC (0xff)
@@ -88,7 +101,6 @@
#define tagptr(p, t) ((value_t)(p) | (t))
#define fixnum(x) ((value_t)(x)<<2)
#define numval(x) ((fixnum_t)(x)>>2)
-#define fits_bits(x, b) (((x)>>(b-1)) == 0 || (~((x)>>(b-1))) == 0) /* mag: UNUSED? */
#define uintval(x) (((unsigned int)(x))>>3)
#define builtin(n) tagptr(((int)n<<3), TAG_FUNCTION)
#define iscons(x) (tag(x) == TAG_CONS)
@@ -428,3 +440,8 @@
extern Fl fl;
#define FL(f) fl.f
+
+extern double D_PNAN, D_NNAN, D_PINF, D_NINF;
+extern float F_PNAN, F_NNAN, F_PINF, F_NINF;
+
+_Noreturn void flmain(const uint8_t *boot, int bootsz, int argc, char **argv);
--- a/flmain.c
+++ b/flmain.c
@@ -1,4 +1,3 @@
-#include "llt.h"
#include "flisp.h"
#include "cvalues.h"
#include "print.h"
--- a/hashing.c
+++ b/hashing.c
@@ -1,9 +1,9 @@
-#include "llt.h"
+#include "flisp.h"
#include "hashing.h"
#include "spooky.h"
-lltuint_t
-nextipow2(lltuint_t i)
+value_t
+nextipow2(value_t i)
{
if(i == 0)
return 1;
@@ -12,7 +12,7 @@
i |= i >> 4;
i |= i >> 8;
i |= i >> 16;
-#ifdef BITS64
+#if defined(BITS64)
i |= i >> 32;
#endif
i++;
--- a/hashing.h
+++ b/hashing.h
@@ -1,6 +1,6 @@
#pragma once
-lltuint_t nextipow2(lltuint_t i);
+value_t nextipow2(value_t i);
uint32_t int32hash(uint32_t a);
uint64_t int64hash(uint64_t key);
uint32_t int64to32hash(uint64_t key);
--- a/htable.c
+++ b/htable.c
@@ -2,7 +2,7 @@
functions common to all hash table instantiations
*/
-#include "llt.h"
+#include "flisp.h"
#include "htable.h"
#include "hashing.h"
@@ -17,7 +17,7 @@
size *= 2; // 2 pointers per key/value pair
size *= 2; // aim for 50% occupancy
h->size = size;
- h->table = LLT_ALLOC(size*sizeof(void*));
+ h->table = MEM_ALLOC(size*sizeof(void*));
}
if(h->table == nil)
return nil;
@@ -31,7 +31,7 @@
htable_free(htable_t *h)
{
if(h->table != &h->_space[0])
- LLT_FREE(h->table);
+ MEM_FREE(h->table);
}
// empty and reduce size
@@ -41,7 +41,7 @@
sz = nextipow2(sz);
if(h->size > sz*4 && h->size > HT_N_INLINE){
size_t newsz = sz*4;
- void **newtab = LLT_REALLOC(h->table, newsz*sizeof(void*));
+ void **newtab = MEM_REALLOC(h->table, newsz*sizeof(void*));
if(newtab == nil)
return;
h->size = newsz;
--- a/htable.inc
+++ b/htable.inc
@@ -13,7 +13,7 @@
static void ** \
HTNAME##_lookup_bp(htable_t *h, void *key) \
{ \
- lltuint_t hv; \
+ value_t hv; \
size_t i, orig, index, iter; \
size_t newsz, sz = hash_size(h); \
size_t maxprobe = max_probe(sz); \
@@ -52,7 +52,7 @@
newsz = HT_N_INLINE; \
else \
newsz = sz<<2; \
- tab = (void**)LLT_ALLOC(newsz*sizeof(void*)); \
+ tab = (void**)MEM_ALLOC(newsz*sizeof(void*)); \
if(tab == nil) \
return nil; \
for(i = 0; i < newsz; i++) \
@@ -64,7 +64,7 @@
(*HTNAME##_lookup_bp(h, ol[i])) = ol[i+1]; \
} \
if(ol != &h->_space[0]) \
- LLT_FREE(ol); \
+ MEM_FREE(ol); \
sz = hash_size(h); \
maxprobe = max_probe(sz); \
tab = h->table; \
--- a/ios.c
+++ b/ios.c
@@ -1,4 +1,4 @@
-#include "llt.h"
+#include "flisp.h"
#include "timefuncs.h"
#define MOST_OF(x) ((x) - ((x)>>4))
@@ -26,7 +26,7 @@
static int
_enonfatal(int err)
{
- return err == EAGAIN || err == EINPROGRESS || err == EINTR || err == EWOULDBLOCK;
+ return err == 0 || err == EAGAIN || err == EINPROGRESS || err == EINTR || err == EWOULDBLOCK;
}
#define SLEEP_TIME 5//ms
#endif
@@ -39,6 +39,9 @@
ssize_t r;
while(1){
+#if !defined(__plan9__)
+ errno = 0;
+#endif
r = read(fd, buf, n);
if(r > -1){
*nread = (size_t)r;
@@ -81,6 +84,9 @@
ssize_t r;
while(1){
+#if !defined(__plan9__)
+ errno = 0;
+#endif
r = write(fd, buf, n);
if(r > -1){
*nwritten = (size_t)r;
@@ -140,11 +146,11 @@
// if we own the buffer we're free to resize it
// always allocate 1 bigger in case user wants to add a NUL
// terminator after taking over the buffer
- temp = LLT_REALLOC(s->buf, sz);
+ temp = MEM_REALLOC(s->buf, sz);
if(temp == nil)
return nil;
}else{
- temp = LLT_ALLOC(sz);
+ temp = MEM_ALLOC(sz);
if(temp == nil)
return nil;
s->ownbuf = 1;
@@ -533,11 +539,11 @@
close(s->fd);
s->fd = -1;
if(s->buf != nil && s->ownbuf && s->buf != &s->local[0])
- LLT_FREE(s->buf);
+ MEM_FREE(s->buf);
s->buf = nil;
s->size = s->maxsize = s->bpos = 0;
if(s->filename != emptystr){
- LLT_FREE(s->filename);
+ MEM_FREE(s->filename);
s->filename = emptystr;
}
}
@@ -564,13 +570,13 @@
ios_flush(s);
if(s->buf == &s->local[0] || s->buf == nil || (!s->ownbuf && s->size == s->maxsize)){
- buf = LLT_ALLOC(s->size+1);
+ buf = MEM_ALLOC(s->size+1);
if(buf == nil)
return nil;
if(s->size)
memcpy(buf, s->buf, s->size);
}else if(s->size == s->maxsize){
- buf = LLT_REALLOC(s->buf, s->size + 1);
+ buf = MEM_REALLOC(s->buf, s->size + 1);
if(buf == nil)
return nil;
}else{
@@ -601,7 +607,7 @@
s->size = nvalid;
if(s->buf != nil && s->ownbuf && s->buf != &s->local[0])
- LLT_FREE(s->buf);
+ MEM_FREE(s->buf);
s->buf = buf;
s->maxsize = size;
s->ownbuf = own;
@@ -738,7 +744,7 @@
goto open_file_err;
if(!wr)
s->readonly = 1;
- s->filename = LLT_STRDUP(fname);
+ s->filename = MEM_STRDUP(fname);
return s;
open_file_err:
s->fd = -1;
@@ -793,19 +799,19 @@
void
ios_init_stdstreams(void)
{
- ios_stdin = LLT_ALLOC(sizeof(ios_t));
+ ios_stdin = MEM_ALLOC(sizeof(ios_t));
ios_fd(ios_stdin, STDIN_FILENO, 0, 0);
- ios_stdin->filename = LLT_STRDUP("*stdin*");
+ ios_stdin->filename = MEM_STRDUP("*stdin*");
- ios_stdout = LLT_ALLOC(sizeof(ios_t));
+ ios_stdout = MEM_ALLOC(sizeof(ios_t));
ios_fd(ios_stdout, STDOUT_FILENO, 0, 0);
ios_stdout->bm = bm_line;
- ios_stdout->filename = LLT_STRDUP("*stdout*");
+ ios_stdout->filename = MEM_STRDUP("*stdout*");
- ios_stderr = LLT_ALLOC(sizeof(ios_t));
+ ios_stderr = MEM_ALLOC(sizeof(ios_t));
ios_fd(ios_stderr, STDERR_FILENO, 0, 0);
ios_stderr->bm = bm_none;
- ios_stderr->filename = LLT_STRDUP("*stderr*");
+ ios_stderr->filename = MEM_STRDUP("*stderr*");
}
/* higher level interface */
@@ -873,7 +879,7 @@
return 1;
if(s->_eof)
return IOS_EOF;
-#ifdef __plan9__
+#if defined(__plan9__)
USED(ws);
return 1; // FIXME(sigrid): wait for input, but not too much
#else
@@ -939,21 +945,24 @@
char *str;
int c;
-#if defined(__plan9__)
- str = vsmprint(format, args);
- if((c = strlen(str)) >= 0)
-#else
+ /* skip allocations if no buffering needed */
+ if(s->bm == bm_none && (s->state == bst_none || s->state == bst_wr))
+ return vdprintf(s->fd, format, args);
+
if((c = vsnprintf(buf, sizeof(buf), format, args)) < nelem(buf))
str = buf;
- else{
- str = LLT_ALLOC(c+1);
- vsnprintf(str, sizeof(c+1), format, args);
+ else if(s->state == bst_none || s->state == bst_wr){
+ /* doesn't fit? prefer no allocations */
+ ios_flush(s);
+ return vdprintf(s->fd, format, args);
+ }else{
+ str = MEM_ALLOC(c+1);
+ c = vsnprintf(str, sizeof(c+1), format, args);
}
if(c > 0)
-#endif
- ios_write(s, str, c);
+ c = ios_write(s, str, c);
if(str != buf)
- LLT_FREE(str);
+ MEM_FREE(str);
return c;
}
--- a/iostream.c
+++ b/iostream.c
@@ -1,4 +1,3 @@
-#include "llt.h"
#include "flisp.h"
#include "cvalues.h"
#include "types.h"
@@ -69,7 +68,7 @@
ios_t *
toiostream(value_t v)
{
- if(!isiostream(v))
+ if(__unlikely(!isiostream(v)))
type_error("iostream", v);
return value2c(ios_t*, v);
}
@@ -204,7 +203,7 @@
{
argcount(nargs, 2);
ios_t *s = toiostream(args[0]);
- size_t pos = toulong(args[1]);
+ size_t pos = tosize(args[1]);
off_t res = ios_seek(s, (off_t)pos);
if(res < 0)
return FL(f);
@@ -241,7 +240,7 @@
if(nargs == 3){
// form (io.read s type count)
ft = get_array_type(args[1]);
- n = toulong(args[2]) * ft->elsz;
+ n = tosize(args[2]) * ft->elsz;
}else{
ft = get_type(args[1]);
if(ft->eltype != nil && !iscons(cdr_(cdr_(args[1]))))
@@ -265,8 +264,8 @@
get_start_count_args(value_t *args, uint32_t nargs, size_t sz, size_t *offs, size_t *nb)
{
if(nargs > 1){
- *offs = toulong(args[1]);
- *nb = nargs > 2 ? toulong(args[2]) : sz - *offs;
+ *offs = tosize(args[1]);
+ *nb = nargs > 2 ? tosize(args[2]) : sz - *offs;
if(*offs >= sz || *offs + *nb > sz)
bounds_error(args[0], args[1]);
}
@@ -297,7 +296,7 @@
static uint8_t
get_delim_arg(value_t arg)
{
- size_t uldelim = toulong(arg);
+ size_t uldelim = tosize(arg);
if(uldelim > 0x7f){
// runes > 0x7f, or anything else > 0xff, are out of range
if((iscprim(arg) && cp_class(ptr(arg)) == FL(runetype)) || uldelim > 0xff)
@@ -348,7 +347,7 @@
ios_t *dest = toiostream(args[0]);
ios_t *src = toiostream(args[1]);
if(nargs == 3)
- return size_wrap(ios_copy(dest, src, toulong(args[2])));
+ return size_wrap(ios_copy(dest, src, tosize(args[2])));
return size_wrap(ios_copyall(dest, src));
}
@@ -367,7 +366,7 @@
BUILTIN("io-set-line!", io_set_line)
{
argcount(nargs, 2);
- toiostream(args[0])->lineno = toulong(args[1]);
+ toiostream(args[0])->lineno = tosize(args[1]);
return FL(t);
}
@@ -380,7 +379,7 @@
BUILTIN("io-set-column!", io_set_column)
{
argcount(nargs, 2);
- toiostream(args[0])->colno = toulong(args[1]);
+ toiostream(args[0])->colno = tosize(args[1]);
return FL(t);
}
--- a/llt.h
+++ /dev/null
@@ -1,33 +1,0 @@
-#pragma once
-
-#include "platform.h"
-#include "utf8.h"
-#include "ios.h"
-#include "bitvector.h"
-
-#include "htableh.inc"
-HTPROT(ptrhash)
-
-#define DBL_MAXINT (1LL<<53)
-#define FLT_MAXINT (1<<24)
-#define BIT63 0x8000000000000000ULL
-#define BIT31 0x80000000UL
-
-#ifdef BITS64
-#define TOP_BIT BIT63
-typedef uint64_t lltuint_t;
-typedef int64_t lltint_t;
-#else
-#define TOP_BIT BIT31
-typedef uint32_t lltuint_t;
-typedef int32_t lltint_t;
-#endif
-
-#define LOG2_10 3.3219280948873626
-#define rel_zero(a, b) (fabs((a)/(b)) < DBL_EPSILON)
-#define LLT_ALIGN(x, sz) (((x) + (sz-1)) & (-sz))
-
-extern double D_PNAN, D_NNAN, D_PINF, D_NINF;
-extern float F_PNAN, F_NNAN, F_PINF, F_NINF;
-
-_Noreturn void flmain(const uint8_t *boot, int bootsz, int argc, char **argv);
--- a/main_plan9.c
+++ b/main_plan9.c
@@ -1,4 +1,4 @@
-#include "llt.h"
+#include "flisp.h"
extern uchar bootcode[];
extern ulong bootlen;
--- a/main_posix.c
+++ b/main_posix.c
@@ -1,4 +1,4 @@
-#include "llt.h"
+#include "flisp.h"
#include "ieee754.h"
static const uint8_t boot[] =
--- a/meson.build
+++ b/meson.build
@@ -98,9 +98,8 @@
endif
sixel = get_option('sixel')
-
+libsixel_dep = []
if sixel.disabled()
- libsixel_dep = []
src += ['sixel_disabled.c']
else
libsixel = dependency('libsixel', required: sixel)
@@ -107,7 +106,7 @@
if libsixel.found()
src += ['sixel.c']
libsixel_dep = [libsixel]
- elif
+ else
src += ['sixel_disabled.c']
endif
endif
@@ -164,8 +163,8 @@
test('argv', flisp, args: ['argv.lsp'], workdir: tests_dir)
test('hash', flisp, args: ['hashtest.lsp'], workdir: tests_dir)
-test('perf', flisp, args: ['perf.lsp'], workdir: tests_dir)
+test('perf', flisp, args: ['perf.lsp'], workdir: tests_dir, timeout: 60)
test('tme', flisp, args: ['tme.lsp'], workdir: tests_dir)
-test('torture', flisp, args: ['torture.scm'], workdir: tests_dir)
+test('torture', flisp, args: ['torture.scm'], workdir: tests_dir, timeout: 60)
test('torus', flisp, args: ['torus.lsp'], workdir: tests_dir)
test('unit', flisp, args: ['unittest.lsp'], workdir: tests_dir)
--- a/mkfile
+++ b/mkfile
@@ -2,12 +2,13 @@
BIN=/$objtype/bin
TARG=flisp
-CFLAGS=$CFLAGS -p -D__plan9__ -D__${objtype}__ -I3rd -Iplan9
+CFLAGS=$CFLAGS -p -I. -I3rd -Iplan9 -D__plan9__ -D__${objtype}__ -DNDEBUG
CLEANFILES=plan9/flisp.boot.s plan9/builtin_fns.h
HFILES=\
equalhash.h\
flisp.h\
+ plan9/platform.h\
OFILES=\
3rd/mt19937-64.$O\
@@ -46,9 +47,10 @@
sed -n 's/^BUILTIN[_]?(\(".*)/BUILTIN_FN\1/gp' \
`{ls `{echo $OFILES | sed 's/\.'$O'/.c/g'} >[2]/dev/null} | sort >$target
-main_plan9.$O: plan9/builtin_fns.h
-flisp.$O: maxstack.inc opcodes.h plan9/builtin_fns.h
builtins.$O: plan9/builtin_fns.h
+cvalues.$O: fl_arith_any.inc
+flisp.$O: maxstack.inc opcodes.h plan9/builtin_fns.h
+main_plan9.$O: plan9/builtin_fns.h
plan9/flisp.boot.s:D: flisp.boot
aux/data2s boot <flisp.boot >$target
--- a/operators.c
+++ b/operators.c
@@ -1,4 +1,3 @@
-#include "llt.h"
#include "flisp.h"
#include "operators.h"
--- a/operators.h
+++ b/operators.h
@@ -14,11 +14,3 @@
int32_t conv_to_int32(void *data, numerictype_t tag);
uint32_t conv_to_uint32(void *data, numerictype_t tag);
Rune conv_to_Rune(void *data, numerictype_t tag);
-
-#if defined(ULONG64)
-#define conv_to_long conv_to_int64
-#define conv_to_ulong conv_to_uint64
-#else
-#define conv_to_long conv_to_int32
-#define conv_to_ulong conv_to_uint32
-#endif
--- a/overflows.h
+++ /dev/null
@@ -1,29 +1,0 @@
-
-#define addof_int64(c,a,b) ( \
- (b < 1)? \
- ((INT64_MIN-(b) <= (a))?((c=(a)+(b))?0:1):1): \
- ((INT64_MAX-(b) >= (a))?((c=(a)+(b))?0:1):1) \
-)
-
-#define subof_int64(c,a,b) ( \
- (b < 1)? \
- ((INT64_MAX+(b) >= (a))?((c=(a)-(b))?0:1):1): \
- ((INT64_MIN+(b) <= (a))?((c=(a)-(b))?0:1):1) \
-)
-
-#define addof_uint64(c,a,b) ( \
- b? \
- ((UINT64_MAX-(b) >= (a))?((c=(a)+(b)),0):1): \
- 0 \
-)
-
-#define subof_uint64(c,a,b) ( \
- (b < 1)? \
- ((UINT64_MAX+(b) >= (a))?((c=(a)-(b))?0:1):1): \
- (((b) <= (a))?((c=(a)-(b))?0:1):1) \
-)
-
-#define mulof(c,a,b) ( \
- (((a) != 0) && ((c=(a)*(b))/(a) != (b)))?1:0 \
-)
-
--- a/plan9/platform.h
+++ b/plan9/platform.h
@@ -3,13 +3,35 @@
#include <ctype.h>
#include <mp.h>
+#ifdef NDEBUG
+#undef assert
+#define assert(x)
+#endif
+
+#define __os_name__ "plan9"
+
#define __thread
-#define LLT_ALLOC(n) malloc(n)
-#define LLT_REALLOC(p, n) realloc((p), (n))
-#define LLT_FREE(x) free(x)
-#define LLT_STRDUP(s) strdup(s)
+#define MEM_ALLOC(n) malloc(n)
+#define MEM_REALLOC(p, n) realloc((p), (n))
+#define MEM_FREE(x) free(x)
+#define MEM_STRDUP(s) strdup(s)
+/* FIXME(sigrid): s*_overflow_* can be more optimal */
+
+#define sadd_overflow_64(a, b, c) ( \
+ (b < 1) ? \
+ ((INT64_MAX-(b) <= (a)) ? ((*(c)=(a)+(b)), 0) : 1) : \
+ ((INT64_MAX-(b) >= (a)) ? ((*(c)=(a)+(b)), 0) : 1) \
+)
+
+#define smul_overflow_64(a, b, c) ( \
+ ((a)>0 ? ((b)>0 ? (a)>INT64_MAX/(b) : (b)<INT64_MIN/(a)) \
+ : ((b)>0 ? (a)<INT64_MIN/(b) : ((a)!=0 && (b)<INT64_MAX/(a)))) \
+ ? 1 \
+ : ((*(c)=(a)*(b)), 0) \
+)
+
#if defined(__amd64__) || \
defined(__arm64__) || \
defined(__mips64__) || \
@@ -16,6 +38,15 @@
defined(__power64__) || \
defined(__sparc64__)
#define BITS64
+#define PRIdPTR PRId64
+#define sadd_overflow(a, b, c) sadd_overflow_64(a, b, c)
+#else
+#define PRIdPTR "ld"
+#define sadd_overflow(a, b, c) ( \
+ (b < 1) ? \
+ ((INT32_MAX-(b) <= (a)) ? ((*(c)=(a)+(b)), 0) : 1) : \
+ ((INT32_MAX-(b) >= (a)) ? ((*(c)=(a)+(b)), 0) : 1) \
+)
#endif
#define unsetenv(name) putenv(name, "")
@@ -25,6 +56,7 @@
#define getcwd getwd
#define vsnprintf vsnprint
+#define vdprintf fprint
#define snprintf snprint
#define strcasecmp cistrcmp
#define lseek seek
@@ -31,17 +63,12 @@
#define towupper toupperrune
#define towlower tolowerrune
#define iswalpha isalpharune
-#define signbit(r) ((*(uint64_t*)&(r)) & BIT63)
+#define signbit(r) ((*(uint64_t*)&(r)) & (1ULL<<63))
#define isfinite(d) (((*(uint64_t*)&(d))&0x7ff0000000000000ULL) != 0x7ff0000000000000ULL)
#define PRIu32 "ud"
#define PRId64 "lld"
#define PRIu64 "llud"
-#ifdef BITS64
-#define PRIdPTR PRId64
-#else
-#define PRIdPTR "ld"
-#endif
#define INT32_MAX 0x7fffffff
#define UINT32_MAX 0xffffffffU
--- a/posix/platform.h
+++ b/posix/platform.h
@@ -25,17 +25,34 @@
#include <wctype.h>
#include <wchar.h>
-#define LLT_ALLOC(n) malloc((size_t)(n))
-#define LLT_REALLOC(p, n) realloc((p), (size_t)(n))
-#define LLT_FREE(x) free(x)
-#define LLT_STRDUP(s) strdup(s)
+#if defined(__linux__)
+#define __os_name__ "linux"
+#elif defined(__OpenBSD__)
+#define __os_name__ "openbsd"
+#elif defined(__FreeBSD__)
+#define __os_name__ "freebsd"
+#elif defined(__NetBSD__)
+#define __os_name__ "netbsd"
+#elif defined(__DragonFly__)
+#define __os_name__ "dragonflybsd"
+#else
+#define __os_name__ "unknown"
+#endif
+#define MEM_ALLOC(n) malloc((size_t)(n))
+#define MEM_REALLOC(p, n) realloc((p), (size_t)(n))
+#define MEM_FREE(x) free(x)
+#define MEM_STRDUP(s) strdup(s)
+
#ifndef __SIZEOF_POINTER__
#error pointer size unknown
#elif __SIZEOF_POINTER__ == 8
-#define BITS64 1
-#define ULONG64 1
+#define BITS64
#endif
+
+#define sadd_overflow __builtin_add_overflow
+#define sadd_overflow_64 __builtin_add_overflow
+#define smul_overflow_64 __builtin_mul_overflow
#define nil NULL
#define USED(x) ((void)(x))
--- a/posix/utf.h
+++ b/posix/utf.h
@@ -7,7 +7,7 @@
UTFmax = 4,
};
-typedef int32_t Rune;
+typedef uint32_t Rune;
int chartorune(Rune *rune, const char *str);
int runetochar(char *str, const Rune *rune);
--- a/print.c
+++ b/print.c
@@ -1,4 +1,3 @@
-#include "llt.h"
#include "flisp.h"
#include "operators.h"
#include "opcodes.h"
@@ -7,6 +6,8 @@
#include "print.h"
#include "read.h"
+#define LOG2_10 3.321928094887362347870319429489
+
static void
outc(char c, ios_t *f)
{
@@ -120,7 +121,7 @@
if((name[0] == '\0') ||
(name[0] == '.' && name[1] == '\0') ||
(name[0] == '#') ||
- isnumtok(name, nil))
+ fl_read_numtok(name, nil, 0))
escape = 1;
i = 0;
while(name[i]){
@@ -592,27 +593,31 @@
if(fpart == 0)
dec = 0;
if(width == 0)
- snprintf(format, 8, "%%.%d%s", dec, num_format);
+ snprintf(format, sizeof(format), "%%.%d%s", dec, num_format);
else
- snprintf(format, 8, "%%%d.%d%s", width, dec, num_format);
+ snprintf(format, sizeof(format), "%%%d.%d%s", width, dec, num_format);
sz = snprintf(s, cnt, format, r);
/* trim trailing zeros from fractions. not when using scientific
notation, since we might have e.g. 1.2000e+100. also not when we
need a specific output width */
if(width == 0 && !keepz){
- if(sz > 2 && fpart && num_format[1] != 'e'){
+ if(sz > 2 && fpart){
+ char *e = nil;
+ if(num_format[1] == 'e'){
+ while(s[--sz] != 'e');
+ e = s + sz--;
+ }
while(s[sz-1] == '0'){
s[sz-1] = '\0';
sz--;
}
// don't need trailing .
- if(s[sz-1] == '.'){
+ if(s[sz-1] == '.')
s[--sz] = '\0';
- }
+ if(num_format[1] == 'e')
+ strcpy(s+sz, e);
}
}
- // TODO. currently 1.1e20 prints as 1.1000000000000000e+20; be able to
- // get rid of all those zeros.
}
// 'weak' means we don't need to accurately reproduce the type, so
@@ -696,11 +701,7 @@
if(type == FL(floatsym) && !FL(print_princ) && !weak)
outc('f', f);
}
-#if defined(ULONG64)
- }else if(type == FL(uint64sym) || type == FL(ulongsym)){
-#else
}else if(type == FL(uint64sym)){
-#endif
uint64_t ui64 = *(uint64_t*)data;
if(weak || FL(print_princ))
FL(hpos) += ios_printf(f, "%"PRIu64, ui64);
@@ -709,11 +710,8 @@
}else if(type == FL(bignumsym)){
mpint *i = *(mpint**)data;
char *s = mptoa(i, 10, nil, 0);
- if(weak || FL(print_princ))
- FL(hpos) += ios_printf(f, "%s", s);
- else
- FL(hpos) += ios_printf(f, "#%s(%s)", symbol_name(type), s);
- LLT_FREE(s);
+ FL(hpos) += ios_printf(f, "%s", s);
+ MEM_FREE(s);
}else if(issymbol(type)){
// handle other integer prims. we know it's smaller than uint64
// at this point, so int64 is big enough to capture everything.
@@ -733,7 +731,7 @@
value_t eltype = car(cdr_(type));
size_t cnt, elsize;
if(iscons(cdr_(cdr_(type)))){
- cnt = toulong(car_(cdr_(cdr_(type))));
+ cnt = tosize(car_(cdr_(cdr_(type))));
elsize = cnt ? len/cnt : 0;
}else{
// incomplete array type
--- a/ptrhash.c
+++ b/ptrhash.c
@@ -3,11 +3,11 @@
optimized for storing info about particular values
*/
-#include "llt.h"
+#include "flisp.h"
#define OP_EQ(x, y) ((x) == (y))
-#ifdef BITS64
+#if defined(BITS64)
static uint64_t
_pinthash(uint64_t key)
{
--- a/random.c
+++ b/random.c
@@ -1,4 +1,4 @@
-#include "llt.h"
+#include "flisp.h"
#include "mt19937-64.h"
#include "timefuncs.h"
#include "random.h"
--- a/read.c
+++ b/read.c
@@ -1,4 +1,3 @@
-#include "llt.h"
#include "flisp.h"
#include "cvalues.h"
#include "read.h"
@@ -21,85 +20,15 @@
static value_t do_read_sexpr(Rctx *ctx, value_t label);
-#if defined(__plan9__)
-static int errno;
-static mpint *mp_vlong_min, *mp_vlong_max, *mp_uvlong_max;
-#endif
-
-static int64_t
-strtoll_mp(const char *nptr, char **rptr, int base, mpint **mp)
-{
- int64_t x;
- mpint *m;
-
- *mp = nil;
- errno = 0;
- x = strtoll(nptr, rptr, base);
-#if defined(__plan9__)
- if((x != INT64_MAX && x != INT64_MIN) || *rptr == nptr)
- return x;
- mpint *c;
- m = strtomp(nptr, rptr, base, nil);
- if(x == INT64_MAX){
- if(mp_vlong_max == nil)
- mp_vlong_max = vtomp(INT64_MAX, nil);
- c = mp_vlong_max;
- }else{
- if(mp_vlong_min == nil)
- mp_vlong_min = vtomp(INT64_MIN, nil);
- c = mp_vlong_min;
- }
- if(mpcmp(c, m) == 0){
- mpfree(m);
- m = nil;
- }
-#else
- m = nil;
- if(errno == ERANGE && (x == LLONG_MAX || x == LLONG_MIN))
- m = strtomp(nptr, rptr, base, nil);
-#endif
- *mp = m;
- return x;
-}
-
-static uint64_t
-strtoull_mp(const char *nptr, char **rptr, int base, mpint **mp)
-{
- uint64_t x;
- mpint *m;
-
- *mp = nil;
- errno = 0;
- x = strtoull(nptr, rptr, base);
-#if defined(__plan9__)
- if(x != INT64_MAX || *rptr == nptr)
- return x;
- m = strtomp(nptr, rptr, base, nil);
- if(mp_uvlong_max == nil)
- mp_uvlong_max = uvtomp(INT64_MAX, nil);
- if(mpcmp(mp_uvlong_max, m) == 0){
- mpfree(m);
- m = nil;
- }
-#else
- m = nil;
- if(errno == ERANGE && x == ULLONG_MAX)
- m = strtomp(nptr, rptr, base, nil);
-#endif
- *mp = m;
- return x;
-}
-
#define RS value2c(ios_t*, FL(readstate)->source)
bool
-isnumtok_base(const char *tok, value_t *pval, int base)
+fl_read_numtok(const char *tok, value_t *pval, int base)
{
char *end;
int64_t i64;
- uint64_t ui64;
double d;
- mpint *mp = nil;
+ mpint *mp;
if(*tok == '\0')
return false;
if(!((tok[0] == '0' && tok[1] == 'x') || (base >= 15)) && strpbrk(tok, ".eEpP")){
@@ -141,31 +70,15 @@
*pval = mk_double(D_NINF);
return true;
}
- i64 = strtoll_mp(tok, &end, base, &mp);
- bool ok = *end == '\0';
- if(pval)
- *pval = mp == nil ? return_from_int64(i64) : mk_mpint(mp);
- return ok;
}
- ui64 = strtoull_mp(tok, &end, base, &mp);
+ i64 = strtoll(tok, &end, base);
+ mp = fits_fixnum(i64) ? nil : strtomp(tok, &end, base, nil);
bool ok = *end == '\0';
if(pval)
- *pval = mp == nil ? return_from_uint64(ui64) : mk_mpint(mp);
+ *pval = mp == nil ? fixnum(i64) : mk_mpint(mp);
return ok;
}
-bool
-isnumtok(const char *tok, value_t *pval)
-{
- return isnumtok_base(tok, pval, 0);
-}
-
-static bool
-read_numtok(const char *tok, value_t *pval, int base)
-{
- return isnumtok_base(tok, pval, base);
-}
-
static char
nextchar(void)
{
@@ -317,7 +230,7 @@
if(cval == 'u' || cval == 'U' || cval == 'x'){
read_token(ctx, 'u', 0);
if(ctx->buf[1] != '\0'){ // not a solitary 'u','U','x'
- if(!read_numtok(&ctx->buf[1], &ctx->tokval, 16))
+ if(!fl_read_numtok(&ctx->buf[1], &ctx->tokval, 16))
parse_error("invalid hex character constant");
cval = numval(ctx->tokval);
}
@@ -415,7 +328,7 @@
(c == 'o' && (base = 8)) ||
(c == 'd' && (base = 10)) ||
(c == 'x' && (base = 16))) && (isdigit_base(ctx->buf[1], base) || ctx->buf[1] == '-')){
- if(!read_numtok(&ctx->buf[1], &ctx->tokval, base))
+ if(!fl_read_numtok(&ctx->buf[1], &ctx->tokval, base))
parse_error("invalid base %d constant", base);
return (ctx->toktype = TOK_NUM);
}
@@ -441,7 +354,7 @@
if(!read_token(ctx, c, 0)){
if(ctx->buf[0] == '.' && ctx->buf[1] == '\0')
return (ctx->toktype = TOK_DOT);
- if(read_numtok(ctx->buf, &ctx->tokval, 0))
+ if(fl_read_numtok(ctx->buf, &ctx->tokval, 0))
return (ctx->toktype = TOK_NUM);
}
ctx->toktype = TOK_SYM;
@@ -512,13 +425,13 @@
value_t s;
Rune r = 0;
- buf = LLT_ALLOC(sz);
+ buf = MEM_ALLOC(sz);
while(1){
if(i >= sz-UTFmax){ // -UTFmax: leaves room for longest utf8 sequence
sz *= 2;
- temp = LLT_REALLOC(buf, sz);
+ temp = MEM_REALLOC(buf, sz);
if(temp == nil){
- LLT_FREE(buf);
+ MEM_FREE(buf);
parse_error("out of memory reading string");
}
buf = temp;
@@ -525,7 +438,7 @@
}
c = ios_getc(RS);
if(c == IOS_EOF){
- LLT_FREE(buf);
+ MEM_FREE(buf);
parse_error("unexpected end of input in string");
}
if(c == '"')
@@ -533,7 +446,7 @@
else if(c == '\\'){
c = ios_getc(RS);
if(c == IOS_EOF){
- LLT_FREE(buf);
+ MEM_FREE(buf);
parse_error("end of input in escape sequence");
}
j = 0;
@@ -561,7 +474,7 @@
if(j)
r = strtol(eseq, nil, 16);
if(!j || r > Runemax){
- LLT_FREE(buf);
+ MEM_FREE(buf);
parse_error("invalid escape sequence");
}
if(ndig == 2)
@@ -573,7 +486,7 @@
}else{
char esc = read_escape_control_char((char)c);
if(esc == (char)c && !strchr("\\'\"`", esc)){
- LLT_FREE(buf);
+ MEM_FREE(buf);
parse_error("invalid escape sequence: \\%c", (char)c);
}
buf[i++] = esc;
@@ -584,7 +497,7 @@
}
s = cvalue_string(i);
memcpy(cvalue_data(s), buf, i);
- LLT_FREE(buf);
+ MEM_FREE(buf);
return s;
}
--- a/read.h
+++ b/read.h
@@ -1,8 +1,7 @@
#pragma once
value_t fl_read_sexpr(value_t f);
-bool isnumtok_base(const char *tok, value_t *pval, int base);
-bool isnumtok(const char *tok, value_t *pval);
+bool fl_read_numtok(const char *tok, value_t *pval, int base);
// defines which characters are ordinary symbol characters.
// exceptions are '.', which is an ordinary symbol character
--- a/sixel.c
+++ b/sixel.c
@@ -1,5 +1,4 @@
#include <sixel.h>
-#include "llt.h"
#include "flisp.h"
#include "cvalues.h"
#include "types.h"
@@ -48,7 +47,7 @@
int numcolors = 256;
if(nargs > 0){
argcount(nargs, 1);
- numcolors = toulong(args[0]);
+ numcolors = tosize(args[0]);
}
if(numcolors < 1 || numcolors > 256)
lerrorf(FL(ArgError), "invalid number of colors: %d", numcolors);
@@ -79,10 +78,10 @@
if(!issixeloutput(args[0]))
type_error("sixel-output", args[0]);
fso_t *f = value2c(fso_t*, args[0]);
- int scalex = toulong(args[1]);
+ int scalex = tosize(args[1]);
int scaley = scalex;
if(nargs > 2)
- scaley = toulong(args[2]);
+ scaley = tosize(args[2]);
if(scalex < 1 || scalex > 32 || scaley < 1 || scaley > 32)
lerrorf(FL(ArgError), "invalid scale factor: %dx%d", scalex, scaley);
f->scalex = scalex;
@@ -175,8 +174,8 @@
uint8_t *pix;
size_t sz;
to_sized_ptr(args[2], &pix, &sz);
- size_t w = toulong(args[3]);
- size_t h = toulong(args[4]);
+ size_t w = tosize(args[3]);
+ size_t h = tosize(args[4]);
if(w <= 0 || w > sz)
bounds_error(args[2], args[3]);
if(h <= 0 || w*h > sz)
@@ -187,7 +186,7 @@
if(ow < 1 || oh < 1 || osz < ow || osz < oh)
lerrorf(FL(ArgError), "scaling out of range");
if(f->bufsz < osz){
- f->buf = LLT_REALLOC(f->buf, osz);
+ f->buf = MEM_REALLOC(f->buf, osz);
f->bufsz = osz;
}
r = sixel_helper_scale_image(
@@ -205,7 +204,7 @@
h = oh;
pix = f->buf;
}else if(f->buf != nil){
- LLT_FREE(f->buf);
+ MEM_FREE(f->buf);
f->buf = nil;
f->bufsz = 0;
}
@@ -240,7 +239,7 @@
fso_t *f = value2c(fso_t*, self);
sixel_dither_destroy(f->dither);
sixel_output_destroy(f->out);
- LLT_FREE(f->buf);
+ MEM_FREE(f->buf);
}
static cvtable_t fso_vtable = {
--- a/string.c
+++ b/string.c
@@ -1,7 +1,6 @@
/*
string functions
*/
-#include "llt.h"
#include "flisp.h"
#include "operators.h"
#include "cvalues.h"
@@ -26,11 +25,11 @@
size_t len = cv_len((cvalue_t*)ptr(args[0]));
size_t stop = len;
if(nargs > 1){
- start = toulong(args[1]);
+ start = tosize(args[1]);
if(start > len)
bounds_error(args[0], args[1]);
if(nargs > 2){
- stop = toulong(args[2]);
+ stop = tosize(args[2]);
if(stop > len)
bounds_error(args[0], args[2]);
if(stop <= start)
@@ -185,7 +184,7 @@
argcount(nargs, 3);
char *s = tostring(args[0]);
size_t lenbytes = cv_len((cvalue_t*)ptr(args[0]));
- size_t startbytes, n, startchar = toulong(args[1]);
+ size_t startbytes, n, startchar = tosize(args[1]);
for(startbytes = n = 0; n < startchar && startbytes < lenbytes; n++)
startbytes += u8_seqlen(s+startbytes);
if(n != startchar)
@@ -192,7 +191,7 @@
bounds_error(args[0], args[1]);
size_t endbytes = lenbytes;
if(nargs == 3){
- size_t endchar = toulong(args[2]);
+ size_t endchar = tosize(args[2]);
for(endbytes = startbytes; n < endchar && endbytes < lenbytes; n++)
endbytes += u8_seqlen(s+endbytes);
if(n != endchar)
@@ -211,7 +210,7 @@
argcount(nargs, 2);
char *s = tostring(args[0]);
size_t lenbytes = cv_len(ptr(args[0]));
- size_t startbytes, n, startchar = toulong(args[1]);
+ size_t startbytes, n, startchar = tosize(args[1]);
for(startbytes = n = 0; n < startchar && startbytes < lenbytes; n++)
startbytes += u8_seqlen(s+startbytes);
if(n != startchar)
@@ -307,7 +306,7 @@
char cbuf[UTFmax+1];
size_t start = 0;
if(nargs == 3)
- start = toulong(args[2]);
+ start = tosize(args[2]);
else
argcount(nargs, 2);
char *s = tostring(args[0]);
@@ -350,7 +349,7 @@
static unsigned long
get_radix_arg(value_t arg)
{
- unsigned long radix = toulong(arg);
+ unsigned long radix = tosize(arg);
if(radix < 2 || radix > 36)
lerrorf(FL(ArgError), "invalid radix");
return radix;
@@ -392,7 +391,7 @@
unsigned long radix = 0;
if(nargs == 2)
radix = get_radix_arg(args[1]);
- if(!isnumtok_base(str, &n, (int)radix))
+ if(!fl_read_numtok(str, &n, (int)radix))
return FL(f);
return n;
}
--- a/table.c
+++ b/table.c
@@ -1,4 +1,3 @@
-#include "llt.h"
#include "flisp.h"
#include "equalhash.h"
#include "cvalues.h"
--- a/terminal_posix.c
+++ b/terminal_posix.c
@@ -1,4 +1,3 @@
-#include "llt.h"
#include "flisp.h"
#include <sys/ioctl.h>
#include <termios.h>
--- a/test/number-boundaries.lsp
+++ b/test/number-boundaries.lsp
@@ -81,17 +81,16 @@
; mul signed
(assert (= 18446744073709551614 (* (high-border int64) 2)))
-;(assert (= -18446744073709551614 (* (high-border int64) -2)))
+(assert (= -18446744073709551614 (* (high-border int64) -2)))
(assert (= 18446744073709551614 (* 2 (high-border int64))))
-;(assert (= -18446744073709551616 (* (low-border int64) 2)))
-;(assert (= -18446744073709551616 (* 2 (low-border int64))))
+(assert (= -18446744073709551616 (* (low-border int64) 2)))
+(assert (= -18446744073709551616 (* 2 (low-border int64))))
; mul unsigned
-;(assert (= 36893488147419103230 (* (high-border uint64) 2)))
-;(assert (= 36893488147419103230 (* 2 (high-border uint64))))
-;(assert (= -36893488147419103230 (* (high-border uint64) -2)))
-;(assert (= -36893488147419103230 (* -2 (high-border uint64))))
+(assert (= 36893488147419103230 (* (high-border uint64) 2)))
+(assert (= 36893488147419103230 (* 2 (high-border uint64))))
+(assert (= -36893488147419103230 (* (high-border uint64) -2)))
+(assert (= -36893488147419103230 (* -2 (high-border uint64))))
(princ "all number boundaries tests pass\n\n")
#t
-
--- a/test/unittest.lsp
+++ b/test/unittest.lsp
@@ -64,7 +64,7 @@
(assert (< (- #uint32(0x80000000)) 0))
(assert (> (- #int32(0x80000000)) 0))
(assert (< (- #uint64(0x8000000000000000)) 0))
-(assert (> (- #int64(0x8000000000000000)) 0))
+(assert (< (- #int64(0x8000000000000000)) 0))
; fixnum versions
(assert (= (- -536870912) 536870912))
(assert (= (- -2305843009213693952) 2305843009213693952))
@@ -93,11 +93,12 @@
(assert (> 0x10000000000000000 0x8fffffffffffffff))
(assert (< 0x8fffffffffffffff 0x10000000000000000))
-(assert (not (bignum? (ash 2 60))))
-(assert (not (bignum? (- (ash 2 60) 1))))
+(assert (bignum? (ash 2 60)))
+(define (bignum-on-32? x) (if #.(fixnum? 0xffffffff) (not (bignum? x)) (bignum? x)))
+(assert (bignum-on-32? (- (ash 2 60) 1)))
(assert (bignum? 1606938044258990275541962092341162602522202993782792835301376))
(assert (bignum? 0xfffffffffffffffff))
-(assert (not (bignum? 0xfffffffffffffff)))
+(assert (bignum-on-32? 0xfffffffffffffff))
(assert (= 4764984380238568507752444984131552966909
(* 66405897020462343733 71755440315342536873)))
--- a/time_plan9.c
+++ b/time_plan9.c
@@ -1,4 +1,4 @@
-#include "llt.h"
+#include "flisp.h"
#include "timefuncs.h"
#include <tos.h>
--- a/time_posix.c
+++ b/time_posix.c
@@ -1,4 +1,4 @@
-#include "llt.h"
+#include "flisp.h"
#include "timefuncs.h"
double
--- a/types.c
+++ b/types.c
@@ -1,4 +1,3 @@
-#include "llt.h"
#include "flisp.h"
#include "cvalues.h"
#include "equalhash.h"
@@ -40,7 +39,7 @@
if(isarray){
fltype_t *eltype = get_type(car_(cdr_(t)));
if(eltype->size == 0){
- LLT_FREE(ft);
+ MEM_FREE(ft);
lerrorf(FL(ArgError), "invalid array element type");
}
ft->elsz = eltype->size;
--- a/utf8.c
+++ b/utf8.c
@@ -13,7 +13,7 @@
A UTF-8 validation routine is included.
*/
-#include "llt.h"
+#include "flisp.h"
static const uint32_t offsetsFromUTF8[6] = {
0x00000000UL, 0x00003080UL, 0x000E2080UL,