aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval_defs.h
blob: 39028fdb1180bce4f1066b0af5c60185908ef8a3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
#ifndef NVIM_EVAL_DEFS_H
#define NVIM_EVAL_DEFS_H

#include <limits.h>
#include <stddef.h>

#include "nvim/hashtab.h"
#include "nvim/lib/queue.h"
#include "nvim/garray.h"   // for garray_T
#include "nvim/profile.h"  // for proftime_T
#include "nvim/pos.h"      // for linenr_T

typedef int varnumber_T;
typedef double float_T;

#define VARNUMBER_MAX INT_MAX
#define VARNUMBER_MIN INT_MIN

typedef struct listvar_S list_T;
typedef struct dictvar_S dict_T;
typedef struct partial_S partial_T;

/// Special variable values
typedef enum {
  kSpecialVarFalse,  ///< v:false
  kSpecialVarTrue,   ///< v:true
  kSpecialVarNull,   ///< v:null
} SpecialVarValue;

/// Variable lock status for typval_T.v_lock
typedef enum {
  VAR_UNLOCKED = 0,  ///< Not locked.
  VAR_LOCKED = 1,    ///< User lock, can be unlocked.
  VAR_FIXED = 2,     ///< Locked forever.
} VarLockStatus;

/// VimL variable types, for use in typval_T.v_type
typedef enum {
  VAR_UNKNOWN = 0,  ///< Unknown (unspecified) value.
  VAR_NUMBER,       ///< Number, .v_number is used.
  VAR_STRING,       ///< String, .v_string is used.
  VAR_FUNC,         ///< Function reference, .v_string is used as function name.
  VAR_LIST,         ///< List, .v_list is used.
  VAR_DICT,         ///< Dictionary, .v_dict is used.
  VAR_FLOAT,        ///< Floating-point value, .v_float is used.
  VAR_SPECIAL,      ///< Special value (true, false, null), .v_special
                    ///< is used.
  VAR_PARTIAL,      ///< Partial, .v_partial is used.
} VarType;

/// Structure that holds an internal variable value
typedef struct {
  VarType v_type;  ///< Variable type.
  VarLockStatus v_lock;  ///< Variable lock status.
  union typval_vval_union {
    varnumber_T v_number;  ///< Number, for VAR_NUMBER.
    SpecialVarValue v_special;  ///< Special value, for VAR_SPECIAL.
    float_T v_float;  ///< Floating-point number, for VAR_FLOAT.
    char_u *v_string;  ///< String, for VAR_STRING and VAR_FUNC, can be NULL.
    list_T *v_list;  ///< List for VAR_LIST, can be NULL.
    dict_T *v_dict;  ///< Dictionary for VAR_DICT, can be NULL.
    partial_T *v_partial;  ///< Closure: function with args.
  }           vval;  ///< Actual value.
} typval_T;

/* Values for "dv_scope". */
#define VAR_SCOPE     1 /* a:, v:, s:, etc. scope dictionaries */
#define VAR_DEF_SCOPE 2 /* l:, g: scope dictionaries: here funcrefs are not
                           allowed to mask existing functions */

/*
 * Structure to hold an item of a list: an internal variable without a name.
 */
typedef struct listitem_S listitem_T;

struct listitem_S {
  listitem_T  *li_next;         /* next item in list */
  listitem_T  *li_prev;         /* previous item in list */
  typval_T li_tv;               /* type and value of the variable */
};

/*
 * Struct used by those that are using an item in a list.
 */
typedef struct listwatch_S listwatch_T;

struct listwatch_S {
  listitem_T          *lw_item;         /* item being watched */
  listwatch_T         *lw_next;         /* next watcher */
};

/*
 * Structure to hold info about a list.
 */
