mirror of
https://github.com/janet-lang/janet
synced 2024-11-29 03:19:54 +00:00
Add proper optional arguments.
Use &opt in the parameter list to get optional arguments.
This commit is contained in:
parent
a246877c1e
commit
d42bdf2443
@ -525,15 +525,20 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int
|
|||||||
/* Set function arity */
|
/* Set function arity */
|
||||||
x = janet_get1(s, janet_csymbolv("arity"));
|
x = janet_get1(s, janet_csymbolv("arity"));
|
||||||
def->arity = janet_checkint(x) ? janet_unwrap_integer(x) : 0;
|
def->arity = janet_checkint(x) ? janet_unwrap_integer(x) : 0;
|
||||||
|
janet_asm_assert(&a, def->arity >= 0, "arity must be non-negative");
|
||||||
|
|
||||||
|
x = janet_get1(s, janet_csymbolv("max-arity"));
|
||||||
|
def->max_arity = janet_checkint(x) ? janet_unwrap_integer(x) : def->arity;
|
||||||
|
janet_asm_assert(&a, def->max_arity >= def->arity, "max-arity must be greater than or equal to arity");
|
||||||
|
|
||||||
|
x = janet_get1(s, janet_csymbolv("min-arity"));
|
||||||
|
def->min_arity = janet_checkint(x) ? janet_unwrap_integer(x) : def->arity;
|
||||||
|
janet_asm_assert(&a, def->min_arity <= def->arity, "min-arity must be less than or equal to arity");
|
||||||
|
|
||||||
/* Check vararg */
|
/* Check vararg */
|
||||||
x = janet_get1(s, janet_csymbolv("vararg"));
|
x = janet_get1(s, janet_csymbolv("vararg"));
|
||||||
if (janet_truthy(x)) def->flags |= JANET_FUNCDEF_FLAG_VARARG;
|
if (janet_truthy(x)) def->flags |= JANET_FUNCDEF_FLAG_VARARG;
|
||||||
|
|
||||||
/* Check strict arity */
|
|
||||||
x = janet_get1(s, janet_csymbolv("fix-arity"));
|
|
||||||
if (janet_truthy(x)) def->flags |= JANET_FUNCDEF_FLAG_FIXARITY;
|
|
||||||
|
|
||||||
/* Check source */
|
/* Check source */
|
||||||
x = janet_get1(s, janet_csymbolv("source"));
|
x = janet_get1(s, janet_csymbolv("source"));
|
||||||
if (janet_checktype(x, JANET_STRING)) def->source = janet_unwrap_string(x);
|
if (janet_checktype(x, JANET_STRING)) def->source = janet_unwrap_string(x);
|
||||||
@ -822,6 +827,8 @@ Janet janet_disasm(JanetFuncDef *def) {
|
|||||||
JanetArray *constants;
|
JanetArray *constants;
|
||||||
JanetTable *ret = janet_table(10);
|
JanetTable *ret = janet_table(10);
|
||||||
janet_table_put(ret, janet_csymbolv("arity"), janet_wrap_integer(def->arity));
|
janet_table_put(ret, janet_csymbolv("arity"), janet_wrap_integer(def->arity));
|
||||||
|
janet_table_put(ret, janet_csymbolv("min-arity"), janet_wrap_integer(def->min_arity));
|
||||||
|
janet_table_put(ret, janet_csymbolv("max-arity"), janet_wrap_integer(def->max_arity));
|
||||||
janet_table_put(ret, janet_csymbolv("bytecode"), janet_wrap_array(bcode));
|
janet_table_put(ret, janet_csymbolv("bytecode"), janet_wrap_array(bcode));
|
||||||
if (NULL != def->source) {
|
if (NULL != def->source) {
|
||||||
janet_table_put(ret, janet_csymbolv("source"), janet_wrap_string(def->source));
|
janet_table_put(ret, janet_csymbolv("source"), janet_wrap_string(def->source));
|
||||||
@ -829,9 +836,6 @@ Janet janet_disasm(JanetFuncDef *def) {
|
|||||||
if (def->flags & JANET_FUNCDEF_FLAG_VARARG) {
|
if (def->flags & JANET_FUNCDEF_FLAG_VARARG) {
|
||||||
janet_table_put(ret, janet_csymbolv("vararg"), janet_wrap_true());
|
janet_table_put(ret, janet_csymbolv("vararg"), janet_wrap_true());
|
||||||
}
|
}
|
||||||
if (def->flags & JANET_FUNCDEF_FLAG_FIXARITY) {
|
|
||||||
janet_table_put(ret, janet_csymbolv("fix-arity"), janet_wrap_true());
|
|
||||||
}
|
|
||||||
if (NULL != def->name) {
|
if (NULL != def->name) {
|
||||||
janet_table_put(ret, janet_csymbolv("name"), janet_wrap_string(def->name));
|
janet_table_put(ret, janet_csymbolv("name"), janet_wrap_string(def->name));
|
||||||
}
|
}
|
||||||
|
@ -208,6 +208,8 @@ JanetFuncDef *janet_funcdef_alloc() {
|
|||||||
def->flags = 0;
|
def->flags = 0;
|
||||||
def->slotcount = 0;
|
def->slotcount = 0;
|
||||||
def->arity = 0;
|
def->arity = 0;
|
||||||
|
def->min_arity = 0;
|
||||||
|
def->max_arity = INT32_MAX;
|
||||||
def->source = NULL;
|
def->source = NULL;
|
||||||
def->sourcemap = NULL;
|
def->sourcemap = NULL;
|
||||||
def->name = NULL;
|
def->name = NULL;
|
||||||
|
@ -643,6 +643,7 @@ JanetFuncDef *janetc_pop_funcdef(JanetCompiler *c) {
|
|||||||
def->source = c->source;
|
def->source = c->source;
|
||||||
|
|
||||||
def->arity = 0;
|
def->arity = 0;
|
||||||
|
def->min_arity = 0;
|
||||||
def->flags = 0;
|
def->flags = 0;
|
||||||
if (scope->flags & JANET_SCOPE_ENV) {
|
if (scope->flags & JANET_SCOPE_ENV) {
|
||||||
def->flags |= JANET_FUNCDEF_FLAG_NEEDSENV;
|
def->flags |= JANET_FUNCDEF_FLAG_NEEDSENV;
|
||||||
|
@ -142,7 +142,7 @@
|
|||||||
|
|
||||||
(defmacro if-not
|
(defmacro if-not
|
||||||
"Shorthand for (if (not ... "
|
"Shorthand for (if (not ... "
|
||||||
[condition exp-1 exp-2 &]
|
[condition exp-1 &opt exp-2]
|
||||||
~(if ,condition ,exp-2 ,exp-1))
|
~(if ,condition ,exp-2 ,exp-1))
|
||||||
|
|
||||||
(defmacro when
|
(defmacro when
|
||||||
@ -414,12 +414,12 @@
|
|||||||
"Create a generator expression using the loop syntax. Returns a fiber
|
"Create a generator expression using the loop syntax. Returns a fiber
|
||||||
that yields all values inside the loop in order. See loop for details."
|
that yields all values inside the loop in order. See loop for details."
|
||||||
[head & body]
|
[head & body]
|
||||||
~(fiber/new (fn [&] (loop ,head (yield (do ,;body))))))
|
~(fiber/new (fn [] (loop ,head (yield (do ,;body))))))
|
||||||
|
|
||||||
(defmacro coro
|
(defmacro coro
|
||||||
"A wrapper for making fibers. Same as (fiber/new (fn [&] ...body))."
|
"A wrapper for making fibers. Same as (fiber/new (fn [] ...body))."
|
||||||
[& body]
|
[& body]
|
||||||
(tuple fiber/new (tuple 'fn '[&] ;body)))
|
(tuple fiber/new (tuple 'fn '[] ;body)))
|
||||||
|
|
||||||
(defn sum
|
(defn sum
|
||||||
"Returns the sum of xs. If xs is empty, returns 0."
|
"Returns the sum of xs. If xs is empty, returns 0."
|
||||||
@ -439,7 +439,7 @@
|
|||||||
"Make multiple bindings, and if all are truthy,
|
"Make multiple bindings, and if all are truthy,
|
||||||
evaluate the tru form. If any are false or nil, evaluate
|
evaluate the tru form. If any are false or nil, evaluate
|
||||||
the fal form. Bindings have the same syntax as the let macro."
|
the fal form. Bindings have the same syntax as the let macro."
|
||||||
[bindings tru fal &]
|
[bindings tru &opt fal]
|
||||||
(def len (length bindings))
|
(def len (length bindings))
|
||||||
(if (zero? len) (error "expected at least 1 binding"))
|
(if (zero? len) (error "expected at least 1 binding"))
|
||||||
(if (odd? len) (error "expected an even number of bindings"))
|
(if (odd? len) (error "expected an even number of bindings"))
|
||||||
@ -565,7 +565,7 @@
|
|||||||
(sort-help a (+ piv 1) hi by))
|
(sort-help a (+ piv 1) hi by))
|
||||||
a)
|
a)
|
||||||
|
|
||||||
(fn sort [a by &]
|
(fn sort [a &opt by]
|
||||||
(sort-help a 0 (- (length a) 1) (or by order<)))))
|
(sort-help a 0 (- (length a) 1) (or by order<)))))
|
||||||
|
|
||||||
(defn sorted
|
(defn sorted
|
||||||
@ -1060,7 +1060,7 @@ value, one key will be ignored."
|
|||||||
(defn spit
|
(defn spit
|
||||||
"Write contents to a file at path.
|
"Write contents to a file at path.
|
||||||
Can optionally append to the file."
|
Can optionally append to the file."
|
||||||
[path contents mode &]
|
[path contents &opt mode]
|
||||||
(default mode :w)
|
(default mode :w)
|
||||||
(def f (file/open path mode))
|
(def f (file/open path mode))
|
||||||
(if-not f (error (string "could not open file " path " with mode " mode)))
|
(if-not f (error (string "could not open file " path " with mode " mode)))
|
||||||
@ -1402,7 +1402,7 @@ value, one key will be ignored."
|
|||||||
"Create a new environment table. The new environment
|
"Create a new environment table. The new environment
|
||||||
will inherit bindings from the parent environment, but new
|
will inherit bindings from the parent environment, but new
|
||||||
bindings will not pollute the parent environment."
|
bindings will not pollute the parent environment."
|
||||||
[parent &]
|
[&opt parent]
|
||||||
(def parent (if parent parent _env))
|
(def parent (if parent parent _env))
|
||||||
(def newenv (table/setproto @{} parent))
|
(def newenv (table/setproto @{} parent))
|
||||||
newenv)
|
newenv)
|
||||||
@ -1513,7 +1513,7 @@ value, one key will be ignored."
|
|||||||
(defn eval-string
|
(defn eval-string
|
||||||
"Evaluates a string in the current environment. If more control over the
|
"Evaluates a string in the current environment. If more control over the
|
||||||
environment is needed, use run-context."
|
environment is needed, use run-context."
|
||||||
[str env &]
|
[str &opt env]
|
||||||
(var state (string str))
|
(var state (string str))
|
||||||
(defn chunks [buf _]
|
(defn chunks [buf _]
|
||||||
(def ret state)
|
(def ret state)
|
||||||
@ -1522,7 +1522,6 @@ value, one key will be ignored."
|
|||||||
(buffer/push-string buf str)
|
(buffer/push-string buf str)
|
||||||
(buffer/push-string buf "\n")))
|
(buffer/push-string buf "\n")))
|
||||||
(var returnval nil)
|
(var returnval nil)
|
||||||
(defn error1 [x &] (error x))
|
|
||||||
(run-context {:env env
|
(run-context {:env env
|
||||||
:chunks chunks
|
:chunks chunks
|
||||||
:on-compile-error (fn [msg errf &]
|
:on-compile-error (fn [msg errf &]
|
||||||
@ -1540,7 +1539,7 @@ value, one key will be ignored."
|
|||||||
(defn eval
|
(defn eval
|
||||||
"Evaluates a form in the current environment. If more control over the
|
"Evaluates a form in the current environment. If more control over the
|
||||||
environment is needed, use run-context."
|
environment is needed, use run-context."
|
||||||
[form env &]
|
[form &opt env]
|
||||||
(default env *env*)
|
(default env *env*)
|
||||||
(def res (compile form env "eval"))
|
(def res (compile form env "eval"))
|
||||||
(if (= (type res) :function)
|
(if (= (type res) :function)
|
||||||
@ -1694,7 +1693,7 @@ value, one key will be ignored."
|
|||||||
get a chunk of source code that should return nil for end of file.
|
get a chunk of source code that should return nil for end of file.
|
||||||
The second parameter is a function that is called when a signal is
|
The second parameter is a function that is called when a signal is
|
||||||
caught."
|
caught."
|
||||||
[chunks onsignal &]
|
[&opt chunks onsignal]
|
||||||
(def newenv (make-env))
|
(def newenv (make-env))
|
||||||
(default onsignal (fn [f x]
|
(default onsignal (fn [f x]
|
||||||
(case (fiber/status f)
|
(case (fiber/status f)
|
||||||
@ -1716,7 +1715,7 @@ value, one key will be ignored."
|
|||||||
|
|
||||||
(defn all-bindings
|
(defn all-bindings
|
||||||
"Get all symbols available in the current environment."
|
"Get all symbols available in the current environment."
|
||||||
[env &]
|
[&opt env]
|
||||||
(default env *env*)
|
(default env *env*)
|
||||||
(def envs @[])
|
(def envs @[])
|
||||||
(do (var e env) (while e (array/push envs e) (set e (table/getproto e))))
|
(do (var e env) (while e (array/push envs e) (set e (table/getproto e))))
|
||||||
|
@ -433,12 +433,16 @@ static void janet_quick_asm(
|
|||||||
int32_t flags,
|
int32_t flags,
|
||||||
const char *name,
|
const char *name,
|
||||||
int32_t arity,
|
int32_t arity,
|
||||||
|
int32_t min_arity,
|
||||||
|
int32_t max_arity,
|
||||||
int32_t slots,
|
int32_t slots,
|
||||||
const uint32_t *bytecode,
|
const uint32_t *bytecode,
|
||||||
size_t bytecode_size,
|
size_t bytecode_size,
|
||||||
const char *doc) {
|
const char *doc) {
|
||||||
JanetFuncDef *def = janet_funcdef_alloc();
|
JanetFuncDef *def = janet_funcdef_alloc();
|
||||||
def->arity = arity;
|
def->arity = arity;
|
||||||
|
def->min_arity = min_arity;
|
||||||
|
def->max_arity = max_arity;
|
||||||
def->flags = flags;
|
def->flags = flags;
|
||||||
def->slotcount = slots;
|
def->slotcount = slots;
|
||||||
def->bytecode = malloc(bytecode_size);
|
def->bytecode = malloc(bytecode_size);
|
||||||
@ -514,6 +518,8 @@ static void templatize_varop(
|
|||||||
flags | JANET_FUNCDEF_FLAG_VARARG,
|
flags | JANET_FUNCDEF_FLAG_VARARG,
|
||||||
name,
|
name,
|
||||||
0,
|
0,
|
||||||
|
0,
|
||||||
|
INT32_MAX,
|
||||||
6,
|
6,
|
||||||
varop_asm,
|
varop_asm,
|
||||||
sizeof(varop_asm),
|
sizeof(varop_asm),
|
||||||
@ -567,6 +573,8 @@ static void templatize_comparator(
|
|||||||
flags | JANET_FUNCDEF_FLAG_VARARG,
|
flags | JANET_FUNCDEF_FLAG_VARARG,
|
||||||
name,
|
name,
|
||||||
0,
|
0,
|
||||||
|
0,
|
||||||
|
INT32_MAX,
|
||||||
6,
|
6,
|
||||||
comparator_asm,
|
comparator_asm,
|
||||||
sizeof(comparator_asm),
|
sizeof(comparator_asm),
|
||||||
@ -604,7 +612,7 @@ static void make_apply(JanetTable *env) {
|
|||||||
S(JOP_TAILCALL, 0)
|
S(JOP_TAILCALL, 0)
|
||||||
};
|
};
|
||||||
janet_quick_asm(env, JANET_FUN_APPLY | JANET_FUNCDEF_FLAG_VARARG,
|
janet_quick_asm(env, JANET_FUN_APPLY | JANET_FUNCDEF_FLAG_VARARG,
|
||||||
"apply", 1, 6, apply_asm, sizeof(apply_asm),
|
"apply", 1, 1, INT32_MAX, 6, apply_asm, sizeof(apply_asm),
|
||||||
JDOC("(apply f & args)\n\n"
|
JDOC("(apply f & args)\n\n"
|
||||||
"Applies a function to a variable number of arguments. Each element in args "
|
"Applies a function to a variable number of arguments. Each element in args "
|
||||||
"is used as an argument to f, except the last element in args, which is expected to "
|
"is used as an argument to f, except the last element in args, which is expected to "
|
||||||
@ -652,38 +660,38 @@ JanetTable *janet_core_env(JanetTable *replacements) {
|
|||||||
janet_core_cfuns(env, NULL, corelib_cfuns);
|
janet_core_cfuns(env, NULL, corelib_cfuns);
|
||||||
|
|
||||||
#ifdef JANET_BOOTSTRAP
|
#ifdef JANET_BOOTSTRAP
|
||||||
janet_quick_asm(env, JANET_FUN_YIELD | JANET_FUNCDEF_FLAG_FIXARITY,
|
janet_quick_asm(env, JANET_FUN_DEBUG,
|
||||||
"debug", 0, 1, debug_asm, sizeof(debug_asm),
|
"debug", 0, 0, 0, 1, debug_asm, sizeof(debug_asm),
|
||||||
JDOC("(debug)\n\n"
|
JDOC("(debug)\n\n"
|
||||||
"Throws a debug signal that can be caught by a parent fiber and used to inspect "
|
"Throws a debug signal that can be caught by a parent fiber and used to inspect "
|
||||||
"the running state of the current fiber. Returns nil."));
|
"the running state of the current fiber. Returns nil."));
|
||||||
janet_quick_asm(env, JANET_FUN_ERROR | JANET_FUNCDEF_FLAG_FIXARITY,
|
janet_quick_asm(env, JANET_FUN_ERROR,
|
||||||
"error", 1, 1, error_asm, sizeof(error_asm),
|
"error", 1, 1, 1, 1, error_asm, sizeof(error_asm),
|
||||||
JDOC("(error e)\n\n"
|
JDOC("(error e)\n\n"
|
||||||
"Throws an error e that can be caught and handled by a parent fiber."));
|
"Throws an error e that can be caught and handled by a parent fiber."));
|
||||||
janet_quick_asm(env, JANET_FUN_YIELD,
|
janet_quick_asm(env, JANET_FUN_YIELD,
|
||||||
"yield", 1, 2, yield_asm, sizeof(yield_asm),
|
"yield", 1, 0, 1, 2, yield_asm, sizeof(yield_asm),
|
||||||
JDOC("(yield x)\n\n"
|
JDOC("(yield x)\n\n"
|
||||||
"Yield a value to a parent fiber. When a fiber yields, its execution is paused until "
|
"Yield a value to a parent fiber. When a fiber yields, its execution is paused until "
|
||||||
"another thread resumes it. The fiber will then resume, and the last yield call will "
|
"another thread resumes it. The fiber will then resume, and the last yield call will "
|
||||||
"return the value that was passed to resume."));
|
"return the value that was passed to resume."));
|
||||||
janet_quick_asm(env, JANET_FUN_RESUME,
|
janet_quick_asm(env, JANET_FUN_RESUME,
|
||||||
"resume", 2, 2, resume_asm, sizeof(resume_asm),
|
"resume", 2, 1, 2, 2, resume_asm, sizeof(resume_asm),
|
||||||
JDOC("(resume fiber [,x])\n\n"
|
JDOC("(resume fiber &opt x)\n\n"
|
||||||
"Resume a new or suspended fiber and optionally pass in a value to the fiber that "
|
"Resume a new or suspended fiber and optionally pass in a value to the fiber that "
|
||||||
"will be returned to the last yield in the case of a pending fiber, or the argument to "
|
"will be returned to the last yield in the case of a pending fiber, or the argument to "
|
||||||
"the dispatch function in the case of a new fiber. Returns either the return result of "
|
"the dispatch function in the case of a new fiber. Returns either the return result of "
|
||||||
"the fiber's dispatch function, or the value from the next yield call in fiber."));
|
"the fiber's dispatch function, or the value from the next yield call in fiber."));
|
||||||
janet_quick_asm(env, JANET_FUN_GET | JANET_FUNCDEF_FLAG_FIXARITY,
|
janet_quick_asm(env, JANET_FUN_GET,
|
||||||
"get", 2, 2, get_asm, sizeof(get_asm),
|
"get", 2, 2, 2, 2, get_asm, sizeof(get_asm),
|
||||||
JDOC("(get ds key)\n\n"
|
JDOC("(get ds key)\n\n"
|
||||||
"Get a value from any associative data structure. Arrays, tuples, tables, structs, strings, "
|
"Get a value from any associative data structure. Arrays, tuples, tables, structs, strings, "
|
||||||
"symbols, and buffers are all associative and can be used with get. Order structures, name "
|
"symbols, and buffers are all associative and can be used with get. Order structures, name "
|
||||||
"arrays, tuples, strings, buffers, and symbols must use integer keys. Structs and tables can "
|
"arrays, tuples, strings, buffers, and symbols must use integer keys. Structs and tables can "
|
||||||
"take any value as a key except nil and return a value except nil. Byte sequences will return "
|
"take any value as a key except nil and return a value except nil. Byte sequences will return "
|
||||||
"integer representations of bytes as result of a get call."));
|
"integer representations of bytes as result of a get call."));
|
||||||
janet_quick_asm(env, JANET_FUN_PUT | JANET_FUNCDEF_FLAG_FIXARITY,
|
janet_quick_asm(env, JANET_FUN_PUT,
|
||||||
"put", 3, 3, put_asm, sizeof(put_asm),
|
"put", 3, 3, 3, 3, put_asm, sizeof(put_asm),
|
||||||
JDOC("(put ds key value)\n\n"
|
JDOC("(put ds key value)\n\n"
|
||||||
"Associate a key with a value in any mutable associative data structure. Indexed data structures "
|
"Associate a key with a value in any mutable associative data structure. Indexed data structures "
|
||||||
"(arrays and buffers) only accept non-negative integer keys, and will expand if an out of bounds "
|
"(arrays and buffers) only accept non-negative integer keys, and will expand if an out of bounds "
|
||||||
@ -691,13 +699,13 @@ JanetTable *janet_core_env(JanetTable *replacements) {
|
|||||||
"space will be filled with 0 bytes. In a table, putting a key that is contained in the table prototype "
|
"space will be filled with 0 bytes. In a table, putting a key that is contained in the table prototype "
|
||||||
"will hide the association defined by the prototype, but will not mutate the prototype table. Putting "
|
"will hide the association defined by the prototype, but will not mutate the prototype table. Putting "
|
||||||
"a value nil into a table will remove the key from the table. Returns the data structure ds."));
|
"a value nil into a table will remove the key from the table. Returns the data structure ds."));
|
||||||
janet_quick_asm(env, JANET_FUN_LENGTH | JANET_FUNCDEF_FLAG_FIXARITY,
|
janet_quick_asm(env, JANET_FUN_LENGTH,
|
||||||
"length", 1, 1, length_asm, sizeof(length_asm),
|
"length", 1, 1, 1, 1, length_asm, sizeof(length_asm),
|
||||||
JDOC("(length ds)\n\n"
|
JDOC("(length ds)\n\n"
|
||||||
"Returns the length or count of a data structure in constant time as an integer. For "
|
"Returns the length or count of a data structure in constant time as an integer. For "
|
||||||
"structs and tables, returns the number of key-value pairs in the data structure."));
|
"structs and tables, returns the number of key-value pairs in the data structure."));
|
||||||
janet_quick_asm(env, JANET_FUN_BNOT | JANET_FUNCDEF_FLAG_FIXARITY,
|
janet_quick_asm(env, JANET_FUN_BNOT,
|
||||||
"bnot", 1, 1, bnot_asm, sizeof(bnot_asm),
|
"bnot", 1, 1, 1, 1, bnot_asm, sizeof(bnot_asm),
|
||||||
JDOC("(bnot x)\n\nReturns the bit-wise inverse of integer x."));
|
JDOC("(bnot x)\n\nReturns the bit-wise inverse of integer x."));
|
||||||
make_apply(env);
|
make_apply(env);
|
||||||
|
|
||||||
|
@ -138,11 +138,8 @@ int janet_fiber_funcframe(JanetFiber *fiber, JanetFunction *func) {
|
|||||||
int32_t next_arity = fiber->stacktop - fiber->stackstart;
|
int32_t next_arity = fiber->stacktop - fiber->stackstart;
|
||||||
|
|
||||||
/* Check strict arity before messing with state */
|
/* Check strict arity before messing with state */
|
||||||
if (func->def->flags & JANET_FUNCDEF_FLAG_FIXARITY) {
|
if (next_arity < func->def->min_arity) return 1;
|
||||||
if (func->def->arity != next_arity) {
|
if (next_arity > func->def->max_arity) return 1;
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fiber->capacity < nextstacktop) {
|
if (fiber->capacity < nextstacktop) {
|
||||||
janet_fiber_setcapacity(fiber, 2 * nextstacktop);
|
janet_fiber_setcapacity(fiber, 2 * nextstacktop);
|
||||||
@ -204,11 +201,8 @@ int janet_fiber_funcframe_tail(JanetFiber *fiber, JanetFunction *func) {
|
|||||||
int32_t stacksize;
|
int32_t stacksize;
|
||||||
|
|
||||||
/* Check strict arity before messing with state */
|
/* Check strict arity before messing with state */
|
||||||
if (func->def->flags & JANET_FUNCDEF_FLAG_FIXARITY) {
|
if (next_arity < func->def->min_arity) return 1;
|
||||||
if (func->def->arity != next_arity) {
|
if (next_arity > func->def->max_arity) return 1;
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fiber->capacity < nextstacktop) {
|
if (fiber->capacity < nextstacktop) {
|
||||||
janet_fiber_setcapacity(fiber, 2 * nextstacktop);
|
janet_fiber_setcapacity(fiber, 2 * nextstacktop);
|
||||||
@ -303,10 +297,8 @@ static Janet cfun_fiber_new(int32_t argc, Janet *argv) {
|
|||||||
janet_arity(argc, 1, 2);
|
janet_arity(argc, 1, 2);
|
||||||
JanetFunction *func = janet_getfunction(argv, 0);
|
JanetFunction *func = janet_getfunction(argv, 0);
|
||||||
JanetFiber *fiber;
|
JanetFiber *fiber;
|
||||||
if (func->def->flags & JANET_FUNCDEF_FLAG_FIXARITY) {
|
if (func->def->min_arity != 0) {
|
||||||
if (func->def->arity != 0) {
|
janet_panic("expected nullary function in fiber constructor");
|
||||||
janet_panic("expected nullary function in fiber constructor");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fiber = janet_fiber(func, 64, 0, NULL);
|
fiber = janet_fiber(func, 64, 0, NULL);
|
||||||
if (argc == 2) {
|
if (argc == 2) {
|
||||||
|
@ -203,6 +203,8 @@ static void marshal_one_def(MarshalState *st, JanetFuncDef *def, int flags) {
|
|||||||
pushint(st, def->flags);
|
pushint(st, def->flags);
|
||||||
pushint(st, def->slotcount);
|
pushint(st, def->slotcount);
|
||||||
pushint(st, def->arity);
|
pushint(st, def->arity);
|
||||||
|
pushint(st, def->min_arity);
|
||||||
|
pushint(st, def->max_arity);
|
||||||
pushint(st, def->constants_length);
|
pushint(st, def->constants_length);
|
||||||
pushint(st, def->bytecode_length);
|
pushint(st, def->bytecode_length);
|
||||||
if (def->flags & JANET_FUNCDEF_FLAG_HASENVS)
|
if (def->flags & JANET_FUNCDEF_FLAG_HASENVS)
|
||||||
@ -708,6 +710,8 @@ static const uint8_t *unmarshal_one_def(
|
|||||||
def->flags = readint(st, &data);
|
def->flags = readint(st, &data);
|
||||||
def->slotcount = readint(st, &data);
|
def->slotcount = readint(st, &data);
|
||||||
def->arity = readint(st, &data);
|
def->arity = readint(st, &data);
|
||||||
|
def->min_arity = readint(st, &data);
|
||||||
|
def->max_arity = readint(st, &data);
|
||||||
|
|
||||||
/* Read some lengths */
|
/* Read some lengths */
|
||||||
constants_length = readint(st, &data);
|
constants_length = readint(st, &data);
|
||||||
|
@ -643,16 +643,17 @@ static JanetSlot janetc_fn(JanetFopts opts, int32_t argn, const Janet *argv) {
|
|||||||
JanetSlot ret;
|
JanetSlot ret;
|
||||||
Janet head;
|
Janet head;
|
||||||
JanetScope fnscope;
|
JanetScope fnscope;
|
||||||
int32_t paramcount, argi, parami, arity, defindex, i;
|
int32_t paramcount, argi, parami, arity, min_arity, max_arity, defindex, i;
|
||||||
JanetFopts subopts = janetc_fopts_default(c);
|
JanetFopts subopts = janetc_fopts_default(c);
|
||||||
const Janet *params;
|
const Janet *params;
|
||||||
const char *errmsg = NULL;
|
const char *errmsg = NULL;
|
||||||
|
|
||||||
/* Function flags */
|
/* Function flags */
|
||||||
int vararg = 0;
|
int vararg = 0;
|
||||||
int fixarity = 1;
|
int allow_extra = 0;
|
||||||
int selfref = 0;
|
int selfref = 0;
|
||||||
int seenamp = 0;
|
int seenamp = 0;
|
||||||
|
int seenopt = 0;
|
||||||
|
|
||||||
/* Begin function */
|
/* Begin function */
|
||||||
c->scope->flags |= JANET_SCOPE_CLOSURE;
|
c->scope->flags |= JANET_SCOPE_CLOSURE;
|
||||||
@ -683,19 +684,32 @@ static JanetSlot janetc_fn(JanetFopts opts, int32_t argn, const Janet *argv) {
|
|||||||
Janet param = params[i];
|
Janet param = params[i];
|
||||||
if (janet_checktype(param, JANET_SYMBOL)) {
|
if (janet_checktype(param, JANET_SYMBOL)) {
|
||||||
/* Check for varargs and unfixed arity */
|
/* Check for varargs and unfixed arity */
|
||||||
if ((!seenamp) &&
|
if (!janet_cstrcmp(janet_unwrap_symbol(param), "&")) {
|
||||||
(0 == janet_cstrcmp(janet_unwrap_symbol(param), "&"))) {
|
if (seenamp) {
|
||||||
seenamp = 1;
|
errmsg = "& in unexpected location";
|
||||||
fixarity = 0;
|
goto error;
|
||||||
if (i == paramcount - 1) {
|
} else if (i == paramcount - 1) {
|
||||||
|
allow_extra = 1;
|
||||||
arity--;
|
arity--;
|
||||||
} else if (i == paramcount - 2) {
|
} else if (i == paramcount - 2) {
|
||||||
vararg = 1;
|
vararg = 1;
|
||||||
arity -= 2;
|
arity -= 2;
|
||||||
} else {
|
} else {
|
||||||
errmsg = "variable argument symbol in unexpected location";
|
errmsg = "& in unexpected location";
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
seenamp = 1;
|
||||||
|
} else if (!janet_cstrcmp(janet_unwrap_symbol(param), "&opt")) {
|
||||||
|
if (seenopt) {
|
||||||
|
errmsg = "only one &opt allowed";
|
||||||
|
goto error;
|
||||||
|
} else if (i == paramcount - 1) {
|
||||||
|
errmsg = "&opt cannot be last item in parameter list";
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
min_arity = i;
|
||||||
|
arity--;
|
||||||
|
seenopt = 1;
|
||||||
} else {
|
} else {
|
||||||
janetc_nameslot(c, janet_unwrap_symbol(param), janetc_farslot(c));
|
janetc_nameslot(c, janet_unwrap_symbol(param), janetc_farslot(c));
|
||||||
}
|
}
|
||||||
@ -704,6 +718,9 @@ static JanetSlot janetc_fn(JanetFopts opts, int32_t argn, const Janet *argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
max_arity = (vararg || allow_extra) ? INT32_MAX : arity;
|
||||||
|
if (!seenopt) min_arity = arity;
|
||||||
|
|
||||||
/* Check for self ref */
|
/* Check for self ref */
|
||||||
if (selfref) {
|
if (selfref) {
|
||||||
JanetSlot slot = janetc_farslot(c);
|
JanetSlot slot = janetc_farslot(c);
|
||||||
@ -715,17 +732,20 @@ static JanetSlot janetc_fn(JanetFopts opts, int32_t argn, const Janet *argv) {
|
|||||||
/* Compile function body */
|
/* Compile function body */
|
||||||
if (parami + 1 == argn) {
|
if (parami + 1 == argn) {
|
||||||
janetc_emit(c, JOP_RETURN_NIL);
|
janetc_emit(c, JOP_RETURN_NIL);
|
||||||
} else for (argi = parami + 1; argi < argn; argi++) {
|
} else {
|
||||||
|
for (argi = parami + 1; argi < argn; argi++) {
|
||||||
subopts.flags = (argi == (argn - 1)) ? JANET_FOPTS_TAIL : JANET_FOPTS_DROP;
|
subopts.flags = (argi == (argn - 1)) ? JANET_FOPTS_TAIL : JANET_FOPTS_DROP;
|
||||||
janetc_value(subopts, argv[argi]);
|
janetc_value(subopts, argv[argi]);
|
||||||
if (c->result.status == JANET_COMPILE_ERROR)
|
if (c->result.status == JANET_COMPILE_ERROR)
|
||||||
goto error2;
|
goto error2;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Build function */
|
/* Build function */
|
||||||
def = janetc_pop_funcdef(c);
|
def = janetc_pop_funcdef(c);
|
||||||
def->arity = arity;
|
def->arity = arity;
|
||||||
if (fixarity) def->flags |= JANET_FUNCDEF_FLAG_FIXARITY;
|
def->min_arity = min_arity;
|
||||||
|
def->max_arity = max_arity;
|
||||||
if (vararg) def->flags |= JANET_FUNCDEF_FLAG_VARARG;
|
if (vararg) def->flags |= JANET_FUNCDEF_FLAG_VARARG;
|
||||||
|
|
||||||
if (selfref) def->name = janet_unwrap_symbol(head);
|
if (selfref) def->name = janet_unwrap_symbol(head);
|
||||||
|
@ -725,7 +725,6 @@ struct JanetAbstractHead {
|
|||||||
/* Some function definition flags */
|
/* Some function definition flags */
|
||||||
#define JANET_FUNCDEF_FLAG_VARARG 0x10000
|
#define JANET_FUNCDEF_FLAG_VARARG 0x10000
|
||||||
#define JANET_FUNCDEF_FLAG_NEEDSENV 0x20000
|
#define JANET_FUNCDEF_FLAG_NEEDSENV 0x20000
|
||||||
#define JANET_FUNCDEF_FLAG_FIXARITY 0x40000
|
|
||||||
#define JANET_FUNCDEF_FLAG_HASNAME 0x80000
|
#define JANET_FUNCDEF_FLAG_HASNAME 0x80000
|
||||||
#define JANET_FUNCDEF_FLAG_HASSOURCE 0x100000
|
#define JANET_FUNCDEF_FLAG_HASSOURCE 0x100000
|
||||||
#define JANET_FUNCDEF_FLAG_HASDEFS 0x200000
|
#define JANET_FUNCDEF_FLAG_HASDEFS 0x200000
|
||||||
@ -755,6 +754,8 @@ struct JanetFuncDef {
|
|||||||
int32_t flags;
|
int32_t flags;
|
||||||
int32_t slotcount; /* The amount of stack space required for the function */
|
int32_t slotcount; /* The amount of stack space required for the function */
|
||||||
int32_t arity; /* Not including varargs */
|
int32_t arity; /* Not including varargs */
|
||||||
|
int32_t min_arity; /* Including varargs */
|
||||||
|
int32_t max_arity; /* Including varargs */
|
||||||
int32_t constants_length;
|
int32_t constants_length;
|
||||||
int32_t bytecode_length;
|
int32_t bytecode_length;
|
||||||
int32_t environments_length;
|
int32_t environments_length;
|
||||||
|
Loading…
Reference in New Issue
Block a user