#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 "matcher.h" #include "value.h" #include "scope.h" #define RESULT_OFF_FOR_LONGJMP 1 struct stack { struct apfl_value *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; // Both scope and closure_scope can be null (scope will be created lazily) struct scope *scope; struct scope *closure_scope; int execution_line; struct matcher *matcher; bool returning_from_matcher; }; 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_stack_entry { enum matcher_mode mode; size_t lower; size_t upper; }; struct matcher_call_stack_entry { size_t pc; struct matcher *matcher; struct matcher_stack_entry *matcher_stack; size_t matcher_stack_len; size_t matcher_stack_cap; }; struct func_dispatch_call_stack_entry { size_t subfunc; bool returning_from_matcher; 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_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 apfl_format_writer apfl_get_output_writer(apfl_ctx); bool apfl_ctx_register_iterative_runner(apfl_ctx, apfl_iterative_runner); void apfl_ctx_unregister_iterative_runner(apfl_ctx, apfl_iterative_runner); void apfl_iterative_runner_visit_gc_objects(apfl_iterative_runner, gc_visitor, void *); #ifdef __cplusplus } #endif #endif