struct listvar_S {
  listitem_T *lv_first;  ///< First item, NULL if none.
  listitem_T *lv_last;  ///< Last item, NULL if none.
  int lv_refcount;  ///< Reference count.
  int lv_len;  ///< Number of items.
  listwatch_T *lv_watch;  ///< First watcher, NULL if none.
  int lv_idx;  ///< Index of a cached item, used for optimising repeated l[idx].
  listitem_T *lv_idx_item;  ///< When not NULL item at index "lv_idx".
  int lv_copyID;  ///< ID used by deepcopy().
  list_T *lv_copylist;  ///< Copied list used by deepcopy().
  VarLockStatus lv_lock;  ///< Zero, VAR_LOCKED, VAR_FIXED.
  list_T *lv_used_next;  ///< next list in used lists list.
  list_T *lv_used_prev;  ///< Previous list in used lists list.
};

// Static list with 10 items. Use init_static_list() to initialize.
typedef struct {
  list_T sl_list;  // must be first
  listitem_T sl_items[10];
} staticList10_T;

// Structure to hold an item of a Dictionary.
// Also used for a variable.
// The key is copied into "di_key" to avoid an extra alloc/free for it.
struct dictitem_S {
  typval_T di_tv;               ///< type and value of the variable
  char_u di_flags;              ///< flags (only used for variable)
  char_u di_key[1];             ///< key (actually longer!)
};

typedef struct dictitem_S dictitem_T;

/// A dictitem with a 16 character key (plus NUL)
struct dictitem16_S {
  typval_T di_tv;     ///< type and value of the variable
  char_u di_flags;    ///< flags (only used for variable)
  char_u di_key[17];  ///< key
};

typedef struct dictitem16_S dictitem16_T;


#define DI_FLAGS_RO     1   // "di_flags" value: read-only variable
#define DI_FLAGS_RO_SBX 2   // "di_flags" value: read-only in the sandbox
#define DI_FLAGS_FIX    4   // "di_flags" value: fixed: no :unlet or remove()
#define DI_FLAGS_LOCK   8   // "di_flags" value: locked variable
#define DI_FLAGS_ALLOC  16  // "di_flags" value: separately allocated

/// Structure representing a Dictionary
struct dictvar_S {
  VarLockStatus dv_lock;  ///< Whole dictionary lock status.
  char dv_scope;          ///< Non-zero (#VAR_SCOPE, #VAR_DEF_SCOPE) if
                          ///< dictionary represents a scope (i.e. g:, l: …).
  int dv_refcount;        ///< Reference count.
  int dv_copyID;          ///< ID used when recursivery traversing a value.
  hashtab_T dv_hashtab;   ///< Hashtab containing all items.
  dict_T *dv_copydict;    ///< Copied dict used by deepcopy().
  dict_T *dv_used_next;   ///< Next dictionary in used dictionaries list.
  dict_T *dv_used_prev;   ///< Previous dictionary in used dictionaries list.
  QUEUE watchers;         ///< Dictionary key watchers set by user code.
};

typedef int scid_T;                     // script ID
typedef struct funccall_S funccall_T;

// Structure to hold info for a user function.
typedef struct ufunc ufunc_T;

struct ufunc {
  int          uf_varargs;       ///< variable nr of arguments
  int          uf_flags;
  int          uf_calls;         ///< nr of active calls
  bool         uf_cleared;       ///< func_clear() was already called
  garray_T     uf_args;          ///< arguments
  garray_T     uf_lines;         ///< function lines
  int          uf_profiling;     ///< true when func is being profiled
  // Profiling the function as a whole.
  int          uf_tm_count;      ///< nr of calls
  proftime_T   uf_tm_total;      ///< time spent in function + children
  proftime_T   uf_tm_self;       ///< time spent in function itself
  proftime_T   uf_tm_children;   ///< time spent in children this call
  // Profiling the function per line.
  int         *uf_tml_count;     ///< nr of times line was executed
  proftime_T  *uf_tml_total;     ///< time spent in a line + children
  proftime_T  *uf_tml_self;      ///< time spent in a line itself
  proftime_T   uf_tml_start;     ///< start time for current line
  proftime_T   uf_tml_children;  ///< time spent in children for this line
  proftime_T   uf_tml_wait;      ///< start wait time for current line
  int          uf_tml_idx;       ///< index of line being timed; -1 if none
  int          uf_tml_execed;    ///< line being timed was executed
  scid_T       uf_script_ID;     ///< ID of script where function was defined,
                                 //   used for s: variables
  int          uf_refcount;      ///< reference count, see func_name_refcount()
  funccall_T   *uf_scoped;       ///< l: local variables for closure
  char_u       uf_name[1];       ///< name of function (actually longer); can
                                 //   start with <SNR>123_ (<SNR> is K_SPECIAL
                                 //   KS_EXTRA KE_SNR)
};

