1 | // This file is part of SmallBASIC |
2 | // |
3 | // SmallBASIC variant type |
4 | // |
5 | // This program is distributed under the terms of the GPL v2.0 or later |
6 | // Download the GNU Public License (GPL) from www.gnu.org |
7 | // |
8 | // Copyright(C) 2018 Chris Warren-Smith |
9 | |
10 | #if !defined(_INC_VAR_T_H) |
11 | #define _INC_VAR_T_H |
12 | |
13 | #include <stdint.h> |
14 | |
15 | // https://en.wikipedia.org/wiki/Dependency_inversion_principle |
16 | |
17 | typedef double var_num_t; |
18 | typedef long long int var_int_t; |
19 | |
20 | #define MAXDIM 6 |
21 | #define OS_INTSZ sizeof(var_int_t) |
22 | #define OS_REALSZ sizeof(var_num_t) |
23 | |
24 | #ifdef V_INT |
25 | #undef V_INT |
26 | #endif |
27 | |
28 | #ifdef V_ARRAY |
29 | #undef V_ARRAY |
30 | #endif |
31 | |
32 | /* |
33 | * Variable - types |
34 | */ |
35 | #define V_INT 0 /**< variable type, 64bit integer @ingroup var */ |
36 | #define V_NUM 1 /**< variable type, 64bit float (same as V_NUM) @ingroup var */ |
37 | #define V_STR 2 /**< variable type, string @ingroup var */ |
38 | #define V_ARRAY 3 /**< variable type, array of variables @ingroup var */ |
39 | #define V_PTR 4 /**< variable type, pointer to UDF or label @ingroup var */ |
40 | #define V_MAP 5 /**< variable type, associative array @ingroup var */ |
41 | #define V_REF 6 /**< variable type, reference another var @ingroup var */ |
42 | #define V_FUNC 7 /**< variable type, object method @ingroup var */ |
43 | #define V_NIL 8 /**< variable type, null value @ingroup var */ |
44 | |
45 | #if defined(__cplusplus) |
46 | extern "C" { |
47 | #endif |
48 | |
49 | struct var_s; |
50 | typedef void (*method) (struct var_s *self, struct var_s *retval); |
51 | |
52 | typedef struct var_s { |
53 | union { |
54 | // numeric |
55 | var_num_t n; |
56 | |
57 | // integer |
58 | var_int_t i; |
59 | |
60 | // pointer to sub/func variable |
61 | struct { |
62 | // address pointer |
63 | uint32_t p; |
64 | // return var ID |
65 | uint32_t v; |
66 | } ap; |
67 | |
68 | // associative array/map |
69 | struct { |
70 | // pointer the map structure |
71 | void *map; |
72 | uint32_t count; |
73 | uint32_t size; |
74 | uint32_t id; |
75 | } m; |
76 | |
77 | // reference variable |
78 | struct var_s *ref; |
79 | |
80 | // object method |
81 | struct { |
82 | method cb; |
83 | uint32_t id; |
84 | } fn; |
85 | |
86 | // generic ptr (string) |
87 | struct { |
88 | char *ptr; |
89 | uint32_t length; |
90 | uint8_t owner; |
91 | } p; |
92 | |
93 | // array |
94 | struct { |
95 | struct var_s *data; |
96 | // the number of elements |
97 | uint32_t size; |
98 | // the number of available element slots |
99 | uint32_t capacity; |
100 | // upper and lower bounds |
101 | int32_t ubound[MAXDIM]; |
102 | int8_t lbound[MAXDIM]; |
103 | // number of dimensions |
104 | uint8_t maxdim; |
105 | } a; |
106 | |
107 | // next item in the free-list |
108 | struct var_s *pool_next; |
109 | } v; |
110 | |
111 | // variables type |
112 | uint8_t type; |
113 | |
114 | // non-zero if constant |
115 | uint8_t const_flag; |
116 | |
117 | // whether help in pooled memory |
118 | uint8_t pooled; |
119 | } var_t; |
120 | |
121 | typedef var_t *var_p_t; |
122 | |
123 | /** |
124 | * @ingroup var |
125 | * |
126 | * creates a new variable |
127 | * |
128 | * @return a newly created var_t object |
129 | */ |
130 | var_t *v_new(void); |
131 | |
132 | /** |
133 | * @ingroup var |
134 | * |
135 | * creates a new variable array |
136 | * |
137 | * @return a newly created var_t array of the given size |
138 | */ |
139 | void v_new_array(var_t *var, unsigned size); |
140 | |
141 | /** |
142 | * @ingroup var |
143 | * |
144 | * frees memory associated with the given array |
145 | */ |
146 | void v_array_free(var_t *var); |
147 | |
148 | /** |
149 | * @ingroup var |
150 | * |
151 | * initialise the variable as a string of the given length |
152 | */ |
153 | void v_init_str(var_t *var, int length); |
154 | |
155 | /** |
156 | * @ingroup var |
157 | * |
158 | * takes ownership of the given allocated string |
159 | */ |
160 | void v_move_str(var_t *var, char *str); |
161 | |
162 | /** |
163 | * @ingroup var |
164 | * |
165 | * returns true if the value is not 0/NULL |
166 | * |
167 | * @param v the variable |
168 | * @return true if the value is not 0/NULL |
169 | */ |
170 | int v_is_nonzero(var_t *v); |
171 | |
172 | /** |
173 | * @ingroup var |
174 | * |
175 | * compares two variables |
176 | * |
177 | * @param a the left-side variable |
178 | * @param b the right-side variable |
179 | * @return 0 if a = b, <0 if a < b, >0 if a > b |
180 | */ |
181 | int v_compare(var_t *a, var_t *b); |
182 | |
183 | /** |
184 | * @ingroup var |
185 | * |
186 | * calculates the result type of the addition of two variables |
187 | * |
188 | * @param a the left-side variable |
189 | * @param b the right-side variable |
190 | * @return the type of the new variable |
191 | */ |
192 | int v_addtype(var_t *a, var_t *b); |
193 | |
194 | /** |
195 | * @ingroup var |
196 | * |
197 | * adds two variables |
198 | * |
199 | * @param result the result |
200 | * @param a the left-side variable |
201 | * @param b the right-side variable |
202 | */ |
203 | void v_add(var_t *result, var_t *a, var_t *b); |
204 | |
205 | /** |
206 | * @ingroup var |
207 | * |
208 | * assigning: dest = src |
209 | * |
210 | * @param dest the destination-var |
211 | * @param src the source-var |
212 | */ |
213 | void v_set(var_t *dest, const var_t *src); |
214 | |
215 | /** |
216 | * @ingroup var |
217 | * |
218 | * assigning: dest = src |
219 | * |
220 | * @param dest the destination-var |
221 | * @param src the source-var |
222 | */ |
223 | void v_move(var_t *dest, const var_t *src); |
224 | |
225 | /** |
226 | * @ingroup var |
227 | * |
228 | * increase the value of variable a by b |
229 | * (similar to v_add()) |
230 | * |
231 | * @param a is the variable |
232 | * @param b is the increment |
233 | */ |
234 | void v_inc(var_t *a, var_t *b); |
235 | |
236 | /** |
237 | * @ingroup var |
238 | * |
239 | * returns the sign of a variable |
240 | * |
241 | * @param x the variable |
242 | * @return the sign |
243 | */ |
244 | int v_sign(var_t *x); |
245 | |
246 | /** |
247 | * @ingroup var |
248 | * |
249 | * create a string variable (with value str) |
250 | * |
251 | * @param v is the variable |
252 | * @param src is the string |
253 | */ |
254 | void v_createstr(var_t *v, const char *src); |
255 | |
256 | /** |
257 | * @ingroup var |
258 | * |
259 | * print variable as string |
260 | * |
261 | * @param arg is the variable |
262 | */ |
263 | char *v_str(var_t *arg); |
264 | |
265 | /** |
266 | * @ingroup var |
267 | * |
268 | * convert variable to string |
269 | * |
270 | * @param arg is the variable |
271 | */ |
272 | void v_tostr(var_t *arg); |
273 | |
274 | /** |
275 | * @ingroup var |
276 | * |
277 | * creates a new variable which is a clone of 'source'. |
278 | * |
279 | * @param source is the source |
280 | * @return a newly created var_t object, clone of 'source' |
281 | */ |
282 | var_t *v_clone(const var_t *source); |
283 | |
284 | /** |
285 | * @ingroup var |
286 | * |
287 | * resizes an array-variable to 1-dimension array of 'size' elements |
288 | * |
289 | * @param v the variable |
290 | * @param size the number of the elements |
291 | */ |
292 | void v_resize_array(var_t *v, uint32_t size); |
293 | |
294 | /** |
295 | * @ingroup var |
296 | * |
297 | * convert variable v to a RxC matrix |
298 | * |
299 | * @param v the variable |
300 | * @param r the number of the rows |
301 | * @param c the number of the columns |
302 | */ |
303 | void v_tomatrix(var_t *v, int r, int c); |
304 | |
305 | /** |
306 | * @ingroup var |
307 | * |
308 | * converts the variable v to an array of R elements. |
309 | * R can be zero for zero-length arrays |
310 | * |
311 | * @param v the variable |
312 | * @param r the number of the elements |
313 | */ |
314 | void v_toarray1(var_t *v, uint32_t r); |
315 | |
316 | /** |
317 | * @ingroup var |
318 | * |
319 | * returns true if the 'v' is empty (see EMPTY()) |
320 | * |
321 | * @param v the variable |
322 | * @return non-zero if v is not 'empty' |
323 | */ |
324 | int v_isempty(var_t *v); |
325 | |
326 | /** |
327 | * @ingroup var |
328 | * |
329 | * returns the length of the variable (see LEN()) |
330 | * |
331 | * @param v the variable |
332 | * @return the length of the variable |
333 | */ |
334 | int v_length(var_t *v); |
335 | |
336 | /** |
337 | * @ingroup var |
338 | * |
339 | * sets a string value to variable 'var' |
340 | * |
341 | * @param var is the variable |
342 | * @param string is the string |
343 | */ |
344 | void v_setstr(var_t *var, const char *string); |
345 | |
346 | /** |
347 | * @ingroup var |
348 | * |
349 | * sets a string value to variable 'var' to the given length |
350 | * |
351 | * @param var is the variable |
352 | * @param string is the string |
353 | */ |
354 | void v_setstrn(var_t *var, const char *string, int len); |
355 | |
356 | /** |
357 | * @ingroup var |
358 | * |
359 | * concate string to variable 'var' |
360 | * |
361 | * @param var is the variable |
362 | * @param string is the string |
363 | */ |
364 | void v_strcat(var_t *var, const char *string); |
365 | |
366 | /** |
367 | * @ingroup var |
368 | * |
369 | * sets a real-number value to variable 'var' |
370 | * |
371 | * @param var is the variable |
372 | * @param number is the number |
373 | */ |
374 | void v_setreal(var_t *var, var_num_t number); |
375 | |
376 | /** |
377 | * @ingroup var |
378 | * |
379 | * sets an integer value to variable 'var' |
380 | * |
381 | * @param var is the variable |
382 | * @param integer is the integer |
383 | */ |
384 | void v_setint(var_t *var, var_int_t integer); |
385 | |
386 | /** |
387 | * @ingroup var |
388 | * |
389 | * makes 'var' an empty string variable |
390 | * |
391 | * @param var is the variable |
392 | */ |
393 | void v_zerostr(var_t *var); |
394 | |
395 | /** |
396 | * @ingroup var |
397 | * |
398 | * assign value 'str' to var. the final type of the var will be decided |
399 | * on that function (numeric if the str is a numeric-constant string or string) |
400 | * |
401 | * @note used by INPUT to convert the variables |
402 | * |
403 | * @param str is the string |
404 | * @param var is the variable |
405 | */ |
406 | void v_input2var(const char *str, var_t *var); |
407 | |
408 | /** |
409 | *< returns the var_t pointer of the element i |
410 | * on the array x. i is a zero-based, one dim, index. |
411 | * @ingroup var |
412 | */ |
413 | #define v_elem(var, i) &((var)->v.a.data[i]) |
414 | |
415 | /** |
416 | * < the number of the elements of the array (x) |
417 | * @ingroup var |
418 | */ |
419 | #define v_asize(x) ((x)->v.a.size) |
420 | |
421 | /** |
422 | * < the number of array dimensions (x) |
423 | * @ingroup var |
424 | */ |
425 | #define v_maxdim(x) ((x)->v.a.maxdim) |
426 | |
427 | /** |
428 | * < the array lower bound of the given dimension (x) |
429 | * @ingroup var |
430 | */ |
431 | #define v_lbound(x, i) ((x)->v.a.lbound[i]) |
432 | |
433 | /** |
434 | * < the array upper bound of the given dimension (x) |
435 | * @ingroup var |
436 | */ |
437 | #define v_ubound(x, i) ((x)->v.a.ubound[i]) |
438 | |
439 | /** |
440 | * < the array data |
441 | * @ingroup var |
442 | */ |
443 | #define v_data(x) ((x)->v.a.data) |
444 | |
445 | /** |
446 | * < the array capacity |
447 | * @ingroup var |
448 | */ |
449 | #define v_capacity(x) ((x)->v.a.capacity) |
450 | |
451 | /** |
452 | * @ingroup var |
453 | * |
454 | * returns the string-pointer of variable v |
455 | * |
456 | * @param v is the variable |
457 | * @return the pointer of the string |
458 | */ |
459 | char *v_getstr(var_t *v); |
460 | |
461 | /** |
462 | * @ingroup var |
463 | * |
464 | * returns the length of the var string |
465 | * |
466 | * @param v is the variable |
467 | * @return the string length |
468 | */ |
469 | int v_strlen(const var_t *v); |
470 | |
471 | /** |
472 | * @ingroup var |
473 | * |
474 | * returns whether the variable is of the given type |
475 | * |
476 | * @param v is the variable |
477 | * @return whether the variable is of the given type |
478 | */ |
479 | #define v_is_type(v, t) (v != NULL && v->type == t) |
480 | |
481 | /** |
482 | * @ingroup var |
483 | * |
484 | * setup a method on the map using the given name |
485 | */ |
486 | void v_create_func(var_p_t map, const char *name, method cb); |
487 | |
488 | #if defined(__cplusplus) |
489 | } |
490 | #endif |
491 | |
492 | #endif |
493 | |