1
0
mirror of https://github.com/stedolan/jq.git synced 2024-05-11 05:55:39 +00:00

Restore import into caller's namespace

This commit is contained in:
Nicolas Williams
2015-06-26 23:40:37 -05:00
parent 8cc31f0f49
commit aaf305868c
6 changed files with 959 additions and 880 deletions

View File

@@ -371,9 +371,10 @@ block block_bind(block binder, block body, int bindflags) {
block block_bind_library(block binder, block body, int bindflags, const char *libname) { block block_bind_library(block binder, block body, int bindflags, const char *libname) {
bindflags |= OP_HAS_BINDING; bindflags |= OP_HAS_BINDING;
int nrefs = 0; int nrefs = 0;
int matchlen = strlen(libname); int matchlen = (libname == NULL) ? 0 : strlen(libname);
char *matchname = jv_mem_alloc(matchlen+2+1); char *matchname = jv_mem_alloc(matchlen+2+1);
if (libname[0] != '\0') { matchname[0] = '\0';
if (libname != NULL && libname[0] != '\0') {
strcpy(matchname,libname); strcpy(matchname,libname);
strcpy(matchname+matchlen, "::"); strcpy(matchname+matchlen, "::");
matchlen += 2; matchlen += 2;
@@ -502,6 +503,7 @@ block gen_import(const char* name, block metadata, const char* as, int is_data)
meta = block_const(metadata); meta = block_const(metadata);
else else
meta = jv_object(); meta = jv_object();
if (as != NULL)
meta = jv_object_set(meta, jv_string("as"), jv_string(as)); meta = jv_object_set(meta, jv_string("as"), jv_string(as));
meta = jv_object_set(meta, jv_string("is_data"), is_data ? jv_true() : jv_false()); meta = jv_object_set(meta, jv_string("is_data"), is_data ? jv_true() : jv_false());
meta = jv_object_set(meta, jv_string("relpath"), jv_string(name)); meta = jv_object_set(meta, jv_string("relpath"), jv_string(name));

View File

@@ -2753,6 +2753,14 @@ sections:
the relative path string. The module's symbols are prefixed the relative path string. The module's symbols are prefixed
with "NAME::". with "NAME::".
- title: "`import RelativePathString;`"
body: |
Imports a module found at the given path relative to a
directory in a search path. A ".jq" suffix will be added to
the relative path string. The module's symbols are imported
into the caller's namespace as if the module's content had
been included directly.
- title: "`import RelativePathString as NAME <metadata>;`" - title: "`import RelativePathString as NAME <metadata>;`"
body: | body: |

View File

@@ -198,6 +198,7 @@ static int process_dependencies(jq_state *jq, jv jq_origin, jv lib_origin, block
jv deps = block_take_imports(src_block); jv deps = block_take_imports(src_block);
block bk = *src_block; block bk = *src_block;
int nerrors = 0; int nerrors = 0;
const char *as_str = NULL;
jv_array_foreach(deps, i, dep) { jv_array_foreach(deps, i, dep) {
int is_data = jv_get_kind(jv_object_get(jv_copy(dep), jv_string("is_data"))) == JV_KIND_TRUE; int is_data = jv_get_kind(jv_object_get(jv_copy(dep), jv_string("is_data"))) == JV_KIND_TRUE;
@@ -208,7 +209,9 @@ static int process_dependencies(jq_state *jq, jv jq_origin, jv lib_origin, block
jv_free(v); jv_free(v);
jv relpath = validate_relpath(jv_object_get(jv_copy(dep), jv_string("relpath"))); jv relpath = validate_relpath(jv_object_get(jv_copy(dep), jv_string("relpath")));
jv as = jv_object_get(jv_copy(dep), jv_string("as")); jv as = jv_object_get(jv_copy(dep), jv_string("as"));
assert(jv_is_valid(as) && jv_get_kind(as) == JV_KIND_STRING); assert(!jv_is_valid(as) || jv_get_kind(as) == JV_KIND_STRING);
if (jv_get_kind(as) == JV_KIND_STRING)
as_str = jv_string_value(as);
jv search = default_search(jq, jv_object_get(dep, jv_string("search"))); jv search = default_search(jq, jv_object_get(dep, jv_string("search")));
// dep is now freed; do not reuse // dep is now freed; do not reuse
@@ -233,14 +236,14 @@ static int process_dependencies(jq_state *jq, jv jq_origin, jv lib_origin, block
if (state_idx < lib_state->ct) { // Found if (state_idx < lib_state->ct) { // Found
jv_free(resolved); jv_free(resolved);
// Bind the library to the program // Bind the library to the program
bk = block_bind_library(lib_state->defs[state_idx], bk, OP_IS_CALL_PSEUDO, jv_string_value(as)); bk = block_bind_library(lib_state->defs[state_idx], bk, OP_IS_CALL_PSEUDO, as_str);
} else { // Not found. Add it to the table before binding. } else { // Not found. Add it to the table before binding.
block dep_def_block = gen_noop(); block dep_def_block = gen_noop();
nerrors += load_library(jq, resolved, is_data, raw, jv_string_value(as), &dep_def_block, lib_state); nerrors += load_library(jq, resolved, is_data, raw, as_str, &dep_def_block, lib_state);
// resolved has been freed // resolved has been freed
if (nerrors == 0) { if (nerrors == 0) {
// Bind the library to the program // Bind the library to the program
bk = block_bind_library(dep_def_block, bk, OP_IS_CALL_PSEUDO, jv_string_value(as)); bk = block_bind_library(dep_def_block, bk, OP_IS_CALL_PSEUDO, as_str);
} }
} }
jv_free(as); jv_free(as);

1767
parser.c
View File

File diff suppressed because it is too large Load Diff

View File

@@ -487,6 +487,12 @@ Import:
jv_free($4); jv_free($4);
jv_free(v); jv_free(v);
} | } |
"import" String ';' {
jv v = block_const($2);
$$ = gen_import(jv_string_value(v), gen_noop(), NULL, 0);
block_free($2);
jv_free(v);
} |
"import" String "as" IDENT Exp ';' { "import" String "as" IDENT Exp ';' {
if (!block_is_const($5)) { if (!block_is_const($5)) {
FAIL(@$, "Module metadata must be constant."); FAIL(@$, "Module metadata must be constant.");
@@ -499,6 +505,17 @@ Import:
block_free($2); block_free($2);
jv_free($4); jv_free($4);
} | } |
"import" String Exp ';' {
if (!block_is_const($3)) {
FAIL(@$, "Module metadata must be constant.");
$$ = gen_noop();
} else {
jv v = block_const($2);
$$ = gen_import(jv_string_value(v), $3, NULL, 0);
jv_free(v);
}
block_free($2);
} |
"import" String "as" '$' IDENT Exp ';' { "import" String "as" '$' IDENT Exp ';' {
if (!block_is_const($6)) { if (!block_is_const($6)) {
FAIL(@$, "Module metadata must be constant."); FAIL(@$, "Module metadata must be constant.");

View File

@@ -1117,6 +1117,10 @@ import "c" as foo; [foo::a, foo::c]
null null
[0,"acmehbah"] [0,"acmehbah"]
import "c"; [a, c]
null
[0,"acmehbah"]
modulemeta modulemeta
"c" "c"
{"whatever":null,"deps":[{"as":"foo","is_data":false,"relpath":"a"},{"search":"./","as":"d","is_data":false,"relpath":"d"},{"search":"./","as":"d2","is_data":false,"relpath":"d"},{"search":"./../lib/jq","as":"e","is_data":false,"relpath":"e"},{"search":"./../lib/jq","as":"f","is_data":false,"relpath":"f"},{"as":"d","is_data":true,"relpath":"data"}]} {"whatever":null,"deps":[{"as":"foo","is_data":false,"relpath":"a"},{"search":"./","as":"d","is_data":false,"relpath":"d"},{"search":"./","as":"d2","is_data":false,"relpath":"d"},{"search":"./../lib/jq","as":"e","is_data":false,"relpath":"e"},{"search":"./../lib/jq","as":"f","is_data":false,"relpath":"f"},{"as":"d","is_data":true,"relpath":"data"}]}