1
0
mirror of https://github.com/janet-lang/janet synced 2025-06-05 16:14:12 +00:00

Add lots of documentation for all functions.

This commit is contained in:
Calvin Rose 2018-11-16 16:24:10 -05:00
parent fe7c591c40
commit fcbd24cedc
15 changed files with 457 additions and 195 deletions

View File

@ -715,7 +715,7 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int
/* Set environments */ /* Set environments */
def->environments = def->environments =
realloc(def->environments, def->environments_length * sizeof(int32_t)); realloc(def->environments, def->environments_length * sizeof(int32_t));
/* Verify the func def */ /* Verify the func def */
if (janet_verify(def)) { if (janet_verify(def)) {
janet_asm_error(&a, "invalid assembly"); janet_asm_error(&a, "invalid assembly");
@ -924,7 +924,7 @@ static int cfun_disasm(JanetArgs args) {
} }
static const JanetReg cfuns[] = { static const JanetReg cfuns[] = {
{"asm", cfun_asm, {"asm", cfun_asm,
"(asm assembly)\n\n" "(asm assembly)\n\n"
"Returns a new function that is the compiled result of the assembly.\n" "Returns a new function that is the compiled result of the assembly.\n"
"The syntax for the assembly can be found on the janet wiki. Will throw an\n" "The syntax for the assembly can be found on the janet wiki. Will throw an\n"

View File

@ -268,12 +268,12 @@ static int cfun_slice(JanetArgs args) {
} }
static const JanetReg cfuns[] = { static const JanetReg cfuns[] = {
{"buffer.new", cfun_new, {"buffer.new", cfun_new,
"(buffer.new capacity)\n\n" "(buffer.new capacity)\n\n"
"Creates a new, empty buffer with enough memory for capacity bytes. " "Creates a new, empty buffer with enough memory for capacity bytes. "
"Returns a new buffer." "Returns a new buffer."
}, },
{"buffer.push-byte", cfun_u8, {"buffer.push-byte", cfun_u8,
"(buffer.push-byte buffer x)\n\n" "(buffer.push-byte buffer x)\n\n"
"Append a byte to a buffer. Will expand the buffer as necessary. " "Append a byte to a buffer. Will expand the buffer as necessary. "
"Returns the modified buffer. Will throw an error if the buffer overflows." "Returns the modified buffer. Will throw an error if the buffer overflows."
@ -290,11 +290,11 @@ static const JanetReg cfuns[] = {
"to strings before being pushed. Returns the modified buffer. " "to strings before being pushed. Returns the modified buffer. "
"Will throw an error if the buffer overflows." "Will throw an error if the buffer overflows."
}, },
{"buffer.popn", cfun_popn, {"buffer.popn", cfun_popn,
"(buffer.popn buffer n)\n\n" "(buffer.popn buffer n)\n\n"
"Removes the last n bytes from the buffer. Returns the modified buffer." "Removes the last n bytes from the buffer. Returns the modified buffer."
}, },
{"buffer.clear", cfun_clear, {"buffer.clear", cfun_clear,
"(buffer.clear buffer)\n\n" "(buffer.clear buffer)\n\n"
"Sets the size of a buffer to 0 and empties it. The buffer retains " "Sets the size of a buffer to 0 and empties it. The buffer retains "
"its memory so it can be efficiently refilled. Returns the modified buffer." "its memory so it can be efficiently refilled. Returns the modified buffer."

View File

@ -407,7 +407,7 @@ static JanetSlot janetc_array(JanetFopts opts, Janet x) {
static JanetSlot janetc_tablector(JanetFopts opts, Janet x, int op) { static JanetSlot janetc_tablector(JanetFopts opts, Janet x, int op) {
JanetCompiler *c = opts.compiler; JanetCompiler *c = opts.compiler;
return janetc_maker(opts, return janetc_maker(opts,
janetc_toslotskv(c, x), janetc_toslotskv(c, x),
op); op);
} }
@ -432,9 +432,9 @@ static JanetSlot janetc_symbol(JanetFopts opts, const uint8_t *sym) {
/* Expand a macro one time. Also get the special form compiler if we /* Expand a macro one time. Also get the special form compiler if we
* find that instead. */ * find that instead. */
static int macroexpand1( static int macroexpand1(
JanetCompiler *c, JanetCompiler *c,
Janet x, Janet x,
Janet *out, Janet *out,
const JanetSpecial **spec) { const JanetSpecial **spec) {
if (!janet_checktype(x, JANET_TUPLE)) if (!janet_checktype(x, JANET_TUPLE))
return 0; return 0;
@ -466,9 +466,9 @@ static int macroexpand1(
JanetFunction *macro = janet_unwrap_function(macroval); JanetFunction *macro = janet_unwrap_function(macroval);
int lock = janet_gclock(); int lock = janet_gclock();
JanetSignal status = janet_call( JanetSignal status = janet_call(
macro, macro,
janet_tuple_length(form) - 1, janet_tuple_length(form) - 1,
form + 1, form + 1,
&x, &x,
&fiberp); &fiberp);
janet_gcunlock(lock); janet_gcunlock(lock);
@ -612,7 +612,7 @@ JanetFuncDef *janetc_pop_funcdef(JanetCompiler *c) {
if (scope->flags & JANET_SCOPE_ENV) { if (scope->flags & JANET_SCOPE_ENV) {
def->flags |= JANET_FUNCDEF_FLAG_NEEDSENV; def->flags |= JANET_FUNCDEF_FLAG_NEEDSENV;
} }
/* Pop the scope */ /* Pop the scope */
janetc_popscope(c); janetc_popscope(c);
@ -706,7 +706,7 @@ static int cfun(JanetArgs args) {
} }
static const JanetReg cfuns[] = { static const JanetReg cfuns[] = {
{"compile", cfun, {"compile", cfun,
"(compile ast)\n\n" "(compile ast)\n\n"
"Compiles an Abstract Sytnax Tree (ast) into a janet function. " "Compiles an Abstract Sytnax Tree (ast) into a janet function. "
"Pair the compile function with parsing functionality to implement " "Pair the compile function with parsing functionality to implement "
@ -718,6 +718,6 @@ static const JanetReg cfuns[] = {
int janet_lib_compile(JanetArgs args) { int janet_lib_compile(JanetArgs args) {
JanetTable *env = janet_env(args); JanetTable *env = janet_env(args);
janet_cfuns(env, NULL, cfuns); janet_cfuns(env, NULL, cfuns);
return 0; return 0;
} }

View File

@ -49,14 +49,14 @@
#define JANET_FUN_ORDER_GT 20 #define JANET_FUN_ORDER_GT 20
#define JANET_FUN_ORDER_LT 21 #define JANET_FUN_ORDER_LT 21
#define JANET_FUN_ORDER_GTE 22 #define JANET_FUN_ORDER_GTE 22
#define JANET_FUN_ORDER_LTE 23 #define JANET_FUN_ORDER_LTE 23
#define JANET_FUN_ORDER_EQ 24 #define JANET_FUN_ORDER_EQ 24
#define JANET_FUN_ORDER_NEQ 25 #define JANET_FUN_ORDER_NEQ 25
#define JANET_FUN_GT 26 #define JANET_FUN_GT 26
#define JANET_FUN_LT 27 #define JANET_FUN_LT 27
#define JANET_FUN_GTE 28 #define JANET_FUN_GTE 28
#define JANET_FUN_LTE 29 #define JANET_FUN_LTE 29
#define JANET_FUN_EQ 30 #define JANET_FUN_EQ 30
#define JANET_FUN_NEQ 31 #define JANET_FUN_NEQ 31
/* Compiler typedefs */ /* Compiler typedefs */
@ -135,7 +135,7 @@ struct JanetScope {
/* Compilation state */ /* Compilation state */
struct JanetCompiler { struct JanetCompiler {
/* Pointer to current scope */ /* Pointer to current scope */
JanetScope *scope; JanetScope *scope;

View File

@ -1096,7 +1096,8 @@ value, one key will be ignored."
@[parent] @[parent]
(def parent (if parent parent _env)) (def parent (if parent parent _env))
(def newenv (table.setproto @{} parent)) (def newenv (table.setproto @{} parent))
(put newenv '_env @{:value newenv :private true}) (put newenv '_env @{:value newenv :private true
:doc "The environment table for the current scope."})
newenv) newenv)
(defn run-context (defn run-context

View File

@ -284,105 +284,105 @@ static int janet_core_hash(JanetArgs args) {
} }
static const JanetReg cfuns[] = { static const JanetReg cfuns[] = {
{"native", janet_core_native, {"native", janet_core_native,
"(native path)\n\n" "(native path)\n\n"
"Load a native module from the given path. The path " "Load a native module from the given path. The path "
"must be an absolute or relative path on the filesystem, and is " "must be an absolute or relative path on the file system, and is "
"usually a .so file on unix systems, and a .dll file on Windows. " "usually a .so file on Unix systems, and a .dll file on Windows. "
"Returns an environment table that contains functions and other values " "Returns an environment table that contains functions and other values "
"from the native module." "from the native module."
}, },
{"print", janet_core_print, {"print", janet_core_print,
"(print & xs)\n\n" "(print & xs)\n\n"
"Print values to the console (standard out). Value are converted " "Print values to the console (standard out). Value are converted "
"to strings if they are not already. After printing all values, a " "to strings if they are not already. After printing all values, a "
"newline character is printed. Returns nil." "newline character is printed. Returns nil."
}, },
{"describe", janet_core_describe, {"describe", janet_core_describe,
"(describe x)\n\n" "(describe x)\n\n"
"Returns a string that is a human readable description of a value x." "Returns a string that is a human readable description of a value x."
}, },
{"string", janet_core_string, {"string", janet_core_string,
"(string & parts)\n\n" "(string & parts)\n\n"
"Creates a string by concatenating values together. Values are " "Creates a string by concatenating values together. Values are "
"converted to bytes via describe if they are not byte sequences. " "converted to bytes via describe if they are not byte sequences. "
"Returns the new string." "Returns the new string."
}, },
{"symbol", janet_core_symbol, {"symbol", janet_core_symbol,
"(symbol & xs)\n\n" "(symbol & xs)\n\n"
"Creates a symbol by concatenating values together. Values are " "Creates a symbol by concatenating values together. Values are "
"converted to bytes via describe if they are not byte sequences. Returns " "converted to bytes via describe if they are not byte sequences. Returns "
"the new symbol." "the new symbol."
}, },
{"buffer", janet_core_buffer, {"buffer", janet_core_buffer,
"(buffer & xs)\n\n" "(buffer & xs)\n\n"
"Creates a new buffer by concatenating values together. Values are " "Creates a new buffer by concatenating values together. Values are "
"converted to bytes via describe if they are not byte sequences. Returns " "converted to bytes via describe if they are not byte sequences. Returns "
"the new symbol." "the new symbol."
}, },
{"table", janet_core_table, {"table", janet_core_table,
"(table & kvs)\n\n" "(table & kvs)\n\n"
"Creates a new table from a variadic number of keys and values. " "Creates a new table from a variadic number of keys and values. "
"kvs is a sequence k1, v1, k2, v2, k3, v3, ... If kvs has " "kvs is a sequence k1, v1, k2, v2, k3, v3, ... If kvs has "
"an odd number of elements, an error will be thrown. Returns the " "an odd number of elements, an error will be thrown. Returns the "
"new table." "new table."
}, },
{"array", janet_core_array, {"array", janet_core_array,
"(array & items)\n\n" "(array & items)\n\n"
"Create a new array that contains items. Returns the new array." "Create a new array that contains items. Returns the new array."
}, },
{"scan-number", janet_core_scannumber, {"scan-number", janet_core_scannumber,
"(scan-number str)\n\n" "(scan-number str)\n\n"
"Parse a number from a byte sequence an return that number, either and integer " "Parse a number from a byte sequence an return that number, either and integer "
"or a real. The number " "or a real. The number "
"must be in the same format as numbers in janet source code. Will return nil " "must be in the same format as numbers in janet source code. Will return nil "
"on an invalid number." "on an invalid number."
}, },
{"scan-integer", janet_core_scaninteger, {"scan-integer", janet_core_scaninteger,
"(scan-integer str)\n\n" "(scan-integer str)\n\n"
"Parse an integer from a byte sequence an return that number. The integer " "Parse an integer from a byte sequence an return that number. The integer "
"must be in the same format as integers in janet source code. Will return nil " "must be in the same format as integers in janet source code. Will return nil "
"on an invalid integer." "on an invalid integer."
}, },
{"scan-real", janet_core_scanreal, {"scan-real", janet_core_scanreal,
"(scan-real str)\n\n" "(scan-real str)\n\n"
"Parse a real number from a byte sequence an return that number. The number " "Parse a real number from a byte sequence an return that number. The number "
"must be in the same format as numbers in janet source code. Will return nil " "must be in the same format as numbers in janet source code. Will return nil "
"on an invalid number." "on an invalid number."
}, },
{"tuple", janet_core_tuple, {"tuple", janet_core_tuple,
"(tuple & items)\n\n" "(tuple & items)\n\n"
"Creates a new tuple that contains items. Returns the new tuple." "Creates a new tuple that contains items. Returns the new tuple."
}, },
{"struct", janet_core_struct, {"struct", janet_core_struct,
"(struct & kvs)\n\n" "(struct & kvs)\n\n"
"Create a new struct from a sequence of key value pairs. " "Create a new struct from a sequence of key value pairs. "
"kvs is a sequence k1, v1, k2, v2, k3, v3, ... If kvs has " "kvs is a sequence k1, v1, k2, v2, k3, v3, ... If kvs has "
"an odd number of elements, an error will be thrown. Returns the " "an odd number of elements, an error will be thrown. Returns the "
"new struct." "new struct."
}, },
{"gensym", janet_core_gensym, {"gensym", janet_core_gensym,
"(gensym)\n\n" "(gensym)\n\n"
"Returns a new symbol that is unique across the runtime. This means it " "Returns a new symbol that is unique across the runtime. This means it "
"will not collide with any already created symbols during compilation, so " "will not collide with any already created symbols during compilation, so "
"it can be used in macros to generate automatic bindings." "it can be used in macros to generate automatic bindings."
}, },
{"gccollect", janet_core_gccollect, {"gccollect", janet_core_gccollect,
"(gccollect)\n\n" "(gccollect)\n\n"
"Run garbage collection. You should probably not call this manually." "Run garbage collection. You should probably not call this manually."
}, },
{"gcsetinterval", janet_core_gcsetinterval, {"gcsetinterval", janet_core_gcsetinterval,
"(gcsetinterval interval)\n\n" "(gcsetinterval interval)\n\n"
"Set an integer number of bytes to allocate before running garbage collection. " "Set an integer number of bytes to allocate before running garbage collection. "
"Low values interval will be slower but use less memory. " "Low values interval will be slower but use less memory. "
"High values will be faster but use more memory." "High values will be faster but use more memory."
}, },
{"gcinterval", janet_core_gcinterval, {"gcinterval", janet_core_gcinterval,
"(gcinterval)\n\n" "(gcinterval)\n\n"
"Returns the integer number of bytes to allocate before running an iteration " "Returns the integer number of bytes to allocate before running an iteration "
"of garbage collection." "of garbage collection."
}, },
{"type", janet_core_type, {"type", janet_core_type,
"(type x)\n\n" "(type x)\n\n"
"Returns the type of x as a keyword symbol. x is one of\n" "Returns the type of x as a keyword symbol. x is one of\n"
"\t:nil\n" "\t:nil\n"
@ -400,7 +400,7 @@ static const JanetReg cfuns[] = {
"\t:function\n" "\t:function\n"
"\t:cfunction" "\t:cfunction"
}, },
{"next", janet_core_next, {"next", janet_core_next,
"(next dict key)\n\n" "(next dict key)\n\n"
"Gets the next key in a struct or table. Can be used to iterate through " "Gets the next key in a struct or table. Can be used to iterate through "
"the keys of a data structure in an unspecified order. Keys are guaranteed " "the keys of a data structure in an unspecified order. Keys are guaranteed "
@ -408,7 +408,7 @@ static const JanetReg cfuns[] = {
"during iteration. If key is nil, next returns the first key. If next " "during iteration. If key is nil, next returns the first key. If next "
"returns nil, there are no more keys to iterate through. " "returns nil, there are no more keys to iterate through. "
}, },
{"hash", janet_core_hash, {"hash", janet_core_hash,
"(hash value)\n\n" "(hash value)\n\n"
"Gets a hash value for any janet value. The hash is an integer can be used " "Gets a hash value for any janet value. The hash is an integer can be used "
"as a cheap hash function for all janet objects. If two values are strictly equal, " "as a cheap hash function for all janet objects. If two values are strictly equal, "
@ -425,7 +425,8 @@ static void janet_quick_asm(
int32_t arity, int32_t 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) {
JanetFuncDef *def = janet_funcdef_alloc(); JanetFuncDef *def = janet_funcdef_alloc();
def->arity = arity; def->arity = arity;
def->flags = flags; def->flags = flags;
@ -437,7 +438,7 @@ static void janet_quick_asm(
JANET_OUT_OF_MEMORY; JANET_OUT_OF_MEMORY;
} }
memcpy(def->bytecode, bytecode, bytecode_size); memcpy(def->bytecode, bytecode, bytecode_size);
janet_def(env, name, janet_wrap_function(janet_thunk(def)), NULL); janet_def(env, name, janet_wrap_function(janet_thunk(def)), doc);
} }
/* Macros for easier inline janet assembly */ /* Macros for easier inline janet assembly */
@ -454,7 +455,8 @@ static void templatize_varop(
const char *name, const char *name,
int32_t nullary, int32_t nullary,
int32_t unary, int32_t unary,
uint32_t op) { uint32_t op,
const char *doc) {
/* Variadic operator assembly. Must be templatized for each different opcode. */ /* Variadic operator assembly. Must be templatized for each different opcode. */
/* Reg 0: Argument tuple (args) */ /* Reg 0: Argument tuple (args) */
@ -504,7 +506,8 @@ static void templatize_varop(
0, 0,
6, 6,
varop_asm, varop_asm,
sizeof(varop_asm)); sizeof(varop_asm),
doc);
} }
/* Templatize variadic comparators */ /* Templatize variadic comparators */
@ -513,7 +516,8 @@ static void templatize_comparator(
int32_t flags, int32_t flags,
const char *name, const char *name,
int invert, int invert,
uint32_t op) { uint32_t op,
const char *doc) {
/* Reg 0: Argument tuple (args) */ /* Reg 0: Argument tuple (args) */
/* Reg 1: Argument count (argn) */ /* Reg 1: Argument count (argn) */
@ -555,7 +559,8 @@ static void templatize_comparator(
0, 0,
6, 6,
comparator_asm, comparator_asm,
sizeof(comparator_asm)); sizeof(comparator_asm),
doc);
} }
/* Make the apply function */ /* Make the apply function */
@ -589,7 +594,14 @@ 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, 6, apply_asm, sizeof(apply_asm),
"(apply f & args)\n\n"
"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 "
"be an array-like. Each element in this last argument is then also pushed as an argument to "
"f. For example:\n\n"
"\t(apply + 1000 (range 10))\n\n"
"sums the first 10 integers and 1000.)");
} }
JanetTable *janet_core_env(void) { JanetTable *janet_core_env(void) {
@ -631,44 +643,132 @@ JanetTable *janet_core_env(void) {
/* Load main functions */ /* Load main functions */
janet_cfuns(env, NULL, cfuns); janet_cfuns(env, NULL, cfuns);
janet_quick_asm(env, JANET_FUN_YIELD, "debug", 0, 1, debug_asm, sizeof(debug_asm)); janet_quick_asm(env, JANET_FUN_YIELD, "debug", 0, 1, debug_asm, sizeof(debug_asm),
janet_quick_asm(env, JANET_FUN_ERROR, "error", 1, 1, error_asm, sizeof(error_asm)); "(debug)\n\n"
janet_quick_asm(env, JANET_FUN_YIELD, "yield", 1, 2, yield_asm, sizeof(yield_asm)); "Throws a debug signal that can be caught by a parent fiber and used to inspect "
janet_quick_asm(env, JANET_FUN_RESUME, "resume", 2, 2, resume_asm, sizeof(resume_asm)); "the running state of the current fiber. Returns nil.");
janet_quick_asm(env, JANET_FUN_GET, "get", 2, 2, get_asm, sizeof(get_asm)); janet_quick_asm(env, JANET_FUN_ERROR, "error", 1, 1, error_asm, sizeof(error_asm),
janet_quick_asm(env, JANET_FUN_PUT, "put", 3, 3, put_asm, sizeof(put_asm)); "(error e)\n\n"
janet_quick_asm(env, JANET_FUN_LENGTH, "length", 1, 1, length_asm, sizeof(length_asm)); "Throws an error e that can be caught and handled by a parent fiber.");
janet_quick_asm(env, JANET_FUN_BNOT, "~", 1, 1, bnot_asm, sizeof(bnot_asm)); janet_quick_asm(env, JANET_FUN_YIELD, "yield", 1, 2, yield_asm, sizeof(yield_asm),
"(yield x)\n\n"
"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 "
"return the value that was passed to resume.");
janet_quick_asm(env, JANET_FUN_RESUME, "resume", 2, 2, resume_asm, sizeof(resume_asm),
"(resume fiber [,x])\n\n"
"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 "
"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.");
janet_quick_asm(env, JANET_FUN_GET, "get", 2, 2, get_asm, sizeof(get_asm),
"(get ds key)\n\n"
"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 "
"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 "
"integer representations of bytes as result of a get call.");
janet_quick_asm(env, JANET_FUN_PUT, "put", 3, 3, put_asm, sizeof(put_asm),
"(put ds key value)\n\n"
"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 "
"value is provided. In an array, extra space will be filled with nils, and in a buffer, extra "
"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 "
"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, "length", 1, 1, length_asm, sizeof(length_asm),
"(length ds)\n\n"
"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.");
janet_quick_asm(env, JANET_FUN_BNOT, "~", 1, 1, bnot_asm, sizeof(bnot_asm),
"(~ x)\n\nReturns the bitwise inverse of integer x.");
make_apply(env); make_apply(env);
/* Variadic ops */ /* Variadic ops */
templatize_varop(env, JANET_FUN_ADD, "+", 0, 0, JOP_ADD); templatize_varop(env, JANET_FUN_ADD, "+", 0, 0, JOP_ADD,
templatize_varop(env, JANET_FUN_SUBTRACT, "-", 0, 0, JOP_SUBTRACT); "(+ & xs)\n\n"
templatize_varop(env, JANET_FUN_MULTIPLY, "*", 1, 1, JOP_MULTIPLY); "Returns the sum of all xs. xs must be integers or real numbers only. If xs is empty, return 0.");
templatize_varop(env, JANET_FUN_DIVIDE, "/", 1, 1, JOP_DIVIDE); templatize_varop(env, JANET_FUN_SUBTRACT, "-", 0, 0, JOP_SUBTRACT,
templatize_varop(env, JANET_FUN_BAND, "&", -1, -1, JOP_BAND); "(- & xs)\n\n"
templatize_varop(env, JANET_FUN_BOR, "|", 0, 0, JOP_BOR); "Returns the difference of xs. If xs is empty, returns 0. If xs has one element, returns the "
templatize_varop(env, JANET_FUN_BXOR, "^", 0, 0, JOP_BXOR); "negative value of that element. Otherwise, returns the first element in xs minus the sum of "
templatize_varop(env, JANET_FUN_LSHIFT, "<<", 1, 1, JOP_SHIFT_LEFT); "the rest of the elements.");
templatize_varop(env, JANET_FUN_RSHIFT, ">>", 1, 1, JOP_SHIFT_RIGHT); templatize_varop(env, JANET_FUN_MULTIPLY, "*", 1, 1, JOP_MULTIPLY,
templatize_varop(env, JANET_FUN_RSHIFTU, ">>>", 1, 1, JOP_SHIFT_RIGHT_UNSIGNED); "(* & xs)\n\n"
"Returns the product of all elements in xs. If xs is empty, returns 1.");
templatize_varop(env, JANET_FUN_DIVIDE, "/", 1, 1, JOP_DIVIDE,
"(/ & xs)\n\n"
"Returns the quotient of xs. If xs is empty, returns 1. If xs has one value x, returns "
"the reciprocal of x. Otherwise return the first value of xs repeatedly divided by the remaining "
"values. Division by two integers uses truncating division.");
templatize_varop(env, JANET_FUN_BAND, "&", -1, -1, JOP_BAND,
"(& & xs)\n\n"
"Returns the bitwise and of all values in xs. Each x in xs must be an integer.");
templatize_varop(env, JANET_FUN_BOR, "|", 0, 0, JOP_BOR,
"(| & xs)\n\n"
"Returns the bitwise or of all values in xs. Each x in xs must be an integer.");
templatize_varop(env, JANET_FUN_BXOR, "^", 0, 0, JOP_BXOR,
"(^ & xs)\n\n"
"Returns the bitwise xor of all values in xs. Each in xs must be an integer.");
templatize_varop(env, JANET_FUN_LSHIFT, "<<", 1, 1, JOP_SHIFT_LEFT,
"(<< x & shifts)\n\n"
"Returns the value of x bit shifted left by the sum of all values in shifts. x "
"and each element in shift must be an integer.");
templatize_varop(env, JANET_FUN_RSHIFT, ">>", 1, 1, JOP_SHIFT_RIGHT,
"(>> x & shifts)\n\n"
"Returns the value of x bit shifted right by the sum of all values in shifts. x "
"and each element in shift must be an integer.");
templatize_varop(env, JANET_FUN_RSHIFTU, ">>>", 1, 1, JOP_SHIFT_RIGHT_UNSIGNED,
"(>> x & shifts)\n\n"
"Returns the value of x bit shifted right by the sum of all values in shifts. x "
"and each element in shift must be an integer. The sign of x is not preserved, so "
"for positive shifts the return value will always be positive.");
/* Variadic comparators */ /* Variadic comparators */
templatize_comparator(env, JANET_FUN_ORDER_GT, "order>", 0, JOP_GREATER_THAN); templatize_comparator(env, JANET_FUN_ORDER_GT, "order>", 0, JOP_GREATER_THAN,
templatize_comparator(env, JANET_FUN_ORDER_LT, "order<", 0, JOP_LESS_THAN); "(order> & xs)\n\n"
templatize_comparator(env, JANET_FUN_ORDER_GTE, "order>=", 1, JOP_LESS_THAN); "Check if xs is strictly descending according to a total order "
templatize_comparator(env, JANET_FUN_ORDER_LTE, "order<=", 1, JOP_GREATER_THAN); "over all values. Returns a boolean.");
templatize_comparator(env, JANET_FUN_ORDER_EQ, "=", 0, JOP_EQUALS); templatize_comparator(env, JANET_FUN_ORDER_LT, "order<", 0, JOP_LESS_THAN,
templatize_comparator(env, JANET_FUN_ORDER_NEQ, "not=", 1, JOP_EQUALS); "(order< & xs)\n\n"
templatize_comparator(env, JANET_FUN_GT, ">", 0, JOP_NUMERIC_GREATER_THAN); "Check if xs is strictly increasing according to a total order "
templatize_comparator(env, JANET_FUN_LT, "<", 0, JOP_NUMERIC_LESS_THAN); "over all values. Returns a boolean.");
templatize_comparator(env, JANET_FUN_GTE, ">=", 0, JOP_NUMERIC_GREATER_THAN_EQUAL); templatize_comparator(env, JANET_FUN_ORDER_GTE, "order>=", 1, JOP_LESS_THAN,
templatize_comparator(env, JANET_FUN_LTE, "<=", 0, JOP_NUMERIC_LESS_THAN_EQUAL); "(order>= & xs)\n\n"
templatize_comparator(env, JANET_FUN_EQ, "==", 0, JOP_NUMERIC_EQUAL); "Check if xs is not increasing according to a total order "
templatize_comparator(env, JANET_FUN_NEQ, "not==", 1, JOP_NUMERIC_EQUAL); "over all values. Returns a boolean.");
templatize_comparator(env, JANET_FUN_ORDER_LTE, "order<=", 1, JOP_GREATER_THAN,
"(order<= & xs)\n\n"
"Check if xs is not decreasing according to a total order "
"over all values. Returns a boolean.");
templatize_comparator(env, JANET_FUN_ORDER_EQ, "=", 0, JOP_EQUALS,
"(= & xs)\n\n"
"Returns true if all values in xs are the same, false otherwise.");
templatize_comparator(env, JANET_FUN_ORDER_NEQ, "not=", 1, JOP_EQUALS,
"(not= & xs)\n\n"
"Return true if any values in xs are not equal, otherwise false.");
templatize_comparator(env, JANET_FUN_GT, ">", 0, JOP_NUMERIC_GREATER_THAN,
"(> & xs)\n\n"
"Check if xs is in numerically descending order. Returns a boolean.");
templatize_comparator(env, JANET_FUN_LT, "<", 0, JOP_NUMERIC_LESS_THAN,
"(< & xs)\n\n"
"Check if xs is in numerically ascending order. Returns a boolean.");
templatize_comparator(env, JANET_FUN_GTE, ">=", 0, JOP_NUMERIC_GREATER_THAN_EQUAL,
"(>= & xs)\n\n"
"Check if xs is in numerically non-ascending order. Returns a boolean.");
templatize_comparator(env, JANET_FUN_LTE, "<=", 0, JOP_NUMERIC_LESS_THAN_EQUAL,
"(<= & xs)\n\n"
"Check if xs is in numerically non-descending order. Returns a boolean.");
templatize_comparator(env, JANET_FUN_EQ, "==", 0, JOP_NUMERIC_EQUAL,
"(== & xs)\n\n"
"Check if all values in xs are numerically equal (4.0 == 4). Returns a boolean.");
templatize_comparator(env, JANET_FUN_NEQ, "not==", 1, JOP_NUMERIC_EQUAL,
"(not== & xs)\n\n"
"Check if any values in xs are not numerically equal (3.0 not== 4). Returns a boolean.");
/* Platform detection */ /* Platform detection */
janet_def(env, "janet.version", janet_cstringv(JANET_VERSION), NULL); janet_def(env, "janet.version", janet_cstringv(JANET_VERSION),
"The version number of the running janet program.");
/* Set as gc root */ /* Set as gc root */
janet_gcroot(janet_wrap_table(env)); janet_gcroot(janet_wrap_table(env));
@ -697,7 +797,7 @@ JanetTable *janet_core_env(void) {
} }
/* Allow references to the environment */ /* Allow references to the environment */
janet_def(env, "_env", ret, NULL); janet_def(env, "_env", ret, "The environment table for the current scope.");
/* Run bootstrap source */ /* Run bootstrap source */
janet_dobytes(env, janet_gen_core, sizeof(janet_gen_core), "core.janet", NULL); janet_dobytes(env, janet_gen_core, sizeof(janet_gen_core), "core.janet", NULL);

View File

@ -162,8 +162,8 @@ static void janetc_moveback(JanetCompiler *c,
/* Call this to release a register after emitting the instruction. */ /* Call this to release a register after emitting the instruction. */
static void janetc_free_regnear(JanetCompiler *c, JanetSlot s, int32_t reg, JanetcRegisterTemp tag) { static void janetc_free_regnear(JanetCompiler *c, JanetSlot s, int32_t reg, JanetcRegisterTemp tag) {
if (reg != s.index || if (reg != s.index ||
s.envindex >= 0 || s.envindex >= 0 ||
s.flags & (JANET_SLOT_CONSTANT | JANET_SLOT_REF)) { s.flags & (JANET_SLOT_CONSTANT | JANET_SLOT_REF)) {
/* We need to free the temporary slot */ /* We need to free the temporary slot */
janetc_regalloc_freetemp(&c->scope->ra, reg, tag); janetc_regalloc_freetemp(&c->scope->ra, reg, tag);

View File

@ -265,7 +265,7 @@ void janet_fiber_cframe(JanetFiber *fiber, JanetCFunction cfun) {
void janet_fiber_popframe(JanetFiber *fiber) { void janet_fiber_popframe(JanetFiber *fiber) {
JanetStackFrame *frame = janet_fiber_frame(fiber); JanetStackFrame *frame = janet_fiber_frame(fiber);
if (fiber->frame == 0) return; if (fiber->frame == 0) return;
/* Clean up the frame (detach environments) */ /* Clean up the frame (detach environments) */
if (NULL != frame->func) if (NULL != frame->func)
janet_env_detach(frame->env); janet_env_detach(frame->env);
@ -305,7 +305,7 @@ static int cfun_new(JanetArgs args) {
case ':': case ':':
break; break;
case 'a': case 'a':
fiber->flags |= fiber->flags |=
JANET_FIBER_MASK_DEBUG | JANET_FIBER_MASK_DEBUG |
JANET_FIBER_MASK_ERROR | JANET_FIBER_MASK_ERROR |
JANET_FIBER_MASK_USER | JANET_FIBER_MASK_USER |
@ -455,7 +455,7 @@ static int cfun_setmaxstack(JanetArgs args) {
} }
static const JanetReg cfuns[] = { static const JanetReg cfuns[] = {
{"fiber.new", cfun_new, {"fiber.new", cfun_new,
"(fiber.new func [,sigmask])\n\n" "(fiber.new func [,sigmask])\n\n"
"Create a new fiber with function body func. Can optionally " "Create a new fiber with function body func. Can optionally "
"take a set of signals to block from the current parent fiber " "take a set of signals to block from the current parent fiber "
@ -472,7 +472,7 @@ static const JanetReg cfuns[] = {
"\ty - block yield signals\n" "\ty - block yield signals\n"
"\t0-9 - block a specific user signal" "\t0-9 - block a specific user signal"
}, },
{"fiber.status", cfun_status, {"fiber.status", cfun_status,
"(fiber.status fib)\n\n" "(fiber.status fib)\n\n"
"Get the status of a fiber. The status will be one of:\n\n" "Get the status of a fiber. The status will be one of:\n\n"
"\t:dead - the fiber has finished\n" "\t:dead - the fiber has finished\n"
@ -483,7 +483,7 @@ static const JanetReg cfuns[] = {
"\t:alive - the fiber is currently running and cannot be resumed\n" "\t:alive - the fiber is currently running and cannot be resumed\n"
"\t:new - the fiber has just been created and not yet run" "\t:new - the fiber has just been created and not yet run"
}, },
{"fiber.stack", cfun_stack, {"fiber.stack", cfun_stack,
"(fiber.stack fib)\n\n" "(fiber.stack fib)\n\n"
"Gets information about the stack as an array of tables. Each table " "Gets information about the stack as an array of tables. Each table "
"in the array contains information about a stack frame. The top most, current " "in the array contains information about a stack frame. The top most, current "
@ -498,24 +498,24 @@ static const JanetReg cfuns[] = {
"\t:source - string with filename or other identifier for the source code\n" "\t:source - string with filename or other identifier for the source code\n"
"\t:tail - boolean indicating a tail call" "\t:tail - boolean indicating a tail call"
}, },
{"fiber.current", cfun_current, {"fiber.current", cfun_current,
"(fiber.current)\n\n" "(fiber.current)\n\n"
"Returns the currently running fiber." "Returns the currently running fiber."
}, },
{"fiber.lineage", cfun_lineage, {"fiber.lineage", cfun_lineage,
"(fiber.lineage fib)\n\n" "(fiber.lineage fib)\n\n"
"Returns an array of all child fibers from a root fiber. This function " "Returns an array of all child fibers from a root fiber. This function "
"is useful when a fiber signals or errors to an ancestor fiber. Using this function, " "is useful when a fiber signals or errors to an ancestor fiber. Using this function, "
"the fiber handling the error can see which fiber raised the signal. This function should " "the fiber handling the error can see which fiber raised the signal. This function should "
"be used mostly for debugging purposes." "be used mostly for debugging purposes."
}, },
{"fiber.maxstack", cfun_maxstack, {"fiber.maxstack", cfun_maxstack,
"(fiber.maxstack fib)\n\n" "(fiber.maxstack fib)\n\n"
"Gets the maximum stack size in janet values allowed for a fiber. While memory for " "Gets the maximum stack size in janet values allowed for a fiber. While memory for "
"the fiber's stack is not allocated up front, the fiber will not allocated more " "the fiber's stack is not allocated up front, the fiber will not allocated more "
"than this amount and will throw a stackoverflow error if more memory is needed. " "than this amount and will throw a stackoverflow error if more memory is needed. "
}, },
{"fiber.setmaxstack", cfun_setmaxstack, {"fiber.setmaxstack", cfun_setmaxstack,
"(fiber.setmaxstack fib maxstack)\n\n" "(fiber.setmaxstack fib maxstack)\n\n"
"Sets the maximum stack size in janet values for a fiber. By default, the " "Sets the maximum stack size in janet values for a fiber. By default, the "
"maximum stacksize is usually 8192." "maximum stacksize is usually 8192."

View File

@ -207,11 +207,11 @@ static const char *read_chunk(IOFile *iof, JanetBuffer *buffer, int32_t nBytesMa
if (!(iof->flags & (IO_READ | IO_UPDATE))) if (!(iof->flags & (IO_READ | IO_UPDATE)))
return "file is not readable"; return "file is not readable";
/* Ensure buffer size */ /* Ensure buffer size */
if (janet_buffer_extra(buffer, nBytesMax)) if (janet_buffer_extra(buffer, nBytesMax))
return "buffer overflow"; return "buffer overflow";
size_t ntoread = nBytesMax; size_t ntoread = nBytesMax;
size_t nread = fread((char *)(buffer->data + buffer->count), 1, ntoread, iof->file); size_t nread = fread((char *)(buffer->data + buffer->count), 1, ntoread, iof->file);
if (nread != ntoread && ferror(iof->file)) if (nread != ntoread && ferror(iof->file))
return "could not read file"; return "could not read file";
buffer->count += (int32_t) nread; buffer->count += (int32_t) nread;
return NULL; return NULL;
@ -366,7 +366,7 @@ static int janet_io_fseek(JanetArgs args) {
} }
static const JanetReg cfuns[] = { static const JanetReg cfuns[] = {
{"file.open", janet_io_fopen, {"file.open", janet_io_fopen,
"(file.open path [,mode])\n\n" "(file.open path [,mode])\n\n"
"Open a file. path is files absolute or relative path, and " "Open a file. path is files absolute or relative path, and "
"mode is a set of flags indicating the mode to open the file in. " "mode is a set of flags indicating the mode to open the file in. "
@ -379,13 +379,13 @@ static const JanetReg cfuns[] = {
"\tb - open the file in binary mode (rather than text mode)\n" "\tb - open the file in binary mode (rather than text mode)\n"
"\t+ - append to the file instead of overwriting it" "\t+ - append to the file instead of overwriting it"
}, },
{"file.close", janet_io_fclose, {"file.close", janet_io_fclose,
"(file.close f)\n\n" "(file.close f)\n\n"
"Close a file and release all related resources. When you are " "Close a file and release all related resources. When you are "
"done reading a file, close it to prevent a resource leak and let " "done reading a file, close it to prevent a resource leak and let "
"other processes read the file." "other processes read the file."
}, },
{"file.read", janet_io_fread, {"file.read", janet_io_fread,
"(file.read f what [,buf])\n\n" "(file.read f what [,buf])\n\n"
"Read a number of bytes from a file into a buffer. A buffer can " "Read a number of bytes from a file into a buffer. A buffer can "
"be provided as an optional fourth argument. otherwise a new buffer " "be provided as an optional fourth argument. otherwise a new buffer "
@ -396,17 +396,17 @@ static const JanetReg cfuns[] = {
"\t:line - read up to and including the next newline character\n" "\t:line - read up to and including the next newline character\n"
"\tn (integer) - read up to n bytes from the file" "\tn (integer) - read up to n bytes from the file"
}, },
{"file.write", janet_io_fwrite, {"file.write", janet_io_fwrite,
"(file.write f bytes)\n\n" "(file.write f bytes)\n\n"
"Writes to a file. 'bytes' must be string, buffer, or symbol. Returns the " "Writes to a file. 'bytes' must be string, buffer, or symbol. Returns the "
"file" "file"
}, },
{"file.flush", janet_io_fflush, {"file.flush", janet_io_fflush,
"(file.flush f)\n\n" "(file.flush f)\n\n"
"Flush any buffered bytes to the filesystem. In most files, writes are " "Flush any buffered bytes to the filesystem. In most files, writes are "
"buffered for efficiency reasons. Returns the file handle." "buffered for efficiency reasons. Returns the file handle."
}, },
{"file.seek", janet_io_fseek, {"file.seek", janet_io_fseek,
"(file.seek f [,whence [,n]])\n\n" "(file.seek f [,whence [,n]])\n\n"
"Jump to a relative location in the file. 'whence' must be one of\n\n" "Jump to a relative location in the file. 'whence' must be one of\n\n"
"\t:cur - jump relative to the current file location\n" "\t:cur - jump relative to the current file location\n"
@ -416,7 +416,7 @@ static const JanetReg cfuns[] = {
"for the relative number of bytes to seek in the file. n may be a real " "for the relative number of bytes to seek in the file. n may be a real "
"number to handle large files of more the 4GB. Returns the file handle." "number to handle large files of more the 4GB. Returns the file handle."
}, },
{"file.popen", janet_io_popen, {"file.popen", janet_io_popen,
"(file.popen path [,mode])\n\n" "(file.popen path [,mode])\n\n"
"Open a file that is backed by a process. The file must be opened in either " "Open a file that is backed by a process. The file must be opened in either "
"the :r (read) or the :w (write) mode. In :r mode, the stdout of the " "the :r (read) or the :w (write) mode. In :r mode, the stdout of the "
@ -433,7 +433,7 @@ int janet_lib_io(JanetArgs args) {
/* stdout */ /* stdout */
janet_def(env, "stdout", janet_def(env, "stdout",
makef(stdout, IO_APPEND | IO_NOT_CLOSEABLE | IO_SERIALIZABLE), makef(stdout, IO_APPEND | IO_NOT_CLOSEABLE | IO_SERIALIZABLE),
"The standard output file."); "The standard output file.");

View File

@ -206,11 +206,11 @@ static void marshal_one_def(MarshalState *st, JanetFuncDef *def, int flags) {
marshal_one(st, janet_wrap_string(def->name), flags); marshal_one(st, janet_wrap_string(def->name), flags);
if (def->flags & JANET_FUNCDEF_FLAG_HASSOURCE) if (def->flags & JANET_FUNCDEF_FLAG_HASSOURCE)
marshal_one(st, janet_wrap_string(def->source), flags); marshal_one(st, janet_wrap_string(def->source), flags);
/* marshal constants */ /* marshal constants */
for (int32_t i = 0; i < def->constants_length; i++) for (int32_t i = 0; i < def->constants_length; i++)
marshal_one(st, def->constants[i], flags); marshal_one(st, def->constants[i], flags);
/* marshal the bytecode */ /* marshal the bytecode */
for (int32_t i = 0; i < def->bytecode_length; i++) { for (int32_t i = 0; i < def->bytecode_length; i++) {
pushbyte(st, def->bytecode[i] & 0xFF); pushbyte(st, def->bytecode[i] & 0xFF);
@ -218,11 +218,11 @@ static void marshal_one_def(MarshalState *st, JanetFuncDef *def, int flags) {
pushbyte(st, (def->bytecode[i] >> 16) & 0xFF); pushbyte(st, (def->bytecode[i] >> 16) & 0xFF);
pushbyte(st, (def->bytecode[i] >> 24) & 0xFF); pushbyte(st, (def->bytecode[i] >> 24) & 0xFF);
} }
/* marshal the environments if needed */ /* marshal the environments if needed */
for (int32_t i = 0; i < def->environments_length; i++) for (int32_t i = 0; i < def->environments_length; i++)
pushint(st, def->environments[i]); pushint(st, def->environments[i]);
/* marshal the sub funcdefs if needed */ /* marshal the sub funcdefs if needed */
for (int32_t i = 0; i < def->defs_length; i++) for (int32_t i = 0; i < def->defs_length; i++)
marshal_one_def(st, def->defs[i], flags); marshal_one_def(st, def->defs[i], flags);
@ -457,7 +457,7 @@ done:
nyi: nyi:
longjmp(st->err, MR_NYI); longjmp(st->err, MR_NYI);
noregval: noregval:
longjmp(st->err, MR_NRV); longjmp(st->err, MR_NRV);
} }
@ -469,7 +469,7 @@ int janet_marshal(
JanetTable *rreg, JanetTable *rreg,
int flags) { int flags) {
int status; int status;
MarshalState st; MarshalState st;
st.buf = buf; st.buf = buf;
st.nextid = 0; st.nextid = 0;
st.seen_defs = NULL; st.seen_defs = NULL;
@ -641,7 +641,7 @@ static const uint8_t *unmarshal_one_def(
int32_t constants_length = 0; int32_t constants_length = 0;
int32_t environments_length = 0; int32_t environments_length = 0;
int32_t defs_length = 0; int32_t defs_length = 0;
/* Read flags and other fixed values */ /* Read flags and other fixed values */
def->flags = readint(st, &data); def->flags = readint(st, &data);
def->slotcount = readint(st, &data); def->slotcount = readint(st, &data);
@ -668,7 +668,7 @@ static const uint8_t *unmarshal_one_def(
if (!janet_checktype(x, JANET_STRING)) longjmp(st->err, UMR_EXPECTED_STRING); if (!janet_checktype(x, JANET_STRING)) longjmp(st->err, UMR_EXPECTED_STRING);
def->source = janet_unwrap_string(x); def->source = janet_unwrap_string(x);
} }
/* Unmarshal constants */ /* Unmarshal constants */
if (constants_length) { if (constants_length) {
def->constants = malloc(sizeof(Janet) * constants_length); def->constants = malloc(sizeof(Janet) * constants_length);
@ -681,7 +681,7 @@ static const uint8_t *unmarshal_one_def(
def->constants = NULL; def->constants = NULL;
} }
def->constants_length = constants_length; def->constants_length = constants_length;
/* Unmarshal bytecode */ /* Unmarshal bytecode */
def->bytecode = malloc(sizeof(uint32_t) * bytecode_length); def->bytecode = malloc(sizeof(uint32_t) * bytecode_length);
if (!def->bytecode) { if (!def->bytecode) {
@ -689,7 +689,7 @@ static const uint8_t *unmarshal_one_def(
} }
for (int32_t i = 0; i < bytecode_length; i++) { for (int32_t i = 0; i < bytecode_length; i++) {
if (data + 4 > end) longjmp(st->err, UMR_EOS); if (data + 4 > end) longjmp(st->err, UMR_EOS);
def->bytecode[i] = def->bytecode[i] =
(uint32_t)(data[0]) | (uint32_t)(data[0]) |
((uint32_t)(data[1]) << 8) | ((uint32_t)(data[1]) << 8) |
((uint32_t)(data[2]) << 16) | ((uint32_t)(data[2]) << 16) |
@ -697,7 +697,7 @@ static const uint8_t *unmarshal_one_def(
data += 4; data += 4;
} }
def->bytecode_length = bytecode_length; def->bytecode_length = bytecode_length;
/* Unmarshal environments */ /* Unmarshal environments */
if (def->flags & JANET_FUNCDEF_FLAG_HASENVS) { if (def->flags & JANET_FUNCDEF_FLAG_HASENVS) {
def->environments = calloc(1, sizeof(int32_t) * environments_length); def->environments = calloc(1, sizeof(int32_t) * environments_length);
@ -711,7 +711,7 @@ static const uint8_t *unmarshal_one_def(
def->environments = NULL; def->environments = NULL;
} }
def->environments_length = environments_length; def->environments_length = environments_length;
/* Unmarshal sub funcdefs */ /* Unmarshal sub funcdefs */
if (def->flags & JANET_FUNCDEF_FLAG_HASDEFS) { if (def->flags & JANET_FUNCDEF_FLAG_HASDEFS) {
def->defs = calloc(1, sizeof(JanetFuncDef *) * defs_length); def->defs = calloc(1, sizeof(JanetFuncDef *) * defs_length);
@ -719,13 +719,13 @@ static const uint8_t *unmarshal_one_def(
JANET_OUT_OF_MEMORY; JANET_OUT_OF_MEMORY;
} }
for (int32_t i = 0; i < defs_length; i++) { for (int32_t i = 0; i < defs_length; i++) {
data = unmarshal_one_def(st, data, def->defs + i, flags + 1); data = unmarshal_one_def(st, data, def->defs + i, flags + 1);
} }
} else { } else {
def->defs = NULL; def->defs = NULL;
} }
def->defs_length = defs_length; def->defs_length = defs_length;
/* Unmarshal source maps if needed */ /* Unmarshal source maps if needed */
if (def->flags & JANET_FUNCDEF_FLAG_HASSOURCEMAP) { if (def->flags & JANET_FUNCDEF_FLAG_HASSOURCEMAP) {
def->sourcemap = malloc(sizeof(JanetSourceMapping) * bytecode_length); def->sourcemap = malloc(sizeof(JanetSourceMapping) * bytecode_length);
@ -738,11 +738,11 @@ static const uint8_t *unmarshal_one_def(
} }
} else { } else {
def->sourcemap = NULL; def->sourcemap = NULL;
} }
/* Validate */ /* Validate */
if (janet_verify(def)) longjmp(st->err, UMR_INVALID_BYTECODE); if (janet_verify(def)) longjmp(st->err, UMR_INVALID_BYTECODE);
/* Set def */ /* Set def */
*out = def; *out = def;
} }
@ -1061,14 +1061,14 @@ static const uint8_t *unmarshal_one(
int janet_unmarshal( int janet_unmarshal(
const uint8_t *bytes, const uint8_t *bytes,
size_t len, size_t len,
int flags, int flags,
Janet *out, Janet *out,
JanetTable *reg, JanetTable *reg,
const uint8_t **next) { const uint8_t **next) {
int status; int status;
/* Avoid longjmp clobber warning in GCC */ /* Avoid longjmp clobber warning in GCC */
UnmarshalState st; UnmarshalState st;
st.end = bytes + len; st.end = bytes + len;
st.lookup_defs = NULL; st.lookup_defs = NULL;
st.lookup_envs = NULL; st.lookup_envs = NULL;
@ -1144,7 +1144,7 @@ static int cfun_unmarshal(JanetArgs args) {
} }
static const JanetReg cfuns[] = { static const JanetReg cfuns[] = {
{"marshal", cfun_marshal, {"marshal", cfun_marshal,
"(marshal x [,reverse-lookup [,buffer]])\n\n" "(marshal x [,reverse-lookup [,buffer]])\n\n"
"Marshal a janet value into a buffer and return the buffer. The buffer " "Marshal a janet value into a buffer and return the buffer. The buffer "
"can the later be unmarshalled to reconstruct the initial value. " "can the later be unmarshalled to reconstruct the initial value. "
@ -1153,13 +1153,13 @@ static const JanetReg cfuns[] = {
"lookup table can be used to recover the origrinal janet value when " "lookup table can be used to recover the origrinal janet value when "
"unmarshaling." "unmarshaling."
}, },
{"unmarshal", cfun_unmarshal, {"unmarshal", cfun_unmarshal,
"(unmarshal buffer [,lookup])\n\n" "(unmarshal buffer [,lookup])\n\n"
"Unmarshal a janet value from a buffer. An optional lookup table " "Unmarshal a janet value from a buffer. An optional lookup table "
"can be provided to allow for aliases to be resolved. Returns the value " "can be provided to allow for aliases to be resolved. Returns the value "
"unmarshaled from the buffer." "unmarshaled from the buffer."
}, },
{"env-lookup", cfun_env_lookup, {"env-lookup", cfun_env_lookup,
"(env-lookup env)\n\n" "(env-lookup env)\n\n"
"Creates a forward lookup table for unmarshaling from an environment. " "Creates a forward lookup table for unmarshaling from an environment. "
"To create a reverse lookup table, use the invert function to swap keys " "To create a reverse lookup table, use the invert function to swap keys "

View File

@ -90,7 +90,7 @@ static int os_execute(JanetArgs args) {
si.cb = sizeof(si); si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi)); ZeroMemory(&pi, sizeof(pi));
// Start the child process. // Start the child process.
if(!CreateProcess(NULL, if(!CreateProcess(NULL,
(LPSTR) sys_str, (LPSTR) sys_str,
NULL, NULL,
@ -234,7 +234,7 @@ static int gettime(struct timespec *spec) {
spec->tv_nsec = mts.tv_nsec; spec->tv_nsec = mts.tv_nsec;
return 0; return 0;
} }
#else #else
#define gettime(TV) clock_gettime(CLOCK_MONOTONIC, (TV)) #define gettime(TV) clock_gettime(CLOCK_MONOTONIC, (TV))
#endif #endif
@ -283,52 +283,52 @@ static int os_cwd(JanetArgs args) {
} }
static const JanetReg cfuns[] = { static const JanetReg cfuns[] = {
{"os.which", os_which, {"os.which", os_which,
"(os.which)\n\n" "(os.which)\n\n"
"Check the current operating system. Returns one of:\n\n" "Check the current operating system. Returns one of:\n\n"
"\t:windows - Microsoft Windows\n" "\t:windows - Microsoft Windows\n"
"\t:macos - Apple macos\n" "\t:macos - Apple macos\n"
"\t:posix - A POSIX compatible system (default)" "\t:posix - A POSIX compatible system (default)"
}, },
{"os.execute", os_execute, {"os.execute", os_execute,
"(os.execute program & args)\n\n" "(os.execute program & args)\n\n"
"Execute a program on the system and pass it string arguments. Returns " "Execute a program on the system and pass it string arguments. Returns "
"the exit status of the program." "the exit status of the program."
}, },
{"os.shell", os_shell, {"os.shell", os_shell,
"(os.shell str)\n\n" "(os.shell str)\n\n"
"Pass a command string str directly to the system shell." "Pass a command string str directly to the system shell."
}, },
{"os.exit", os_exit, {"os.exit", os_exit,
"(os.exit x)\n\n" "(os.exit x)\n\n"
"Exit from janet with an exit code equal to x. If x is not an integer, " "Exit from janet with an exit code equal to x. If x is not an integer, "
"the exit with status equal the hash of x." "the exit with status equal the hash of x."
}, },
{"os.getenv", os_getenv, {"os.getenv", os_getenv,
"(os.getenv variable)\n\n" "(os.getenv variable)\n\n"
"Get the string value of an environment variable." "Get the string value of an environment variable."
}, },
{"os.setenv", os_setenv, {"os.setenv", os_setenv,
"(os.setenv variable value)\n\n" "(os.setenv variable value)\n\n"
"Set an environment variable." "Set an environment variable."
}, },
{"os.time", os_time, {"os.time", os_time,
"(os.time)\n\n" "(os.time)\n\n"
"Get the current time expressed as the number of seconds since " "Get the current time expressed as the number of seconds since "
"January 1, 1970, the Unix epoch. Returns a real number." "January 1, 1970, the Unix epoch. Returns a real number."
}, },
{"os.clock", os_clock, {"os.clock", os_clock,
"(os.clock)\n\n" "(os.clock)\n\n"
"Return the number of seconds since some fixed point in time. The clock " "Return the number of seconds since some fixed point in time. The clock "
"is guaranteed to be non decreased in real time." "is guaranteed to be non decreased in real time."
}, },
{"os.sleep", os_sleep, {"os.sleep", os_sleep,
"(os.sleep nsec)\n\n" "(os.sleep nsec)\n\n"
"Suspend the program for nsec seconds. 'nsec' can be a real number. Returns " "Suspend the program for nsec seconds. 'nsec' can be a real number. Returns "
"nil." "nil."
}, },
{"os.cwd", os_cwd, {"os.cwd", os_cwd,
"(os.cwd)\n\n" "(os.cwd)\n\n"
"Returns the current working directory." "Returns the current working directory."
}, },

View File

@ -32,7 +32,7 @@ static Janet quote(Janet x) {
/* Check if a character is whitespace */ /* Check if a character is whitespace */
static int is_whitespace(uint8_t c) { static int is_whitespace(uint8_t c) {
return c == ' ' return c == ' '
|| c == '\t' || c == '\t'
|| c == '\n' || c == '\n'
|| c == '\r' || c == '\r'
@ -42,7 +42,7 @@ static int is_whitespace(uint8_t c) {
|| c == ','; || c == ',';
} }
/* Code generated by tools/symcharsgen.c. /* Code generated by tools/symcharsgen.c.
* The table contains 256 bits, where each bit is 1 * The table contains 256 bits, where each bit is 1
* if the corresponding ascci code is a symbol char, and 0 * if the corresponding ascci code is a symbol char, and 0
* if not. The upper characters are also considered symbol * if not. The upper characters are also considered symbol
@ -84,7 +84,7 @@ static int valid_utf8(const uint8_t *str, int32_t len) {
if ((str[j] >> 6) != 2) return 0; if ((str[j] >> 6) != 2) return 0;
} }
/* Check for overlong encodings */ /* Check for overlong encodings */
if ((nexti == i + 2) && str[i] < 0xC2) return 0; if ((nexti == i + 2) && str[i] < 0xC2) return 0;
if ((str[i] == 0xE0) && str[i + 1] < 0xA0) return 0; if ((str[i] == 0xE0) && str[i + 1] < 0xA0) return 0;
if ((str[i] == 0xF0) && str[i + 1] < 0x90) return 0; if ((str[i] == 0xF0) && str[i + 1] < 0x90) return 0;
@ -192,15 +192,15 @@ static int checkescape(uint8_t c) {
switch (c) { switch (c) {
default: return -1; default: return -1;
case 'x': return 1; case 'x': return 1;
case 'n': return '\n'; case 'n': return '\n';
case 't': return '\t'; case 't': return '\t';
case 'r': return '\r'; case 'r': return '\r';
case '0': return '\0'; case '0': return '\0';
case 'z': return '\0'; case 'z': return '\0';
case 'f': return '\f'; case 'f': return '\f';
case 'e': return 27; case 'e': return 27;
case '"': return '"'; case '"': return '"';
case '\\': return '\\'; case '\\': return '\\';
} }
} }
@ -774,15 +774,59 @@ static int cfun_state(JanetArgs args) {
} }
static const JanetReg cfuns[] = { static const JanetReg cfuns[] = {
{"parser.new", cfun_parser, NULL}, {"parser.new", cfun_parser,
{"parser.produce", cfun_produce, NULL}, "(parser.new)\n\n"
{"parser.consume", cfun_consume, NULL}, "Creates and returns a new parser object. Parsers are state machines "
{"parser.byte", cfun_byte, NULL}, "that can receive bytes, and generate a stream of janet values. "
{"parser.error", cfun_error, NULL}, },
{"parser.status", cfun_status, NULL}, {"parser.produce", cfun_produce,
{"parser.flush", cfun_flush, NULL}, "(parser.produce parser)\n\n"
{"parser.state", cfun_state, NULL}, "Dequeue the next value in the parse queue. Will return nil if "
{"parser.where", cfun_where, NULL}, "no parsed values are in the queue, otherwise will dequeue the "
"next value."
},
{"parser.consume", cfun_consume,
"(parser.consume parser bytes)\n\n"
"Input bytes into the parser and parse them. Will not throw errors "
"if there is a parse error. Returns the parser."
},
{"parser.byte", cfun_byte,
"(parser.byte parser b)\n\n"
"Input a single byte into the parser byte stream. Returns the parser."
},
{"parser.error", cfun_error,
"(parser.error parser)\n\n"
"If the parser is in the error state, returns the message asscoiated with "
"that error. Otherwise, returns nil."
},
{"parser.status", cfun_status,
"(parser.status parser)\n\n"
"Gets the current status of the parser state machine. The status will "
"be one of:\n\n"
"\t:full - there are values in the parse queue to be consumed.\n"
"\t:pending - no values in the queue but a value is being parsed.\n"
"\t:error - a parsing error was encountered.\n"
"\t:root - the parser can either read more values or safely terminate."
},
{"parser.flush", cfun_flush,
"(parser.flush parser)\n\n"
"Clears the parser state and parse queue. Can be used to reset the parser "
"if an error was encountered. Does not reset the line and column counter, so "
"to begin parsing in a new context, create a new parser."
},
{"parser.state", cfun_state,
"(parser.state parser)\n\n"
"Returns a string representation of the internal state of the parser. "
"Each byte in the string represents a nested data structure. For example, "
"if the parser state is '([\"', then the parser is in the middle of parsing a "
"string inside of square brackets inside parens. Can be used to augment a repl prompt."
},
{"parser.where", cfun_where,
"(parser.where parser)\n\n"
"Returns the current line number and column number of the parser's location "
"in the byte stream as a tuple (line, column). Lines and columns are counted from "
"1, (the first byte is line1, column 1) and a newline is considered ascii 0x0A."
},
{NULL, NULL, NULL} {NULL, NULL, NULL}
}; };

View File

@ -1040,21 +1040,97 @@ static int cfun_number(JanetArgs args) {
} }
static const JanetReg cfuns[] = { static const JanetReg cfuns[] = {
{"string.slice", cfun_slice, NULL}, {"string.slice", cfun_slice,
{"string.repeat", cfun_repeat, NULL}, "(string.slice bytes [,start=0 [,end=(length str)]])\n\n"
{"string.bytes", cfun_bytes, NULL}, "Returns a substring from a byte sequence. The substring is from "
{"string.from-bytes", cfun_frombytes, NULL}, "index start inclusive to index end exclusive. All indexing "
{"string.ascii-lower", cfun_asciilower, NULL}, "is from 0. 'start' and 'end' can also be negative to indicate indexing "
{"string.ascii-upper", cfun_asciiupper, NULL}, "from the end of the string."
{"string.reverse", cfun_reverse, NULL}, },
{"string.find", cfun_find, NULL}, {"string.repeat", cfun_repeat,
{"string.find-all", cfun_findall, NULL}, "(string.repeat bytes n)\n\n"
{"string.replace", cfun_replace, NULL}, "Returns a string that is n copies of bytes concatenated."
{"string.replace-all", cfun_replaceall, NULL}, },
{"string.split", cfun_split, NULL}, {"string.bytes", cfun_bytes,
{"string.check-set", cfun_checkset, NULL}, "(string.bytes str)\n\n"
{"string.join", cfun_join, NULL}, "Returns an array of integers that are the byte values of the string."
{"string.number", cfun_number, NULL}, },
{"string.from-bytes", cfun_frombytes,
"(string.from-bytes byte-array)\n\n"
"Creates a string from an array of integers with byte values. All integers "
"will be coerced to the range of 1 byte 0-255."
},
{"string.ascii-lower", cfun_asciilower,
"(string.ascii-lower str)\n\n"
"Returns a new string where all bytes are replaced with the "
"lowercase version of themselves in ascii. Does only a very simple "
"case check, meaning no unicode support."
},
{"string.ascii-upper", cfun_asciiupper,
"(string.ascii-upper str)\n\n"
"Returns a new string where all bytes are replaced with the "
"uppercase version of themselves in ascii. Does only a very simple "
"case check, meaning no unicode support."
},
{"string.reverse", cfun_reverse,
"(string.reverse str)\n\n"
"Returns a string that is the reversed version of str."
},
{"string.find", cfun_find,
"(string.find patt str)\n\n"
"Searches for the first instance of pattern patt in string "
"str. Returns the index of the first character in patt if found, "
"otherwise returns nil."
},
{"string.find-all", cfun_findall,
"(string.find patt str)\n\n"
"Searches for all instances of pattern patt in string "
"str. Returns an array of all indices of found patterns. Overlapping "
"instances of the pattern are not counted, meaning a byte in string "
"will only contribute to finding at most on occurrence of pattern. If no "
"occurrences are found, will return an empty array."
},
{"string.replace", cfun_replace,
"(string.replace patt subst str)\n\n"
"Replace the first occurrence of patt with subst in the the string str. "
"Will return the new string if patt is found, otherwise returns str."
},
{"string.replace-all", cfun_replaceall,
"(string.replace-all patt subst str)\n\n"
"Replace all instances of patt with subst in the string str. "
"Will return the new string if patt is found, otherwise returns str."
},
{"string.split", cfun_split,
"(string.split delim str)\n\n"
"Splits a string str with delimiter delim and returns an array of "
"substrings. The substrings will not contain the delimiter delim. If delim "
"is not found, the returned array will have one element."
},
{"string.check-set", cfun_checkset,
"(string.check-set set str)\n\n"
"Checks if any of the bytes in the string set appear in the string str. "
"Returns true if some bytes in set do appear in str, false if no bytes do."
},
{"string.join", cfun_join,
"(string.join parts [,sep])\n\n"
"Joins an array of strings into one string, optionally separated by "
"a separator string sep."
},
{"string.number", cfun_number,
"(string.number x [,format [,maxlen [,precision]]])\n\n"
"Formats a number as string. The format parameter indicates how "
"to display the number, either as floating point, scientific, or "
"whichever representation is shorter. format can be:\n\n"
"\t:g - (default) shortest representation with lowercase e.\n"
"\t:G - shortest representation with uppercase E.\n"
"\t:e - scientific with lowercase e.\n"
"\t:E - scientific with uppercase E.\n"
"\t:f - floating point representation.\n"
"\t:F - same as :f\n\n"
"The programmer can also specify the max length of the output string "
"and the precision (number of places after decimal) in the output number. "
"Returns a string representation of x."
},
{NULL, NULL, NULL} {NULL, NULL, NULL}
}; };

View File

@ -252,11 +252,33 @@ static int cfun_rawget(JanetArgs args) {
} }
static const JanetReg cfuns[] = { static const JanetReg cfuns[] = {
{"table.new", cfun_new, NULL}, {"table.new", cfun_new,
{"table.to-struct", cfun_tostruct, NULL}, "(table.new capacity)\n\n"
{"table.getproto", cfun_getproto, NULL}, "Creates a new empty table with pre-allocated memory "
{"table.setproto", cfun_setproto, NULL}, "for capacity entries. This means that if one knows the number of "
{"table.rawget", cfun_rawget, NULL}, "entries going to go in a table on creation, extra memory allocation "
"can be avoided. Returns the new table."
},
{"table.to-struct", cfun_tostruct,
"(table.to-struct tab)\n\n"
"Convert a table to a struct. Returns a new struct. This function "
"does not take into account prototype tables."
},
{"table.getproto", cfun_getproto,
"(table.getproto tab)\n\n"
"Get the prototype table of a table. Returns nil if a table "
"has no prototype, otherwise returns the prototype."
},
{"table.setproto", cfun_setproto,
"(table.setproto tab proto)\n\n"
"Set the prototype of a table. Returns the original table tab."
},
{"table.rawget", cfun_rawget,
"(table.rawget tab key)\n\n"
"Gets a value from a table without looking at the prototype table. "
"If a table tab does not contain t directly, the function will return "
"nil without checking the prototype. Returns the value in the table."
},
{NULL, NULL, NULL} {NULL, NULL, NULL}
}; };

View File

@ -127,13 +127,16 @@ static int cfun_slice(JanetArgs args) {
static int cfun_prepend(JanetArgs args) { static int cfun_prepend(JanetArgs args) {
const Janet *t; const Janet *t;
int32_t len; int32_t len, i;
Janet *n; Janet *n;
JANET_FIXARITY(args, 2); JANET_MINARITY(args, 1);
if (!janet_indexed_view(args.v[0], &t, &len)) JANET_THROW(args, "expected tuple/array"); if (!janet_indexed_view(args.v[0], &t, &len))
n = janet_tuple_begin(len + 1); JANET_THROW(args, "expected tuple/array");
memcpy(n + 1, t, sizeof(Janet) * len); n = janet_tuple_begin(len - 1 + args.n);
n[0] = args.v[1]; memcpy(n - 1 + args.n, t, sizeof(Janet) * len);
for (i = 1; i < args.n; i++) {
n[args.n - i - 1] = args.v[i];
}
JANET_RETURN_TUPLE(args, janet_tuple_end(n)); JANET_RETURN_TUPLE(args, janet_tuple_end(n));
} }
@ -141,18 +144,34 @@ static int cfun_append(JanetArgs args) {
const Janet *t; const Janet *t;
int32_t len; int32_t len;
Janet *n; Janet *n;
JANET_FIXARITY(args, 2); JANET_MINARITY(args, 1);
if (!janet_indexed_view(args.v[0], &t, &len)) JANET_THROW(args, "expected tuple/array"); if (!janet_indexed_view(args.v[0], &t, &len))
n = janet_tuple_begin(len + 1); JANET_THROW(args, "expected tuple/array");
n = janet_tuple_begin(len - 1 + args.n);
memcpy(n, t, sizeof(Janet) * len); memcpy(n, t, sizeof(Janet) * len);
n[len] = args.v[1]; memcpy(n + len, args.v + 1, sizeof(Janet) * (args.n - 1));
JANET_RETURN_TUPLE(args, janet_tuple_end(n)); JANET_RETURN_TUPLE(args, janet_tuple_end(n));
} }
static const JanetReg cfuns[] = { static const JanetReg cfuns[] = {
{"tuple.slice", cfun_slice, NULL}, {"tuple.slice", cfun_slice,
{"tuple.append", cfun_append, NULL}, "(tuple.slice arrtup [,start=0 [,end=(length arrtup)]])\n\n"
{"tuple.prepend", cfun_prepend, NULL}, "Take a sub sequence of an array or tuple from index start "
"inclusive to index end exclusive. If start or end are not provided, "
"they default to 0 and the length of arrtup respectively."
"Returns the new tuple."
},
{"tuple.append", cfun_append,
"(tuple.append tup & items)\n\n"
"Returns a new tuple that is the result of appending "
"each element in items to tup."
},
{"tuple.prepend", cfun_prepend,
"(tuple.prepend tup & items)\n\n"
"Prepends each element in items to tuple and "
"returns a new tuple. Items are prepended such that the "
"last element in items is the first element in the new tuple."
},
{NULL, NULL, NULL} {NULL, NULL, NULL}
}; };