blob: 67c9a710a58b615198e8b8129da77ce197da18da [file] [log] [blame]
/* vi:set ts=8 sts=4 sw=4 noet:
*
* VIM - Vi IMproved by Bram Moolenaar
*
* Do ":help uganda" in Vim to read copying and usage conditions.
* Do ":help credits" in Vim to see a list of people who contributed.
* See README.txt for an overview of the Vim source code.
*/
/*
* vim9.h: types and globals used for Vim9 script.
*/
typedef enum {
ISN_EXEC, // execute Ex command line isn_arg.string
ISN_EXECCONCAT, // execute Ex command from isn_arg.number items on stack
ISN_EXEC_SPLIT, // execute Ex command from isn_arg.string split at NL
ISN_LEGACY_EVAL, // evaluate expression isn_arg.string with legacy syntax.
ISN_ECHO, // :echo with isn_arg.echo.echo_count items on top of stack
ISN_EXECUTE, // :execute with isn_arg.number items on top of stack
ISN_ECHOMSG, // :echomsg with isn_arg.number items on top of stack
ISN_ECHOCONSOLE, // :echoconsole with isn_arg.number items on top of stack
ISN_ECHOERR, // :echoerr with isn_arg.number items on top of stack
ISN_RANGE, // compute range from isn_arg.string, push to stack
ISN_SUBSTITUTE, // :s command with expression
ISN_INSTR, // instructions compiled from expression
// get and set variables
ISN_LOAD, // push local variable isn_arg.number
ISN_LOADV, // push v: variable isn_arg.number
ISN_LOADG, // push g: variable isn_arg.string
ISN_LOADAUTO, // push g: autoload variable isn_arg.string
ISN_LOADB, // push b: variable isn_arg.string
ISN_LOADW, // push w: variable isn_arg.string
ISN_LOADT, // push t: variable isn_arg.string
ISN_LOADGDICT, // push g: dict
ISN_LOADBDICT, // push b: dict
ISN_LOADWDICT, // push w: dict
ISN_LOADTDICT, // push t: dict
ISN_LOADS, // push s: variable isn_arg.loadstore
ISN_LOADOUTER, // push variable from outer scope isn_arg.outer
ISN_LOADSCRIPT, // push script-local variable isn_arg.script.
ISN_LOADOPT, // push option isn_arg.string
ISN_LOADENV, // push environment variable isn_arg.string
ISN_LOADREG, // push register isn_arg.number
ISN_STORE, // pop into local variable isn_arg.number
ISN_STOREV, // pop into v: variable isn_arg.number
ISN_STOREG, // pop into global variable isn_arg.string
ISN_STOREAUTO, // pop into global autoload variable isn_arg.string
ISN_STOREB, // pop into buffer-local variable isn_arg.string
ISN_STOREW, // pop into window-local variable isn_arg.string
ISN_STORET, // pop into tab-local variable isn_arg.string
ISN_STORES, // pop into script variable isn_arg.loadstore
ISN_STOREOUTER, // pop variable into outer scope isn_arg.outer
ISN_STORESCRIPT, // pop into script variable isn_arg.script
ISN_STOREOPT, // pop into option isn_arg.string
ISN_STOREENV, // pop into environment variable isn_arg.string
ISN_STOREREG, // pop into register isn_arg.number
// ISN_STOREOTHER, // pop into other script variable isn_arg.other.
ISN_STORENR, // store number into local variable isn_arg.storenr.stnr_idx
ISN_STOREINDEX, // store into list or dictionary, type isn_arg.vartype,
// value/index/variable on stack
ISN_STORERANGE, // store into blob,
// value/index 1/index 2/variable on stack
ISN_UNLET, // unlet variable isn_arg.unlet.ul_name
ISN_UNLETENV, // unlet environment variable isn_arg.unlet.ul_name
ISN_UNLETINDEX, // unlet item of list or dict
ISN_UNLETRANGE, // unlet items of list
ISN_LOCKUNLOCK, // :lock and :unlock for local variable member
ISN_LOCKCONST, // lock constant value
// constants
ISN_PUSHNR, // push number isn_arg.number
ISN_PUSHBOOL, // push bool value isn_arg.number
ISN_PUSHSPEC, // push special value isn_arg.number
ISN_PUSHF, // push float isn_arg.fnumber
ISN_PUSHS, // push string isn_arg.string
ISN_PUSHBLOB, // push blob isn_arg.blob
ISN_PUSHFUNC, // push func isn_arg.string
ISN_PUSHCHANNEL, // push channel isn_arg.channel
ISN_PUSHJOB, // push channel isn_arg.job
ISN_NEWLIST, // push list from stack items, size is isn_arg.number
ISN_NEWDICT, // push dict from stack items, size is isn_arg.number
// function call
ISN_BCALL, // call builtin function isn_arg.bfunc
ISN_DCALL, // call def function isn_arg.dfunc
ISN_UCALL, // call user function or funcref/partial isn_arg.ufunc
ISN_PCALL, // call partial, use isn_arg.pfunc
ISN_PCALL_END, // cleanup after ISN_PCALL with cpf_top set
ISN_RETURN, // return, result is on top of stack
ISN_RETURN_VOID, // Push void, then return
ISN_FUNCREF, // push a function ref to dfunc isn_arg.funcref
ISN_NEWFUNC, // create a global function from a lambda function
ISN_DEF, // list functions
// expression operations
ISN_JUMP, // jump if condition is matched isn_arg.jump
ISN_JUMP_IF_ARG_SET, // jump if argument is already set, uses
// isn_arg.jumparg
// loop
ISN_FOR, // get next item from a list, uses isn_arg.forloop
ISN_TRY, // add entry to ec_trystack, uses isn_arg.try
ISN_THROW, // pop value of stack, store in v:exception
ISN_PUSHEXC, // push v:exception
ISN_CATCH, // drop v:exception
ISN_FINALLY, // start of :finally block
ISN_ENDTRY, // take entry off from ec_trystack
ISN_TRYCONT, // handle :continue inside a :try statement
// more expression operations
ISN_ADDLIST, // add two lists
ISN_ADDBLOB, // add two blobs
// operation with two arguments; isn_arg.op.op_type is exprtype_T
ISN_OPNR,
ISN_OPFLOAT,
ISN_OPANY,
// comparative operations; isn_arg.op.op_type is exprtype_T, op_ic used
ISN_COMPAREBOOL,
ISN_COMPARESPECIAL,
ISN_COMPARENR,
ISN_COMPAREFLOAT,
ISN_COMPARESTRING,
ISN_COMPAREBLOB,
ISN_COMPARELIST,
ISN_COMPAREDICT,
ISN_COMPAREFUNC,
ISN_COMPAREANY,
// expression operations
ISN_CONCAT,
ISN_STRINDEX, // [expr] string index
ISN_STRSLICE, // [expr:expr] string slice
ISN_LISTAPPEND, // append to a list, like add()
ISN_LISTINDEX, // [expr] list index
ISN_LISTSLICE, // [expr:expr] list slice
ISN_BLOBINDEX, // [expr] blob index
ISN_BLOBSLICE, // [expr:expr] blob slice
ISN_ANYINDEX, // [expr] runtime index
ISN_ANYSLICE, // [expr:expr] runtime slice
ISN_SLICE, // drop isn_arg.number items from start of list
ISN_BLOBAPPEND, // append to a blob, like add()
ISN_GETITEM, // push list item, isn_arg.number is the index
ISN_MEMBER, // dict[member]
ISN_STRINGMEMBER, // dict.member using isn_arg.string
ISN_2BOOL, // falsy/truthy to bool, uses isn_arg.tobool
ISN_COND2BOOL, // convert value to bool
ISN_2STRING, // convert value to string at isn_arg.tostring on stack
ISN_2STRING_ANY, // like ISN_2STRING but check type
ISN_NEGATENR, // apply "-" to number
ISN_CHECKNR, // check value can be used as a number
ISN_CHECKTYPE, // check value type is isn_arg.type.ct_type
ISN_CHECKLEN, // check list length is isn_arg.checklen.cl_min_len
ISN_SETTYPE, // set dict type to isn_arg.type.ct_type
ISN_PUT, // ":put", uses isn_arg.put
ISN_CMDMOD, // set cmdmod
ISN_CMDMOD_REV, // undo ISN_CMDMOD
ISN_PROF_START, // start a line for profiling
ISN_PROF_END, // end a line for profiling
ISN_DEBUG, // check for debug breakpoint, uses isn_arg.debug
ISN_UNPACK, // unpack list into items, uses isn_arg.unpack
ISN_SHUFFLE, // move item on stack up or down
ISN_DROP, // pop stack and discard value
ISN_REDIRSTART, // :redir =>
ISN_REDIREND, // :redir END, isn_arg.number == 1 for append
ISN_CEXPR_AUCMD, // first part of :cexpr isn_arg.number is cmdidx
ISN_CEXPR_CORE, // second part of :cexpr, uses isn_arg.cexpr
ISN_FINISH // end marker in list of instructions
} isntype_T;
// arguments to ISN_BCALL
typedef struct {
int cbf_idx; // index in "global_functions"
int cbf_argcount; // number of arguments on top of stack
} cbfunc_T;
// arguments to ISN_DCALL
typedef struct {
int cdf_idx; // index in "def_functions" for ISN_DCALL
int cdf_argcount; // number of arguments on top of stack
} cdfunc_T;
// arguments to ISN_PCALL
typedef struct {
int cpf_top; // when TRUE partial is above the arguments
int cpf_argcount; // number of arguments on top of stack
} cpfunc_T;
// arguments to ISN_UCALL and ISN_XCALL
typedef struct {
char_u *cuf_name;
int cuf_argcount; // number of arguments on top of stack
} cufunc_T;
// arguments to ISN_GETITEM
typedef struct {
varnumber_T gi_index;
int gi_with_op;
} getitem_T;
typedef enum {
JUMP_ALWAYS,
JUMP_IF_FALSE, // pop and jump if false
JUMP_AND_KEEP_IF_TRUE, // jump if top of stack is truthy, drop if not
JUMP_AND_KEEP_IF_FALSE, // jump if top of stack is falsy, drop if not
JUMP_IF_COND_TRUE, // jump if top of stack is true, drop if not
JUMP_IF_COND_FALSE, // jump if top of stack is false, drop if not
} jumpwhen_T;
// arguments to ISN_JUMP
typedef struct {
jumpwhen_T jump_when;
int jump_where; // position to jump to
} jump_T;
// arguments to ISN_JUMP_IF_ARG_SET
typedef struct {
int jump_arg_off; // argument index, negative
int jump_where; // position to jump to
} jumparg_T;
// arguments to ISN_FOR
typedef struct {
int for_idx; // loop variable index
int for_end; // position to jump to after done
} forloop_T;
// indirect arguments to ISN_TRY
typedef struct {
int try_catch; // position to jump to on throw
int try_finally; // :finally or :endtry position to jump to
int try_endtry; // :endtry position to jump to
} tryref_T;
// arguments to ISN_TRY
typedef struct {
tryref_T *try_ref;
} try_T;
// arguments to ISN_TRYCONT
typedef struct {
int tct_levels; // number of nested try statements
int tct_where; // position to jump to, WHILE or FOR
} trycont_T;
// arguments to ISN_ECHO
typedef struct {
int echo_with_white; // :echo instead of :echon
int echo_count; // number of expressions
} echo_T;
// arguments to ISN_OPNR, ISN_OPFLOAT, etc.
typedef struct {
exprtype_T op_type;
int op_ic; // TRUE with '#', FALSE with '?', else MAYBE
} opexpr_T;
// arguments to ISN_CHECKTYPE
typedef struct {
type_T *ct_type;
int8_T ct_off; // offset in stack, -1 is bottom
int8_T ct_arg_idx; // argument index or zero
} checktype_T;
// arguments to ISN_STORENR
typedef struct {
int stnr_idx;
varnumber_T stnr_val;
} storenr_T;
// arguments to ISN_STOREOPT
typedef struct {
char_u *so_name;
int so_flags;
} storeopt_T;
// arguments to ISN_LOADS and ISN_STORES
typedef struct {
char_u *ls_name; // variable name (with s: for ISN_STORES)
int ls_sid; // script ID
} loadstore_T;
// arguments to ISN_LOADSCRIPT and ISN_STORESCRIPT
typedef struct {
int sref_sid; // script ID
int sref_idx; // index in sn_var_vals
int sref_seq; // sn_script_seq when compiled
type_T *sref_type; // type of the variable when compiled
} scriptref_T;
typedef struct {
scriptref_T *scriptref;
} script_T;
// arguments to ISN_UNLET
typedef struct {
char_u *ul_name; // variable name with g:, w:, etc.
int ul_forceit; // forceit flag
} unlet_T;
// arguments to ISN_FUNCREF
typedef struct {
int fr_func; // function index
} funcref_T;
// arguments to ISN_NEWFUNC
typedef struct {
char_u *nf_lambda; // name of the lambda already defined
char_u *nf_global; // name of the global function to be created
} newfunc_T;
// arguments to ISN_CHECKLEN
typedef struct {
int cl_min_len; // minimum length
int cl_more_OK; // longer is allowed
} checklen_T;
// arguments to ISN_SHUFFLE
typedef struct {
int shfl_item; // item to move (relative to top of stack)
int shfl_up; // places to move upwards
} shuffle_T;
// arguments to ISN_PUT
typedef struct {
int put_regname; // register, can be NUL
linenr_T put_lnum; // line number to put below
} put_T;
// arguments to ISN_CMDMOD
typedef struct {
cmdmod_T *cf_cmdmod; // allocated
} cmod_T;
// arguments to ISN_UNPACK
typedef struct {
int unp_count; // number of items to produce
int unp_semicolon; // last item gets list of remainder
} unpack_T;
// arguments to ISN_LOADOUTER and ISN_STOREOUTER
typedef struct {
int outer_idx; // index
int outer_depth; // nesting level, stack frames to go up
} isn_outer_T;
// arguments to ISN_SUBSTITUTE
typedef struct {
char_u *subs_cmd; // :s command
isn_T *subs_instr; // sequence of instructions
} subs_T;
// indirect arguments to ISN_TRY
typedef struct {
int cer_cmdidx;
char_u *cer_cmdline;
int cer_forceit;
} cexprref_T;
// arguments to ISN_CEXPR_CORE
typedef struct {
cexprref_T *cexpr_ref;
} cexpr_T;
// arguments to ISN_2STRING and ISN_2STRING_ANY
typedef struct {
int offset;
int tolerant;
} tostring_T;
// arguments to ISN_2BOOL
typedef struct {
int offset;
int invert;
} tobool_T;
// arguments to ISN_DEBUG
typedef struct {
varnumber_T dbg_var_names_len; // current number of local variables
int dbg_break_lnum; // first line to break after
} debug_T;
/*
* Instruction
*/
struct isn_S {
isntype_T isn_type;
int isn_lnum;
union {
char_u *string;
varnumber_T number;
blob_T *blob;
vartype_T vartype;
#ifdef FEAT_FLOAT
float_T fnumber;
#endif
channel_T *channel;
job_T *job;
partial_T *partial;
jump_T jump;
jumparg_T jumparg;
forloop_T forloop;
try_T try;
trycont_T trycont;
cbfunc_T bfunc;
cdfunc_T dfunc;
cpfunc_T pfunc;
cufunc_T ufunc;
echo_T echo;
opexpr_T op;
checktype_T type;
storenr_T storenr;
storeopt_T storeopt;
loadstore_T loadstore;
script_T script;
unlet_T unlet;
funcref_T funcref;
newfunc_T newfunc;
checklen_T checklen;
shuffle_T shuffle;
put_T put;
cmod_T cmdmod;
unpack_T unpack;
isn_outer_T outer;
subs_T subs;
cexpr_T cexpr;
isn_T *instr;
tostring_T tostring;
tobool_T tobool;
getitem_T getitem;
debug_T debug;
} isn_arg;
};
/*
* Info about a function defined with :def. Used in "def_functions".
*/
struct dfunc_S {
ufunc_T *df_ufunc; // struct containing most stuff
int df_refcount; // how many ufunc_T point to this dfunc_T
int df_idx; // index in def_functions
int df_deleted; // if TRUE function was deleted
int df_script_seq; // Value of sctx_T sc_seq when the function
// was compiled.
char_u *df_name; // name used for error messages
garray_T df_def_args_isn; // default argument instructions
garray_T df_var_names; // names of local vars
// After compiling "df_instr" and/or "df_instr_prof" is not NULL.
isn_T *df_instr; // function body to be executed
int df_instr_count; // size of "df_instr"
int df_instr_debug_count; // size of "df_instr_debug"
isn_T *df_instr_debug; // like "df_instr" with debugging
#ifdef FEAT_PROFILE
isn_T *df_instr_prof; // like "df_instr" with profiling
int df_instr_prof_count; // size of "df_instr_prof"
#endif
int df_varcount; // number of local variables
int df_has_closure; // one if a closure was created
};
// Number of entries used by stack frame for a function call.
// - ec_dfunc_idx: function index
// - ec_iidx: instruction index
// - ec_instr: instruction list pointer
// - ec_outer: stack used for closures
// - funclocal: function-local data
// - ec_frame_idx: previous frame index
#define STACK_FRAME_FUNC_OFF 0
#define STACK_FRAME_IIDX_OFF 1
#define STACK_FRAME_INSTR_OFF 2
#define STACK_FRAME_OUTER_OFF 3
#define STACK_FRAME_FUNCLOCAL_OFF 4
#define STACK_FRAME_IDX_OFF 5
#define STACK_FRAME_SIZE 6
#ifdef DEFINE_VIM9_GLOBALS
// Functions defined with :def are stored in this growarray.
// They are never removed, so that they can be found by index.
// Deleted functions have the df_deleted flag set.
garray_T def_functions = {0, 0, sizeof(dfunc_T), 50, NULL};
#else
extern garray_T def_functions;
#endif
// Used for "lnum" when a range is to be taken from the stack.
#define LNUM_VARIABLE_RANGE -999
// Used for "lnum" when a range is to be taken from the stack and "!" is used.
#define LNUM_VARIABLE_RANGE_ABOVE -888
// Keep in sync with COMPILE_TYPE()
#ifdef FEAT_PROFILE
# define INSTRUCTIONS(dfunc) \
(debug_break_level > 0 || dfunc->df_ufunc->uf_has_breakpoint \
? (dfunc)->df_instr_debug \
: ((do_profiling == PROF_YES && (dfunc->df_ufunc)->uf_profiling) \
? (dfunc)->df_instr_prof \
: (dfunc)->df_instr))
#else
# define INSTRUCTIONS(dfunc) \
(debug_break_level > 0 || dfunc->df_ufunc->uf_has_breakpoint \
? (dfunc)->df_instr_debug \
: (dfunc)->df_instr)
#endif