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 */
def->environments =
realloc(def->environments, def->environments_length * sizeof(int32_t));
/* Verify the func def */
if (janet_verify(def)) {
janet_asm_error(&a, "invalid assembly");
@ -924,7 +924,7 @@ static int cfun_disasm(JanetArgs args) {
}
static const JanetReg cfuns[] = {
{"asm", cfun_asm,
{"asm", cfun_asm,
"(asm assembly)\n\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"

View File

@ -268,12 +268,12 @@ static int cfun_slice(JanetArgs args) {
}
static const JanetReg cfuns[] = {
{"buffer.new", cfun_new,
{"buffer.new", cfun_new,
"(buffer.new capacity)\n\n"
"Creates a new, empty buffer with enough memory for capacity bytes. "
"Returns a new buffer."
},
{"buffer.push-byte", cfun_u8,
{"buffer.push-byte", cfun_u8,
"(buffer.push-byte buffer x)\n\n"
"Append a byte to a buffer. Will expand the buffer as necessary. "
"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. "
"Will throw an error if the buffer overflows."
},
{"buffer.popn", cfun_popn,
{"buffer.popn", cfun_popn,
"(buffer.popn buffer n)\n\n"
"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"
"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."

View File

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

View File

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

View File

@ -1096,7 +1096,8 @@ value, one key will be ignored."
@[parent]
(def parent (if parent parent _env))
(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)
(defn run-context

View File

@ -284,105 +284,105 @@ static int janet_core_hash(JanetArgs args) {
}
static const JanetReg cfuns[] = {
{"native", janet_core_native,
{"native", janet_core_native,
"(native path)\n\n"
"Load a native module from the given path. The path "
"must be an absolute or relative path on the filesystem, and is "
"usually a .so file on unix systems, and a .dll file on Windows. "
"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. "
"Returns an environment table that contains functions and other values "
"from the native module."
},
{"print", janet_core_print,
{"print", janet_core_print,
"(print & xs)\n\n"
"Print values to the console (standard out). Value are converted "
"to strings if they are not already. After printing all values, a "
"newline character is printed. Returns nil."
},
{"describe", janet_core_describe,
{"describe", janet_core_describe,
"(describe x)\n\n"
"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"
"Creates a string by concatenating values together. Values are "
"converted to bytes via describe if they are not byte sequences. "
"Returns the new string."
},
{"symbol", janet_core_symbol,
{"symbol", janet_core_symbol,
"(symbol & xs)\n\n"
"Creates a symbol by concatenating values together. Values are "
"converted to bytes via describe if they are not byte sequences. Returns "
"the new symbol."
},
{"buffer", janet_core_buffer,
{"buffer", janet_core_buffer,
"(buffer & xs)\n\n"
"Creates a new buffer by concatenating values together. Values are "
"converted to bytes via describe if they are not byte sequences. Returns "
"the new symbol."
},
{"table", janet_core_table,
{"table", janet_core_table,
"(table & kvs)\n\n"
"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 "
"an odd number of elements, an error will be thrown. Returns the "
"new table."
},
{"array", janet_core_array,
{"array", janet_core_array,
"(array & items)\n\n"
"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"
"Parse a number from a byte sequence an return that number, either and integer "
"or a real. The number "
"must be in the same format as numbers in janet source code. Will return nil "
"on an invalid number."
},
{"scan-integer", janet_core_scaninteger,
{"scan-integer", janet_core_scaninteger,
"(scan-integer str)\n\n"
"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 "
"on an invalid integer."
},
{"scan-real", janet_core_scanreal,
{"scan-real", janet_core_scanreal,
"(scan-real str)\n\n"
"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 "
"on an invalid number."
},
{"tuple", janet_core_tuple,
{"tuple", janet_core_tuple,
"(tuple & items)\n\n"
"Creates a new tuple that contains items. Returns the new tuple."
},
{"struct", janet_core_struct,
{"struct", janet_core_struct,
"(struct & kvs)\n\n"
"Create a new struct from a sequence of key value pairs. "
"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 "
"new struct."
},
{"gensym", janet_core_gensym,
{"gensym", janet_core_gensym,
"(gensym)\n\n"
"Returns a new symbol that is unique across the runtime. This means it "
"will not collide with any already created symbols during compilation, so "
"it can be used in macros to generate automatic bindings."
},
{"gccollect", janet_core_gccollect,
{"gccollect", janet_core_gccollect,
"(gccollect)\n\n"
"Run garbage collection. You should probably not call this manually."
},
{"gcsetinterval", janet_core_gcsetinterval,
{"gcsetinterval", janet_core_gcsetinterval,
"(gcsetinterval interval)\n\n"
"Set an integer number of bytes to allocate before running garbage collection. "
"Low values interval will be slower but use less memory. "
"High values will be faster but use more memory."
},
{"gcinterval", janet_core_gcinterval,
{"gcinterval", janet_core_gcinterval,
"(gcinterval)\n\n"
"Returns the integer number of bytes to allocate before running an iteration "
"of garbage collection."
},
{"type", janet_core_type,
{"type", janet_core_type,
"(type x)\n\n"
"Returns the type of x as a keyword symbol. x is one of\n"
"\t:nil\n"
@ -400,7 +400,7 @@ static const JanetReg cfuns[] = {
"\t:function\n"
"\t:cfunction"
},
{"next", janet_core_next,
{"next", janet_core_next,
"(next dict key)\n\n"
"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 "
@ -408,7 +408,7 @@ static const JanetReg cfuns[] = {
"during iteration. If key is nil, next returns the first key. If next "
"returns nil, there are no more keys to iterate through. "
},
{"hash", janet_core_hash,
{"hash", janet_core_hash,
"(hash value)\n\n"
"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, "
@ -425,7 +425,8 @@ static void janet_quick_asm(
int32_t arity,
int32_t slots,
const uint32_t *bytecode,
size_t bytecode_size) {
size_t bytecode_size,
const char *doc) {
JanetFuncDef *def = janet_funcdef_alloc();
def->arity = arity;
def->flags = flags;
@ -437,7 +438,7 @@ static void janet_quick_asm(
JANET_OUT_OF_MEMORY;
}
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 */
@ -454,7 +455,8 @@ static void templatize_varop(
const char *name,
int32_t nullary,
int32_t unary,
uint32_t op) {
uint32_t op,
const char *doc) {
/* Variadic operator assembly. Must be templatized for each different opcode. */
/* Reg 0: Argument tuple (args) */
@ -504,7 +506,8 @@ static void templatize_varop(
0,
6,
varop_asm,
sizeof(varop_asm));
sizeof(varop_asm),
doc);
}
/* Templatize variadic comparators */
@ -513,7 +516,8 @@ static void templatize_comparator(
int32_t flags,
const char *name,
int invert,
uint32_t op) {
uint32_t op,
const char *doc) {
/* Reg 0: Argument tuple (args) */
/* Reg 1: Argument count (argn) */
@ -555,7 +559,8 @@ static void templatize_comparator(
0,
6,
comparator_asm,
sizeof(comparator_asm));
sizeof(comparator_asm),
doc);
}
/* Make the apply function */
@ -589,7 +594,14 @@ static void make_apply(JanetTable *env) {
S(JOP_TAILCALL, 0)
};
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) {
@ -631,44 +643,132 @@ JanetTable *janet_core_env(void) {
/* Load main functions */
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_ERROR, "error", 1, 1, error_asm, sizeof(error_asm));
janet_quick_asm(env, JANET_FUN_YIELD, "yield", 1, 2, yield_asm, sizeof(yield_asm));
janet_quick_asm(env, JANET_FUN_RESUME, "resume", 2, 2, resume_asm, sizeof(resume_asm));
janet_quick_asm(env, JANET_FUN_GET, "get", 2, 2, get_asm, sizeof(get_asm));
janet_quick_asm(env, JANET_FUN_PUT, "put", 3, 3, put_asm, sizeof(put_asm));
janet_quick_asm(env, JANET_FUN_LENGTH, "length", 1, 1, length_asm, sizeof(length_asm));
janet_quick_asm(env, JANET_FUN_BNOT, "~", 1, 1, bnot_asm, sizeof(bnot_asm));
janet_quick_asm(env, JANET_FUN_YIELD, "debug", 0, 1, debug_asm, sizeof(debug_asm),
"(debug)\n\n"
"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.");
janet_quick_asm(env, JANET_FUN_ERROR, "error", 1, 1, error_asm, sizeof(error_asm),
"(error e)\n\n"
"Throws an error e that can be caught and handled by a parent fiber.");
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);
/* Variadic ops */
templatize_varop(env, JANET_FUN_ADD, "+", 0, 0, JOP_ADD);
templatize_varop(env, JANET_FUN_SUBTRACT, "-", 0, 0, JOP_SUBTRACT);
templatize_varop(env, JANET_FUN_MULTIPLY, "*", 1, 1, JOP_MULTIPLY);
templatize_varop(env, JANET_FUN_DIVIDE, "/", 1, 1, JOP_DIVIDE);
templatize_varop(env, JANET_FUN_BAND, "&", -1, -1, JOP_BAND);
templatize_varop(env, JANET_FUN_BOR, "|", 0, 0, JOP_BOR);
templatize_varop(env, JANET_FUN_BXOR, "^", 0, 0, JOP_BXOR);
templatize_varop(env, JANET_FUN_LSHIFT, "<<", 1, 1, JOP_SHIFT_LEFT);
templatize_varop(env, JANET_FUN_RSHIFT, ">>", 1, 1, JOP_SHIFT_RIGHT);
templatize_varop(env, JANET_FUN_RSHIFTU, ">>>", 1, 1, JOP_SHIFT_RIGHT_UNSIGNED);
templatize_varop(env, JANET_FUN_ADD, "+", 0, 0, JOP_ADD,
"(+ & xs)\n\n"
"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_SUBTRACT, "-", 0, 0, JOP_SUBTRACT,
"(- & xs)\n\n"
"Returns the difference of xs. If xs is empty, returns 0. If xs has one element, returns the "
"negative value of that element. Otherwise, returns the first element in xs minus the sum of "
"the rest of the elements.");
templatize_varop(env, JANET_FUN_MULTIPLY, "*", 1, 1, JOP_MULTIPLY,
"(* & 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 */
templatize_comparator(env, JANET_FUN_ORDER_GT, "order>", 0, JOP_GREATER_THAN);
templatize_comparator(env, JANET_FUN_ORDER_LT, "order<", 0, JOP_LESS_THAN);
templatize_comparator(env, JANET_FUN_ORDER_GTE, "order>=", 1, JOP_LESS_THAN);
templatize_comparator(env, JANET_FUN_ORDER_LTE, "order<=", 1, JOP_GREATER_THAN);
templatize_comparator(env, JANET_FUN_ORDER_EQ, "=", 0, JOP_EQUALS);
templatize_comparator(env, JANET_FUN_ORDER_NEQ, "not=", 1, JOP_EQUALS);
templatize_comparator(env, JANET_FUN_GT, ">", 0, JOP_NUMERIC_GREATER_THAN);
templatize_comparator(env, JANET_FUN_LT, "<", 0, JOP_NUMERIC_LESS_THAN);
templatize_comparator(env, JANET_FUN_GTE, ">=", 0, JOP_NUMERIC_GREATER_THAN_EQUAL);
templatize_comparator(env, JANET_FUN_LTE, "<=", 0, JOP_NUMERIC_LESS_THAN_EQUAL);
templatize_comparator(env, JANET_FUN_EQ, "==", 0, JOP_NUMERIC_EQUAL);
templatize_comparator(env, JANET_FUN_NEQ, "not==", 1, JOP_NUMERIC_EQUAL);
templatize_comparator(env, JANET_FUN_ORDER_GT, "order>", 0, JOP_GREATER_THAN,
"(order> & xs)\n\n"
"Check if xs is strictly descending according to a total order "
"over all values. Returns a boolean.");
templatize_comparator(env, JANET_FUN_ORDER_LT, "order<", 0, JOP_LESS_THAN,
"(order< & xs)\n\n"
"Check if xs is strictly increasing according to a total order "
"over all values. Returns a boolean.");
templatize_comparator(env, JANET_FUN_ORDER_GTE, "order>=", 1, JOP_LESS_THAN,
"(order>= & xs)\n\n"
"Check if xs is not increasing according to a total order "
"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 */
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 */
janet_gcroot(janet_wrap_table(env));
@ -697,7 +797,7 @@ JanetTable *janet_core_env(void) {
}
/* 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 */
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. */
static void janetc_free_regnear(JanetCompiler *c, JanetSlot s, int32_t reg, JanetcRegisterTemp tag) {
if (reg != s.index ||
s.envindex >= 0 ||
if (reg != s.index ||
s.envindex >= 0 ||
s.flags & (JANET_SLOT_CONSTANT | JANET_SLOT_REF)) {
/* We need to free the temporary slot */
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) {
JanetStackFrame *frame = janet_fiber_frame(fiber);
if (fiber->frame == 0) return;
/* Clean up the frame (detach environments) */
if (NULL != frame->func)
janet_env_detach(frame->env);
@ -305,7 +305,7 @@ static int cfun_new(JanetArgs args) {
case ':':
break;
case 'a':
fiber->flags |=
fiber->flags |=
JANET_FIBER_MASK_DEBUG |
JANET_FIBER_MASK_ERROR |
JANET_FIBER_MASK_USER |
@ -455,7 +455,7 @@ static int cfun_setmaxstack(JanetArgs args) {
}
static const JanetReg cfuns[] = {
{"fiber.new", cfun_new,
{"fiber.new", cfun_new,
"(fiber.new func [,sigmask])\n\n"
"Create a new fiber with function body func. Can optionally "
"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"
"\t0-9 - block a specific user signal"
},
{"fiber.status", cfun_status,
{"fiber.status", cfun_status,
"(fiber.status fib)\n\n"
"Get the status of a fiber. The status will be one of:\n\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:new - the fiber has just been created and not yet run"
},
{"fiber.stack", cfun_stack,
{"fiber.stack", cfun_stack,
"(fiber.stack fib)\n\n"
"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 "
@ -498,24 +498,24 @@ static const JanetReg cfuns[] = {
"\t:source - string with filename or other identifier for the source code\n"
"\t:tail - boolean indicating a tail call"
},
{"fiber.current", cfun_current,
{"fiber.current", cfun_current,
"(fiber.current)\n\n"
"Returns the currently running fiber."
},
{"fiber.lineage", cfun_lineage,
{"fiber.lineage", cfun_lineage,
"(fiber.lineage fib)\n\n"
"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, "
"the fiber handling the error can see which fiber raised the signal. This function should "
"be used mostly for debugging purposes."
},
{"fiber.maxstack", cfun_maxstack,
{"fiber.maxstack", cfun_maxstack,
"(fiber.maxstack fib)\n\n"
"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 "
"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"
"Sets the maximum stack size in janet values for a fiber. By default, the "
"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)))
return "file is not readable";
/* Ensure buffer size */
if (janet_buffer_extra(buffer, nBytesMax))
if (janet_buffer_extra(buffer, nBytesMax))
return "buffer overflow";
size_t ntoread = nBytesMax;
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";
buffer->count += (int32_t) nread;
return NULL;
@ -366,7 +366,7 @@ static int janet_io_fseek(JanetArgs args) {
}
static const JanetReg cfuns[] = {
{"file.open", janet_io_fopen,
{"file.open", janet_io_fopen,
"(file.open path [,mode])\n\n"
"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. "
@ -379,13 +379,13 @@ static const JanetReg cfuns[] = {
"\tb - open the file in binary mode (rather than text mode)\n"
"\t+ - append to the file instead of overwriting it"
},
{"file.close", janet_io_fclose,
{"file.close", janet_io_fclose,
"(file.close f)\n\n"
"Close a file and release all related resources. When you are "
"done reading a file, close it to prevent a resource leak and let "
"other processes read the file."
},
{"file.read", janet_io_fread,
{"file.read", janet_io_fread,
"(file.read f what [,buf])\n\n"
"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 "
@ -396,17 +396,17 @@ static const JanetReg cfuns[] = {
"\t:line - read up to and including the next newline character\n"
"\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"
"Writes to a file. 'bytes' must be string, buffer, or symbol. Returns the "
"file"
},
{"file.flush", janet_io_fflush,
{"file.flush", janet_io_fflush,
"(file.flush f)\n\n"
"Flush any buffered bytes to the filesystem. In most files, writes are "
"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"
"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"
@ -416,7 +416,7 @@ static const JanetReg cfuns[] = {
"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."
},
{"file.popen", janet_io_popen,
{"file.popen", janet_io_popen,
"(file.popen path [,mode])\n\n"
"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 "
@ -433,7 +433,7 @@ int janet_lib_io(JanetArgs args) {
/* 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.");

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);
if (def->flags & JANET_FUNCDEF_FLAG_HASSOURCE)
marshal_one(st, janet_wrap_string(def->source), flags);
/* marshal constants */
for (int32_t i = 0; i < def->constants_length; i++)
marshal_one(st, def->constants[i], flags);
/* marshal the bytecode */
for (int32_t i = 0; i < def->bytecode_length; i++) {
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] >> 24) & 0xFF);
}
/* marshal the environments if needed */
for (int32_t i = 0; i < def->environments_length; i++)
pushint(st, def->environments[i]);
/* marshal the sub funcdefs if needed */
for (int32_t i = 0; i < def->defs_length; i++)
marshal_one_def(st, def->defs[i], flags);
@ -457,7 +457,7 @@ done:
nyi:
longjmp(st->err, MR_NYI);
noregval:
longjmp(st->err, MR_NRV);
}
@ -469,7 +469,7 @@ int janet_marshal(
JanetTable *rreg,
int flags) {
int status;
MarshalState st;
MarshalState st;
st.buf = buf;
st.nextid = 0;
st.seen_defs = NULL;
@ -641,7 +641,7 @@ static const uint8_t *unmarshal_one_def(
int32_t constants_length = 0;
int32_t environments_length = 0;
int32_t defs_length = 0;
/* Read flags and other fixed values */
def->flags = 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);
def->source = janet_unwrap_string(x);
}
/* Unmarshal constants */
if (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_length = constants_length;
/* Unmarshal bytecode */
def->bytecode = malloc(sizeof(uint32_t) * bytecode_length);
if (!def->bytecode) {
@ -689,7 +689,7 @@ static const uint8_t *unmarshal_one_def(
}
for (int32_t i = 0; i < bytecode_length; i++) {
if (data + 4 > end) longjmp(st->err, UMR_EOS);
def->bytecode[i] =
def->bytecode[i] =
(uint32_t)(data[0]) |
((uint32_t)(data[1]) << 8) |
((uint32_t)(data[2]) << 16) |
@ -697,7 +697,7 @@ static const uint8_t *unmarshal_one_def(
data += 4;
}
def->bytecode_length = bytecode_length;
/* Unmarshal environments */
if (def->flags & JANET_FUNCDEF_FLAG_HASENVS) {
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_length = environments_length;
/* Unmarshal sub funcdefs */
if (def->flags & JANET_FUNCDEF_FLAG_HASDEFS) {
def->defs = calloc(1, sizeof(JanetFuncDef *) * defs_length);
@ -719,13 +719,13 @@ static const uint8_t *unmarshal_one_def(
JANET_OUT_OF_MEMORY;
}
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 {
def->defs = NULL;
}
def->defs_length = defs_length;
/* Unmarshal source maps if needed */
if (def->flags & JANET_FUNCDEF_FLAG_HASSOURCEMAP) {
def->sourcemap = malloc(sizeof(JanetSourceMapping) * bytecode_length);
@ -738,11 +738,11 @@ static const uint8_t *unmarshal_one_def(
}
} else {
def->sourcemap = NULL;
}
}
/* Validate */
if (janet_verify(def)) longjmp(st->err, UMR_INVALID_BYTECODE);
/* Set def */
*out = def;
}
@ -1061,14 +1061,14 @@ static const uint8_t *unmarshal_one(
int janet_unmarshal(
const uint8_t *bytes,
size_t len,
int flags,
Janet *out,
size_t len,
int flags,
Janet *out,
JanetTable *reg,
const uint8_t **next) {
int status;
/* Avoid longjmp clobber warning in GCC */
UnmarshalState st;
UnmarshalState st;
st.end = bytes + len;
st.lookup_defs = NULL;
st.lookup_envs = NULL;
@ -1144,7 +1144,7 @@ static int cfun_unmarshal(JanetArgs args) {
}
static const JanetReg cfuns[] = {
{"marshal", cfun_marshal,
{"marshal", cfun_marshal,
"(marshal x [,reverse-lookup [,buffer]])\n\n"
"Marshal a janet value into a buffer and return the buffer. The buffer "
"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 "
"unmarshaling."
},
{"unmarshal", cfun_unmarshal,
{"unmarshal", cfun_unmarshal,
"(unmarshal buffer [,lookup])\n\n"
"Unmarshal a janet value from a buffer. An optional lookup table "
"can be provided to allow for aliases to be resolved. Returns the value "
"unmarshaled from the buffer."
},
{"env-lookup", cfun_env_lookup,
{"env-lookup", cfun_env_lookup,
"(env-lookup env)\n\n"
"Creates a forward lookup table for unmarshaling from an environment. "
"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);
ZeroMemory(&pi, sizeof(pi));
// Start the child process.
// Start the child process.
if(!CreateProcess(NULL,
(LPSTR) sys_str,
NULL,
@ -234,7 +234,7 @@ static int gettime(struct timespec *spec) {
spec->tv_nsec = mts.tv_nsec;
return 0;
}
#else
#else
#define gettime(TV) clock_gettime(CLOCK_MONOTONIC, (TV))
#endif
@ -283,52 +283,52 @@ static int os_cwd(JanetArgs args) {
}
static const JanetReg cfuns[] = {
{"os.which", os_which,
{"os.which", os_which,
"(os.which)\n\n"
"Check the current operating system. Returns one of:\n\n"
"\t:windows - Microsoft Windows\n"
"\t:macos - Apple macos\n"
"\t:posix - A POSIX compatible system (default)"
},
{"os.execute", os_execute,
{"os.execute", os_execute,
"(os.execute program & args)\n\n"
"Execute a program on the system and pass it string arguments. Returns "
"the exit status of the program."
},
{"os.shell", os_shell,
{"os.shell", os_shell,
"(os.shell str)\n\n"
"Pass a command string str directly to the system shell."
},
{"os.exit", os_exit,
{"os.exit", os_exit,
"(os.exit x)\n\n"
"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."
},
{"os.getenv", os_getenv,
{"os.getenv", os_getenv,
"(os.getenv variable)\n\n"
"Get the string value of an environment variable."
},
{"os.setenv", os_setenv,
{"os.setenv", os_setenv,
"(os.setenv variable value)\n\n"
"Set an environment variable."
},
{"os.time", os_time,
{"os.time", os_time,
"(os.time)\n\n"
"Get the current time expressed as the number of seconds since "
"January 1, 1970, the Unix epoch. Returns a real number."
},
{"os.clock", os_clock,
{"os.clock", os_clock,
"(os.clock)\n\n"
"Return the number of seconds since some fixed point in time. The clock "
"is guaranteed to be non decreased in real time."
},
{"os.sleep", os_sleep,
{"os.sleep", os_sleep,
"(os.sleep nsec)\n\n"
"Suspend the program for nsec seconds. 'nsec' can be a real number. Returns "
"nil."
},
{"os.cwd", os_cwd,
{"os.cwd", os_cwd,
"(os.cwd)\n\n"
"Returns the current working directory."
},

View File

@ -32,7 +32,7 @@ static Janet quote(Janet x) {
/* Check if a character is whitespace */
static int is_whitespace(uint8_t c) {
return c == ' '
return c == ' '
|| c == '\t'
|| c == '\n'
|| c == '\r'
@ -42,7 +42,7 @@ static int is_whitespace(uint8_t c) {
|| c == ',';
}
/* Code generated by tools/symcharsgen.c.
/* Code generated by tools/symcharsgen.c.
* The table contains 256 bits, where each bit is 1
* if the corresponding ascci code is a symbol char, and 0
* 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;
}
/* Check for overlong encodings */
/* Check for overlong encodings */
if ((nexti == i + 2) && str[i] < 0xC2) return 0;
if ((str[i] == 0xE0) && str[i + 1] < 0xA0) return 0;
if ((str[i] == 0xF0) && str[i + 1] < 0x90) return 0;
@ -192,15 +192,15 @@ static int checkescape(uint8_t c) {
switch (c) {
default: return -1;
case 'x': return 1;
case 'n': return '\n';
case 't': return '\t';
case 'r': return '\r';
case '0': return '\0';
case 'z': return '\0';
case 'n': return '\n';
case 't': return '\t';
case 'r': return '\r';
case '0': return '\0';
case 'z': return '\0';
case 'f': return '\f';
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[] = {
{"parser.new", cfun_parser, NULL},
{"parser.produce", cfun_produce, NULL},
{"parser.consume", cfun_consume, NULL},
{"parser.byte", cfun_byte, NULL},
{"parser.error", cfun_error, NULL},
{"parser.status", cfun_status, NULL},
{"parser.flush", cfun_flush, NULL},
{"parser.state", cfun_state, NULL},
{"parser.where", cfun_where, NULL},
{"parser.new", cfun_parser,
"(parser.new)\n\n"
"Creates and returns a new parser object. Parsers are state machines "
"that can receive bytes, and generate a stream of janet values. "
},
{"parser.produce", cfun_produce,
"(parser.produce parser)\n\n"
"Dequeue the next value in the parse queue. Will return nil if "
"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}
};

View File

@ -1040,21 +1040,97 @@ static int cfun_number(JanetArgs args) {
}
static const JanetReg cfuns[] = {
{"string.slice", cfun_slice, NULL},
{"string.repeat", cfun_repeat, NULL},
{"string.bytes", cfun_bytes, NULL},
{"string.from-bytes", cfun_frombytes, NULL},
{"string.ascii-lower", cfun_asciilower, NULL},
{"string.ascii-upper", cfun_asciiupper, NULL},
{"string.reverse", cfun_reverse, NULL},
{"string.find", cfun_find, NULL},
{"string.find-all", cfun_findall, NULL},
{"string.replace", cfun_replace, NULL},
{"string.replace-all", cfun_replaceall, NULL},
{"string.split", cfun_split, NULL},
{"string.check-set", cfun_checkset, NULL},
{"string.join", cfun_join, NULL},
{"string.number", cfun_number, NULL},
{"string.slice", cfun_slice,
"(string.slice bytes [,start=0 [,end=(length str)]])\n\n"
"Returns a substring from a byte sequence. The substring is from "
"index start inclusive to index end exclusive. All indexing "
"is from 0. 'start' and 'end' can also be negative to indicate indexing "
"from the end of the string."
},
{"string.repeat", cfun_repeat,
"(string.repeat bytes n)\n\n"
"Returns a string that is n copies of bytes concatenated."
},
{"string.bytes", cfun_bytes,
"(string.bytes str)\n\n"
"Returns an array of integers that are the byte values of the string."
},
{"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}
};

View File

@ -252,11 +252,33 @@ static int cfun_rawget(JanetArgs args) {
}
static const JanetReg cfuns[] = {
{"table.new", cfun_new, NULL},
{"table.to-struct", cfun_tostruct, NULL},
{"table.getproto", cfun_getproto, NULL},
{"table.setproto", cfun_setproto, NULL},
{"table.rawget", cfun_rawget, NULL},
{"table.new", cfun_new,
"(table.new capacity)\n\n"
"Creates a new empty table with pre-allocated memory "
"for capacity entries. This means that if one knows the number of "
"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}
};

View File

@ -127,13 +127,16 @@ static int cfun_slice(JanetArgs args) {
static int cfun_prepend(JanetArgs args) {
const Janet *t;
int32_t len;
int32_t len, i;
Janet *n;
JANET_FIXARITY(args, 2);
if (!janet_indexed_view(args.v[0], &t, &len)) JANET_THROW(args, "expected tuple/array");
n = janet_tuple_begin(len + 1);
memcpy(n + 1, t, sizeof(Janet) * len);
n[0] = args.v[1];
JANET_MINARITY(args, 1);
if (!janet_indexed_view(args.v[0], &t, &len))
JANET_THROW(args, "expected tuple/array");
n = janet_tuple_begin(len - 1 + args.n);
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));
}
@ -141,18 +144,34 @@ static int cfun_append(JanetArgs args) {
const Janet *t;
int32_t len;
Janet *n;
JANET_FIXARITY(args, 2);
if (!janet_indexed_view(args.v[0], &t, &len)) JANET_THROW(args, "expected tuple/array");
n = janet_tuple_begin(len + 1);
JANET_MINARITY(args, 1);
if (!janet_indexed_view(args.v[0], &t, &len))
JANET_THROW(args, "expected tuple/array");
n = janet_tuple_begin(len - 1 + args.n);
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));
}
static const JanetReg cfuns[] = {
{"tuple.slice", cfun_slice, NULL},
{"tuple.append", cfun_append, NULL},
{"tuple.prepend", cfun_prepend, NULL},
{"tuple.slice", cfun_slice,
"(tuple.slice arrtup [,start=0 [,end=(length arrtup)]])\n\n"
"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}
};