summaryrefslogtreecommitdiffhomepage
path: root/compiler.c
diff options
context:
space:
mode:
Diffstat (limited to 'compiler.c')
-rw-r--r--compiler.c97
1 files changed, 77 insertions, 20 deletions
diff --git a/compiler.c b/compiler.c
index b6793d7..c5b0ee5 100644
--- a/compiler.c
+++ b/compiler.c
@@ -21,8 +21,11 @@
#include "ucode/chunk.h"
#include "ucode/vm.h" /* I_* */
#include "ucode/source.h"
+#include "ucode/program.h"
#include "ucode/lib.h" /* uc_error_context_format() */
+#ifndef NO_COMPILE
+
static void uc_compiler_compile_unary(uc_compiler_t *compiler);
static void uc_compiler_compile_binary(uc_compiler_t *compiler);
static void uc_compiler_compile_delete(uc_compiler_t *compiler);
@@ -113,14 +116,15 @@ uc_compiler_exprstack_is(uc_compiler_t *compiler, uc_exprflag_t flag)
}
static void
-uc_compiler_init(uc_compiler_t *compiler, const char *name, size_t srcpos, uc_source_t *source, bool strict)
+uc_compiler_init(uc_compiler_t *compiler, const char *name, size_t srcpos, uc_program_t *program, bool strict)
{
uc_value_t *varname = ucv_string_new("(callee)");
uc_function_t *fn;
compiler->scope_depth = 0;
- compiler->function = ucv_function_new(name, srcpos, source);
+ compiler->program = program;
+ compiler->function = uc_program_function_new(program, name, srcpos);
compiler->locals.count = 0;
compiler->locals.entries = NULL;
@@ -154,9 +158,7 @@ uc_compiler_current_chunk(uc_compiler_t *compiler)
static uc_source_t *
uc_compiler_current_source(uc_compiler_t *compiler)
{
- uc_function_t *fn = (uc_function_t *)compiler->function;
-
- return fn->source;
+ return compiler->program->source;
}
__attribute__((format(printf, 3, 0))) static void
@@ -481,8 +483,7 @@ uc_compiler_set_u32(uc_compiler_t *compiler, size_t off, uint32_t n)
static size_t
uc_compiler_emit_constant(uc_compiler_t *compiler, size_t srcpos, uc_value_t *val)
{
- uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
- size_t cidx = uc_chunk_add_constant(chunk, val);
+ size_t cidx = uc_program_add_constant(compiler->program, val);
uc_compiler_emit_insn(compiler, srcpos, I_LOAD);
uc_compiler_emit_u32(compiler, 0, cidx);
@@ -493,8 +494,7 @@ uc_compiler_emit_constant(uc_compiler_t *compiler, size_t srcpos, uc_value_t *va
static size_t
uc_compiler_emit_regexp(uc_compiler_t *compiler, size_t srcpos, uc_value_t *val)
{
- uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
- size_t cidx = uc_chunk_add_constant(chunk, val);
+ size_t cidx = uc_program_add_constant(compiler->program, val);
uc_compiler_emit_insn(compiler, srcpos, I_LREXP);
uc_compiler_emit_u32(compiler, 0, cidx);
@@ -1084,7 +1084,7 @@ uc_compiler_emit_variable_rw(uc_compiler_t *compiler, uc_value_t *varname, uc_to
((sub_insn & 0xff) << 24) | idx);
}
else {
- idx = uc_chunk_add_constant(uc_compiler_current_chunk(compiler), varname);
+ idx = uc_program_add_constant(compiler->program, varname);
insn = sub_insn ? I_UVAR : (type ? I_SVAR : I_LVAR);
uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, insn);
@@ -1132,7 +1132,7 @@ uc_compiler_compile_arrowfn(uc_compiler_t *compiler, uc_value_t *args, bool rest
pos = compiler->parser->prev.pos;
uc_compiler_init(&fncompiler, NULL, compiler->parser->prev.pos,
- uc_compiler_current_source(compiler),
+ compiler->program,
uc_compiler_is_strict(compiler));
fncompiler.parent = compiler;
@@ -1193,8 +1193,7 @@ uc_compiler_compile_arrowfn(uc_compiler_t *compiler, uc_value_t *args, bool rest
if (fn)
uc_compiler_set_u32(compiler, load_off,
- uc_chunk_add_constant(uc_compiler_current_chunk(compiler),
- &fn->header));
+ uc_program_add_constant(compiler->program, &fn->header));
return true;
}
@@ -1563,7 +1562,7 @@ uc_compiler_compile_function(uc_compiler_t *compiler)
uc_compiler_init(&fncompiler,
name ? ucv_string_get(name) : NULL, compiler->parser->prev.pos,
- uc_compiler_current_source(compiler),
+ compiler->program,
uc_compiler_is_strict(compiler));
fncompiler.parent = compiler;
@@ -1633,8 +1632,7 @@ uc_compiler_compile_function(uc_compiler_t *compiler)
if (fn)
uc_compiler_set_u32(compiler, load_off,
- uc_chunk_add_constant(uc_compiler_current_chunk(compiler),
- &fn->header));
+ uc_program_add_constant(compiler->program, &fn->header));
/* if a local variable of the same name already existed, overwrite its value
* with the compiled function here */
@@ -2869,16 +2867,28 @@ uc_compiler_compile_declaration(uc_compiler_t *compiler)
uc_compiler_parse_synchronize(compiler);
}
-uc_function_t *
-uc_compile(uc_parse_config_t *config, uc_source_t *source, char **errp)
+#endif /* NO_COMPILE */
+
+
+static uc_function_t *
+uc_compile_from_source(uc_parse_config_t *config, uc_source_t *source, char **errp)
{
+#ifdef NO_COMPILE
+ if (errp)
+ xasprintf(errp, "Source code compilation not supported\n");
+
+ return NULL;
+#else
+ uc_function_t *fn = NULL;
uc_exprstack_t expr = { .token = TK_EOF };
uc_parser_t parser = { .config = config };
uc_compiler_t compiler = { .parser = &parser, .exprstack = &expr };
- uc_function_t *fn;
+ uc_program_t *prog;
+
+ prog = uc_program_new(source);
uc_lexer_init(&parser.lex, config, source);
- uc_compiler_init(&compiler, "main", 0, source,
+ uc_compiler_init(&compiler, "main", 0, prog,
config && config->strict_declarations);
uc_compiler_parse_advance(&compiler);
@@ -2899,4 +2909,51 @@ uc_compile(uc_parse_config_t *config, uc_source_t *source, char **errp)
uc_lexer_free(&parser.lex);
return fn;
+#endif
+}
+
+static uc_function_t *
+uc_compile_from_bytecode(uc_parse_config_t *config, uc_source_t *source, char **errp)
+{
+ uc_function_t *fn = NULL;
+ uc_program_t *prog;
+
+ prog = uc_program_from_file(source->fp, errp);
+
+ if (prog) {
+ fn = uc_program_entry(prog);
+
+ if (!fn) {
+ if (errp)
+ xasprintf(errp, "Program file contains no entry function\n");
+
+ uc_program_free(prog);
+ }
+ }
+
+ return fn;
+}
+
+uc_function_t *
+uc_compile(uc_parse_config_t *config, uc_source_t *source, char **errp)
+{
+ uc_function_t *fn = NULL;
+
+ switch (uc_source_type_test(source)) {
+ case UC_SOURCE_TYPE_PLAIN:
+ fn = uc_compile_from_source(config, source, errp);
+ break;
+
+ case UC_SOURCE_TYPE_PRECOMPILED:
+ fn = uc_compile_from_bytecode(config, source, errp);
+ break;
+
+ default:
+ if (errp)
+ xasprintf(errp, "Unrecognized source type\n");
+
+ break;
+ }
+
+ return fn;
}