bc: for "dc only" remove handling of LAST, move OBASE enums up to IBASE

function                                             old     new   delta
dc_LEX_to_INST                                         -      82     +82
bc_parse_pushNUM                                       -      62     +62
zbc_program_num                                      981     978      -3
bc_result_free                                        46      43      -3
zbc_program_binOpPrep                                305     300      -5
static.msg                                            24      12     -12
zbc_program_exec                                    4013    3994     -19
zdc_parse_expr                                       583     507     -76
dc_parse_insts                                        83       -     -83
------------------------------------------------------------------------------
(add/remove: 2/1 grow/shrink: 0/6 up/down: 144/-201)          Total: -57 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2018-12-24 00:50:32 +01:00
parent 9471bd4660
commit ad0bd381e9

View File

@ -141,7 +141,7 @@
//usage:#define dc_full_usage "\n"
//usage: "\nTiny RPN calculator. Operations:"
//usage: "\n+, -, *, /, %, ~, ^," IF_NOT_FEATURE_DC_SMALL(" |,")
//usage: "\np - print top of the stack (without popping)"
//usage: "\np - print top of the stack without popping"
//usage: "\nf - print entire stack"
//usage: "\nk - pop the value and set the precision"
//usage: "\ni - pop the value and set input radix"
@ -286,14 +286,14 @@ typedef enum BcInst {
BC_INST_VAR,
BC_INST_ARRAY_ELEM,
BC_INST_ARRAY,
BC_INST_SCALE_FUNC,
BC_INST_IBASE,
BC_INST_SCALE,
BC_INST_LAST,
BC_INST_IBASE, // order of these constans should match other enums
BC_INST_OBASE, // order of these constans should match other enums
BC_INST_SCALE, // order of these constans should match other enums
IF_BC(BC_INST_LAST,) // order of these constans should match other enums
BC_INST_LENGTH,
BC_INST_READ,
BC_INST_OBASE,
BC_INST_SQRT,
BC_INST_PRINT,
@ -365,12 +365,12 @@ typedef enum BcResultType {
BC_RESULT_STR,
//code uses "inst - BC_INST_IBASE + BC_RESULT_IBASE" construct,
BC_RESULT_IBASE, // relative order should match for: BC_INST_IBASE
BC_RESULT_SCALE, // relative order should match for: BC_INST_SCALE
BC_RESULT_LAST, // relative order should match for: BC_INST_LAST
BC_RESULT_IBASE, // relative order should match for: BC_INST_IBASE
BC_RESULT_OBASE, // relative order should match for: BC_INST_OBASE
BC_RESULT_SCALE, // relative order should match for: BC_INST_SCALE
IF_BC(BC_RESULT_LAST,) // relative order should match for: BC_INST_LAST
BC_RESULT_CONSTANT,
BC_RESULT_ONE,
BC_RESULT_OBASE, // relative order should match for: BC_INST_OBASE
} BcResultType;
typedef union BcResultData {
@ -453,12 +453,12 @@ typedef enum BcLexType {
BC_LEX_KEY_FOR,
BC_LEX_KEY_HALT,
// code uses "type - BC_LEX_KEY_IBASE + BC_INST_IBASE" construct,
BC_LEX_KEY_IBASE, // relative order should match for: BC_INST_IBASE
BC_LEX_KEY_IBASE, // relative order should match for: BC_INST_IBASE
BC_LEX_KEY_OBASE, // relative order should match for: BC_INST_OBASE
BC_LEX_KEY_IF,
BC_LEX_KEY_LAST, // relative order should match for: BC_INST_LAST
IF_BC(BC_LEX_KEY_LAST,) // relative order should match for: BC_INST_LAST
BC_LEX_KEY_LENGTH,
BC_LEX_KEY_LIMITS,
BC_LEX_KEY_OBASE, // relative order should match for: BC_INST_OBASE
BC_LEX_KEY_PRINT,
BC_LEX_KEY_QUIT,
BC_LEX_KEY_READ,
@ -487,11 +487,11 @@ typedef enum BcLexType {
// code uses "t - BC_LEX_STORE_IBASE + BC_INST_IBASE" construct,
BC_LEX_STORE_IBASE, // relative order should match for: BC_INST_IBASE
BC_LEX_STORE_OBASE, // relative order should match for: BC_INST_OBASE
BC_LEX_STORE_SCALE, // relative order should match for: BC_INST_SCALE
BC_LEX_LOAD,
BC_LEX_LOAD_POP,
BC_LEX_STORE_PUSH,
BC_LEX_STORE_OBASE, // relative order should match for: BC_INST_OBASE
BC_LEX_PRINT_POP,
BC_LEX_NQUIT,
BC_LEX_SCALE_FACTOR,
@ -513,11 +513,11 @@ static const struct BcLexKeyword bc_lex_kws[20] = {
BC_LEX_KW_ENTRY("for" , 1), // 5
BC_LEX_KW_ENTRY("halt" , 0), // 6
BC_LEX_KW_ENTRY("ibase" , 1), // 7
BC_LEX_KW_ENTRY("if" , 1), // 8
BC_LEX_KW_ENTRY("last" , 0), // 9
BC_LEX_KW_ENTRY("length" , 1), // 10
BC_LEX_KW_ENTRY("limits" , 0), // 11
BC_LEX_KW_ENTRY("obase" , 1), // 12
BC_LEX_KW_ENTRY("obase" , 1), // 8
BC_LEX_KW_ENTRY("if" , 1), // 9
BC_LEX_KW_ENTRY("last" , 0), // 10
BC_LEX_KW_ENTRY("length" , 1), // 11
BC_LEX_KW_ENTRY("limits" , 0), // 12
BC_LEX_KW_ENTRY("print" , 0), // 13
BC_LEX_KW_ENTRY("quit" , 1), // 14
BC_LEX_KW_ENTRY("read" , 0), // 15
@ -527,10 +527,10 @@ static const struct BcLexKeyword bc_lex_kws[20] = {
BC_LEX_KW_ENTRY("while" , 1), // 19
};
#undef BC_LEX_KW_ENTRY
#define STRING_if (bc_lex_kws[8].name8)
#define STRING_else (bc_lex_kws[4].name8)
#define STRING_while (bc_lex_kws[19].name8)
#define STRING_for (bc_lex_kws[5].name8)
#define STRING_if (bc_lex_kws[9].name8)
#define STRING_while (bc_lex_kws[19].name8)
enum {
POSIX_KWORD_MASK = 0
| (1 << 0) // 0
@ -542,10 +542,10 @@ enum {
| (0 << 6) // 6
| (1 << 7) // 7
| (1 << 8) // 8
| (0 << 9) // 9
| (1 << 10) // 10
| (0 << 11) // 11
| (1 << 12) // 12
| (1 << 9) // 9
| (0 << 10) // 10
| (1 << 11) // 11
| (0 << 12) // 12
| (0 << 13) // 13
| (1 << 14) // 14
| (0 << 15) // 15
@ -560,19 +560,19 @@ enum {
// true if the token is valid in an expression, false otherwise.
// Used to figure out when expr parsing should stop *without error message*
// - 0 element indicates this condition. 1 means "this token is to be eaten
// as part of the expression", token can them still be determined to be invalid
// as part of the expression", it can then still be determined to be invalid
// by later processing.
enum {
#define EXBITS(a,b,c,d,e,f,g,h) \
((uint64_t)((a << 0)+(b << 1)+(c << 2)+(d << 3)+(e << 4)+(f << 5)+(g << 6)+(h << 7)))
BC_PARSE_EXPRS_BITS = 0
+ (EXBITS(0,0,1,1,1,1,1,1) << (0*8)) // 0: eof inval ++ -- - ^ * /
+ (EXBITS(1,1,1,1,1,1,1,1) << (1*8)) // 8: % + - == <= >= != <
+ (EXBITS(1,1,1,1,1,1,1,1) << (2*8)) // 16: > ! || && ^= *= /= %=
+ (EXBITS(1,1,1,0,0,1,1,0) << (3*8)) // 24: += -= = NL WS ( ) [
+ (EXBITS(0,0,0,0,0,0,1,1) << (4*8)) // 32: , ] { ; } STR NAME NUM
+ (EXBITS(0,0,0,0,0,0,0,1) << (5*8)) // 40: auto break cont define else for halt ibase
+ (EXBITS(0,1,1,1,1,0,0,1) << (6*8)) // 48: if last len limits obase print quit read - bug, why "limits" is allowed?
BC_PARSE_EXPRS_BITS = 0 // corresponding BC_LEX_xyz:
+ (EXBITS(0,0,1,1,1,1,1,1) << (0*8)) // 0: eof inval ++ -- - ^ * /
+ (EXBITS(1,1,1,1,1,1,1,1) << (1*8)) // 8: % + - == <= >= != <
+ (EXBITS(1,1,1,1,1,1,1,1) << (2*8)) // 16: > ! || && ^= *= /= %=
+ (EXBITS(1,1,1,0,0,1,1,0) << (3*8)) // 24: += -= = NL WS ( ) [
+ (EXBITS(0,0,0,0,0,0,1,1) << (4*8)) // 32: , ] { ; } STR NAME NUM
+ (EXBITS(0,0,0,0,0,0,0,1) << (5*8)) // 40: auto break cont define else for halt ibase
+ (EXBITS(1,0,1,1,1,0,0,1) << (6*8)) // 48: obase if last len limits print quit read - bug, why "limits" is allowed?
+ (EXBITS(0,1,1,0,0,0,0,0) << (7*8)) // 56: return scale sqrt while
#undef EXBITS
};
@ -615,30 +615,30 @@ static const uint8_t bc_parse_ops[] = {
#if ENABLE_DC
static const //BcInst - should be this type. Using signed narrow type since BC_INST_INVALID is -1
int8_t
dc_parse_insts[] = {
BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GE,
BC_INST_INVALID, BC_INST_POWER, BC_INST_MULTIPLY, BC_INST_DIVIDE,
BC_INST_MODULUS, BC_INST_PLUS, BC_INST_MINUS,
BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
BC_INST_INVALID, BC_INST_INVALID,
BC_INST_BOOL_NOT, BC_INST_INVALID, BC_INST_INVALID,
BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GT, BC_INST_INVALID,
BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GE,
BC_INST_INVALID, BC_INST_INVALID,
BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_IBASE,
BC_INST_INVALID, BC_INST_INVALID, BC_INST_LENGTH, BC_INST_INVALID,
BC_INST_OBASE, BC_INST_PRINT, BC_INST_QUIT, BC_INST_INVALID,
BC_INST_INVALID, BC_INST_SCALE, BC_INST_SQRT, BC_INST_INVALID,
BC_INST_REL_EQ, BC_INST_MODEXP, BC_INST_DIVMOD, BC_INST_INVALID,
BC_INST_INVALID, BC_INST_EXECUTE, BC_INST_PRINT_STACK, BC_INST_CLEAR_STACK,
BC_INST_STACK_LEN, BC_INST_DUPLICATE, BC_INST_SWAP, BC_INST_POP,
BC_INST_ASCIIFY, BC_INST_PRINT_STREAM, BC_INST_INVALID, BC_INST_INVALID,
BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
BC_INST_PRINT, BC_INST_NQUIT, BC_INST_SCALE_FUNC,
dc_LEX_to_INST[] = { // (so many INVALIDs b/c dc parser does not generate these LEXs) // corresponding BC_LEX_xyz:
BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GE, // EOF INVALID OP_INC OP_DEC
BC_INST_INVALID, BC_INST_POWER, BC_INST_MULTIPLY, BC_INST_DIVIDE, // NEG OP_POWER OP_MULTIPLY OP_DIVIDE
BC_INST_MODULUS, BC_INST_PLUS, BC_INST_MINUS, // OP_MODULUS OP_PLUS OP_MINUS
BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, // OP_REL_EQ OP_REL_LE OP_REL_GE OP_REL_NE
BC_INST_INVALID, BC_INST_INVALID, // OP_REL_LT OP_REL_GT
BC_INST_BOOL_NOT, BC_INST_INVALID, BC_INST_INVALID, // OP_BOOL_NOT OP_BOOL_OR OP_BOOL_AND
BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, // OP_ASSIGN_POWER OP_ASSIGN_MULTIPLY OP_ASSIGN_DIVIDE OP_ASSIGN_MODULUS
BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, // OP_ASSIGN_PLUS OP_ASSIGN_MINUS OP_ASSIGN
BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GT, BC_INST_INVALID, // NLINE WHITESPACE LPAREN RPAREN
BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GE, // LBRACKET COMMA RBRACKET LBRACE
BC_INST_INVALID, BC_INST_INVALID, // SCOLON RBRACE
BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, // STR NAME NUMBER
BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, // KEY_AUTO KEY_BREAK KEY_CONTINUE KEY_DEFINE
BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_IBASE, // KEY_ELSE KEY_FOR KEY_HALT KEY_IBASE
BC_INST_OBASE, BC_INST_INVALID, IF_BC(BC_INST_INVALID,) BC_INST_LENGTH,//KEY_OBASE KEY_IF KEY_LAST(bc) KEY_LENGTH
BC_INST_INVALID, BC_INST_PRINT, BC_INST_QUIT, BC_INST_INVALID, // KEY_LIMITS KEY_PRINT KEY_QUIT KEY_READ
BC_INST_INVALID, BC_INST_SCALE, BC_INST_SQRT, BC_INST_INVALID, // KEY_RETURN KEY_SCALE KEY_SQRT KEY_WHILE
BC_INST_REL_EQ, BC_INST_MODEXP, BC_INST_DIVMOD, BC_INST_INVALID, // EQ_NO_REG OP_MODEXP OP_DIVMOD COLON
BC_INST_INVALID, BC_INST_EXECUTE, BC_INST_PRINT_STACK, BC_INST_CLEAR_STACK, //ELSE EXECUTE PRINT_STACK CLEAR_STACK
BC_INST_STACK_LEN, BC_INST_DUPLICATE, BC_INST_SWAP, BC_INST_POP, // STACK_LEVEL DUPLICATE SWAP POP
BC_INST_ASCIIFY, BC_INST_PRINT_STREAM, BC_INST_INVALID, BC_INST_INVALID, //ASCIIFY PRINT_STREAM STORE_IBASE STORE_OBASE
BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, // STORE_SCALE LOAD LOAD_POP STORE_PUSH
BC_INST_PRINT, BC_INST_NQUIT, BC_INST_SCALE_FUNC, // PRINT_POP NQUIT SCALE_FACTOR
};
#endif // ENABLE_DC
@ -2667,7 +2667,7 @@ static void dc_result_copy(BcResult *d, BcResult *src)
d->d.id.name = xstrdup(src->d.id.name);
break;
case BC_RESULT_CONSTANT:
case BC_RESULT_LAST:
IF_BC(case BC_RESULT_LAST:)
case BC_RESULT_ONE:
case BC_RESULT_STR:
memcpy(&d->d.n, &src->d.n, sizeof(BcNum));
@ -4919,11 +4919,13 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t)
case BC_LEX_OP_REL_NE:
case BC_LEX_OP_REL_LT:
case BC_LEX_OP_REL_GT:
dbg_lex("%s:%d LEX_OP_REL_xyz", __func__, __LINE__);
s = zdc_parse_cond(p, t - BC_LEX_OP_REL_EQ + BC_INST_REL_EQ);
get_token = false;
break;
case BC_LEX_SCOLON:
case BC_LEX_COLON:
dbg_lex("%s:%d LEX_[S]COLON", __func__, __LINE__);
s = zdc_parse_mem(p, BC_INST_ARRAY_ELEM, true, t == BC_LEX_COLON);
break;
case BC_LEX_STR:
@ -4931,34 +4933,39 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t)
dc_parse_string(p);
break;
case BC_LEX_NEG:
case BC_LEX_NUMBER:
dbg_lex("%s:%d LEX_NEG/NUMBER", __func__, __LINE__);
if (t == BC_LEX_NEG) {
s = zbc_lex_next(&p->l);
if (s) RETURN_STATUS(s);
if (p->l.t.t != BC_LEX_NUMBER)
RETURN_STATUS(bc_error_bad_token());
}
dbg_lex("%s:%d LEX_NEG", __func__, __LINE__);
s = zbc_lex_next(&p->l);
if (s) RETURN_STATUS(s);
if (p->l.t.t != BC_LEX_NUMBER)
RETURN_STATUS(bc_error_bad_token());
bc_parse_pushNUM(p);
bc_parse_push(p, BC_INST_NEG);
break;
case BC_LEX_NUMBER:
dbg_lex("%s:%d LEX_NUMBER", __func__, __LINE__);
bc_parse_pushNUM(p);
if (t == BC_LEX_NEG) bc_parse_push(p, BC_INST_NEG);
break;
case BC_LEX_KEY_READ:
dbg_lex("%s:%d LEX_KEY_READ", __func__, __LINE__);
bc_parse_push(p, BC_INST_READ);
break;
case BC_LEX_OP_ASSIGN:
case BC_LEX_STORE_PUSH:
dbg_lex("%s:%d LEX_OP_ASSIGN/STORE_PUSH", __func__, __LINE__);
assign = t == BC_LEX_OP_ASSIGN;
inst = assign ? BC_INST_VAR : BC_INST_PUSH_TO_VAR;
s = zdc_parse_mem(p, inst, true, assign);
break;
case BC_LEX_LOAD:
case BC_LEX_LOAD_POP:
dbg_lex("%s:%d LEX_OP_LOAD[_POP]", __func__, __LINE__);
inst = t == BC_LEX_LOAD_POP ? BC_INST_PUSH_VAR : BC_INST_LOAD;
s = zdc_parse_mem(p, inst, true, false);
break;
case BC_LEX_STORE_IBASE:
case BC_LEX_STORE_SCALE:
case BC_LEX_STORE_OBASE:
dbg_lex("%s:%d LEX_OP_STORE_I/OBASE/SCALE", __func__, __LINE__);
inst = t - BC_LEX_STORE_IBASE + BC_INST_IBASE;
s = zdc_parse_mem(p, inst, false, true);
break;
@ -4979,7 +4986,7 @@ static BC_STATUS zdc_parse_expr(BcParse *p)
BcInst inst;
BcStatus s;
inst = dc_parse_insts[p->l.t.t];
inst = dc_LEX_to_INST[p->l.t.t];
if (inst != BC_INST_INVALID) {
bc_parse_push(p, inst);
s = zbc_lex_next(&p->l);
@ -5086,9 +5093,11 @@ static BC_STATUS zbc_program_num(BcResult *r, BcNum **num, bool hex)
*num = &G.prog.one;
break;
#endif
#if SANITY_CHECKS
default:
// Testing the theory that dc does not reach LAST/ONE
bb_error_msg_and_die("BUG:%d", r->t);
#endif
}
RETURN_STATUS(BC_STATUS_SUCCESS);
@ -5750,11 +5759,8 @@ static BC_STATUS zbc_program_assign(char inst)
if (ib || sc || left->t == BC_RESULT_OBASE) {
static const char *const msg[] = {
"bad ibase; must be [2,16]", //BC_RESULT_IBASE
"bad scale; must be [0,"BC_MAX_SCALE_STR"]", //BC_RESULT_SCALE
NULL, //can't happen //BC_RESULT_LAST
NULL, //can't happen //BC_RESULT_CONSTANT
NULL, //can't happen //BC_RESULT_ONE
"bad obase; must be [2,"BC_MAX_OBASE_STR"]", //BC_RESULT_OBASE
"bad scale; must be [0,"BC_MAX_SCALE_STR"]", //BC_RESULT_SCALE
};
size_t *ptr;
size_t max;
@ -6474,16 +6480,17 @@ static BC_STATUS zbc_program_exec(void)
dbg_exec("BC_INST_ARRAY[_ELEM]:");
s = zbc_program_pushArray(code, &ip->inst_idx, inst);
break;
#if ENABLE_BC
case BC_INST_LAST:
//TODO: this can't happen on dc, right?
dbg_exec("BC_INST_LAST:");
r.t = BC_RESULT_LAST;
bc_vec_push(&G.prog.results, &r);
break;
#endif
case BC_INST_IBASE:
case BC_INST_SCALE:
case BC_INST_OBASE:
dbg_exec("BC_INST_internalvar:");
case BC_INST_SCALE:
dbg_exec("BC_INST_internalvar(%d):", inst - BC_INST_IBASE);
bc_program_pushGlobal(inst);
break;
case BC_INST_SCALE_FUNC: