#ifndef APFL_CONTEXT_H #define APFL_CONTEXT_H #ifdef __cplusplus extern "C" { #endif #include #include #include "bytecode.h" #include "hashmap.h" #include "gc.h" #include "value.h" #include "scope.h" #define RESULT_OFF_FOR_LONGJMP 1 struct scopes { // Both scope and closure_scope can be null struct scope *local; struct scope *closure; }; struct matcher_capture_transfer { struct apfl_string *var; size_t path_start; size_t path_len; bool local; }; struct matcher { struct matcher_instruction_list *instructions; size_t value_count; struct apfl_value *values; }; struct stack { struct apfl_value *items; size_t len; size_t cap; }; struct matcher_stack { struct matcher **items; size_t len; size_t cap; }; enum call_stack_entry_type { CSE_FUNCTION, CSE_CFUNCTION, CSE_MATCHER, CSE_FUNCTION_DISPATCH, }; struct func_call_stack_entry { size_t pc; struct instruction_list *instructions; // scopes.scope will be created lazily struct scopes scopes; int execution_line; struct matcher_stack matcher_stack; bool returning_from_matcher; bool matcher_result; }; struct cfunc_call_stack_entry { struct cfunction *func; }; enum matcher_mode { MATCHER_MODE_VALUE, MATCHER_MODE_STOP, MATCHER_MODE_LIST_START, MATCHER_MODE_LIST_END, MATCHER_MODE_LIST_REMAINING, MATCHER_MODE_LIST_UNDERFLOW, }; struct matcher_state { enum matcher_mode mode; size_t lower; size_t upper; }; struct matcher_call_stack_entry { size_t pc; bool from_predicate; struct matcher *matcher; struct scopes scopes; size_t capture_index; size_t capture_count; struct apfl_value *captures; struct matcher_capture_transfer *transfers; struct matcher_state *matcher_state_stack; size_t matcher_state_stack_len; size_t matcher_state_stack_cap; }; struct func_dispatch_call_stack_entry { size_t subfunc; struct scopes scopes; bool returning_from_matcher; bool matcher_result; struct function *function; }; struct call_stack_entry { enum call_stack_entry_type type; struct stack stack; union { struct func_call_stack_entry func; struct cfunc_call_stack_entry cfunc; struct matcher_call_stack_entry matcher; struct func_dispatch_call_stack_entry func_dispatch; }; }; struct call_stack { struct call_stack_entry *items; size_t len; size_t cap; }; struct error_handler { jmp_buf jump; bool with_error_on_stack; }; struct iterative_runners_list { apfl_iterative_runner *items; size_t len; size_t cap; }; struct apfl_ctx_data { struct gc gc; apfl_panic_callback panic_callback; void *panic_callback_data; struct stack toplevel_stack; struct scope *globals; struct call_stack call_stack; struct error_handler *error_handler; struct iterative_runners_list iterative_runners; struct apfl_format_writer output_writer; }; void apfl_matcher_call_stack_entry_deinit(struct apfl_allocator, struct matcher_call_stack_entry *); void apfl_call_stack_entry_deinit(struct apfl_allocator, struct call_stack_entry *); struct stack apfl_stack_new(void); bool apfl_stack_push(apfl_ctx, struct apfl_value); void apfl_stack_must_push(apfl_ctx ctx, struct apfl_value value); bool apfl_stack_check_index(apfl_ctx, apfl_stackidx *); bool apfl_stack_has_index(apfl_ctx, apfl_stackidx); bool apfl_stack_pop(apfl_ctx, struct apfl_value *value, apfl_stackidx); struct apfl_value apfl_stack_must_pop(apfl_ctx, apfl_stackidx); bool apfl_stack_get(apfl_ctx, struct apfl_value *value, apfl_stackidx); struct apfl_value apfl_stack_must_get(apfl_ctx, apfl_stackidx); bool apfl_stack_drop(apfl_ctx, apfl_stackidx); bool apfl_stack_drop_multi(apfl_ctx ctx, size_t count, apfl_stackidx *indices); void apfl_stack_clear(apfl_ctx); struct apfl_value *apfl_stack_push_placeholder(apfl_ctx); bool apfl_move_string_onto_stack(apfl_ctx, struct apfl_string); struct call_stack_entry *apfl_call_stack_cur_entry(apfl_ctx); struct scope *apfl_closure_scope_for_func(apfl_ctx, struct scopes); struct apfl_format_writer apfl_get_output_writer(apfl_ctx); enum apfl_result apfl_do_protected( apfl_ctx ctx, void (*callback)(apfl_ctx, void *), void *opaque, bool *with_error_on_stack ); bool apfl_ctx_register_iterative_runner(apfl_ctx, apfl_iterative_runner); void apfl_ctx_unregister_iterative_runner(apfl_ctx, apfl_iterative_runner); struct matcher *apfl_matcher_new(struct gc *, struct matcher_instruction_list *); void apfl_matcher_deinit(struct apfl_allocator, struct matcher *); void apfl_gc_matcher_traverse(struct matcher *, gc_visitor, void *); void apfl_iterative_runner_visit_gc_objects(apfl_iterative_runner, gc_visitor, void *); #ifdef __cplusplus } #endif #endif