Skip to content

Commit b1f7266

Browse files
committed
COMMON: ref var wip
1 parent a4d2ec1 commit b1f7266

File tree

4 files changed

+107
-35
lines changed

4 files changed

+107
-35
lines changed

src/common/blib.c

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -28,28 +28,31 @@
2828
* CONST v[(x)] = any
2929
*/
3030
void cmd_let(int allowConst) {
31-
var_t *var_p;
32-
var_t arg;
33-
34-
var_p = code_getvarptr();
31+
var_t *v_left = code_getvarptr();
3532

3633
if (!prog_error) {
37-
if (var_p->const_flag && !allowConst) {
34+
if (v_left->const_flag && !allowConst) {
3835
err_const();
3936
return;
4037
}
4138

42-
if (prog_source[prog_ip] == kwTYPE_CMPOPR && prog_source[prog_ip + 1] == '=') {
39+
if (prog_source[prog_ip] == kwTYPE_CMPOPR &&
40+
prog_source[prog_ip + 1] == '=') {
4341
code_skipopr();
4442
}
4543

46-
v_init(&arg);
47-
eval(&arg);
48-
49-
if (!prog_error) {
50-
v_set(var_p, &arg);
51-
v_free(&arg);
52-
var_p->const_flag = allowConst;
44+
if (code_peek() == kwBYREF) {
45+
code_skipnext();
46+
v_eval_ref(v_left);
47+
} else {
48+
var_t v_right;
49+
v_init(&v_right);
50+
eval(&v_right);
51+
if (!prog_error) {
52+
v_set(v_left, &v_right);
53+
v_left->const_flag = allowConst;
54+
}
55+
v_free(&v_right);
5356
}
5457
}
5558
}
@@ -192,21 +195,27 @@ void cmd_ladd() {
192195
do {
193196
// get parameter on arg_p
194197
v_free(arg_p);
195-
eval(arg_p);
196-
if (prog_error) {
197-
break;
198-
}
199198

200-
// append data
201-
if (var_p->type != V_ARRAY) {
202-
v_toarray1(var_p, 1);
203-
elem_p = (var_t *) var_p->v.a.ptr;
199+
if (code_peek() == kwBYREF) {
200+
code_skipnext();
201+
v_eval_ref(var_p);
204202
} else {
205-
v_resize_array(var_p, var_p->v.a.size + 1);
206-
elem_p = (var_t *) (var_p->v.a.ptr + (sizeof(var_t) * (var_p->v.a.size - 1)));
203+
eval(arg_p);
204+
if (prog_error) {
205+
break;
206+
}
207+
208+
// append data
209+
if (var_p->type != V_ARRAY) {
210+
v_toarray1(var_p, 1);
211+
elem_p = (var_t *) var_p->v.a.ptr;
212+
} else {
213+
v_resize_array(var_p, var_p->v.a.size + 1);
214+
elem_p = (var_t *) (var_p->v.a.ptr + (sizeof(var_t) * (var_p->v.a.size - 1)));
215+
}
216+
217+
v_set(elem_p, arg_p);
207218
}
208-
209-
v_set(elem_p, arg_p);
210219

211220
// next parameter
212221
if (code_peek() != kwTYPE_SEP) {

src/common/kw.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,10 @@ enum keyword { // line 50
7676
kwTYPE_CALLP, /* Call a build-in procedure */
7777
kwTYPE_CALL_UDF, /* Call user defined function */
7878
kwTYPE_CALL_UDP, /* Call user defined procedure */
79-
kwTYPE_CALL_PTR, /* Call user defined procedure or function from
80-
* address pointer */
79+
kwTYPE_CALL_PTR, /* Call user defined procedure or function from address pointer */
8180
kwTYPE_CALLEXTF, /* Call an external function */
8281
kwTYPE_CALLEXTP, /* Call an external procedure */
83-
kwTYPE_CRVAR, /* Create dynamic variable (PARAMETERS OR
84-
* LOCALS) */
82+
kwTYPE_CRVAR, /* Create dynamic variable (PARAMETERS OR LOCALS) */
8583
kwTYPE_RET, /* Return from UDF|UDP */
8684
kwTYPE_PARAM, /* Parameters */
8785
kwTYPE_PTR, /* Address pointer, eg f=@foo */

src/common/var.c

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ int v_isempty(var_t *var) {
4343
return (var->v.n == 0.0);
4444
case V_ARRAY:
4545
return (var->v.a.size == 0);
46+
case V_REF:
47+
return v_isempty(var->v.ref);
4648
}
4749

4850
return 1;
@@ -70,6 +72,8 @@ int v_length(var_t *var) {
7072
return strlen(tmpsb);
7173
case V_ARRAY:
7274
return var->v.a.size;
75+
case V_REF:
76+
return v_length(var->v.ref);
7377
}
7478

7579
return 1;
@@ -257,6 +261,8 @@ int v_is_nonzero(var_t *v) {
257261
return (v->v.ap.p != 0);
258262
case V_ARRAY:
259263
return (v->v.a.size != 0);
264+
case V_REF:
265+
return v_is_nonzero(v->v.ref);
260266
};
261267
return 0;
262268
}
@@ -349,6 +355,11 @@ int v_compare(var_t *a, var_t *b) {
349355
return hash_compare(a, b);
350356
}
351357

358+
if (a->type == V_REF || b->type == V_REF) {
359+
return v_compare(a->type == V_REF ? a->v.ref : a,
360+
b->type == V_REF ? b->v.ref : b);
361+
}
362+
352363
err_evtype();
353364
return 1;
354365
}
@@ -407,11 +418,11 @@ void v_add(var_t *result, var_t *a, var_t *b) {
407418
} else if ((a->type == V_INT || a->type == V_NUM) && b->type == V_STR) {
408419
if (is_number((char *) b->v.p.ptr)) {
409420
result->type = V_NUM;
410-
if (a->type == V_INT
411-
)
421+
if (a->type == V_INT) {
412422
result->v.n = a->v.i + v_getval(b);
413-
else
423+
} else {
414424
result->v.n = a->v.n + v_getval(b);
425+
}
415426
} else {
416427
result->type = V_STR;
417428
result->v.p.ptr = (byte *) tmp_alloc(strlen((char *)b->v.p.ptr) + 64);
@@ -424,6 +435,9 @@ void v_add(var_t *result, var_t *a, var_t *b) {
424435
strcat((char *) result->v.p.ptr, (char *) b->v.p.ptr);
425436
result->v.p.size = strlen((char *) result->v.p.ptr) + 1;
426437
}
438+
} else if (a->type == V_REF || b->type == V_REF) {
439+
v_add(result, a->type == V_REF ? a->v.ref : a,
440+
b->type == V_REF ? b->v.ref : b);
427441
}
428442
}
429443

@@ -556,6 +570,10 @@ void v_tostr(var_t *arg) {
556570
case V_NUM:
557571
ftostr(arg->v.n, tmp);
558572
break;
573+
case V_REF:
574+
v_tostr(arg->v.ref);
575+
tmp_free(tmp);
576+
return;
559577
default:
560578
err_varisarray();
561579
tmp_free(tmp);
@@ -753,3 +771,39 @@ void v_eval_str(var_p_t v) {
753771
prog_ip += len;
754772
}
755773

774+
/*
775+
* evaluate variable reference assignment
776+
*/
777+
void v_eval_ref(var_t *v_left) {
778+
var_t *v_right = NULL;
779+
// can only reference regular non-dynamic variable
780+
if (code_peek() == kwTYPE_VAR) {
781+
code_skipnext();
782+
v_right = tvar[code_getaddr()];
783+
switch (v_right->type) {
784+
case V_REF:
785+
// multiple levels not supported
786+
v_right = NULL;
787+
break;
788+
case V_ARRAY:
789+
case V_HASH:
790+
switch (code_peek()) {
791+
case kwTYPE_LEVEL_BEGIN:
792+
case kwTYPE_UDS_EL:
793+
// base variable only supported
794+
v_right = NULL;
795+
break;
796+
}
797+
break;
798+
default:
799+
break;
800+
}
801+
}
802+
if (v_right == NULL) {
803+
rt_raise("Invalid variable reference");
804+
} else {
805+
v_free(v_left);
806+
v_left->type = V_REF;
807+
v_left->v.ref = v_right;
808+
}
809+
}

src/common/var.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#define V_ARRAY 3 /**< variable type, array of variables @ingroup var */
3737
#define V_PTR 4 /**< variable type, pointer to UDF or label @ingroup var */
3838
#define V_HASH 5 /**< variable type, hash @ingroup var */
39+
#define V_REF 6 /**< variable type, reference another var @ingroup var */
3940

4041
/*
4142
* predefined system variables - index
@@ -76,8 +77,8 @@ extern "C" {
7677
* VARIANT DATA TYPE
7778
*/
7879
struct var_s {
79-
byte type: 7; /**< variable's type */
80-
byte const_flag: 1; /**< non-zero if constants */
80+
byte type; /**< variable's type */
81+
byte const_flag; /**< non-zero if constants */
8182

8283
// value
8384
union {
@@ -91,7 +92,10 @@ struct var_s {
9192
} ap;
9293

9394
// hash map
94-
void* hash; /** pointer the hash structure */
95+
void *hash; /** pointer the hash structure */
96+
97+
// reference variable
98+
void *ref;
9599

96100
// generic ptr (string)
97101
struct {
@@ -635,6 +639,13 @@ char *v_getstr(var_t *v);
635639
*/
636640
void v_eval_str(var_p_t v);
637641

642+
/**
643+
* @ingroup var
644+
*
645+
* evaluate variable reference assignment
646+
*/
647+
void v_eval_ref(var_t *l_value);
648+
638649
/*
639650
* low-level byte-code parsing
640651
*

0 commit comments

Comments
 (0)