diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2019-01-25 14:24:03 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2019-02-14 14:40:57 +0100 |
commit | 5c6b9165e776f60b7bfeb01a2d5fa6331ee0cb89 (patch) | |
tree | 6e5770c2b8fbc28d7d43934d79d6c28e3eeec205 | |
parent | 8296334c1f457c598e04e1aa0f79cbdbbba27427 (diff) | |
download | busybox-w32-5c6b9165e776f60b7bfeb01a2d5fa6331ee0cb89.tar.gz busybox-w32-5c6b9165e776f60b7bfeb01a2d5fa6331ee0cb89.tar.bz2 busybox-w32-5c6b9165e776f60b7bfeb01a2d5fa6331ee0cb89.zip |
bc: implement pass-by-reference code from upstream
function old new delta
zxc_program_popResultAndCopyToVar 298 493 +195
bc_vec_pushIndex - 75 +75
zxc_vm_process 859 928 +69
xc_program_dereference - 66 +66
bc_vec_npush - 65 +65
zbc_num_s 239 249 +10
zxc_program_num 1024 1032 +8
zbc_num_divmod 150 156 +6
xc_program_search 143 146 +3
zxc_program_assign 392 389 -3
zdc_program_execStr 520 517 -3
xc_program_pushVar 198 195 -3
zxc_program_exec 4101 4092 -9
zbc_program_call 318 308 -10
zbc_func_insert 120 104 -16
zbc_parse_stmt_possibly_auto 1460 1439 -21
bc_vec_push 53 12 -41
xc_parse_pushIndex 61 18 -43
------------------------------------------------------------------------------
(add/remove: 3/0 grow/shrink: 6/9 up/down: 497/-149) Total: 348 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | miscutils/bc.c | 271 | ||||
-rw-r--r-- | testsuite/bc_references.bc | 106 | ||||
-rw-r--r-- | testsuite/bc_references_results.txt | 212 |
3 files changed, 503 insertions, 86 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c index 8e0069658..a8b4332c1 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c | |||
@@ -4,8 +4,8 @@ | |||
4 | * Adapted from https://github.com/gavinhoward/bc | 4 | * Adapted from https://github.com/gavinhoward/bc |
5 | * Original code copyright (c) 2018 Gavin D. Howard and contributors. | 5 | * Original code copyright (c) 2018 Gavin D. Howard and contributors. |
6 | */ | 6 | */ |
7 | //TODO: GNU extensions: | 7 | //TODO: |
8 | // support "define f(*param[])" - "pass array by reference" syntax | 8 | // maybe implement a^b for non-integer b? |
9 | 9 | ||
10 | #define DEBUG_LEXER 0 | 10 | #define DEBUG_LEXER 0 |
11 | #define DEBUG_COMPILE 0 | 11 | #define DEBUG_COMPILE 0 |
@@ -380,6 +380,12 @@ typedef struct BcInstPtr { | |||
380 | size_t inst_idx; | 380 | size_t inst_idx; |
381 | } BcInstPtr; | 381 | } BcInstPtr; |
382 | 382 | ||
383 | typedef enum BcType { | ||
384 | BC_TYPE_VAR, | ||
385 | BC_TYPE_ARRAY, | ||
386 | BC_TYPE_REF, | ||
387 | } BcType; | ||
388 | |||
383 | typedef enum BcLexType { | 389 | typedef enum BcLexType { |
384 | XC_LEX_EOF, | 390 | XC_LEX_EOF, |
385 | XC_LEX_INVALID, | 391 | XC_LEX_INVALID, |
@@ -1092,15 +1098,25 @@ static void bc_vec_pop_all(BcVec *v) | |||
1092 | bc_vec_npop(v, v->len); | 1098 | bc_vec_npop(v, v->len); |
1093 | } | 1099 | } |
1094 | 1100 | ||
1095 | static size_t bc_vec_push(BcVec *v, const void *data) | 1101 | static size_t bc_vec_npush(BcVec *v, size_t n, const void *data) |
1096 | { | 1102 | { |
1097 | size_t len = v->len; | 1103 | size_t len = v->len; |
1098 | if (len >= v->cap) bc_vec_grow(v, 1); | 1104 | if (len + n > v->cap) bc_vec_grow(v, n); |
1099 | memmove(v->v + (v->size * len), data, v->size); | 1105 | memmove(v->v + (v->size * len), data, v->size * n); |
1100 | v->len++; | 1106 | v->len = len + n; |
1101 | return len; | 1107 | return len; |
1102 | } | 1108 | } |
1103 | 1109 | ||
1110 | static size_t bc_vec_push(BcVec *v, const void *data) | ||
1111 | { | ||
1112 | return bc_vec_npush(v, 1, data); | ||
1113 | //size_t len = v->len; | ||
1114 | //if (len >= v->cap) bc_vec_grow(v, 1); | ||
1115 | //memmove(v->v + (v->size * len), data, v->size); | ||
1116 | //v->len = len + 1; | ||
1117 | //return len; | ||
1118 | } | ||
1119 | |||
1104 | // G.prog.results often needs "pop old operand, push result" idiom. | 1120 | // G.prog.results often needs "pop old operand, push result" idiom. |
1105 | // Can do this without a few extra ops | 1121 | // Can do this without a few extra ops |
1106 | static size_t bc_result_pop_and_push(const void *data) | 1122 | static size_t bc_result_pop_and_push(const void *data) |
@@ -3528,14 +3544,14 @@ static void xc_parse_pushName(char *name) | |||
3528 | // (The above describes 32-bit case). | 3544 | // (The above describes 32-bit case). |
3529 | #define SMALL_INDEX_LIMIT (0x100 - sizeof(size_t)) | 3545 | #define SMALL_INDEX_LIMIT (0x100 - sizeof(size_t)) |
3530 | 3546 | ||
3531 | static void xc_parse_pushIndex(size_t idx) | 3547 | static void bc_vec_pushIndex(BcVec *v, size_t idx) |
3532 | { | 3548 | { |
3533 | size_t mask; | 3549 | size_t mask; |
3534 | unsigned amt; | 3550 | unsigned amt; |
3535 | 3551 | ||
3536 | dbg_lex("%s:%d pushing index %zd", __func__, __LINE__, idx); | 3552 | dbg_lex("%s:%d pushing index %zd", __func__, __LINE__, idx); |
3537 | if (idx < SMALL_INDEX_LIMIT) { | 3553 | if (idx < SMALL_INDEX_LIMIT) { |
3538 | xc_parse_push(idx); | 3554 | bc_vec_pushByte(v, idx); |
3539 | return; | 3555 | return; |
3540 | } | 3556 | } |
3541 | 3557 | ||
@@ -3548,14 +3564,19 @@ static void xc_parse_pushIndex(size_t idx) | |||
3548 | } | 3564 | } |
3549 | // amt is at least 1 here - "one byte of length data follows" | 3565 | // amt is at least 1 here - "one byte of length data follows" |
3550 | 3566 | ||
3551 | xc_parse_push((SMALL_INDEX_LIMIT - 1) + amt); | 3567 | bc_vec_pushByte(v, (SMALL_INDEX_LIMIT - 1) + amt); |
3552 | 3568 | ||
3553 | do { | 3569 | do { |
3554 | xc_parse_push((unsigned char)idx); | 3570 | bc_vec_pushByte(v, (unsigned char)idx); |
3555 | idx >>= 8; | 3571 | idx >>= 8; |
3556 | } while (idx != 0); | 3572 | } while (idx != 0); |
3557 | } | 3573 | } |
3558 | 3574 | ||
3575 | static void xc_parse_pushIndex(size_t idx) | ||
3576 | { | ||
3577 | bc_vec_pushIndex(&G.prs.func->code, idx); | ||
3578 | } | ||
3579 | |||
3559 | static void xc_parse_pushInst_and_Index(unsigned inst, size_t idx) | 3580 | static void xc_parse_pushInst_and_Index(unsigned inst, size_t idx) |
3560 | { | 3581 | { |
3561 | xc_parse_push(inst); | 3582 | xc_parse_push(inst); |
@@ -4340,7 +4361,7 @@ static BC_STATUS zbc_parse_break_or_continue(BcLexType type) | |||
4340 | } | 4361 | } |
4341 | #define zbc_parse_break_or_continue(...) (zbc_parse_break_or_continue(__VA_ARGS__) COMMA_SUCCESS) | 4362 | #define zbc_parse_break_or_continue(...) (zbc_parse_break_or_continue(__VA_ARGS__) COMMA_SUCCESS) |
4342 | 4363 | ||
4343 | static BC_STATUS zbc_func_insert(BcFunc *f, char *name, bool var) | 4364 | static BC_STATUS zbc_func_insert(BcFunc *f, char *name, BcType type) |
4344 | { | 4365 | { |
4345 | BcId *autoid; | 4366 | BcId *autoid; |
4346 | BcId a; | 4367 | BcId a; |
@@ -4349,13 +4370,13 @@ static BC_STATUS zbc_func_insert(BcFunc *f, char *name, bool var) | |||
4349 | autoid = (void*)f->autos.v; | 4370 | autoid = (void*)f->autos.v; |
4350 | for (i = 0; i < f->autos.len; i++, autoid++) { | 4371 | for (i = 0; i < f->autos.len; i++, autoid++) { |
4351 | if (strcmp(name, autoid->name) == 0 | 4372 | if (strcmp(name, autoid->name) == 0 |
4352 | && var == autoid->idx | 4373 | && type == (BcType) autoid->idx |
4353 | ) { | 4374 | ) { |
4354 | RETURN_STATUS(bc_error("duplicate function parameter or auto name")); | 4375 | RETURN_STATUS(bc_error("duplicate function parameter or auto name")); |
4355 | } | 4376 | } |
4356 | } | 4377 | } |
4357 | 4378 | ||
4358 | a.idx = var; | 4379 | a.idx = type; |
4359 | a.name = name; | 4380 | a.name = name; |
4360 | 4381 | ||
4361 | bc_vec_push(&f->autos, &a); | 4382 | bc_vec_push(&f->autos, &a); |
@@ -4368,7 +4389,7 @@ static BC_STATUS zbc_parse_funcdef(void) | |||
4368 | { | 4389 | { |
4369 | BcParse *p = &G.prs; | 4390 | BcParse *p = &G.prs; |
4370 | BcStatus s; | 4391 | BcStatus s; |
4371 | bool var, comma, voidfunc; | 4392 | bool comma, voidfunc; |
4372 | char *name; | 4393 | char *name; |
4373 | 4394 | ||
4374 | dbg_lex_enter("%s:%d entered", __func__, __LINE__); | 4395 | dbg_lex_enter("%s:%d entered", __func__, __LINE__); |
@@ -4406,6 +4427,16 @@ static BC_STATUS zbc_parse_funcdef(void) | |||
4406 | 4427 | ||
4407 | comma = false; | 4428 | comma = false; |
4408 | while (p->lex != BC_LEX_RPAREN) { | 4429 | while (p->lex != BC_LEX_RPAREN) { |
4430 | BcType t = BC_TYPE_VAR; | ||
4431 | |||
4432 | if (p->lex == XC_LEX_OP_MULTIPLY) { | ||
4433 | t = BC_TYPE_REF; | ||
4434 | s = zxc_lex_next(); | ||
4435 | if (s) RETURN_STATUS(s); | ||
4436 | s = zbc_POSIX_does_not_allow("references"); | ||
4437 | if (s) RETURN_STATUS(s); | ||
4438 | } | ||
4439 | |||
4409 | if (p->lex != XC_LEX_NAME) | 4440 | if (p->lex != XC_LEX_NAME) |
4410 | RETURN_STATUS(bc_error_bad_function_definition()); | 4441 | RETURN_STATUS(bc_error_bad_function_definition()); |
4411 | 4442 | ||
@@ -4415,9 +4446,8 @@ static BC_STATUS zbc_parse_funcdef(void) | |||
4415 | s = zxc_lex_next(); | 4446 | s = zxc_lex_next(); |
4416 | if (s) goto err; | 4447 | if (s) goto err; |
4417 | 4448 | ||
4418 | var = p->lex != BC_LEX_LBRACKET; | 4449 | if (p->lex == BC_LEX_LBRACKET) { |
4419 | 4450 | if (t == BC_TYPE_VAR) t = BC_TYPE_ARRAY; | |
4420 | if (!var) { | ||
4421 | s = zxc_lex_next(); | 4451 | s = zxc_lex_next(); |
4422 | if (s) goto err; | 4452 | if (s) goto err; |
4423 | 4453 | ||
@@ -4429,6 +4459,10 @@ static BC_STATUS zbc_parse_funcdef(void) | |||
4429 | s = zxc_lex_next(); | 4459 | s = zxc_lex_next(); |
4430 | if (s) goto err; | 4460 | if (s) goto err; |
4431 | } | 4461 | } |
4462 | else if (t == BC_TYPE_REF) { | ||
4463 | s = bc_error_at("vars can't be references"); | ||
4464 | goto err; | ||
4465 | } | ||
4432 | 4466 | ||
4433 | comma = p->lex == BC_LEX_COMMA; | 4467 | comma = p->lex == BC_LEX_COMMA; |
4434 | if (comma) { | 4468 | if (comma) { |
@@ -4436,7 +4470,7 @@ static BC_STATUS zbc_parse_funcdef(void) | |||
4436 | if (s) goto err; | 4470 | if (s) goto err; |
4437 | } | 4471 | } |
4438 | 4472 | ||
4439 | s = zbc_func_insert(p->func, name, var); | 4473 | s = zbc_func_insert(p->func, name, t); |
4440 | if (s) goto err; | 4474 | if (s) goto err; |
4441 | } | 4475 | } |
4442 | 4476 | ||
@@ -4488,7 +4522,7 @@ static BC_STATUS zbc_parse_auto(void) | |||
4488 | if (s) RETURN_STATUS(s); | 4522 | if (s) RETURN_STATUS(s); |
4489 | 4523 | ||
4490 | for (;;) { | 4524 | for (;;) { |
4491 | bool var; | 4525 | BcType t; |
4492 | 4526 | ||
4493 | if (p->lex != XC_LEX_NAME) | 4527 | if (p->lex != XC_LEX_NAME) |
4494 | RETURN_STATUS(bc_error_at("bad 'auto' syntax")); | 4528 | RETURN_STATUS(bc_error_at("bad 'auto' syntax")); |
@@ -4497,8 +4531,9 @@ static BC_STATUS zbc_parse_auto(void) | |||
4497 | s = zxc_lex_next(); | 4531 | s = zxc_lex_next(); |
4498 | if (s) goto err; | 4532 | if (s) goto err; |
4499 | 4533 | ||
4500 | var = (p->lex != BC_LEX_LBRACKET); | 4534 | t = BC_TYPE_VAR; |
4501 | if (!var) { | 4535 | if (p->lex == BC_LEX_LBRACKET) { |
4536 | t = BC_TYPE_ARRAY; | ||
4502 | s = zxc_lex_next(); | 4537 | s = zxc_lex_next(); |
4503 | if (s) goto err; | 4538 | if (s) goto err; |
4504 | 4539 | ||
@@ -4510,7 +4545,7 @@ static BC_STATUS zbc_parse_auto(void) | |||
4510 | if (s) goto err; | 4545 | if (s) goto err; |
4511 | } | 4546 | } |
4512 | 4547 | ||
4513 | s = zbc_func_insert(p->func, name, var); | 4548 | s = zbc_func_insert(p->func, name, t); |
4514 | if (s) goto err; | 4549 | if (s) goto err; |
4515 | 4550 | ||
4516 | if (p->lex == XC_LEX_NLINE | 4551 | if (p->lex == XC_LEX_NLINE |
@@ -5119,12 +5154,64 @@ static BC_STATUS zdc_parse_exprs_until_eof(void) | |||
5119 | #define STACK_HAS_MORE_THAN(s, n) ((s)->len > ((size_t)(n))) | 5154 | #define STACK_HAS_MORE_THAN(s, n) ((s)->len > ((size_t)(n))) |
5120 | #define STACK_HAS_EQUAL_OR_MORE_THAN(s, n) ((s)->len >= ((size_t)(n))) | 5155 | #define STACK_HAS_EQUAL_OR_MORE_THAN(s, n) ((s)->len >= ((size_t)(n))) |
5121 | 5156 | ||
5122 | static BcVec* xc_program_search(char *id, bool var) | 5157 | static size_t xc_program_index(char *code, size_t *bgn) |
5158 | { | ||
5159 | unsigned char *bytes = (void*)(code + *bgn); | ||
5160 | unsigned amt; | ||
5161 | unsigned i; | ||
5162 | size_t res; | ||
5163 | |||
5164 | amt = *bytes++; | ||
5165 | if (amt < SMALL_INDEX_LIMIT) { | ||
5166 | *bgn += 1; | ||
5167 | return amt; | ||
5168 | } | ||
5169 | amt -= (SMALL_INDEX_LIMIT - 1); // amt is 1 or more here | ||
5170 | *bgn += amt + 1; | ||
5171 | |||
5172 | res = 0; | ||
5173 | i = 0; | ||
5174 | do { | ||
5175 | res |= (size_t)(*bytes++) << i; | ||
5176 | i += 8; | ||
5177 | } while (--amt != 0); | ||
5178 | |||
5179 | return res; | ||
5180 | } | ||
5181 | |||
5182 | static char *xc_program_name(char *code, size_t *bgn) | ||
5183 | { | ||
5184 | code += *bgn; | ||
5185 | *bgn += strlen(code) + 1; | ||
5186 | |||
5187 | return xstrdup(code); | ||
5188 | } | ||
5189 | |||
5190 | static BcVec* xc_program_dereference(BcVec *vec) | ||
5191 | { | ||
5192 | BcVec *v; | ||
5193 | size_t vidx, nidx, i = 0; | ||
5194 | |||
5195 | //assert(vec->size == sizeof(uint8_t)); | ||
5196 | |||
5197 | vidx = xc_program_index(vec->v, &i); | ||
5198 | nidx = xc_program_index(vec->v, &i); | ||
5199 | |||
5200 | v = bc_vec_item(&G.prog.arrs, vidx); | ||
5201 | v = bc_vec_item(v, nidx); | ||
5202 | |||
5203 | //assert(v->size != sizeof(uint8_t)); | ||
5204 | |||
5205 | return v; | ||
5206 | } | ||
5207 | |||
5208 | static BcVec* xc_program_search(char *id, BcType type) | ||
5123 | { | 5209 | { |
5124 | BcId e, *ptr; | 5210 | BcId e, *ptr; |
5125 | BcVec *v, *map; | 5211 | BcVec *v, *map; |
5126 | size_t i; | 5212 | size_t i; |
5127 | int new; | 5213 | int new; |
5214 | bool var = (type == BC_TYPE_VAR); | ||
5128 | 5215 | ||
5129 | v = var ? &G.prog.vars : &G.prog.arrs; | 5216 | v = var ? &G.prog.vars : &G.prog.arrs; |
5130 | map = var ? &G.prog.var_map : &G.prog.arr_map; | 5217 | map = var ? &G.prog.var_map : &G.prog.arr_map; |
@@ -5178,17 +5265,20 @@ static BC_STATUS zxc_program_num(BcResult *r, BcNum **num) | |||
5178 | case XC_RESULT_VAR: | 5265 | case XC_RESULT_VAR: |
5179 | case XC_RESULT_ARRAY: | 5266 | case XC_RESULT_ARRAY: |
5180 | case XC_RESULT_ARRAY_ELEM: { | 5267 | case XC_RESULT_ARRAY_ELEM: { |
5181 | BcVec *v; | 5268 | BcType type = (r->t == XC_RESULT_VAR) ? BC_TYPE_VAR : BC_TYPE_ARRAY; |
5182 | void *p; | 5269 | BcVec *v = xc_program_search(r->d.id.name, type); |
5183 | v = xc_program_search(r->d.id.name, r->t == XC_RESULT_VAR); | 5270 | void *p = bc_vec_top(v); |
5184 | // dc variables are all stacks, so here we have this: | 5271 | |
5185 | p = bc_vec_top(v); | ||
5186 | // TODO: eliminate these stacks for bc-only config? | ||
5187 | if (r->t == XC_RESULT_ARRAY_ELEM) { | 5272 | if (r->t == XC_RESULT_ARRAY_ELEM) { |
5273 | size_t idx = r->d.id.idx; | ||
5274 | |||
5188 | v = p; | 5275 | v = p; |
5189 | if (v->len <= r->d.id.idx) | 5276 | if (v->size == sizeof(uint8_t)) |
5190 | bc_array_expand(v, r->d.id.idx + 1); | 5277 | v = xc_program_dereference(v); |
5191 | *num = bc_vec_item(v, r->d.id.idx); | 5278 | //assert(v->size == sizeof(BcNum)); |
5279 | if (v->len <= idx) | ||
5280 | bc_array_expand(v, idx + 1); | ||
5281 | *num = bc_vec_item(v, idx); | ||
5192 | } else { | 5282 | } else { |
5193 | *num = p; | 5283 | *num = p; |
5194 | } | 5284 | } |
@@ -5347,39 +5437,6 @@ static BC_STATUS zxc_program_read(void) | |||
5347 | } | 5437 | } |
5348 | #define zxc_program_read(...) (zxc_program_read(__VA_ARGS__) COMMA_SUCCESS) | 5438 | #define zxc_program_read(...) (zxc_program_read(__VA_ARGS__) COMMA_SUCCESS) |
5349 | 5439 | ||
5350 | static size_t xc_program_index(char *code, size_t *bgn) | ||
5351 | { | ||
5352 | unsigned char *bytes = (void*)(code + *bgn); | ||
5353 | unsigned amt; | ||
5354 | unsigned i; | ||
5355 | size_t res; | ||
5356 | |||
5357 | amt = *bytes++; | ||
5358 | if (amt < SMALL_INDEX_LIMIT) { | ||
5359 | *bgn += 1; | ||
5360 | return amt; | ||
5361 | } | ||
5362 | amt -= (SMALL_INDEX_LIMIT - 1); // amt is 1 or more here | ||
5363 | *bgn += amt + 1; | ||
5364 | |||
5365 | res = 0; | ||
5366 | i = 0; | ||
5367 | do { | ||
5368 | res |= (size_t)(*bytes++) << i; | ||
5369 | i += 8; | ||
5370 | } while (--amt != 0); | ||
5371 | |||
5372 | return res; | ||
5373 | } | ||
5374 | |||
5375 | static char *xc_program_name(char *code, size_t *bgn) | ||
5376 | { | ||
5377 | code += *bgn; | ||
5378 | *bgn += strlen(code) + 1; | ||
5379 | |||
5380 | return xstrdup(code); | ||
5381 | } | ||
5382 | |||
5383 | static void xc_program_printString(const char *str) | 5440 | static void xc_program_printString(const char *str) |
5384 | { | 5441 | { |
5385 | #if ENABLE_DC | 5442 | #if ENABLE_DC |
@@ -5755,43 +5812,81 @@ static BC_STATUS zdc_program_assignStr(BcResult *r, BcVec *v, bool push) | |||
5755 | #define zdc_program_assignStr(...) (zdc_program_assignStr(__VA_ARGS__) COMMA_SUCCESS) | 5812 | #define zdc_program_assignStr(...) (zdc_program_assignStr(__VA_ARGS__) COMMA_SUCCESS) |
5756 | #endif // ENABLE_DC | 5813 | #endif // ENABLE_DC |
5757 | 5814 | ||
5758 | static BC_STATUS zxc_program_popResultAndCopyToVar(char *name, bool var) | 5815 | static BC_STATUS zxc_program_popResultAndCopyToVar(char *name, BcType t) |
5759 | { | 5816 | { |
5760 | BcStatus s; | 5817 | BcStatus s; |
5761 | BcResult *ptr, r; | 5818 | BcResult *ptr, r; |
5762 | BcVec *v; | 5819 | BcVec *vec; |
5763 | BcNum *n; | 5820 | BcNum *n; |
5821 | bool var = (t == BC_TYPE_VAR); | ||
5764 | 5822 | ||
5765 | if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) | 5823 | if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) |
5766 | RETURN_STATUS(bc_error_stack_has_too_few_elements()); | 5824 | RETURN_STATUS(bc_error_stack_has_too_few_elements()); |
5767 | 5825 | ||
5768 | ptr = bc_vec_top(&G.prog.results); | 5826 | ptr = bc_vec_top(&G.prog.results); |
5769 | if ((ptr->t == XC_RESULT_ARRAY) != !var) | 5827 | if ((ptr->t == XC_RESULT_ARRAY) == var) |
5770 | RETURN_STATUS(bc_error_variable_is_wrong_type()); | 5828 | RETURN_STATUS(bc_error_variable_is_wrong_type()); |
5771 | v = xc_program_search(name, var); | 5829 | vec = xc_program_search(name, t); |
5772 | 5830 | ||
5773 | #if ENABLE_DC | 5831 | #if ENABLE_DC |
5774 | if (ptr->t == XC_RESULT_STR && !var) | 5832 | if (ptr->t == XC_RESULT_STR) { |
5775 | RETURN_STATUS(bc_error_variable_is_wrong_type()); | 5833 | if (!var) |
5776 | if (ptr->t == XC_RESULT_STR) | 5834 | RETURN_STATUS(bc_error_variable_is_wrong_type()); |
5777 | RETURN_STATUS(zdc_program_assignStr(ptr, v, true)); | 5835 | RETURN_STATUS(zdc_program_assignStr(ptr, vec, true)); |
5836 | } | ||
5778 | #endif | 5837 | #endif |
5779 | 5838 | ||
5780 | s = zxc_program_num(ptr, &n); | 5839 | s = zxc_program_num(ptr, &n); |
5781 | if (s) RETURN_STATUS(s); | 5840 | if (s) RETURN_STATUS(s); |
5782 | 5841 | ||
5783 | // Do this once more to make sure that pointers were not invalidated. | 5842 | // Do this once more to make sure that pointers were not invalidated. |
5784 | v = xc_program_search(name, var); | 5843 | vec = xc_program_search(name, t); |
5785 | 5844 | ||
5786 | if (var) { | 5845 | if (var) { |
5787 | bc_num_init_DEF_SIZE(&r.d.n); | 5846 | bc_num_init_DEF_SIZE(&r.d.n); |
5788 | bc_num_copy(&r.d.n, n); | 5847 | bc_num_copy(&r.d.n, n); |
5789 | } else { | 5848 | } else { |
5849 | BcVec *v = (BcVec*) n; | ||
5850 | bool ref, ref_size; | ||
5851 | |||
5852 | ref = (v->size == sizeof(BcVec) && t != BC_TYPE_ARRAY); | ||
5853 | ref_size = (v->size == sizeof(uint8_t)); | ||
5854 | |||
5855 | if (ref || (ref_size && t == BC_TYPE_REF)) { | ||
5856 | bc_vec_init(&r.d.v, sizeof(uint8_t), NULL); | ||
5857 | if (ref) { | ||
5858 | size_t vidx, idx; | ||
5859 | BcId id; | ||
5860 | |||
5861 | id.name = ptr->d.id.name; | ||
5862 | v = xc_program_search(ptr->d.id.name, BC_TYPE_REF); | ||
5863 | |||
5864 | // Make sure the pointer was not invalidated. | ||
5865 | vec = xc_program_search(name, t); | ||
5866 | |||
5867 | vidx = bc_map_find_exact(&G.prog.arr_map, &id); | ||
5868 | //assert(vidx != BC_VEC_INVALID_IDX); | ||
5869 | vidx = ((BcId*) bc_vec_item(&G.prog.arr_map, vidx))->idx; | ||
5870 | idx = v->len - 1; | ||
5871 | |||
5872 | bc_vec_pushIndex(&r.d.v, vidx); | ||
5873 | bc_vec_pushIndex(&r.d.v, idx); | ||
5874 | } | ||
5875 | // If we get here, we are copying a ref to a ref. | ||
5876 | else bc_vec_npush(&r.d.v, v->len, v->v); | ||
5877 | |||
5878 | // We need to return early. | ||
5879 | goto ret; | ||
5880 | } | ||
5881 | |||
5882 | if (ref_size && t != BC_TYPE_REF) | ||
5883 | v = xc_program_dereference(v); | ||
5884 | |||
5790 | bc_array_init(&r.d.v, true); | 5885 | bc_array_init(&r.d.v, true); |
5791 | bc_array_copy(&r.d.v, (BcVec *) n); | 5886 | bc_array_copy(&r.d.v, v); |
5792 | } | 5887 | } |
5793 | 5888 | ret: | |
5794 | bc_vec_push(v, &r.d); | 5889 | bc_vec_push(vec, &r.d); |
5795 | bc_vec_pop(&G.prog.results); | 5890 | bc_vec_pop(&G.prog.results); |
5796 | 5891 | ||
5797 | RETURN_STATUS(s); | 5892 | RETURN_STATUS(s); |
@@ -5818,7 +5913,7 @@ static BC_STATUS zxc_program_assign(char inst) | |||
5818 | 5913 | ||
5819 | if (left->t != XC_RESULT_VAR) | 5914 | if (left->t != XC_RESULT_VAR) |
5820 | RETURN_STATUS(bc_error_variable_is_wrong_type()); | 5915 | RETURN_STATUS(bc_error_variable_is_wrong_type()); |
5821 | v = xc_program_search(left->d.id.name, true); | 5916 | v = xc_program_search(left->d.id.name, BC_TYPE_VAR); |
5822 | 5917 | ||
5823 | RETURN_STATUS(zdc_program_assignStr(right, v, false)); | 5918 | RETURN_STATUS(zdc_program_assignStr(right, v, false)); |
5824 | } | 5919 | } |
@@ -5897,7 +5992,7 @@ static BC_STATUS xc_program_pushVar(char *code, size_t *bgn, | |||
5897 | 5992 | ||
5898 | #if ENABLE_DC | 5993 | #if ENABLE_DC |
5899 | if (pop || copy) { | 5994 | if (pop || copy) { |
5900 | BcVec *v = xc_program_search(name, true); | 5995 | BcVec *v = xc_program_search(name, BC_TYPE_VAR); |
5901 | BcNum *num = bc_vec_top(v); | 5996 | BcNum *num = bc_vec_top(v); |
5902 | 5997 | ||
5903 | free(name); | 5998 | free(name); |
@@ -6014,16 +6109,19 @@ static BC_STATUS zbc_program_call(char *code, size_t *idx) | |||
6014 | for (i = 0; i < nparams; ++i) { | 6109 | for (i = 0; i < nparams; ++i) { |
6015 | BcResult *arg; | 6110 | BcResult *arg; |
6016 | BcStatus s; | 6111 | BcStatus s; |
6112 | bool arr; | ||
6017 | 6113 | ||
6018 | a = bc_vec_item(&func->autos, nparams - 1 - i); | 6114 | a = bc_vec_item(&func->autos, nparams - 1 - i); |
6019 | arg = bc_vec_top(&G.prog.results); | 6115 | arg = bc_vec_top(&G.prog.results); |
6020 | 6116 | ||
6021 | if ((!a->idx) != (arg->t == XC_RESULT_ARRAY) // array/variable mismatch | 6117 | arr = (a->idx == BC_TYPE_ARRAY || a->idx == BC_TYPE_REF); |
6118 | |||
6119 | if (arr != (arg->t == XC_RESULT_ARRAY) // array/variable mismatch | ||
6022 | // || arg->t == XC_RESULT_STR - impossible, f("str") is not a legal syntax (strings are not bc expressions) | 6120 | // || arg->t == XC_RESULT_STR - impossible, f("str") is not a legal syntax (strings are not bc expressions) |
6023 | ) { | 6121 | ) { |
6024 | RETURN_STATUS(bc_error_variable_is_wrong_type()); | 6122 | RETURN_STATUS(bc_error_variable_is_wrong_type()); |
6025 | } | 6123 | } |
6026 | s = zxc_program_popResultAndCopyToVar(a->name, a->idx); | 6124 | s = zxc_program_popResultAndCopyToVar(a->name, (BcType) a->idx); |
6027 | if (s) RETURN_STATUS(s); | 6125 | if (s) RETURN_STATUS(s); |
6028 | } | 6126 | } |
6029 | 6127 | ||
@@ -6031,12 +6129,13 @@ static BC_STATUS zbc_program_call(char *code, size_t *idx) | |||
6031 | for (; i < func->autos.len; i++, a++) { | 6129 | for (; i < func->autos.len; i++, a++) { |
6032 | BcVec *v; | 6130 | BcVec *v; |
6033 | 6131 | ||
6034 | v = xc_program_search(a->name, a->idx); | 6132 | v = xc_program_search(a->name, (BcType) a->idx); |
6035 | if (a->idx) { | 6133 | if (a->idx == BC_TYPE_VAR) { |
6036 | BcNum n2; | 6134 | BcNum n2; |
6037 | bc_num_init_DEF_SIZE(&n2); | 6135 | bc_num_init_DEF_SIZE(&n2); |
6038 | bc_vec_push(v, &n2); | 6136 | bc_vec_push(v, &n2); |
6039 | } else { | 6137 | } else { |
6138 | //assert(a->idx == BC_TYPE_ARRAY); | ||
6040 | BcVec v2; | 6139 | BcVec v2; |
6041 | bc_array_init(&v2, true); | 6140 | bc_array_init(&v2, true); |
6042 | bc_vec_push(v, &v2); | 6141 | bc_vec_push(v, &v2); |
@@ -6087,7 +6186,7 @@ static BC_STATUS zbc_program_return(char inst) | |||
6087 | a = (void*)f->autos.v; | 6186 | a = (void*)f->autos.v; |
6088 | for (i = 0; i < f->autos.len; i++, a++) { | 6187 | for (i = 0; i < f->autos.len; i++, a++) { |
6089 | BcVec *v; | 6188 | BcVec *v; |
6090 | v = xc_program_search(a->name, a->idx); | 6189 | v = xc_program_search(a->name, (BcType) a->idx); |
6091 | bc_vec_pop(v); | 6190 | bc_vec_pop(v); |
6092 | } | 6191 | } |
6093 | 6192 | ||
@@ -6399,7 +6498,7 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) | |||
6399 | 6498 | ||
6400 | if (exec) { | 6499 | if (exec) { |
6401 | BcVec *v; | 6500 | BcVec *v; |
6402 | v = xc_program_search(name, true); | 6501 | v = xc_program_search(name, BC_TYPE_VAR); |
6403 | n = bc_vec_top(v); | 6502 | n = bc_vec_top(v); |
6404 | } | 6503 | } |
6405 | 6504 | ||
@@ -6724,7 +6823,7 @@ static BC_STATUS zxc_program_exec(void) | |||
6724 | } | 6823 | } |
6725 | case DC_INST_PUSH_TO_VAR: { | 6824 | case DC_INST_PUSH_TO_VAR: { |
6726 | char *name = xc_program_name(code, &ip->inst_idx); | 6825 | char *name = xc_program_name(code, &ip->inst_idx); |
6727 | s = zxc_program_popResultAndCopyToVar(name, true); | 6826 | s = zxc_program_popResultAndCopyToVar(name, BC_TYPE_VAR); |
6728 | free(name); | 6827 | free(name); |
6729 | break; | 6828 | break; |
6730 | } | 6829 | } |
diff --git a/testsuite/bc_references.bc b/testsuite/bc_references.bc new file mode 100644 index 000000000..fc48c1a56 --- /dev/null +++ b/testsuite/bc_references.bc | |||
@@ -0,0 +1,106 @@ | |||
1 | define printarray(a[], len) { | ||
2 | |||
3 | auto i | ||
4 | |||
5 | for (i = 0; i < len; ++i) { | ||
6 | a[i] | ||
7 | } | ||
8 | } | ||
9 | |||
10 | define a2(a[], len) { | ||
11 | |||
12 | auto i | ||
13 | |||
14 | for (i = 0; i < len; ++i) { | ||
15 | a[i] = a[i] * a[i] | ||
16 | } | ||
17 | |||
18 | printarray(a[], len) | ||
19 | } | ||
20 | |||
21 | define a4(a__[], len) { | ||
22 | |||
23 | auto i | ||
24 | |||
25 | for (i = 0; i < len; ++i) { | ||
26 | a__[i] = a__[i] * a__[i] | ||
27 | } | ||
28 | |||
29 | printarray(a__[], len) | ||
30 | } | ||
31 | |||
32 | define a6(*a__[], len) { | ||
33 | |||
34 | auto i | ||
35 | |||
36 | for (i = 0; i < len; ++i) { | ||
37 | a__[i] = a__[i] * a__[i] | ||
38 | } | ||
39 | |||
40 | printarray(a__[], len) | ||
41 | } | ||
42 | |||
43 | define a1(*a[], len) { | ||
44 | |||
45 | auto i | ||
46 | |||
47 | for (i = 0; i < len; ++i) { | ||
48 | a[i] = i | ||
49 | } | ||
50 | |||
51 | a2(a[], len) | ||
52 | |||
53 | printarray(a[], len) | ||
54 | } | ||
55 | |||
56 | define a3(*a__[], len) { | ||
57 | |||
58 | auto i | ||
59 | |||
60 | for (i = 0; i < len; ++i) { | ||
61 | a__[i] = i | ||
62 | } | ||
63 | |||
64 | a4(a__[], len) | ||
65 | |||
66 | printarray(a__[], len) | ||
67 | } | ||
68 | |||
69 | define a5(*a__[], len) { | ||
70 | |||
71 | auto i | ||
72 | |||
73 | for (i = 0; i < len; ++i) { | ||
74 | a__[i] = i | ||
75 | } | ||
76 | |||
77 | a2(a__[], len) | ||
78 | |||
79 | printarray(a__[], len) | ||
80 | } | ||
81 | |||
82 | define a7(*a__[], len) { | ||
83 | |||
84 | auto i | ||
85 | |||
86 | for (i = 0; i < len; ++i) { | ||
87 | a__[i] = i | ||
88 | } | ||
89 | |||
90 | a6(a__[], len) | ||
91 | |||
92 | printarray(a__[], len) | ||
93 | } | ||
94 | |||
95 | len = 16 | ||
96 | |||
97 | a1(a[], len) | ||
98 | printarray(a[], len) | ||
99 | a3(a[], len) | ||
100 | printarray(a[], len) | ||
101 | a5(a[], len) | ||
102 | printarray(a[], len) | ||
103 | a7(a[], len) | ||
104 | printarray(a[], len) | ||
105 | |||
106 | halt | ||
diff --git a/testsuite/bc_references_results.txt b/testsuite/bc_references_results.txt new file mode 100644 index 000000000..564b54a3a --- /dev/null +++ b/testsuite/bc_references_results.txt | |||
@@ -0,0 +1,212 @@ | |||
1 | 0 | ||
2 | 1 | ||
3 | 4 | ||
4 | 9 | ||
5 | 16 | ||
6 | 25 | ||
7 | 36 | ||
8 | 49 | ||
9 | 64 | ||
10 | 81 | ||
11 | 100 | ||
12 | 121 | ||
13 | 144 | ||
14 | 169 | ||
15 | 196 | ||
16 | 225 | ||
17 | 0 | ||
18 | 0 | ||
19 | 0 | ||
20 | 1 | ||
21 | 2 | ||
22 | 3 | ||
23 | 4 | ||
24 | 5 | ||
25 | 6 | ||
26 | 7 | ||
27 | 8 | ||
28 | 9 | ||
29 | 10 | ||
30 | 11 | ||
31 | 12 | ||
32 | 13 | ||
33 | 14 | ||
34 | 15 | ||
35 | 0 | ||
36 | 0 | ||
37 | 0 | ||
38 | 1 | ||
39 | 2 | ||
40 | 3 | ||
41 | 4 | ||
42 | 5 | ||
43 | 6 | ||
44 | 7 | ||
45 | 8 | ||
46 | 9 | ||
47 | 10 | ||
48 | 11 | ||
49 | 12 | ||
50 | 13 | ||
51 | 14 | ||
52 | 15 | ||
53 | 0 | ||
54 | 0 | ||
55 | 1 | ||
56 | 4 | ||
57 | 9 | ||
58 | 16 | ||
59 | 25 | ||
60 | 36 | ||
61 | 49 | ||
62 | 64 | ||
63 | 81 | ||
64 | 100 | ||
65 | 121 | ||
66 | 144 | ||
67 | 169 | ||
68 | 196 | ||
69 | 225 | ||
70 | 0 | ||
71 | 0 | ||
72 | 0 | ||
73 | 1 | ||
74 | 2 | ||
75 | 3 | ||
76 | 4 | ||
77 | 5 | ||
78 | 6 | ||
79 | 7 | ||
80 | 8 | ||
81 | 9 | ||
82 | 10 | ||
83 | 11 | ||
84 | 12 | ||
85 | 13 | ||
86 | 14 | ||
87 | 15 | ||
88 | 0 | ||
89 | 0 | ||
90 | 0 | ||
91 | 1 | ||
92 | 2 | ||
93 | 3 | ||
94 | 4 | ||
95 | 5 | ||
96 | 6 | ||
97 | 7 | ||
98 | 8 | ||
99 | 9 | ||
100 | 10 | ||
101 | 11 | ||
102 | 12 | ||
103 | 13 | ||
104 | 14 | ||
105 | 15 | ||
106 | 0 | ||
107 | 0 | ||
108 | 1 | ||
109 | 4 | ||
110 | 9 | ||
111 | 16 | ||
112 | 25 | ||
113 | 36 | ||
114 | 49 | ||
115 | 64 | ||
116 | 81 | ||
117 | 100 | ||
118 | 121 | ||
119 | 144 | ||
120 | 169 | ||
121 | 196 | ||
122 | 225 | ||
123 | 0 | ||
124 | 0 | ||
125 | 0 | ||
126 | 1 | ||
127 | 2 | ||
128 | 3 | ||
129 | 4 | ||
130 | 5 | ||
131 | 6 | ||
132 | 7 | ||
133 | 8 | ||
134 | 9 | ||
135 | 10 | ||
136 | 11 | ||
137 | 12 | ||
138 | 13 | ||
139 | 14 | ||
140 | 15 | ||
141 | 0 | ||
142 | 0 | ||
143 | 0 | ||
144 | 1 | ||
145 | 2 | ||
146 | 3 | ||
147 | 4 | ||
148 | 5 | ||
149 | 6 | ||
150 | 7 | ||
151 | 8 | ||
152 | 9 | ||
153 | 10 | ||
154 | 11 | ||
155 | 12 | ||
156 | 13 | ||
157 | 14 | ||
158 | 15 | ||
159 | 0 | ||
160 | 0 | ||
161 | 1 | ||
162 | 4 | ||
163 | 9 | ||
164 | 16 | ||
165 | 25 | ||
166 | 36 | ||
167 | 49 | ||
168 | 64 | ||
169 | 81 | ||
170 | 100 | ||
171 | 121 | ||
172 | 144 | ||
173 | 169 | ||
174 | 196 | ||
175 | 225 | ||
176 | 0 | ||
177 | 0 | ||
178 | 0 | ||
179 | 1 | ||
180 | 4 | ||
181 | 9 | ||
182 | 16 | ||
183 | 25 | ||
184 | 36 | ||
185 | 49 | ||
186 | 64 | ||
187 | 81 | ||
188 | 100 | ||
189 | 121 | ||
190 | 144 | ||
191 | 169 | ||
192 | 196 | ||
193 | 225 | ||
194 | 0 | ||
195 | 0 | ||
196 | 0 | ||
197 | 1 | ||
198 | 4 | ||
199 | 9 | ||
200 | 16 | ||
201 | 25 | ||
202 | 36 | ||
203 | 49 | ||
204 | 64 | ||
205 | 81 | ||
206 | 100 | ||
207 | 121 | ||
208 | 144 | ||
209 | 169 | ||
210 | 196 | ||
211 | 225 | ||
212 | 0 | ||