/* xslate.h */ #include "xshelper.h" #if defined(__GNUC__) && !defined(TX_NO_DTC) /* enable DTC optimization */ #define TX_DIRECT_THREADED_CODE #endif #define TX_RAW_CLASS "Text::Xslate::Type::Raw" #define TX_PAIR_CLASS "Text::Xslate::Type::Pair" #define TX_MACRO_CLASS "Text::Xslate::Type::Macro" /* arbitrary initial buffer size */ #define TX_HINT_SIZE 200 /* max calling depth (execution/macrocall) */ #define TX_MAX_DEPTH 100 #define TXC(name) static void CAT2(TXCODE_, name)(pTHX_ tx_state_t* const txst PERL_UNUSED_DECL) /* TXC_xxx macros provide the information of arguments, interpreted by tool/opcode.pl */ #define TXC_w_sv(n) TXC(n) /* has TX_op_arg_sv as a SV */ #define TXC_w_key(n) TXC(n) /* has TX_op_arg_sv as a keyword */ #define TXC_w_sviv(n) TXC(n) /* has TX_op_arg_sv able to SvIVX */ #define TXC_w_int(n) TXC(n) /* has TX_op_arg_iv */ #define TXC_w_var(n) TXC(n) /* has TX_op_arg_iv as a local variable index */ #define TXC_goto(n) TXC(n) /* has TX_op_arg_pc for goto */ #define TXARGf_SV ((U8)(0x01)) #define TXARGf_INT ((U8)(0x02)) #define TXARGf_KEY ((U8)(0x04)) #define TXARGf_VAR ((U8)(0x08)) #define TXARGf_PC ((U8)(0x10)) #define TXCODE_W_SV (TXARGf_SV) #define TXCODE_W_SVIV (TXARGf_SV | TXARGf_INT) #define TXCODE_W_KEY (TXARGf_SV | TXARGf_KEY) #define TXCODE_W_INT (TXARGf_INT) #define TXCODE_W_VAR (TXARGf_INT | TXARGf_VAR) #define TXCODE_GOTO (TXARGf_PC) /* TX_st and TX_op are valid only in opcodes */ #define TX_st (txst) #define TX_pop() (*(PL_stack_sp--)) #define TX_frame_at(st, ix) ((AV*)AvARRAY((st)->frames)[ix]) #define TX_current_framex(st) TX_frame_at((st), (st)->current_frame) #define TX_current_frame() TX_current_framex(TX_st) #define TX_CATCH_ERROR() UNLIKELY(!!sv_true(ERRSV)) /* template object, stored in $self->{template}{$file} */ enum tx_tobj_ix { TXo_MTIME, TXo_CACHEPATH, TXo_FULLPATH, /* TXo_FULLPATH must be the last one */ /* dependencies here */ TXo_least_size }; /* vm execution frame object */ enum tx_frame_ix { TXframe_NAME, TXframe_OUTPUT, TXframe_RETADDR, TXframe_START_LVAR, /* TXframe_START_LVAR must be the last one */ /* local variables here */ TXframe_least_size = TXframe_START_LVAR }; /* macro object */ enum tx_macro_ix { TXm_NAME, TXm_ADDR, TXm_NARGS, TXm_OUTER, TXm_size, }; /* for-loop variables */ enum tx_for_ix { TXfor_ITEM, TXfor_ITER, TXfor_ARRAY, }; struct tx_state_s; struct tx_code_s; struct tx_info_s; typedef struct tx_state_s tx_state_t; typedef struct tx_code_s tx_code_t; typedef struct tx_info_s tx_info_t; #define TX_op (TX_st->pc) #define TX_PC2POS(st, p) ((UV)((p) - (st)->code)) #define TX_POS2PC(st, u) ((st)->code + (u)) typedef tx_code_t* tx_pc_t; #define TX_RETURN_NEXT() STMT_START { TX_st->pc++; return; } STMT_END #define TX_RETURN_PC(x) STMT_START { TX_st->pc = (x); return; } STMT_END #ifdef TX_DIRECT_THREADED_CODE typedef const void* tx_exec_t; #define TX_RUNOPS(st) tx_runops(aTHX_ st) #else /* TX_DIRECT_THREADED_CODE */ typedef void (*tx_exec_t)(pTHX_ tx_state_t* const); #define TX_RUNOPS(st) STMT_START { \ while((st)->pc->exec_code != TXCODE_end) { \ CALL_FPTR((st)->pc->exec_code)(aTHX_ (st)); \ } \ } STMT_END #endif /* TX_DIRECT_THREADED_CODE */ /* virtual machine state */ struct tx_state_s { tx_pc_t pc; /* the program counter */ tx_code_t* code; /* compiled code */ U32 code_len; SV* output; /* registers */ SV* sa; SV* sb; SV* targ; /* variables */ HV* vars; /* template variables */ /* stack frame */ AV* frames; /* see enum txframeo_ix */ I32 current_frame; /* current frame index */ SV** pad; /* AvARRAY(frame[current_frame]) + 3 */ HV* symbol; /* symbol table (e.g. name => \&body | [macro object]) */ U32 hint_size; /* suggested template size (bytes) */ AV* tmpl; /* template objects. see enum txtmplo_ix */ SV* engine; /* Text::Xslate instance */ tx_info_t* info; /* index -> an oinfo object */ }; /* opcode structure */ struct tx_code_s { tx_exec_t exec_code; union { SV* sv; IV iv; tx_pc_t pc; } u_arg; }; /* opcode information */ struct tx_info_s { U16 optype; U16 line; SV* file; }; #define TX_VERBOSE_DEFAULT 1 void tx_warn(pTHX_ tx_state_t* const, const char* const fmt, ...) __attribute__format__(__printf__, pTHX_2, pTHX_3); void tx_error(pTHX_ tx_state_t* const, const char* const fmt, ...) __attribute__format__(__printf__, pTHX_2, pTHX_3); const char* tx_neat(pTHX_ SV* const sv); SV* tx_call_sv(pTHX_ tx_state_t* const st, SV* const sv, I32 const flags, const char* const name); SV* tx_proccall(pTHX_ tx_state_t* const st, SV* const proc, const char* const name); SV* tx_mark_raw(pTHX_ SV* const str); SV* tx_unmark_raw(pTHX_ SV* const str); int tx_sv_is_array_ref(pTHX_ SV* const sv); int tx_sv_is_hash_ref(pTHX_ SV* const sv); /* builtin method stuff */ SV* tx_methodcall(pTHX_ tx_state_t* const st, SV* const method); void tx_register_builtin_methods(pTHX_ HV* const hv);