#include "sl.h"#include "operators.h"#include "cvalues.h"#include "types.h"#include "io.h"#include "equal.h" enum { MAX_INL_SIZE = 384, CVALUE_NWORDS = sizeof(sl_cv)/sizeof(sl_v), CV_OWNED = 1<<0,}; #define owned(cv) ((uintptr)(cv)->type & CV_OWNED)#define isinlined(cv) ((cv)->data == (cv)->_space) sl_type *unboxedtypes[T_UNBOXED_NUM];sl_v unboxedtypesyms[T_UNBOXED_NUM]; static void cvalue_init(sl_type *type, sl_v v, void *dest); voidadd_finalizer(sl_cv *cv){ if(slg.nfinalizers == slg.maxfinalizers){ slg.maxfinalizers *= 2; slg.finalizers = MEM_REALLOC(slg.finalizers, slg.maxfinalizers*sizeof(slg.finalizers)); assert(slg.finalizers != nil); } slg.finalizers[slg.nfinalizers++] = cv;} // remove dead objects from finalization list in-placevoidsweep_finalizers(void){ sl_cv **lst = slg.finalizers; usize n = 0, ndel = 0, l = slg.nfinalizers; sl_cv *tmp;#define SWAP_sf(a, b) (tmp = a, a = b, b = tmp, 1) if(l == 0) return; do{ tmp = lst[n]; if(isforwarded((sl_v)tmp)){ // object is alive lst[n] = ptr(forwardloc((sl_v)tmp)); n++; }else{ sl_type *t = cv_class(tmp); if(t->vtable != nil && t->vtable->finalize != nil) t->vtable->finalize(tagptr(tmp, TAG_CVALUE)); if(!isinlined(tmp) && owned(tmp)) MEM_FREE(cv_data(tmp)); ndel++; } }while((n < l-ndel) && SWAP_sf(lst[n], lst[n+ndel])); slg.nfinalizers -= ndel; slg.malloc_pressure = 0;} char *tostr(sl_v v, usize *sz, sl_v *tmp){ if(isubstr(v)){ if(sz != nil) *sz = ubstrsz(v); *tmp = v >> 8; return (char*)tmp; } if(iscvalue(v) && cv_isstr(ptr(v))){ if(sz != nil) *sz = cv_len(ptr(v)); return cvalue_data(v); } type_error("str", v);} // compute the size of the metadata object for a cvaluestatic usizecv_nwords(sl_cv *cv){ if(!isinlined(cv)) return CVALUE_NWORDS; usize n = cv_len(cv); if(cv_isstr(cv)) n++; return CVALUE_NWORDS + NWORDS(n);} voidcv_autorelease(sl_cv *cv){ cv->type = (sl_type*)(((uintptr)cv->type) | CV_OWNED); add_finalizer(cv);} static sl_vcprim(sl_type *type, usize sz){ assert(!ismanaged((uintptr)type)); assert(sz == type->size); sl_cprim *pcp = alloc_words(CPRIM_NWORDS+NWORDS(sz)); pcp->type = type; return tagptr(pcp, TAG_CPRIM);} sl_vcvalue_(sl_type *type, usize sz, bool nofinalize){ assert(type != nil); if(valid_numtype(type->numtype) && type->numtype != T_MP) return cprim(type, sz); bool str = false; if(type->eltype == sl_utf8type){ if(sz == 0) return sl_emptystr; sz++; str = true; } sl_cv *pcv; if(sz <= MAX_INL_SIZE){ usize nw = CVALUE_NWORDS + NWORDS(sz); pcv = alloc_words(nw); pcv->type = type; pcv->data = pcv->_space; if(!nofinalize && type->vtable != nil && type->vtable->finalize != nil) add_finalizer(pcv); }else{ if(slg.malloc_pressure > ALLOC_LIMIT_TRIGGER) sl_gc(false); pcv = alloc_words(CVALUE_NWORDS); pcv->type = type; pcv->data = MEM_ALLOC(sz); cv_autorelease(pcv); slg.malloc_pressure += sz; } if(str) ((char*)pcv->data)[--sz] = '\0'; pcv->len = sz; return tagptr(pcv, TAG_CVALUE);} // this effectively dereferences a pointer// just like *p in C, it only removes a level of indirection from the type,// it doesn't copy any data.// this method of creating a cvalue only allocates metadata.// ptr is user-managed; we don't autorelease it unless the// user explicitly calls (autorelease ) on the result of this function.// 'parent' is an optional cvalue that this pointer is known to point// into; NIL if none.sl_vcvalue_from_ref(sl_type *type, void *ptr, usize sz){ sl_cv *pcv; assert(type != nil); assert(ptr != nil); pcv = alloc_words(CVALUE_NWORDS); pcv->data = ptr; pcv->len = sz; pcv->type = type; return tagptr(pcv, TAG_CVALUE);} sl_vcvalue_str(usize n){ if(n <= UBSTR_MAX){ sl_v v = n<<5 | TAG_UBSTR; return v; } return cvalue(sl_strtype, n);} sl_vcvalue_static_cstr(const char *str){ usize n = strlen(str); if(n <= UBSTR_MAX){ sl_v v = n<<5 | TAG_UBSTR; memcpy(ubstr(v), str, n); return v; } return cvalue_from_ref(sl_strtype, (char*)str, n);} sl_vstr_from_cstrn(char *str, usize n){ sl_v v; if(n <= UBSTR_MAX){ v = n<<5 | TAG_UBSTR; memcpy(ubstr(v), str, n); }else{ v = cvalue(sl_strtype, n); memcpy(cvalue_data(v), str, n); } return v;} sl_vstr_from_cstr(char *str){ return str_from_cstrn(str, strlen(str));} boolsl_isstr(sl_v v){ return isubstr(v) || (iscvalue(v) && cv_isstr(ptr(v)));} // convert to malloc representation (fixed address)voidcv_pin(sl_cv *cv){ if(!isinlined(cv)) return; usize n = cv_len(cv); if(cv_isstr(cv)) n++; void *data = MEM_ALLOC(n); memcpy(data, cv_data(cv), n); cv->data = data; cv_autorelease(cv);} static voidcvalue_rune_init(sl_type *type, sl_v a, void *dest){ Rune r; USED(type); if(isfixnum(a)){ r = numval(a); }else if(isrune(a)){ r = torune(a); }else if(isubnumu(a)){ uintptr v = ubnumuval(a); r = conv_to_u32(&v, ubnumtype(a)); }else if(isubnums(a)){ intptr v = ubnumsval(a); r = conv_to_u32(&v, ubnumtype(a)); }else if(iscprim(a)){ sl_cprim *cp = ptr(a); r = conv_to_u32(cp_data(cp), cp_numtype(cp)); }else if(ismp(a)){ r = conv_to_u32(cv_data(ptr(a)), T_MP); }else type_error("num", a); *((Rune*)dest) = r;} #define num_init(ctype, cnvt, tag) \ static void \ cvalue_##ctype##_init(sl_type *type, sl_v a, void *dest) \ { \ ctype n; \ USED(type); \ if(isfixnum(a)){ \ n = (ctype)numval(a); \ }else if(isubnumu(a)){ \ uintptr v = ubnumuval(a); \ n = (ctype)conv_to_##cnvt(&v, ubnumtype(a)); \ }else if(isubnums(a)){ \ intptr v = ubnumsval(a); \ n = (ctype)conv_to_##cnvt(&v, ubnumtype(a)); \ }else if(iscprim(a)){ \ sl_cprim *cp = ptr(a); \ n = (ctype)conv_to_##cnvt(cp_data(cp), cp_numtype(cp)); \ }else if(ismp(a)){ \ n = (ctype)conv_to_##cnvt(cv_data(ptr(a)), T_MP); \ }else \ type_error("num", a); \ *((ctype*)dest) = n; \ } num_init(s8int, s32, T_S8)num_init(u8int, u32, T_U8)num_init(s16int, s32, T_S16)num_init(u16int, u32, T_U16)num_init(s32int, s32, T_S32)num_init(u32int, u32, T_U32)num_init(s64int, s64, T_S64)num_init(u64int, u64, T_U64)num_init(float, double, T_FLOAT)num_init(double, double, T_DOUBLE) BUILTIN("rune", rune){ if(nargs == 0){ PUSH(fixnum(0)); args = sl.sp-1; } Rune r; cvalue_rune_init(sl_runetype, args[0], &r); return mk_rune(r);} #define num_ctor_init(typenam, ctype, tag) \ static \ BUILTIN(#typenam, typenam) \ { \ if(nargs == 0){ \ PUSH(fixnum(0)); \ args = sl.sp-1; \ } \ sl_v v = cprim(sl_##typenam##type, sizeof(ctype)); \ cvalue_##ctype##_init(sl_##typenam##type, args[0], cp_data(ptr(v))); \ return v; \ } #define num_ctor_init_unboxed(typenam, ctype, tag) \ static \ BUILTIN(#typenam, typenam) \ { \ if(nargs == 0){ \ PUSH(fixnum(0)); \ args = sl.sp-1; \ } \ sl_v v; \ if(tag < T_UNBOXED_NUM && \ sizeof(ctype) < sizeof(sl_v)){ \ ctype u; \ cvalue_##ctype##_init(sl_##typenam##type, args[0], &u); \ v = (sl_v)u<<TAG_EXT_BITS | tag<<4 | TAG_UNBOXED; \ }else{ \ v = cprim(sl_##typenam##type, sizeof(ctype)); \ cvalue_##ctype##_init(sl_##typenam##type, args[0], cp_data(ptr(v))); \ } \ return v; \ } #define num_ctor_ctor(typenam, ctype, tag) \ sl_v \ mk_##typenam(ctype n) \ { \ sl_v v = cprim(sl_##typenam##type, sizeof(n)); \ *(ctype*)cp_data(ptr(v)) = n; \ return v; \ } #define num_ctor_ctor_unboxed(typenam, ctype, tag) \ sl_constfn \ sl_v \ mk_##typenam(ctype n) \ { \ sl_v v; \ if(tag < T_UNBOXED_NUM && \ (sizeof(n) < sizeof(sl_v) || fits_bits(n, UNBOXED_BITS))){ \ v = n<<TAG_EXT_BITS | tag<<4 | TAG_UNBOXED; \ }else{ \ v = cprim(sl_##typenam##type, sizeof(n)); \ *(ctype*)cp_data(ptr(v)) = n; \ } \ return v; \ } #define num_ctor(typenam, ctype, tag) \ num_ctor_init(typenam, ctype, tag) \ num_ctor_ctor(typenam, ctype, tag) #define num_ctor_unboxed(typenam, ctype, tag) \ num_ctor_init_unboxed(typenam, ctype, tag) \ num_ctor_ctor_unboxed(typenam, ctype, tag) num_ctor_init_unboxed(s8, s8int, T_S8)num_ctor_init_unboxed(u8, u8int, T_U8)num_ctor_init_unboxed(s16, s16int, T_S16)num_ctor_init_unboxed(u16, u16int, T_U16)num_ctor_unboxed(s32, s32int, T_S32)num_ctor_unboxed(u32, u32int, T_U32)num_ctor_unboxed(s64, s64int, T_S64)num_ctor_unboxed(u64, u64int, T_U64)num_ctor_init(utf8, u8int, T_U8)num_ctor(float, float, T_FLOAT)num_ctor(double, double, T_DOUBLE) static voidcvalue_mp_init(sl_type *type, sl_v a, void *dest){ mpint *n; USED(type); if(isfixnum(a)) n = vtomp(numval(a), nil); else if(isubnum(a)){ uintptr v; void *p = &v; if(isubnumu(a)) v = ubnumuval(a); else v = ubnumsval(a); n = conv_to_mp(p, ubnumtype(a)); }else if(iscvalue(a)){ sl_cv *cv = ptr(a); void *p = cv_data(cv); n = conv_to_mp(p, cv_numtype(cv)); }else if(iscprim(a)){ sl_cprim *cp = ptr(a); void *p = cp_data(cp); n = conv_to_mp(p, cp_numtype(cp)); }else type_error("num", a); *((mpint**)dest) = n;} BUILTIN("bignum", bignum){ if(nargs == 0){ PUSH(fixnum(0)); args = sl.sp-1; } sl_v cv = cvalue(sl_mptype, sizeof(mpint*)); cvalue_mp_init(sl_mptype, args[0], cvalue_data(cv)); return cv;} sl_vmk_mp(mpint *n){ sl_v cv = cvalue(sl_mptype, sizeof(mpint*)); *(mpint**)cvalue_data(cv) = n; return cv;} static voidfree_mp(sl_v self){ mpint **s = value2c(mpint**, self); if(*s != mpzero && *s != mpone && *s != mptwo) mpfree(*s);} static sl_cvtable mp_vtable = { nil, nil, free_mp, nil }; sl_constfnsl_vsize_wrap(usize sz){ if(sizeof(usize) == 8) return fits_fixnum(sz) ? fixnum(sz): mk_u64(sz); else return fits_fixnum(sz) ? fixnum(sz): mk_u32(sz);} usizetosize(sl_v n){ if(isfixnum(n)) return (usize)numval(n); if(isubnum(n)) return (usize)ubnumuval(n); if(iscprim(n)){ sl_cprim *cp = ptr(n); if(sizeof(usize) == 8) return conv_to_u64(cp_data(cp), cp_numtype(cp)); return conv_to_u32(cp_data(cp), cp_numtype(cp)); } type_error("num", n);} soffsettooffset(sl_v n){ if(isfixnum(n)) return numval(n); if(isubnumu(n)) return ubnumuval(n); if(isubnums(n)) return ubnumsval(n); if(iscprim(n)){ sl_cprim *cp = ptr(n); return conv_to_s64(cp_data(cp), cp_numtype(cp)); } type_error("num", n);} boolisarr(sl_v v){ return iscvalue(v) && cv_class(ptr(v))->eltype != nil;} static usizepredict_arrlen(sl_v arg){ if(isvec(arg)) return vec_size(arg); if(iscons(arg)) return llength(arg); if(arg == sl_nil) return 0; if(isarr(arg)) return cvalue_arrlen(arg); return 1;}Lines 1–500 of 1571. Load more
#include "sl.h" #include "operators.h" #include "cvalues.h" #include "types.h" #include "io.h" #include "equal.h" enum { MAX_INL_SIZE = 384, CVALUE_NWORDS = sizeof(sl_cv)/sizeof(sl_v), CV_OWNED = 1<<0, }; #define owned(cv) ((uintptr)(cv)->type & CV_OWNED) #define isinlined(cv) ((cv)->data == (cv)->_space) sl_type *unboxedtypes[T_UNBOXED_NUM]; sl_v unboxedtypesyms[T_UNBOXED_NUM]; static void cvalue_init(sl_type *type, sl_v v, void *dest); void add_finalizer(sl_cv *cv) { if(slg.nfinalizers == slg.maxfinalizers){ slg.maxfinalizers *= 2; slg.finalizers = MEM_REALLOC(slg.finalizers, slg.maxfinalizers*sizeof(slg.finalizers)); assert(slg.finalizers != nil); } slg.finalizers[slg.nfinalizers++] = cv; } // remove dead objects from finalization list in-place void sweep_finalizers(void) { sl_cv **lst = slg.finalizers; usize n = 0, ndel = 0, l = slg.nfinalizers; sl_cv *tmp; #define SWAP_sf(a, b) (tmp = a, a = b, b = tmp, 1) if(l == 0) return; do{ tmp = lst[n]; if(isforwarded((sl_v)tmp)){ // object is alive lst[n] = ptr(forwardloc((sl_v)tmp)); n++; }else{ sl_type *t = cv_class(tmp); if(t->vtable != nil && t->vtable->finalize != nil) t->vtable->finalize(tagptr(tmp, TAG_CVALUE)); if(!isinlined(tmp) && owned(tmp)) MEM_FREE(cv_data(tmp)); ndel++; } }while((n < l-ndel) && SWAP_sf(lst[n], lst[n+ndel])); slg.nfinalizers -= ndel; slg.malloc_pressure = 0; } char * tostr(sl_v v, usize *sz, sl_v *tmp) { if(isubstr(v)){ if(sz != nil) *sz = ubstrsz(v); *tmp = v >> 8; return (char*)tmp; } if(iscvalue(v) && cv_isstr(ptr(v))){ if(sz != nil) *sz = cv_len(ptr(v)); return cvalue_data(v); } type_error("str", v); } // compute the size of the metadata object for a cvalue static usize cv_nwords(sl_cv *cv) { if(!isinlined(cv)) return CVALUE_NWORDS; usize n = cv_len(cv); if(cv_isstr(cv)) n++; return CVALUE_NWORDS + NWORDS(n); } void cv_autorelease(sl_cv *cv) { cv->type = (sl_type*)(((uintptr)cv->type) | CV_OWNED); add_finalizer(cv); } static sl_v cprim(sl_type *type, usize sz) { assert(!ismanaged((uintptr)type)); assert(sz == type->size); sl_cprim *pcp = alloc_words(CPRIM_NWORDS+NWORDS(sz)); pcp->type = type; return tagptr(pcp, TAG_CPRIM); } sl_v cvalue_(sl_type *type, usize sz, bool nofinalize) { assert(type != nil); if(valid_numtype(type->numtype) && type->numtype != T_MP) return cprim(type, sz); bool str = false; if(type->eltype == sl_utf8type){ if(sz == 0) return sl_emptystr; sz++; str = true; } sl_cv *pcv; if(sz <= MAX_INL_SIZE){ usize nw = CVALUE_NWORDS + NWORDS(sz); pcv = alloc_words(nw); pcv->type = type; pcv->data = pcv->_space; if(!nofinalize && type->vtable != nil && type->vtable->finalize != nil) add_finalizer(pcv); }else{ if(slg.malloc_pressure > ALLOC_LIMIT_TRIGGER) sl_gc(false); pcv = alloc_words(CVALUE_NWORDS); pcv->type = type; pcv->data = MEM_ALLOC(sz); cv_autorelease(pcv); slg.malloc_pressure += sz; } if(str) ((char*)pcv->data)[--sz] = '\0'; pcv->len = sz; return tagptr(pcv, TAG_CVALUE); } // this effectively dereferences a pointer // just like *p in C, it only removes a level of indirection from the type, // it doesn't copy any data. // this method of creating a cvalue only allocates metadata. // ptr is user-managed; we don't autorelease it unless the // user explicitly calls (autorelease ) on the result of this function. // 'parent' is an optional cvalue that this pointer is known to point // into; NIL if none. sl_v cvalue_from_ref(sl_type *type, void *ptr, usize sz) { sl_cv *pcv; assert(type != nil); assert(ptr != nil); pcv = alloc_words(CVALUE_NWORDS); pcv->data = ptr; pcv->len = sz; pcv->type = type; return tagptr(pcv, TAG_CVALUE); } sl_v cvalue_str(usize n) { if(n <= UBSTR_MAX){ sl_v v = n<<5 | TAG_UBSTR; return v; } return cvalue(sl_strtype, n); } sl_v cvalue_static_cstr(const char *str) { usize n = strlen(str); if(n <= UBSTR_MAX){ sl_v v = n<<5 | TAG_UBSTR; memcpy(ubstr(v), str, n); return v; } return cvalue_from_ref(sl_strtype, (char*)str, n); } sl_v str_from_cstrn(char *str, usize n) { sl_v v; if(n <= UBSTR_MAX){ v = n<<5 | TAG_UBSTR; memcpy(ubstr(v), str, n); }else{ v = cvalue(sl_strtype, n); memcpy(cvalue_data(v), str, n); } return v; } sl_v str_from_cstr(char *str) { return str_from_cstrn(str, strlen(str)); } bool sl_isstr(sl_v v) { return isubstr(v) || (iscvalue(v) && cv_isstr(ptr(v))); } // convert to malloc representation (fixed address) void cv_pin(sl_cv *cv) { if(!isinlined(cv)) return; usize n = cv_len(cv); if(cv_isstr(cv)) n++; void *data = MEM_ALLOC(n); memcpy(data, cv_data(cv), n); cv->data = data; cv_autorelease(cv); } static void cvalue_rune_init(sl_type *type, sl_v a, void *dest) { Rune r; USED(type); if(isfixnum(a)){ r = numval(a); }else if(isrune(a)){ r = torune(a); }else if(isubnumu(a)){ uintptr v = ubnumuval(a); r = conv_to_u32(&v, ubnumtype(a)); }else if(isubnums(a)){ intptr v = ubnumsval(a); r = conv_to_u32(&v, ubnumtype(a)); }else if(iscprim(a)){ sl_cprim *cp = ptr(a); r = conv_to_u32(cp_data(cp), cp_numtype(cp)); }else if(ismp(a)){ r = conv_to_u32(cv_data(ptr(a)), T_MP); }else type_error("num", a); *((Rune*)dest) = r; } #define num_init(ctype, cnvt, tag) \ static void \ cvalue_##ctype##_init(sl_type *type, sl_v a, void *dest) \ { \ ctype n; \ USED(type); \ if(isfixnum(a)){ \ n = (ctype)numval(a); \ }else if(isubnumu(a)){ \ uintptr v = ubnumuval(a); \ n = (ctype)conv_to_##cnvt(&v, ubnumtype(a)); \ }else if(isubnums(a)){ \ intptr v = ubnumsval(a); \ n = (ctype)conv_to_##cnvt(&v, ubnumtype(a)); \ }else if(iscprim(a)){ \ sl_cprim *cp = ptr(a); \ n = (ctype)conv_to_##cnvt(cp_data(cp), cp_numtype(cp)); \ }else if(ismp(a)){ \ n = (ctype)conv_to_##cnvt(cv_data(ptr(a)), T_MP); \ }else \ type_error("num", a); \ *((ctype*)dest) = n; \ } num_init(s8int, s32, T_S8) num_init(u8int, u32, T_U8) num_init(s16int, s32, T_S16) num_init(u16int, u32, T_U16) num_init(s32int, s32, T_S32) num_init(u32int, u32, T_U32) num_init(s64int, s64, T_S64) num_init(u64int, u64, T_U64) num_init(float, double, T_FLOAT) num_init(double, double, T_DOUBLE) BUILTIN("rune", rune) { if(nargs == 0){ PUSH(fixnum(0)); args = sl.sp-1; } Rune r; cvalue_rune_init(sl_runetype, args[0], &r); return mk_rune(r); } #define num_ctor_init(typenam, ctype, tag) \ static \ BUILTIN(#typenam, typenam) \ { \ if(nargs == 0){ \ PUSH(fixnum(0)); \ args = sl.sp-1; \ } \ sl_v v = cprim(sl_##typenam##type, sizeof(ctype)); \ cvalue_##ctype##_init(sl_##typenam##type, args[0], cp_data(ptr(v))); \ return v; \ } #define num_ctor_init_unboxed(typenam, ctype, tag) \ static \ BUILTIN(#typenam, typenam) \ { \ if(nargs == 0){ \ PUSH(fixnum(0)); \ args = sl.sp-1; \ } \ sl_v v; \ if(tag < T_UNBOXED_NUM && \ sizeof(ctype) < sizeof(sl_v)){ \ ctype u; \ cvalue_##ctype##_init(sl_##typenam##type, args[0], &u); \ v = (sl_v)u<<TAG_EXT_BITS | tag<<4 | TAG_UNBOXED; \ }else{ \ v = cprim(sl_##typenam##type, sizeof(ctype)); \ cvalue_##ctype##_init(sl_##typenam##type, args[0], cp_data(ptr(v))); \ } \ return v; \ } #define num_ctor_ctor(typenam, ctype, tag) \ sl_v \ mk_##typenam(ctype n) \ { \ sl_v v = cprim(sl_##typenam##type, sizeof(n)); \ *(ctype*)cp_data(ptr(v)) = n; \ return v; \ } #define num_ctor_ctor_unboxed(typenam, ctype, tag) \ sl_constfn \ sl_v \ mk_##typenam(ctype n) \ { \ sl_v v; \ if(tag < T_UNBOXED_NUM && \ (sizeof(n) < sizeof(sl_v) || fits_bits(n, UNBOXED_BITS))){ \ v = n<<TAG_EXT_BITS | tag<<4 | TAG_UNBOXED; \ }else{ \ v = cprim(sl_##typenam##type, sizeof(n)); \ *(ctype*)cp_data(ptr(v)) = n; \ } \ return v; \ } #define num_ctor(typenam, ctype, tag) \ num_ctor_init(typenam, ctype, tag) \ num_ctor_ctor(typenam, ctype, tag) #define num_ctor_unboxed(typenam, ctype, tag) \ num_ctor_init_unboxed(typenam, ctype, tag) \ num_ctor_ctor_unboxed(typenam, ctype, tag) num_ctor_init_unboxed(s8, s8int, T_S8) num_ctor_init_unboxed(u8, u8int, T_U8) num_ctor_init_unboxed(s16, s16int, T_S16) num_ctor_init_unboxed(u16, u16int, T_U16) num_ctor_unboxed(s32, s32int, T_S32) num_ctor_unboxed(u32, u32int, T_U32) num_ctor_unboxed(s64, s64int, T_S64) num_ctor_unboxed(u64, u64int, T_U64) num_ctor_init(utf8, u8int, T_U8) num_ctor(float, float, T_FLOAT) num_ctor(double, double, T_DOUBLE) static void cvalue_mp_init(sl_type *type, sl_v a, void *dest) { mpint *n; USED(type); if(isfixnum(a)) n = vtomp(numval(a), nil); else if(isubnum(a)){ uintptr v; void *p = &v; if(isubnumu(a)) v = ubnumuval(a); else v = ubnumsval(a); n = conv_to_mp(p, ubnumtype(a)); }else if(iscvalue(a)){ sl_cv *cv = ptr(a); void *p = cv_data(cv); n = conv_to_mp(p, cv_numtype(cv)); }else if(iscprim(a)){ sl_cprim *cp = ptr(a); void *p = cp_data(cp); n = conv_to_mp(p, cp_numtype(cp)); }else type_error("num", a); *((mpint**)dest) = n; } BUILTIN("bignum", bignum) { if(nargs == 0){ PUSH(fixnum(0)); args = sl.sp-1; } sl_v cv = cvalue(sl_mptype, sizeof(mpint*)); cvalue_mp_init(sl_mptype, args[0], cvalue_data(cv)); return cv; } sl_v mk_mp(mpint *n) { sl_v cv = cvalue(sl_mptype, sizeof(mpint*)); *(mpint**)cvalue_data(cv) = n; return cv; } static void free_mp(sl_v self) { mpint **s = value2c(mpint**, self); if(*s != mpzero && *s != mpone && *s != mptwo) mpfree(*s); } static sl_cvtable mp_vtable = { nil, nil, free_mp, nil }; sl_constfn sl_v size_wrap(usize sz) { if(sizeof(usize) == 8) return fits_fixnum(sz) ? fixnum(sz): mk_u64(sz); else return fits_fixnum(sz) ? fixnum(sz): mk_u32(sz); } usize tosize(sl_v n) { if(isfixnum(n)) return (usize)numval(n); if(isubnum(n)) return (usize)ubnumuval(n); if(iscprim(n)){ sl_cprim *cp = ptr(n); if(sizeof(usize) == 8) return conv_to_u64(cp_data(cp), cp_numtype(cp)); return conv_to_u32(cp_data(cp), cp_numtype(cp)); } type_error("num", n); } soffset tooffset(sl_v n) { if(isfixnum(n)) return numval(n); if(isubnumu(n)) return ubnumuval(n); if(isubnums(n)) return ubnumsval(n); if(iscprim(n)){ sl_cprim *cp = ptr(n); return conv_to_s64(cp_data(cp), cp_numtype(cp)); } type_error("num", n); } bool isarr(sl_v v) { return iscvalue(v) && cv_class(ptr(v))->eltype != nil; } static usize predict_arrlen(sl_v arg) { if(isvec(arg)) return vec_size(arg); if(iscons(arg)) return llength(arg); if(arg == sl_nil) return 0; if(isarr(arg)) return cvalue_arrlen(arg); return 1; }