diff options
-rw-r--r-- | compiler.c | 70 | ||||
-rw-r--r-- | include/ucode/types.h | 1 | ||||
-rw-r--r-- | main.c | 14 | ||||
-rw-r--r-- | tests/cram/test_basic.t | 3 |
4 files changed, 82 insertions, 6 deletions
@@ -3330,6 +3330,68 @@ uc_compiler_acquire_source(uc_compiler_t *compiler, const char *path) } static bool +uc_compiler_compile_dynload(uc_compiler_t *compiler, const char *name, uc_value_t *imports) +{ + uc_value_t *modname = ucv_string_new(name); + size_t i, n_imports; + uc_value_t *import; + + for (i = 0, n_imports = 0; i < ucv_array_length(imports); i++) { + import = ucv_array_get(imports, i); + + if (ucv_boolean_get(import)) { + uc_compiler_emit_insn(compiler, 0, I_DYNLOAD); + uc_compiler_emit_u32(compiler, 0, 0); + uc_compiler_emit_constant_index(compiler, 0, modname); + } + else { + n_imports++; + } + } + + if (n_imports > 0) { + uc_compiler_emit_insn(compiler, 0, I_DYNLOAD); + uc_compiler_emit_u32(compiler, 0, n_imports | ((compiler->upvals.count - n_imports) << 16)); + uc_compiler_emit_constant_index(compiler, 0, modname); + + for (i = 0; i < ucv_array_length(imports); i++) { + import = ucv_get(ucv_array_get(imports, i)); + + if (!import) + import = ucv_string_new("default"); + + if (!ucv_boolean_get(import)) + uc_compiler_emit_constant_index(compiler, 0, import); + + ucv_put(import); + } + } + + ucv_put(modname); + + return true; +} + +static bool +uc_compiler_is_dynlink_module(uc_compiler_t *compiler, const char *name, const char *path) +{ + uc_search_path_t *dynlink_list = &compiler->parser->config->force_dynlink_list; + size_t i; + char *p; + + for (i = 0; i < dynlink_list->count; i++) + if (!strcmp(dynlink_list->entries[i], name)) + return true; + + if (!path) + return false; + + p = strrchr(path, '.'); + + return (p && !strcmp(p, ".so")); +} + +static bool uc_compiler_compile_module(uc_compiler_t *compiler, const char *name, uc_value_t *imports) { uc_source_t *source; @@ -3341,7 +3403,10 @@ uc_compiler_compile_module(uc_compiler_t *compiler, const char *name, uc_value_t path = uc_compiler_resolve_module_path(compiler, name); - if (path) { + if (uc_compiler_is_dynlink_module(compiler, name, path)) { + res = uc_compiler_compile_dynload(compiler, name, imports); + } + else if (path) { source = uc_compiler_acquire_source(compiler, path); if (source) { @@ -3361,6 +3426,8 @@ uc_compiler_compile_module(uc_compiler_t *compiler, const char *name, uc_value_t res = false; } + + uc_source_put(source); } else { uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, @@ -3369,7 +3436,6 @@ uc_compiler_compile_module(uc_compiler_t *compiler, const char *name, uc_value_t return false; } - uc_source_put(source); free(path); return res; diff --git a/include/ucode/types.h b/include/ucode/types.h index 636d6e4..e20f3d6 100644 --- a/include/ucode/types.h +++ b/include/ucode/types.h @@ -227,6 +227,7 @@ typedef struct { bool strict_declarations; bool raw_mode; uc_search_path_t module_search_path; + uc_search_path_t force_dynlink_list; } uc_parse_config_t; extern uc_parse_config_t uc_default_parse_config; @@ -90,7 +90,8 @@ print_usage(const char *app) "-c[flag,flag,...]\n" " Compile the given source file(s) to bytecode instead of executing them.\n" " Supported flags: no-interp (omit interpreter line), interp=... (over-\n" - " ride interpreter line with ...)\n\n" + " ride interpreter line with ...), dynlink=... (force import from ... to\n" + " be treated as shared extensions loaded at runtime).\n\n" "-o path\n" " Output file path when compiling. If omitted, the compiled byte code\n" @@ -204,7 +205,7 @@ parse_template_modeflags(char *opt, uc_parse_config_t *config) } static void -parse_compile_flags(char *opt, char **interp) +parse_compile_flags(char *opt, char **interp, uc_search_path_t *dynlink_list) { char *p, *k, *v; @@ -230,6 +231,12 @@ parse_compile_flags(char *opt, char **interp) else *interp = v; } + else if (!strcmp(k, "dynlink")) { + if (!v) + fprintf(stderr, "Compile flag \"%s\" requires a value, ignoring\n", k); + else + uc_vector_push(dynlink_list, v); + } else { fprintf(stderr, "Unrecognized -c flag \"%s\", ignoring\n", k); } @@ -577,7 +584,7 @@ main(int argc, char **argv) case 'c': outfile = "./uc.out"; - parse_compile_flags(optarg, &interp); + parse_compile_flags(optarg, &interp, &config.force_dynlink_list); break; case 's': @@ -640,6 +647,7 @@ main(int argc, char **argv) out: uc_search_path_free(&config.module_search_path); + uc_vector_clear(&config.force_dynlink_list); uc_source_put(source); diff --git a/tests/cram/test_basic.t b/tests/cram/test_basic.t index 7308002..5911ac9 100644 --- a/tests/cram/test_basic.t +++ b/tests/cram/test_basic.t @@ -61,7 +61,8 @@ check that ucode provides exepected help: -c[flag,flag,...] Compile the given source file(s) to bytecode instead of executing them. Supported flags: no-interp (omit interpreter line), interp=... (over- - ride interpreter line with ...) + ride interpreter line with ...), dynlink=... (force import from ... to + be treated as shared extensions loaded at runtime). -o path Output file path when compiling. If omitted, the compiled byte code |