diff --git a/src/core/capi.c b/src/core/capi.c index 6cb81712..f26a81d3 100644 --- a/src/core/capi.c +++ b/src/core/capi.c @@ -86,13 +86,23 @@ type janet_get##name(const Janet *argv, int32_t n) { \ janet_panic_type(x, n, JANET_TFLAG_##NAME); \ } \ return janet_unwrap_##name(x); \ -} \ +} + +#define DEFINE_OPT(name, NAME, type) \ type janet_opt##name(const Janet *argv, int32_t argc, int32_t n, type dflt) { \ - if (argc >= n) return dflt; \ + if (n >= argc) return dflt; \ if (janet_checktype(argv[n], JANET_NIL)) return dflt; \ return janet_get##name(argv, n); \ } +#define DEFINE_OPTLEN(name, NAME, type) \ +type janet_opt##name(const Janet *argv, int32_t argc, int32_t n, int32_t dflt_len) { \ + if (n >= argc || janet_checktype(argv[n], JANET_NIL)) {\ + return janet_##name(dflt_len); \ + }\ + return janet_get##name(argv, n); \ +} + Janet janet_getmethod(const uint8_t *method, const JanetMethod *methods) { while (methods->name) { if (!janet_cstrcmp(method, methods->name)) @@ -117,6 +127,26 @@ DEFINE_GETTER(cfunction, CFUNCTION, JanetCFunction) DEFINE_GETTER(boolean, BOOLEAN, int) DEFINE_GETTER(pointer, POINTER, void *) +DEFINE_OPT(number, NUMBER, double) +DEFINE_OPT(tuple, TUPLE, const Janet *) +DEFINE_OPT(struct, STRUCT, const JanetKV *) +DEFINE_OPT(string, STRING, const uint8_t *) +DEFINE_OPT(keyword, KEYWORD, const uint8_t *) +DEFINE_OPT(symbol, SYMBOL, const uint8_t *) +DEFINE_OPT(fiber, FIBER, JanetFiber *) +DEFINE_OPT(function, FUNCTION, JanetFunction *) +DEFINE_OPT(cfunction, CFUNCTION, JanetCFunction) +DEFINE_OPT(boolean, BOOLEAN, int) +DEFINE_OPT(pointer, POINTER, void *) + +DEFINE_OPTLEN(buffer, BUFFER, JanetBuffer *) +DEFINE_OPTLEN(table, TABLE, JanetTable *) +DEFINE_OPTLEN(array, ARRAY, JanetArray *) + +#undef DEFINE_GETTER +#undef DEFINE_OPT +#undef DEFINE_OPTLEN + const char *janet_getcstring(const Janet *argv, int32_t n) { const uint8_t *jstr = janet_getstring(argv, n); const char *cstr = (const char *)jstr; @@ -126,6 +156,16 @@ const char *janet_getcstring(const Janet *argv, int32_t n) { return cstr; } +int32_t janet_getnat(const Janet *argv, int32_t n) { + Janet x = argv[n]; + if (!janet_checkint(x)) goto bad; + int32_t ret = janet_unwrap_integer(x); + if (ret < 0) goto bad; + return ret; +bad: + janet_panicf("bad slot #%d, expected non-negative 32 bit signed integer, got %v", n, x); +} + int32_t janet_getinteger(const Janet *argv, int32_t n) { Janet x = argv[n]; if (!janet_checkint(x)) { @@ -269,6 +309,12 @@ uint64_t janet_getflags(const Janet *argv, int32_t n, const char *flags) { return ret; } +int32_t janet_optnat(const Janet *argv, int32_t argc, int32_t n, int32_t dflt) { + if (argc <= n) return dflt; + if (janet_checktype(argv[n], JANET_NIL)) return dflt; + return janet_getnat(argv, n); +} + int32_t janet_optinteger(const Janet *argv, int32_t argc, int32_t n, int32_t dflt) { if (argc <= n) return dflt; if (janet_checktype(argv[n], JANET_NIL)) return dflt; diff --git a/src/core/math.c b/src/core/math.c index 3182eadb..13bdf924 100644 --- a/src/core/math.c +++ b/src/core/math.c @@ -115,15 +115,15 @@ static Janet cfun_rng_int(int32_t argc, Janet *argv) { uint32_t word = janet_rng_u32(rng) >> 1; return janet_wrap_integer(word); } else { - int32_t max = janet_getinteger(argv, 1); - if (max <= 0) return janet_wrap_number(0); + int32_t max = janet_optnat(argv, argc, 1, INT32_MAX); + if (max == 0) return janet_wrap_number(0.0); uint32_t modulo = (uint32_t) max; - uint32_t bad = UINT32_MAX % modulo; + uint32_t maxgen = INT32_MAX; + uint32_t maxword = maxgen - (maxgen % modulo); uint32_t word; do { - word = janet_rng_u32(rng); - } while (word > UINT32_MAX - bad); - word >>= 1; + word = janet_rng_u32(rng) >> 1; + } while (word > maxword); return janet_wrap_integer(word % modulo); } } diff --git a/src/include/janet.h b/src/include/janet.h index 9b6f1a32..3c5417f6 100644 --- a/src/include/janet.h +++ b/src/include/janet.h @@ -1289,7 +1289,6 @@ JANET_API int32_t janet_length(Janet x); JANET_API Janet janet_lengthv(Janet x); JANET_API void janet_put(Janet ds, Janet key, Janet value); JANET_API void janet_putindex(Janet ds, int32_t index, Janet value); -JANET_API uint64_t janet_getflags(const Janet *argv, int32_t n, const char *flags); #define janet_flag_at(F, I) ((F) & ((1ULL) << (I))) JANET_API Janet janet_wrap_number_safe(double x); @@ -1363,6 +1362,7 @@ JANET_API JanetCFunction janet_getcfunction(const Janet *argv, int32_t n); JANET_API int janet_getboolean(const Janet *argv, int32_t n); JANET_API void *janet_getpointer(const Janet *argv, int32_t n); +JANET_API int32_t janet_getnat(const Janet *argv, int32_t n); JANET_API int32_t janet_getinteger(const Janet *argv, int32_t n); JANET_API int64_t janet_getinteger64(const Janet *argv, int32_t n); JANET_API size_t janet_getsize(const Janet *argv, int32_t n); @@ -1373,28 +1373,32 @@ JANET_API void *janet_getabstract(const Janet *argv, int32_t n, const JanetAbstr JANET_API JanetRange janet_getslice(int32_t argc, const Janet *argv); JANET_API int32_t janet_gethalfrange(const Janet *argv, int32_t n, int32_t length, const char *which); JANET_API int32_t janet_getargindex(const Janet *argv, int32_t n, int32_t length, const char *which); +JANET_API uint64_t janet_getflags(const Janet *argv, int32_t n, const char *flags); /* Optionals */ JANET_API double janet_optnumber(const Janet *argv, int32_t argc, int32_t n, double dflt); -JANET_API JanetArray *janet_optarray(const Janet *argv, int32_t argc, int32_t n, JanetArray *dflt); JANET_API const Janet *janet_opttuple(const Janet *argv, int32_t argc, int32_t n, const Janet *dflt); -JANET_API JanetTable *janet_opttable(const Janet *argv, int32_t argc, int32_t n, JanetTable *dflt); JANET_API const JanetKV *janet_optstruct(const Janet *argv, int32_t argc, int32_t n, const JanetKV *dflt); JANET_API const uint8_t *janet_optstring(const Janet *argv, int32_t argc, int32_t n, const uint8_t *dflt); JANET_API const char *janet_optcstring(const Janet *argv, int32_t argc, int32_t n, const char *dflt); JANET_API const uint8_t *janet_optsymbol(const Janet *argv, int32_t argc, int32_t n, const uint8_t *dflt); JANET_API const uint8_t *janet_optkeyword(const Janet *argv, int32_t argc, int32_t n, const uint8_t *dflt); -JANET_API JanetBuffer *janet_optbuffer(const Janet *argv, int32_t argc, int32_t n, JanetBuffer *dflt); JANET_API JanetFiber *janet_optfiber(const Janet *argv, int32_t argc, int32_t n, JanetFiber *dflt); JANET_API JanetFunction *janet_optfunction(const Janet *argv, int32_t argc, int32_t n, JanetFunction *dflt); JANET_API JanetCFunction janet_optcfunction(const Janet *argv, int32_t argc, int32_t n, JanetCFunction dflt); JANET_API int janet_optboolean(const Janet *argv, int32_t argc, int32_t n, int dflt); JANET_API void *janet_optpointer(const Janet *argv, int32_t argc, int32_t n, void *dflt); +JANET_API int32_t janet_optnat(const Janet *argv, int32_t argc, int32_t n, int32_t dflt); JANET_API int32_t janet_optinteger(const Janet *argv, int32_t argc, int32_t n, int32_t dflt); JANET_API int64_t janet_optinteger64(const Janet *argv, int32_t argc, int32_t n, int64_t dflt); JANET_API size_t janet_optsize(const Janet *argv, int32_t argc, int32_t n, size_t dflt); JANET_API void *janet_optabstract(const Janet *argv, int32_t argc, int32_t n, const JanetAbstractType *at, void *dflt); +/* Mutable optional types specify a size default, and construct a new value if none is provided */ +JANET_API JanetBuffer *janet_optbuffer(const Janet *argv, int32_t argc, int32_t n, int32_t dflt_len); +JANET_API JanetTable *janet_opttable(const Janet *argv, int32_t argc, int32_t n, int32_t dflt_len); +JANET_API JanetArray *janet_optarray(const Janet *argv, int32_t argc, int32_t n, int32_t dflt_len); + JANET_API Janet janet_dyn(const char *name); JANET_API void janet_setdyn(const char *name, Janet value);