/// Maximum number of function arguments
#define MAX_FUNC_ARGS   20
#define VAR_SHORT_LEN   20      // short variable name length
#define FIXVAR_CNT      12      // number of fixed variables

// structure to hold info for a function that is currently being executed.
struct funccall_S {
  ufunc_T     *func;            ///< function being called
  int linenr;                   ///< next line to be executed
  int returned;                 ///< ":return" used
  struct {                      ///< fixed variables for arguments
    dictitem_T var;                     ///< variable (without room for name)
    char_u room[VAR_SHORT_LEN];         ///< room for the name
  } fixvar[FIXVAR_CNT];
  dict_T l_vars;                ///< l: local function variables
  dictitem_T l_vars_var;        ///< variable for l: scope
  dict_T l_avars;               ///< a: argument variables
  dictitem_T l_avars_var;       ///< variable for a: scope
  list_T l_varlist;             ///< list for a:000
  listitem_T l_listitems[MAX_FUNC_ARGS];        ///< listitems for a:000
  typval_T    *rettv;           ///< return value
  linenr_T breakpoint;          ///< next line with breakpoint or zero
  int dbg_tick;                 ///< debug_tick when breakpoint was set
  int level;                    ///< top nesting level of executed function
  proftime_T prof_child;        ///< time spent in a child
  funccall_T  *caller;          ///< calling function or NULL
  int fc_refcount;              ///< number of user functions that reference
                                // this funccal
  int fc_copyID;                ///< for garbage collection
  garray_T fc_funcs;            ///< list of ufunc_T* which keep a reference
                                // to "func"
};

// structure used by trans_function_name()
typedef struct {
  dict_T      *fd_dict;         ///< Dictionary used.
  char_u      *fd_newkey;       ///< New key in "dict" in allocated memory.
  dictitem_T  *fd_di;           ///< Dictionary item used.
} funcdict_T;

struct partial_S {
  int pt_refcount;        ///< Reference count.
  char_u *pt_name;        ///< Function name; when NULL use pt_func->name.
  ufunc_T *pt_func;       ///< Function pointer; when NULL lookup function
                          ///< with pt_name.
  bool pt_auto;           ///< when true the partial was created for using
                          ///< dict.member in handle_subscript().
  int pt_argc;            ///< Number of arguments.
  typval_T *pt_argv;      ///< Arguments in allocated array.
  dict_T *pt_dict;        ///< Dict for "self".
};

// structure used for explicit stack while garbage collecting hash tables
typedef struct ht_stack_S {
  hashtab_T *ht;
  struct ht_stack_S *prev;
} ht_stack_T;

// structure used for explicit stack while garbage collecting lists
typedef struct list_stack_S {
  list_T *list;
  struct list_stack_S *prev;
} list_stack_T;

// In a hashtab item "hi_key" points to "di_key" in a dictitem.
// This avoids adding a pointer to the hashtab item.

/// Convert a dictitem pointer to a hashitem key pointer
#define DI2HIKEY(di) ((di)->di_key)

/// Convert a hashitem key pointer to a dictitem pointer
#define HIKEY2DI(p)  ((dictitem_T *)(p - offsetof(dictitem_T, di_key)))

/// Convert a hashitem value pointer to a dictitem pointer
#define HIVAL2DI(p) \
    ((dictitem_T *)(((char *)p) - offsetof(dictitem_T, di_tv)))

/// Convert a hashitem pointer to a dictitem pointer
#define HI2DI(hi)     HIKEY2DI((hi)->hi_key)

/// Type of assert_* check being performed
typedef enum
{
  ASSERT_EQUAL,
  ASSERT_NOTEQUAL,
  ASSERT_MATCH,
  ASSERT_NOTMATCH,
  ASSERT_INRANGE,
  ASSERT_OTHER,
} assert_type_T;

#endif  // NVIM_EVAL_DEFS_H