summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilliam Langford <wlangfor@gmail.com>2017-02-05 01:28:15 -0500
committerWilliam Langford <wlangfor@gmail.com>2017-02-13 11:36:20 -0500
commit1c806b74eaeaa63802725b8329a68d83f73b551e (patch)
tree5f53b72a42c52df75a952470aec06bb3bf21afa0
parent8001955fb76f784480fba3300fea602012ee9446 (diff)
Add `builtins` builtin
-rw-r--r--docs/content/3.manual/manual.yml8
-rw-r--r--src/builtin.c43
-rw-r--r--src/compile.c12
-rw-r--r--src/compile.h1
4 files changed, 40 insertions, 24 deletions
diff --git a/docs/content/3.manual/manual.yml b/docs/content/3.manual/manual.yml
index 0f917426..adeeb7cf 100644
--- a/docs/content/3.manual/manual.yml
+++ b/docs/content/3.manual/manual.yml
@@ -1919,6 +1919,14 @@ sections:
This builtin outputs `true` if any value in the source stream
appears in the second stream, otherwise it outputs `false`.
+ - title: "`builtins`"
+ body: |
+
+ Returns a list of all builtin functions in the format `name/arity`.
+ Since functions with the same name but different arities are considered
+ separate functions, `all/0`, `all/1`, and `all/2` would all be present
+ in the list.
+
- title: Conditionals and Comparisons
entries:
- title: "`==`, `!=`"
diff --git a/src/builtin.c b/src/builtin.c
index c278869c..31f2ae99 100644
--- a/src/builtin.c
+++ b/src/builtin.c
@@ -1341,15 +1341,15 @@ static jv f_current_line(jq_state *jq, jv a) {
}
#define LIBM_DD(name) \
- {(cfunction_ptr)f_ ## name, "_" #name, 1},
+ {(cfunction_ptr)f_ ## name, #name, 1},
#define LIBM_DD_NO(name)
#define LIBM_DDD(name) \
- {(cfunction_ptr)f_ ## name, "_" #name, 3},
+ {(cfunction_ptr)f_ ## name, #name, 3},
#define LIBM_DDD_NO(name)
#define LIBM_DDDD(name) \
- {(cfunction_ptr)f_ ## name, "_" #name, 4},
+ {(cfunction_ptr)f_ ## name, #name, 4},
#define LIBM_DDDD_NO(name)
static const struct cfunction function_list[] = {
@@ -1469,30 +1469,16 @@ static block bind_bytecoded_builtins(block b) {
BLOCK(gen_param("start"), gen_param("end")),
range));
}
-
- return block_bind_referenced(builtins, b, OP_IS_CALL_PSEUDO);
+ return block_bind(builtins, b, OP_IS_CALL_PSEUDO);
}
-#define LIBM_DD(name) "def " #name ": _" #name ";"
-#define LIBM_DDD(name) "def " #name "(a;b): _" #name "(a;b);"
-#define LIBM_DDDD(name) "def " #name "(a;b;c): _" #name "(a;b;c);"
-#define LIBM_DD_NO(name)
-#define LIBM_DDD_NO(name)
-#define LIBM_DDDD_NO(name)
+
static const char* const jq_builtins =
-/* Include supported math functions first */
-#include "libm.h"
-/* Include jq-coded builtins next (some depend on math) */
+/* Include jq-coded builtins */
#include "src/builtin.inc"
/* Include unsupported math functions next */
-#undef LIBM_DDDD_NO
-#undef LIBM_DDD_NO
-#undef LIBM_DD_NO
-#undef LIBM_DDDD
-#undef LIBM_DDD
-#undef LIBM_DD
#define LIBM_DD(name)
#define LIBM_DDD(name)
#define LIBM_DDDD(name)
@@ -1510,13 +1496,18 @@ static const char* const jq_builtins =
#undef LIBM_DD
+static block gen_builtin_list(block builtins) {
+ jv list = jv_array_append(block_list_funcs(builtins, 1), jv_string("builtins"));
+ return BLOCK(builtins, gen_function("builtins", gen_noop(), gen_const(list)));
+}
+
static int builtins_bind_one(jq_state *jq, block* bb, const char* code) {
struct locfile* src;
src = locfile_init(jq, "<builtin>", code, strlen(code));
block funcs;
int nerrors = jq_parse_library(src, &funcs);
if (nerrors == 0) {
- *bb = block_bind_referenced(funcs, *bb, OP_IS_CALL_PSEUDO);
+ *bb = block_bind(funcs, *bb, OP_IS_CALL_PSEUDO);
}
locfile_free(src);
return nerrors;
@@ -1538,14 +1529,18 @@ static int slurp_lib(jq_state *jq, block* bb) {
}
int builtins_bind(jq_state *jq, block* bb) {
+ block builtins = gen_noop();
int nerrors = slurp_lib(jq, bb);
if (nerrors) {
block_free(*bb);
return nerrors;
}
- nerrors = builtins_bind_one(jq, bb, jq_builtins);
+ nerrors = builtins_bind_one(jq, &builtins, jq_builtins);
assert(!nerrors);
- *bb = bind_bytecoded_builtins(*bb);
- *bb = gen_cbinding(function_list, sizeof(function_list)/sizeof(function_list[0]), *bb);
+ builtins = bind_bytecoded_builtins(builtins);
+ builtins = gen_cbinding(function_list, sizeof(function_list)/sizeof(function_list[0]), builtins);
+ builtins = gen_builtin_list(builtins);
+ *bb = block_bind(builtins, *bb, OP_IS_CALL_PSEUDO);
+ *bb = block_drop_unreferenced(*bb);
return nerrors;
}
diff --git a/src/compile.c b/src/compile.c
index a5c75c96..44479e37 100644
--- a/src/compile.c
+++ b/src/compile.c
@@ -480,6 +480,18 @@ jv block_take_imports(block* body) {
return imports;
}
+jv block_list_funcs(block body, int omit_underscores) {
+ jv funcs = jv_object(); // Use the keys for set semantics.
+ for (inst *pos = body.first; pos != NULL; pos = pos->next) {
+ if (pos->op == CLOSURE_CREATE || pos->op == CLOSURE_CREATE_C) {
+ if (pos->symbol != NULL && (!omit_underscores || pos->symbol[0] != '_')) {
+ funcs = jv_object_set(funcs, jv_string_fmt("%s/%i", pos->symbol, pos->nformals), jv_null());
+ }
+ }
+ }
+ return jv_keys_unsorted(funcs);
+}
+
block gen_module(block metadata) {
inst* i = inst_new(MODULEMETA);
i->imm.constant = block_const(metadata);
diff --git a/src/compile.h b/src/compile.h
index 4572c9cc..60765515 100644
--- a/src/compile.h
+++ b/src/compile.h
@@ -75,6 +75,7 @@ block block_bind_referenced(block binder, block body, int bindflags);
block block_drop_unreferenced(block body);
jv block_take_imports(block* body);
+jv block_list_funcs(block body, int omit_underscores);
int block_compile(block, struct bytecode**, struct locfile*);