summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2021-07-09 21:22:52 +0200
committerJo-Philipp Wich <jo@mein.io>2021-07-11 15:49:14 +0200
commit498fe870251a9a73b2ed8d47d2292652bde84c3c (patch)
treec90b842c10834a73e0e1764b00d669772c0ad61e
parentff52440341bcb8c61105ff144bfcb210315207e4 (diff)
main: refactor option parsing and VM setup
Set VM options and environment variables and load modules on the fly while parsing the cli options instead of aggregating all the values in memory first. This vastly reduces the amount of arguments we need to pass to the parse() function. Also rename parse() to compile() while we're at it. Also slightly adjust the usage output. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
-rw-r--r--main.c97
-rw-r--r--tests/cram/test_basic.t6
2 files changed, 39 insertions, 64 deletions
diff --git a/main.c b/main.c
index 58ac2b3..58c9826 100644
--- a/main.c
+++ b/main.c
@@ -39,11 +39,11 @@ static void
print_usage(const char *app)
{
printf(
- "== Usage ==\n\n"
+ "Usage\n\n"
" # %s [-t] [-l] [-r] [-S] [-R] [-e '[prefix=]{\"var\": ...}'] [-E [prefix=]env.json] {-i <file> | -s \"ucode script...\"}\n"
" -h, --help Print this help\n"
- " -i file Specify an ucode script to parse\n"
- " -s \"ucode script...\" Specify an ucode fragment to parse\n"
+ " -i file Execute the given ucode script file\n"
+ " -s \"ucode script...\" Execute the given string as ucode script\n"
" -t Enable VM execution tracing\n"
" -l Do not strip leading block whitespace\n"
" -r Do not trim trailing block newlines\n"
@@ -74,22 +74,14 @@ register_variable(uc_value_t *scope, const char *key, uc_value_t *val)
static int
-parse(uc_parse_config_t *config, uc_source_t *src,
- uc_value_t *env, uc_value_t *modules,
- int argc, char **argv, int trace)
+compile(uc_vm_t *vm, uc_source_t *src)
{
- uc_value_t *globals = NULL, *res = NULL, *arr, *name, *mod;
+ uc_value_t *res = NULL;
uc_function_t *entry;
- uc_vm_t vm = { 0 };
- int i, rc = 0;
- size_t idx;
+ int rc = 0;
char *err;
- uc_vm_init(&vm, config);
-
- uc_vm_trace_set(&vm, trace);
-
- entry = uc_compile(config, src, &err);
+ entry = uc_compile(vm->config, src, &err);
if (!entry) {
fprintf(stderr, "%s", err);
@@ -98,36 +90,7 @@ parse(uc_parse_config_t *config, uc_source_t *src,
goto out;
}
- /* allocate global scope */
- globals = uc_vm_scope_get(&vm);
-
- /* register ARGV array */
- arr = ucv_array_new_length(&vm, argc);
-
- for (i = 0; i < argc; i++)
- ucv_array_push(arr, ucv_string_new(argv[i]));
-
- ucv_object_add(globals, "ARGV", arr);
-
- /* load env variables */
- if (env) {
- ucv_object_foreach(env, key, val)
- register_variable(globals, key, ucv_get(val));
- }
-
- /* load std functions into global scope */
- uc_load_stdlib(globals);
-
- /* preload modules */
- for (idx = 0; idx < ucv_array_length(modules); idx++) {
- name = ucv_array_get(modules, idx);
- mod = uc_vm_invoke(&vm, "require", 1, name);
-
- if (mod)
- register_variable(globals, ucv_string_get(name), mod);
- }
-
- rc = uc_vm_execute(&vm, entry, &res);
+ rc = uc_vm_execute(vm, entry, &res);
switch (rc) {
case STATUS_OK:
@@ -148,7 +111,6 @@ parse(uc_parse_config_t *config, uc_source_t *src,
}
out:
- uc_vm_free(&vm);
ucv_put(res);
return rc;
@@ -224,10 +186,11 @@ parse_envfile(FILE *fp)
int
main(int argc, char **argv)
{
- uc_value_t *env = NULL, *modules = NULL, *o, *p;
uc_source_t *source = NULL, *envfile = NULL;
- int opt, rv = 0, trace = 0;
char *stdin = NULL, *c;
+ uc_vm_t vm = { 0 };
+ uc_value_t *o, *p;
+ int opt, rv = 0;
uc_parse_config_t config = {
.strict_declarations = false,
@@ -241,6 +204,20 @@ main(int argc, char **argv)
goto out;
}
+ uc_vm_init(&vm, &config);
+
+ /* load std functions into global scope */
+ uc_load_stdlib(uc_vm_scope_get(&vm));
+
+ /* register ARGV array */
+ o = ucv_array_new_length(&vm, argc);
+
+ for (opt = 0; opt < argc; opt++)
+ ucv_array_push(o, ucv_string_new(argv[opt]));
+
+ ucv_object_add(uc_vm_scope_get(&vm), "ARGV", o);
+
+ /* parse options */
while ((opt = getopt(argc, argv, "hlrtSRe:E:i:s:m:")) != -1)
{
switch (opt) {
@@ -337,32 +314,31 @@ main(int argc, char **argv)
goto out;
}
- env = env ? env : ucv_object_new(NULL);
-
if (c > optarg && optarg[0]) {
- p = ucv_object_new(NULL);
- ucv_object_add(env, optarg, p);
+ p = ucv_object_new(&vm);
+ ucv_object_add(uc_vm_scope_get(&vm), optarg, p);
}
else {
- p = env;
+ p = uc_vm_scope_get(&vm);
}
ucv_object_foreach(o, key, val)
- ucv_object_add(p, key, ucv_get(val));
+ register_variable(p, key, ucv_get(val));
ucv_put(o);
break;
case 'm':
- modules = modules ? modules : ucv_array_new(NULL);
+ o = uc_vm_invoke(&vm, "require", 1, ucv_string_new(optarg));
- ucv_array_push(modules, ucv_string_new(optarg));
+ if (o)
+ register_variable(uc_vm_scope_get(&vm), optarg, o);
break;
case 't':
- trace = 1;
+ uc_vm_trace_set(&vm, 1);
break;
}
}
@@ -383,13 +359,12 @@ main(int argc, char **argv)
goto out;
}
- rv = parse(&config, source, env, modules, argc, argv, trace);
+ rv = compile(&vm, source);
out:
- ucv_put(modules);
- ucv_put(env);
-
uc_source_put(source);
+ uc_vm_free(&vm);
+
return rv;
}
diff --git a/tests/cram/test_basic.t b/tests/cram/test_basic.t
index 940f1d1..7296b5d 100644
--- a/tests/cram/test_basic.t
+++ b/tests/cram/test_basic.t
@@ -10,12 +10,12 @@ setup common environment:
check that ucode provides exepected help:
$ ucode | sed 's/ucode-san/ucode/'
- == Usage ==
+ Usage
# ucode [-t] [-l] [-r] [-S] [-R] [-e '[prefix=]{"var": ...}'] [-E [prefix=]env.json] {-i <file> | -s "ucode script..."}
-h, --help\tPrint this help (esc)
- -i file\tSpecify an ucode script to parse (esc)
- -s "ucode script..."\tSpecify an ucode fragment to parse (esc)
+ -i file\tExecute the given ucode script file (esc)
+ -s "ucode script..."\tExecute the given string as ucode script (esc)
-t Enable VM execution tracing
-l Do not strip leading block whitespace
-r Do not trim trailing block newlines