//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"
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,
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 {
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,
// 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,
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
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
| (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
// 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
};
#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
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));
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:
dc_parse_string(p);
break;
case BC_LEX_NEG:
+ 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_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_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;
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);
*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);
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;
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: