summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--compiler.c70
-rw-r--r--include/ucode/types.h1
-rw-r--r--main.c14
-rw-r--r--tests/cram/test_basic.t3
4 files changed, 82 insertions, 6 deletions
diff --git a/compiler.c b/compiler.c
index 7fd4da2..1199d82 100644
--- a/compiler.c
+++ b/compiler.c
@@ -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;
diff --git a/main.c b/main.c
index 087efff..02df3b1 100644
--- a/main.c
+++ b/main.c
@@ -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