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
17typedef double var_num_t;
18typedef 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)
46extern "C" {
47#endif
48
49struct var_s;
50typedef void (*method) (struct var_s *self, struct var_s *retval);
51
52typedef 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
121typedef 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 */
130var_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 */
139void v_new_array(var_t *var, unsigned size);
140
141/**
142 * @ingroup var
143 *
144 * frees memory associated with the given array
145 */
146void v_array_free(var_t *var);
147
148/**
149 * @ingroup var
150 *
151 * initialise the variable as a string of the given length
152 */
153void v_init_str(var_t *var, int length);
154
155/**
156 * @ingroup var
157 *
158 * takes ownership of the given allocated string
159 */
160void 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 */
170int 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 */
181int 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 */
192int 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 */
203void 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 */
213void 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 */
223void 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 */
234void 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 */
244int 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 */
254void 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 */
263char *v_str(var_t *arg);
264
265/**
266 * @ingroup var
267 *
268 * convert variable to string
269 *
270 * @param arg is the variable
271 */
272void 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 */
282var_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 */
292void 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 */
303void 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 */
314void 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 */
324int 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 */
334int 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 */
344void 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 */
354void 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 */
364void 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 */
374void 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 */
384void 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 */
393void 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 */
406void 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 */
459char *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 */
469int 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 */
486void v_create_func(var_p_t map, const char *name, method cb);
487
488#if defined(__cplusplus)
489}
490#endif
491
492#endif
493