summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--compiler.c17
-rw-r--r--include/ucode/program.h5
-rw-r--r--include/ucode/types.h5
-rw-r--r--lib.c4
-rw-r--r--program.c160
-rw-r--r--types.c10
-rw-r--r--vm.c4
7 files changed, 129 insertions, 76 deletions
diff --git a/compiler.c b/compiler.c
index 67053c5..d03ce5e 100644
--- a/compiler.c
+++ b/compiler.c
@@ -121,7 +121,7 @@ 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_program_t *program, bool strict)
+uc_compiler_init(uc_compiler_t *compiler, const char *name, uc_source_t *source, size_t srcpos, uc_program_t *program, bool strict)
{
uc_value_t *varname = ucv_string_new("(callee)");
uc_function_t *fn;
@@ -129,7 +129,7 @@ uc_compiler_init(uc_compiler_t *compiler, const char *name, size_t srcpos, uc_pr
compiler->scope_depth = 0;
compiler->program = program;
- compiler->function = uc_program_function_new(program, name, srcpos);
+ compiler->function = uc_program_function_new(program, name, source, srcpos);
compiler->locals.count = 0;
compiler->locals.entries = NULL;
@@ -163,7 +163,7 @@ uc_compiler_current_chunk(uc_compiler_t *compiler)
static uc_source_t *
uc_compiler_current_source(uc_compiler_t *compiler)
{
- return compiler->program->source;
+ return uc_program_function_source(compiler->function);
}
__attribute__((format(printf, 3, 0))) static void
@@ -1110,7 +1110,8 @@ 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_init(&fncompiler, NULL, uc_compiler_current_source(compiler),
+ compiler->parser->prev.pos,
compiler->program,
uc_compiler_is_strict(compiler));
@@ -1561,7 +1562,9 @@ uc_compiler_compile_function(uc_compiler_t *compiler)
}
uc_compiler_init(&fncompiler,
- name ? ucv_string_get(name) : NULL, compiler->parser->prev.pos,
+ name ? ucv_string_get(name) : NULL,
+ uc_compiler_current_source(compiler),
+ compiler->parser->prev.pos,
compiler->program,
uc_compiler_is_strict(compiler));
@@ -2926,10 +2929,10 @@ uc_compile_from_source(uc_parse_config_t *config, uc_source_t *source, char **er
uc_program_t *prog;
uc_function_t *fn;
- prog = uc_program_new(source);
+ prog = uc_program_new();
uc_lexer_init(&parser.lex, config, source);
- uc_compiler_init(&compiler, "main", 0, prog,
+ uc_compiler_init(&compiler, "main", source, 0, prog,
config && config->strict_declarations);
uc_compiler_parse_advance(&compiler);
diff --git a/include/ucode/program.h b/include/ucode/program.h
index e8b96ed..e540807 100644
--- a/include/ucode/program.h
+++ b/include/ucode/program.h
@@ -20,7 +20,7 @@
#include "types.h"
-uc_program_t *uc_program_new(uc_source_t *);
+uc_program_t *uc_program_new(void);
static inline uc_program_t *
uc_program_get(uc_program_t *prog) {
@@ -46,9 +46,10 @@ uc_program_put(uc_program_t *prog) {
fn = fn##_tmp, \
fn##_tmp = (uc_function_t *)fn##_tmp->progref.prev)
-uc_function_t *uc_program_function_new(uc_program_t *, const char *, size_t);
+uc_function_t *uc_program_function_new(uc_program_t *, const char *, uc_source_t *, size_t);
size_t uc_program_function_id(uc_program_t *, uc_function_t *);
uc_function_t *uc_program_function_load(uc_program_t *, size_t);
+uc_source_t *uc_program_function_source(uc_function_t *);
size_t uc_program_function_srcpos(uc_function_t *, size_t);
void uc_program_function_free(uc_function_t *);
diff --git a/include/ucode/types.h b/include/ucode/types.h
index cde84f6..14f2a43 100644
--- a/include/ucode/types.h
+++ b/include/ucode/types.h
@@ -115,6 +115,7 @@ typedef struct uc_function {
bool arrow, vararg, strict;
size_t nargs;
size_t nupvals;
+ size_t srcidx;
size_t srcpos;
uc_chunk_t chunk;
struct uc_program *program;
@@ -204,11 +205,13 @@ uc_declare_vector(uc_resource_types_t, uc_resource_type_t *);
/* Program structure definitions */
+uc_declare_vector(uc_sources_t, uc_source_t *);
+
typedef struct uc_program {
uc_value_t header;
uc_value_list_t constants;
uc_weakref_t functions;
- uc_source_t *source;
+ uc_sources_t sources;
} uc_program_t;
diff --git a/lib.c b/lib.c
index 0dee073..779e3f5 100644
--- a/lib.c
+++ b/lib.c
@@ -2378,7 +2378,7 @@ uc_include_common(uc_vm_t *vm, size_t nargs, bool raw_mode)
if (!closure)
return NULL;
- p = include_path(closure->function->program->source->runpath, ucv_string_get(path));
+ p = include_path(uc_program_function_source(closure->function)->runpath, ucv_string_get(path));
if (!p) {
uc_vm_raise_exception(vm, EXCEPTION_RUNTIME,
@@ -2896,7 +2896,7 @@ uc_sourcepath(uc_vm_t *vm, size_t nargs)
continue;
}
- path = realpath(frame->closure->function->program->source->runpath, NULL);
+ path = realpath(uc_program_function_source(frame->closure->function)->runpath, NULL);
break;
}
diff --git a/program.c b/program.c
index 57252f8..4321409 100644
--- a/program.c
+++ b/program.c
@@ -25,7 +25,7 @@
uc_program_t *
-uc_program_new(uc_source_t *source)
+uc_program_new(void)
{
uc_program_t *prog;
@@ -37,15 +37,13 @@ uc_program_new(uc_source_t *source)
prog->functions.next = &prog->functions;
prog->functions.prev = &prog->functions;
- prog->source = uc_source_get(source);
-
uc_vallist_init(&prog->constants);
return prog;
}
uc_function_t *
-uc_program_function_new(uc_program_t *prog, const char *name, size_t srcpos)
+uc_program_function_new(uc_program_t *prog, const char *name, uc_source_t *source, size_t srcpos)
{
uc_function_t *func;
size_t namelen = 0;
@@ -58,6 +56,13 @@ uc_program_function_new(uc_program_t *prog, const char *name, size_t srcpos)
if (name)
strcpy(func->name, name);
+ for (func->srcidx = 0; func->srcidx < prog->sources.count; func->srcidx++)
+ if (prog->sources.entries[func->srcidx] == source)
+ break;
+
+ if (func->srcidx >= prog->sources.count)
+ uc_vector_push(&prog->sources, uc_source_get(source));
+
func->nargs = 0;
func->nupvals = 0;
func->srcpos = srcpos;
@@ -97,6 +102,14 @@ uc_program_function_load(uc_program_t *prog, size_t id)
return NULL;
}
+uc_source_t *
+uc_program_function_source(uc_function_t *fn)
+{
+ assert(fn->srcidx < fn->program->sources.count);
+
+ return fn->program->sources.entries[fn->srcidx];
+}
+
size_t
uc_program_function_srcpos(uc_function_t *fn, size_t off)
{
@@ -294,6 +307,7 @@ write_function(uc_function_t *func, FILE *file, bool debug)
write_u16(func->nargs, file);
write_u16(func->nupvals, file);
+ write_u32(func->srcidx, file);
write_u32(func->srcpos, file);
write_chunk(&func->chunk, file, flags);
@@ -308,33 +322,38 @@ uc_program_write(uc_program_t *prog, FILE *file, bool debug)
if (debug)
flags |= UC_PROGRAM_F_DEBUG;
- if (debug && prog->source) {
+ if (debug && prog->sources.count)
flags |= UC_PROGRAM_F_SOURCEINFO;
- if (prog->source->buffer)
- flags |= UC_PROGRAM_F_SOURCEBUF;
- }
-
/* magic word + flags */
write_u32(UC_PRECOMPILED_BYTECODE_MAGIC, file);
write_u32(flags, file);
+ /* write source information */
if (flags & UC_PROGRAM_F_SOURCEINFO) {
- /* write source file name */
- write_string(prog->source->filename, file);
+ write_u32(prog->sources.count, file);
- /* include source buffer if program was compiled from stdin */
- if (flags & UC_PROGRAM_F_SOURCEBUF)
- write_string(prog->source->buffer, file);
+ for (i = 0; i < prog->sources.count; i++) {
+ /* write source file name */
+ write_string(prog->sources.entries[i]->filename, file);
- /* write lineinfo data */
- write_vector(&prog->source->lineinfo, file);
+ /* include source buffer if program was compiled from stdin */
+ if (prog->sources.entries[i]->buffer)
+ write_string(prog->sources.entries[i]->buffer, file);
+ else
+ //write_string("", file);
+ write_u32(0, file);
+
+ /* write lineinfo data */
+ write_vector(&prog->sources.entries[i]->lineinfo, file);
+ }
}
/* write constants */
write_vallist(&prog->constants, file);
/* write program sections */
+ i = 0;
uc_program_function_foreach(prog, fn1) {
(void)fn1;
i++;
@@ -542,57 +561,73 @@ out:
}
static uc_source_t *
-read_sourceinfo(uc_source_t *input, uint32_t flags, char **errp)
+read_sourceinfo(uc_source_t *input, uint32_t flags, char **errp, uc_program_t *program)
{
char *path = NULL, *code = NULL;
uc_source_t *source = NULL;
- size_t len;
+ size_t len, count;
if (flags & UC_PROGRAM_F_SOURCEINFO) {
- if (!read_size_t(input->fp, &len, sizeof(uint32_t), "sourceinfo filename length", errp))
- goto out;
+ if (!read_size_t(input->fp, &count, sizeof(uint32_t), "amount of source entries", errp))
+ return NULL;
- path = xalloc(len);
+ while (count > 0) {
+ if (!read_size_t(input->fp, &len, sizeof(uint32_t), "sourceinfo filename length", errp))
+ return NULL;
- if (!read_string(input->fp, path, len, "sourceinfo filename", errp))
- goto out;
+ path = xalloc(len);
+
+ if (!read_string(input->fp, path, len, "sourceinfo filename", errp)) {
+ free(path);
+
+ return NULL;
+ }
- if (flags & UC_PROGRAM_F_SOURCEBUF) {
if (!read_size_t(input->fp, &len, sizeof(uint32_t), "sourceinfo code buffer length", errp))
- goto out;
+ return NULL;
- code = xalloc(len);
+ if (len > 0) {
+ code = xalloc(len);
- if (!read_string(input->fp, code, len, "sourceinfo code buffer data", errp)) {
- free(code);
- goto out;
+ if (!read_string(input->fp, code, len, "sourceinfo code buffer data", errp)) {
+ free(code);
+ free(path);
+
+ return NULL;
+ }
+
+ source = uc_source_new_buffer(path, code, len);
}
+ else {
+ source = uc_source_new_file(path);
- source = uc_source_new_buffer(path, code, len);
- }
- else {
- source = uc_source_new_file(path);
+ if (!source) {
+ fprintf(stderr, "Unable to open source file %s: %s\n", path, strerror(errno));
+ source = uc_source_new_buffer(path, xstrdup(""), 0);
+ }
+ }
+
+ if (!read_vector(input->fp, &source->lineinfo, "sourceinfo lineinfo", errp)) {
+ uc_source_put(source);
+ free(path);
- if (!source) {
- fprintf(stderr, "Unable to open source file %s: %s\n", path, strerror(errno));
- source = uc_source_new_buffer(path, xstrdup(""), 0);
+ return NULL;
}
- }
- if (!read_vector(input->fp, &source->lineinfo, "sourceinfo lineinfo", errp)) {
- uc_source_put(source);
- source = NULL;
- goto out;
+ uc_source_runpath_set(source, input->runpath);
+ uc_vector_push(&program->sources, source);
+
+ free(path);
+
+ count--;
}
}
else {
source = uc_source_new_buffer("[no source]", xstrdup(""), 0);
- }
-
- uc_source_runpath_set(source, input->runpath);
-out:
- free(path);
+ uc_source_runpath_set(source, input->runpath);
+ uc_vector_push(&program->sources, source);
+ }
return source;
}
@@ -701,8 +736,10 @@ out:
static bool
read_function(FILE *file, uc_program_t *program, size_t idx, char **errp)
{
+ size_t nargs, nupvals, srcidx, srcpos;
char subjbuf[64], *name = NULL;
uc_function_t *func = NULL;
+ uc_source_t *source;
uint32_t flags, u32;
snprintf(subjbuf, sizeof(subjbuf), "function #%zu flags", idx);
@@ -726,15 +763,25 @@ read_function(FILE *file, uc_program_t *program, size_t idx, char **errp)
snprintf(subjbuf, sizeof(subjbuf), "function #%zu (%s) arg count and offset", idx, name ? name : "-");
- func = (uc_function_t *)uc_program_function_new(program, name, 0);
+ if (!read_size_t(file, &nargs, sizeof(uint16_t), subjbuf, errp) ||
+ !read_size_t(file, &nupvals, sizeof(uint16_t), subjbuf, errp) ||
+ !read_size_t(file, &srcidx, sizeof(uint32_t), subjbuf, errp) ||
+ !read_size_t(file, &srcpos, sizeof(uint32_t), subjbuf, errp)) {
+ goto out;
+ }
+
+ // FIXME
+ if (srcidx < program->sources.count)
+ source = program->sources.entries[srcidx];
+ else
+ source = program->sources.entries[0];
+
+ func = (uc_function_t *)uc_program_function_new(program, name, source, srcpos);
func->arrow = (flags & UC_FUNCTION_F_IS_ARROW);
func->vararg = (flags & UC_FUNCTION_F_IS_VARARG);
func->strict = (flags & UC_FUNCTION_F_IS_STRICT);
-
- if (!read_size_t(file, &func->nargs, sizeof(uint16_t), subjbuf, errp) ||
- !read_size_t(file, &func->nupvals, sizeof(uint16_t), subjbuf, errp) ||
- !read_size_t(file, &func->srcpos, sizeof(uint32_t), subjbuf, errp))
- goto out;
+ func->nargs = nargs;
+ func->nupvals = nupvals;
snprintf(subjbuf, sizeof(subjbuf), "function #%zu (%s) body", idx, name ? name : "-");
@@ -755,7 +802,6 @@ uc_program_t *
uc_program_load(uc_source_t *input, char **errp)
{
uc_program_t *program = NULL;
- uc_source_t *source = NULL;
uint32_t flags, nfuncs, i;
if (!read_u32(input->fp, &i, "file magic", errp))
@@ -769,15 +815,11 @@ uc_program_load(uc_source_t *input, char **errp)
if (!read_u32(input->fp, &flags, "program flags", errp))
goto out;
- source = read_sourceinfo(input, flags, errp);
+ program = uc_program_new();
- if (!source)
+ if (!read_sourceinfo(input, flags, errp, program))
goto out;
- program = uc_program_new(source);
-
- uc_source_put(source);
-
if (!read_vallist(input->fp, &program->constants, "constants", errp))
goto out;
diff --git a/types.c b/types.c
index 2fba207..d0b933d 100644
--- a/types.c
+++ b/types.c
@@ -191,8 +191,8 @@ ucv_gc_mark(uc_value_t *uv)
case UC_PROGRAM:
program = (uc_program_t *)uv;
- if (program->source)
- ucv_gc_mark(&program->source->header);
+ for (i = 0; i < program->sources.count; i++)
+ ucv_gc_mark(&program->sources.entries[i]->header);
break;
@@ -283,7 +283,11 @@ ucv_free(uc_value_t *uv, bool retain)
uc_program_function_free(func);
uc_vallist_free(&program->constants);
- ucv_put_value(&program->source->header, retain);
+
+ for (i = 0; i < program->sources.count; i++)
+ ucv_put_value(&program->sources.entries[i]->header, retain);
+
+ uc_vector_clear(&program->sources);
break;
case UC_SOURCE:
diff --git a/vm.c b/vm.c
index 29ace38..0529ee3 100644
--- a/vm.c
+++ b/vm.c
@@ -211,7 +211,7 @@ uc_vm_frame_program(uc_callframe_t *frame)
static uc_source_t *
uc_vm_frame_source(uc_callframe_t *frame)
{
- return frame->closure ? frame->closure->function->program->source : NULL;
+ return frame->closure ? uc_program_function_source(frame->closure->function) : NULL;
}
static uc_callframe_t *
@@ -829,7 +829,7 @@ uc_vm_capture_stacktrace(uc_vm_t *vm, size_t i)
if (frame->closure) {
function = frame->closure->function;
- source = function->program->source;
+ source = uc_program_function_source(function);
off = (frame->ip - uc_vm_frame_chunk(frame)->entries) - 1;
srcpos = uc_program_function_srcpos(function, off);