diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c669b50..a1eb726 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,7 +13,9 @@ set(commonfiles alloc.c bytecode.c compile.c + context.c encode.c + eval.c error.c expr.c format.c @@ -21,12 +23,16 @@ set(commonfiles hashmap.c io.c messages.c + modules.c numparse.c parser.c position.c + registry.c resizable.c + scope.c source_readers.c strings.c + symbols.c token.c tokenizer.c value.c @@ -34,14 +40,8 @@ set(commonfiles add_library(apfl ${commonfiles} - builtins.c - context.c - eval.c - modules.c + globals.c re.c - registry.c - scope.c - symbols.c mod_globals.c mod_re.c diff --git a/src/apfl.h b/src/apfl.h index c585d62..05a8989 100644 --- a/src/apfl.h +++ b/src/apfl.h @@ -860,6 +860,8 @@ void apfl_error_decorate_with_backtrace(apfl_ctx ctx, void *ignored); void apfl_load(apfl_ctx, struct apfl_source_reader, apfl_stackidx name); +void apfl_bytecode_save(apfl_ctx, struct apfl_io_writer, apfl_stackidx func); + void apfl_registry_set(apfl_ctx, void *key_major, size_t key_minor, apfl_stackidx); void apfl_registry_delete(apfl_ctx, void *key_major, size_t key_minor); bool apfl_registry_try_get(apfl_ctx, void *key_major, size_t key_minor); diff --git a/src/apflc.c b/src/apflc.c index 5297246..79a9249 100644 --- a/src/apflc.c +++ b/src/apflc.c @@ -83,23 +83,6 @@ c_source_epilogue(struct apfl_io_writer w, const char *function_name) ); } -struct roots { - struct instruction_list *ilist; - struct apfl_string *name; -}; - -static void -getroots(void *own_opaque, gc_visitor visitor, void *visitor_opaque) -{ - struct roots *roots = own_opaque; - if (roots->ilist != NULL) { - visitor(visitor_opaque, GC_OBJECT_FROM(roots->ilist, GC_TYPE_INSTRUCTIONS)); - } - if (roots->name != NULL) { - visitor(visitor_opaque, GC_OBJECT_FROM(roots->name, GC_TYPE_STRING)); - } -} - static const char * get_next_string_from_arg(const char *progname, const char ***argpp) { @@ -132,48 +115,24 @@ closefile(FILE *f) } } -static bool -compile( - const char *progname, - struct gc *gc, - struct apfl_io_reader r, - struct instruction_list *ilist -) { - apfl_tokenizer_ptr tokenizer = apfl_tokenizer_new(gc->allocator, apfl_io_reader_as_source_reader(&r)); - if (tokenizer == NULL) { - return false; - } +struct protected_compiling_data { + const char *name; + struct apfl_io_reader *r; + struct apfl_io_writer *w; +}; - apfl_parser_ptr parser = apfl_parser_new( - gc->allocator, - apfl_tokenizer_as_token_source(tokenizer) - ); - if (parser == NULL) { - apfl_tokenizer_destroy(tokenizer); - fprintf(stderr, "%s: Failed to init parser\n", progname); - return false; - } +static void +protected_compiling(apfl_ctx ctx, void *opaque) +{ + struct protected_compiling_data *data = opaque; - struct apfl_error error; - if (!apfl_compile_whole_file( - gc, - parser, - &error, - ilist - )) { - fprintf(stderr, "%s: Could not compile file:\n", progname); - apfl_error_print(error, stderr); - - apfl_parser_destroy(parser); - apfl_tokenizer_destroy(tokenizer); - return false; - } - - apfl_parser_destroy(parser); - apfl_tokenizer_destroy(tokenizer); - return true; + apfl_push_const_string(ctx, data->name); + apfl_load(ctx, apfl_io_reader_as_source_reader(data->r), -1); + apfl_bytecode_save(ctx, *data->w, -1); } +#define MAIN_TRY_FMT(x) if (!(x)) { goto error; } + int main(int argc, const char *argv[]) { @@ -187,7 +146,7 @@ main(int argc, const char *argv[]) if (*argp != NULL && apfl_string_eq(*argp, "-c")) { argp++; if ((c_function_name = get_next_string_from_arg(argv[0], &argp)) == NULL) { - goto error_before_gc; + goto error_before_ctx; } } @@ -197,7 +156,7 @@ main(int argc, const char *argv[]) (name_in = get_next_string_from_arg(argv[0], &argp)) == NULL || (name_out = get_next_string_from_arg(argv[0], &argp)) == NULL ) { - goto error_before_gc; + goto error_before_ctx; } int rv = 1; @@ -206,40 +165,18 @@ main(int argc, const char *argv[]) (in = openfile(argv[0], name_in, "rb")) == NULL || (out = openfile(argv[0], name_out, "wb")) == NULL ) { - goto error_before_gc; + goto error_before_ctx; } struct apfl_io_reader r = apfl_io_file_reader(in); struct apfl_io_writer w_raw = apfl_io_file_writer(out); - struct roots roots = { - .ilist = NULL, - .name = NULL, - }; - - struct gc gc; - apfl_gc_init(&gc, apfl_allocator_default(), getroots, &roots); - - if ((roots.name = apfl_string_copy_to_new_gc_string( - &gc, - apfl_string_view_from(name_in) - )) == NULL) { - goto error; - } - - if ((roots.ilist = apfl_instructions_new(&gc, 1, roots.name)) == NULL) { - goto error; - } - - if (!compile(argv[0], &gc, r, roots.ilist)) { - goto error; - } - if (c_function_name != NULL && !c_source_prelude(w_raw)) { fprintf(stderr, "%s: IO error\n", argv[0]); - goto error; + goto error_before_ctx; } + struct apfl_io_writer w_err = apfl_io_file_writer(stderr); struct apfl_io_writer bytecode_writer = w_raw; struct c_writer_data c_writer_data = { .w = w_raw, @@ -252,12 +189,40 @@ main(int argc, const char *argv[]) }; } - if (!apfl_bytecode_serialize( - gc.allocator, - bytecode_writer, - roots.ilist - )) { - fprintf(stderr, "%s: Could not serialize bytecode\n", argv[0]); + apfl_ctx ctx = apfl_ctx_new((struct apfl_config) { + .allocator = apfl_allocator_default(), + .output_writer = apfl_io_file_writer(stdout), + .no_standard_modules = true, + }); + + if (ctx == NULL) { + fprintf(stderr, "Could not init context\n"); + goto error; + } + + struct protected_compiling_data data = { + .name = name_in, + .r = &r, + .w = &bytecode_writer, + }; + + switch (apfl_do_protected(ctx, protected_compiling, &data, NULL)) { + case APFL_RESULT_OK : + break; + case APFL_RESULT_ERR: + MAIN_TRY_FMT(apfl_io_write_string(w_err, "Error occurred during compilation:\n")); + if (apfl_get_type(ctx, -1) == APFL_VALUE_STRING) { + MAIN_TRY_FMT(apfl_io_write_string(w_err, apfl_get_string(ctx, -1))); + } else { + MAIN_TRY_FMT(apfl_debug_print_val(ctx, -1, w_err)); + } + MAIN_TRY_FMT(apfl_io_write_byte(w_err, '\n')); + break; + case APFL_RESULT_ERRERR: + MAIN_TRY_FMT(apfl_io_write_string(w_err, "Error occurred during error handling.\n")); + break; + case APFL_RESULT_ERR_ALLOC: + MAIN_TRY_FMT(apfl_io_write_string(w_err, "Fatal: Could not allocate memory.\n")); goto error; } @@ -268,8 +233,8 @@ main(int argc, const char *argv[]) rv = 0; error: - apfl_gc_deinit(&gc); -error_before_gc: + apfl_ctx_destroy(ctx); +error_before_ctx: closefile(in); closefile(out); return rv; diff --git a/src/bytecode.c b/src/bytecode.c index 1f5626b..86f7720 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -4,6 +4,7 @@ #include "alloc.h" #include "bytecode.h" +#include "context.h" #include "encode.h" #include "format.h" #include "gc.h" @@ -1014,39 +1015,6 @@ bytecode_serialize_inner( return true; } -bool -apfl_bytecode_serialize( - struct apfl_allocator allocator, - struct apfl_io_writer w, - struct instruction_list *ilist -) { - struct serializer serializer = { - .allocator = allocator, - .w = w, - .next_string_index = 0, - }; - - if (!apfl_hashmap_init( - &serializer.string_lookup, - allocator, - (struct apfl_hashmap_callbacks) { - .opaque = NULL, - .keys_eq = serializer_strings_eq, - .calc_hash = serializer_strings_hash, - }, - sizeof(struct apfl_string *), - sizeof(uint_least64_t) - )) { - return false; - } - - bool out = bytecode_serialize_inner(&serializer, ilist); - - apfl_hashmap_deinit(&serializer.string_lookup); - - return out; -} - static bool set_ilist_root( struct unserializer *unserializer, @@ -1102,3 +1070,45 @@ apfl_bytecode_unserialize( return out; } + +void +apfl_bytecode_save(apfl_ctx ctx, struct apfl_io_writer w, apfl_stackidx func) +{ + struct apfl_value val = apfl_stack_must_get(ctx, func); + if (val.type != VALUE_FUNC) { + apfl_raise_const_error(ctx, "Can only dump apfl functions"); + } + if (val.func->subfunctions_len != 1) { + apfl_raise_const_error(ctx, "Can only dump functions with exactly one subfunction"); + } + + struct apfl_allocator allocator = apfl_get_allocator(ctx); + + struct serializer serializer = { + .allocator = allocator, + .w = w, + .next_string_index = 0, + }; + + if (!apfl_hashmap_init( + &serializer.string_lookup, + allocator, + (struct apfl_hashmap_callbacks) { + .opaque = NULL, + .keys_eq = serializer_strings_eq, + .calc_hash = serializer_strings_hash, + }, + sizeof(struct apfl_string *), + sizeof(uint_least64_t) + )) { + apfl_raise_alloc_error(ctx); + } + + bool ok = bytecode_serialize_inner(&serializer, val.func->subfunctions[0].body); + + apfl_hashmap_deinit(&serializer.string_lookup); + + if (!ok) { + apfl_raise_const_error(ctx, apfl_messages.io_error); + } +} diff --git a/src/bytecode.h b/src/bytecode.h index 0d61a59..8d290f3 100644 --- a/src/bytecode.h +++ b/src/bytecode.h @@ -107,12 +107,6 @@ void apfl_matcher_instructions_deinit(struct apfl_allocator, struct matcher_inst bool apfl_bytecode_dump_matcher(unsigned indent, struct apfl_io_writer w, struct matcher_instruction_list *milist); bool apfl_bytecode_dump(unsigned indent, struct apfl_io_writer w, struct instruction_list *ilist); -bool apfl_bytecode_serialize( - struct apfl_allocator, - struct apfl_io_writer, - struct instruction_list * -); - struct instruction_list *apfl_bytecode_unserialize( struct gc *gc, struct apfl_io_reader r diff --git a/src/context.c b/src/context.c index 70a4022..07641cd 100644 --- a/src/context.c +++ b/src/context.c @@ -6,10 +6,10 @@ #include "apfl.h" #include "alloc.h" -#include "builtins.h" #include "compile.h" #include "context.h" #include "gc.h" +#include "globals.h" #include "hashmap.h" #include "modules.h" #include "registry.h" @@ -846,8 +846,7 @@ init_globals_protected(apfl_ctx ctx, void *opaque) { (void)opaque; - apfl_builtins(ctx); - apfl_build_native_and_bytecode_combined_module(ctx, -1, apfl_mod_globals()); + apfl_globals(ctx); struct apfl_value val = apfl_stack_must_get(ctx, -1); if (val.type != VALUE_DICT) { diff --git a/src/encode.h b/src/encode.h index 7624309..62b0b9c 100644 --- a/src/encode.h +++ b/src/encode.h @@ -1,5 +1,5 @@ -#ifndef APFL_CONTEXT_H -#define APFL_CONTEXT_H +#ifndef APFL_ENCODE_H +#define APFL_ENCODE_H #ifdef __cplusplus extern "C" { diff --git a/src/globals.apfl b/src/globals.apfl index 28c1c79..eb60d56 100644 --- a/src/globals.apfl +++ b/src/globals.apfl @@ -30,8 +30,6 @@ raise := C.raise symbol := C.symbol splice := C.splice - -serialize-bytecode := C.-serialize-bytecode - -unserialize-bytecode := C.-unserialize-bytecode Some := (C.getsym-Some) @@ -394,8 +392,6 @@ 'load-file -> load-file 'load-string -> load-string 'run-file -> run-file - '-serialize-bytecode -> -serialize-bytecode - '-unserialize-bytecode -> -unserialize-bytecode '& -> & 'substr -> substr 'strsearch -> strsearch diff --git a/src/builtins.c b/src/globals.c similarity index 92% rename from src/builtins.c rename to src/globals.c index a7fe8f6..d0c5843 100644 --- a/src/builtins.c +++ b/src/globals.c @@ -6,9 +6,9 @@ #include "apfl.h" #include "alloc.h" -#include "builtins.h" #include "bytecode.h" #include "context.h" +#include "globals.h" #include "modules.h" #include "parsing.h" #include "scope.h" @@ -602,41 +602,6 @@ loadstring(apfl_ctx ctx) apfl_drop(ctx, -2); } -static void -serialize_bytecode(apfl_ctx ctx) -{ - apfl_get_list_member_by_index(ctx, 0, 0); - struct apfl_value value = apfl_stack_must_get(ctx, -1); - if (value.type == VALUE_CFUNC) { - apfl_raise_const_error(ctx, "-serialize-bytecode needs a apfl function, got a native function instead"); - } else if (value.type != VALUE_FUNC) { - apfl_raise_errorfmt(ctx, "-serialize-bytecode needs a apfl function, got value of type {value:type} instead", value); - } - - apfl_get_list_member_by_index(ctx, 0, 1); - FILE **fh = apfl_get_native_object(ctx, &file_object, -1); - - struct apfl_io_writer w = apfl_io_file_writer(*fh); - - if (!apfl_bytecode_serialize(ctx->gc.allocator, w, value.func->subfunctions[0].body)) { - apfl_raise_const_error(ctx, "Could not serialize function"); - } - - apfl_push_nil(ctx); -} - -static void -unserialize_bytecode(apfl_ctx ctx) -{ - apfl_get_list_member_by_index(ctx, 0, 0); - apfl_drop(ctx, -2); - FILE **fh = apfl_get_native_object(ctx, &file_object, -1); - - struct apfl_io_reader r = apfl_io_file_reader(*fh); - - apfl_load_bytecode(ctx, r); -} - static void set_func_name(apfl_ctx ctx) { @@ -860,19 +825,11 @@ add_builtin(apfl_ctx ctx, const char *name, apfl_cfunc func) apfl_dict_set(ctx, -3, -2, -1); } -static int cmod_searcher_registry_key; - static void cmod_searcher(apfl_ctx ctx) { ONE_ARG(ctx, "cmod-searcher"); - if (!apfl_registry_try_get(ctx, &cmod_searcher_registry_key, 0)) { - apfl_drop(ctx, -1); - apfl_push_nil(ctx); - return; - } - - if (apfl_get_member_if_exists(ctx, -1, -2)) { + if (apfl_modules_query(ctx, -1)) { apfl_sym_some(ctx); apfl_push_pair(ctx, -1, -2); } else { @@ -881,22 +838,7 @@ cmod_searcher(apfl_ctx ctx) } void -apfl_modules_register(apfl_ctx ctx, const char *name, apfl_stackidx modloader) -{ - apfl_move_to_top_of_stack(ctx, modloader); - - if (!apfl_registry_try_get(ctx, &cmod_searcher_registry_key, 0)) { - apfl_dict_create(ctx); - } - - apfl_push_const_string(ctx, name); - apfl_dict_set(ctx, -2, -1, -3); - - apfl_registry_set(ctx, &cmod_searcher_registry_key, 0, -1); -} - -void -apfl_builtins(apfl_ctx ctx) +apfl_globals(apfl_ctx ctx) { apfl_dict_create(ctx); @@ -928,8 +870,6 @@ apfl_builtins(apfl_ctx ctx) add_builtin(ctx, "fclose", impl_fclose); add_builtin(ctx, "load-file", loadfile); add_builtin(ctx, "load-string", loadstring); - add_builtin(ctx, "-serialize-bytecode", serialize_bytecode); - add_builtin(ctx, "-unserialize-bytecode", unserialize_bytecode); add_builtin(ctx, "set-func-name", set_func_name); add_builtin(ctx, "substring", substring); add_builtin(ctx, "stringsearch", stringsearch); @@ -942,4 +882,6 @@ apfl_builtins(apfl_ctx ctx) add_builtin(ctx, "cmod-searcher", cmod_searcher); add_builtin(ctx, "tonumber", tonumber); add_builtin(ctx, "splice", splice); + + apfl_build_native_and_bytecode_combined_module(ctx, -1, apfl_mod_globals()); } diff --git a/src/builtins.h b/src/globals.h similarity index 55% rename from src/builtins.h rename to src/globals.h index ee8983e..ab51429 100644 --- a/src/builtins.h +++ b/src/globals.h @@ -1,5 +1,5 @@ -#ifndef APFL_BUILTINS_H -#define APFL_BUILTINS_H +#ifndef APFL_GLOBALS_H +#define APFL_GLOBALS_H #ifdef __cplusplus extern "C" { @@ -7,7 +7,7 @@ extern "C" { #include "apfl.h" -void apfl_builtins(apfl_ctx); +void apfl_globals(apfl_ctx); #ifdef __cplusplus } diff --git a/src/modules.c b/src/modules.c index b163d08..00b3e77 100644 --- a/src/modules.c +++ b/src/modules.c @@ -19,3 +19,33 @@ apfl_build_native_and_bytecode_combined_module( apfl_list_append(ctx, -1, -3); apfl_call(ctx, -2, -1); } + +static int cmod_searcher_registry_key; + +bool +apfl_modules_query(apfl_ctx ctx, apfl_stackidx modname) +{ + apfl_move_to_top_of_stack(ctx, modname); + + if (!apfl_registry_try_get(ctx, &cmod_searcher_registry_key, 0)) { + apfl_drop(ctx, -1); + return false; + } + + return apfl_get_member_if_exists(ctx, -1, -2); +} + +void +apfl_modules_register(apfl_ctx ctx, const char *name, apfl_stackidx modloader) +{ + apfl_move_to_top_of_stack(ctx, modloader); + + if (!apfl_registry_try_get(ctx, &cmod_searcher_registry_key, 0)) { + apfl_dict_create(ctx); + } + + apfl_push_const_string(ctx, name); + apfl_dict_set(ctx, -2, -1, -3); + + apfl_registry_set(ctx, &cmod_searcher_registry_key, 0, -1); +} diff --git a/src/modules.h b/src/modules.h index 4c6c113..fd685d9 100644 --- a/src/modules.h +++ b/src/modules.h @@ -14,6 +14,8 @@ apfl_build_native_and_bytecode_combined_module( struct apfl_string_view bytecode ); +bool apfl_modules_query(apfl_ctx, apfl_stackidx modname); + struct apfl_string_view apfl_mod_globals(void); struct apfl_string_view apfl_mod_re(void); diff --git a/src/stubs_for_apflc.c b/src/stubs_for_apflc.c index 089df65..c783598 100644 --- a/src/stubs_for_apflc.c +++ b/src/stubs_for_apflc.c @@ -1,32 +1,16 @@ #include #include -#include "context.h" -#include "scope.h" +#include "apfl.h" +#include "globals.h" -#define GC_TRAVERSE_STUB(name, T) \ - void \ - name(T arg, gc_visitor visitor, void *opaque) \ - { \ - (void)arg; \ - (void)visitor; \ - (void)opaque; \ - \ - assert(false && "Stub " #name " called"); \ +#define MODULE_STUB(name) \ + void \ + name(apfl_ctx ctx) \ + { \ + (void)ctx; \ + apfl_dict_create(ctx); \ } -#define GC_DEINIT_STUB(name, T) \ - void name(struct apfl_allocator allocator, T arg) \ - { \ - (void)allocator; \ - (void)arg; \ - \ - assert(false && "Stub " #name " called"); \ - } - -GC_TRAVERSE_STUB(apfl_gc_var_traverse, struct apfl_value *) -GC_TRAVERSE_STUB(apfl_gc_scope_traverse, struct scope *) -GC_TRAVERSE_STUB(apfl_gc_matcher_traverse, struct matcher *) - -GC_DEINIT_STUB(apfl_scope_deinit, struct scope *) -GC_DEINIT_STUB(apfl_matcher_deinit, struct matcher *) +MODULE_STUB(apfl_globals) +MODULE_STUB(apfl_module_re)