diff options
-rw-r--r-- | compiler.c | 17 | ||||
-rw-r--r-- | include/ucode/program.h | 5 | ||||
-rw-r--r-- | include/ucode/types.h | 5 | ||||
-rw-r--r-- | lib.c | 4 | ||||
-rw-r--r-- | program.c | 160 | ||||
-rw-r--r-- | types.c | 10 | ||||
-rw-r--r-- | vm.c | 4 |
7 files changed, 129 insertions, 76 deletions
@@ -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; @@ -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; } @@ -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; @@ -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: @@ -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); |