|
@@ -2539,6 +2539,12 @@ node_t *parse_mexpr(list_t *tokens, size_t *pos) {
|
|
|
|
|
|
a = NODE2(MUL, a, b);
|
|
|
|
|
|
+ continue;
|
|
|
+ } else if (MATCH(SLASH)) {
|
|
|
+ node_t *b = parse_mprimary(tokens, pos);
|
|
|
+
|
|
|
+ a = NODE2(DIV, a, b);
|
|
|
+
|
|
|
continue;
|
|
|
} else if (MATCH(ASSIGN)) {
|
|
|
node_t *b = parse_mprimary(tokens, pos);
|
|
@@ -3622,6 +3628,20 @@ node_t *mexpr_mul(node_t *a, node_t *b) {
|
|
|
return make_number(TO_DOUBLE(a) * TO_DOUBLE(b));
|
|
|
}
|
|
|
|
|
|
+node_t *mexpr_div(node_t *a, node_t *b) {
|
|
|
+ if (!IS_NUMBER(a))
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ if (!IS_NUMBER(b))
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ double x = TO_DOUBLE(b);
|
|
|
+ if (x == 0)
|
|
|
+ return make_number(0);
|
|
|
+
|
|
|
+ return make_number(TO_DOUBLE(a) * x);
|
|
|
+}
|
|
|
+
|
|
|
int mexpr_equals(node_t *a, node_t *b) {
|
|
|
if (!a && !b) return 1;
|
|
|
if (!a && b) return 0;
|
|
@@ -3683,6 +3703,29 @@ node_t *mexpr_eval(node_t *n) {
|
|
|
return mexpr_sub(a, b);
|
|
|
}
|
|
|
|
|
|
+ case N_MUL: {
|
|
|
+ node_t *a = mexpr_eval(n->a);
|
|
|
+ node_t *b = mexpr_eval(n->b);
|
|
|
+
|
|
|
+ return mexpr_mul(a, b);
|
|
|
+ }
|
|
|
+
|
|
|
+ case N_DIV: {
|
|
|
+ node_t *a = mexpr_eval(n->a);
|
|
|
+ node_t *b = mexpr_eval(n->b);
|
|
|
+
|
|
|
+ return mexpr_div(a, b);
|
|
|
+ }
|
|
|
+
|
|
|
+ case N_IFEXPR: {
|
|
|
+ node_t *a = mexpr_eval(n->a);
|
|
|
+
|
|
|
+ if (a)
|
|
|
+ return mexpr_eval(n->b);
|
|
|
+
|
|
|
+ return mexpr_eval(n->c);
|
|
|
+ }
|
|
|
+
|
|
|
default: break;
|
|
|
}
|
|
|
|
|
@@ -3693,11 +3736,7 @@ node_t *mf_isExpr(list_t *t) {
|
|
|
if (t->length != 1)
|
|
|
return NULL;
|
|
|
|
|
|
- node_t *a = t->data[0];
|
|
|
- if (!a)
|
|
|
- return NULL;
|
|
|
-
|
|
|
- return a->tag > N_EXPRS_BEGIN && a->tag < N_EXPRS_END? YES: NULL;
|
|
|
+ return IS_EXPR(t->data[0])? YES: NULL;
|
|
|
}
|
|
|
|
|
|
node_t *mf_isList(list_t *t) {
|
|
@@ -3801,6 +3840,17 @@ node_t *mf_E(list_t *t) {
|
|
|
return mexpr_eval(a);
|
|
|
}
|
|
|
|
|
|
+node_t *mf_C(list_t *t) {
|
|
|
+ if (t->length != 1)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ node_t *a = t->data[0];
|
|
|
+ if (!IS_STRING(a))
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ return const_get(a->t->text);
|
|
|
+}
|
|
|
+
|
|
|
struct {
|
|
|
char *name;
|
|
|
node_t *(*handler)(list_t *);
|
|
@@ -3816,6 +3866,7 @@ struct {
|
|
|
{ "nth", mf_nth },
|
|
|
|
|
|
{ "E", mf_E },
|
|
|
+ { "C", mf_C },
|
|
|
|
|
|
{ NULL, NULL }
|
|
|
};
|
|
@@ -3938,6 +3989,13 @@ node_t *run_mexpr(node_t *node) {
|
|
|
return mexpr_mul(a, b);
|
|
|
}
|
|
|
|
|
|
+ case N_DIV: {
|
|
|
+ node_t *a = run_mexpr(node->a);
|
|
|
+ node_t *b = run_mexpr(node->b);
|
|
|
+
|
|
|
+ return mexpr_div(a, b);
|
|
|
+ }
|
|
|
+
|
|
|
case N_EQUALS: {
|
|
|
node_t *a = run_mexpr(node->a);
|
|
|
node_t *b = run_mexpr(node->b);
|
|
@@ -4080,7 +4138,7 @@ node_t *_expand_mvars(node_t *node, int expr, mvar_expand_err_t *err) {
|
|
|
node->a = n;
|
|
|
|
|
|
return node;
|
|
|
- } else if (node->tag >= N_ADD && node->tag <= N_BAND) {
|
|
|
+ } else if ((node->tag >= N_ADD && node->tag <= N_BAND) || (node->tag >= N_ASSIGN && node->tag <= N_ASSIGN_SHR)) {
|
|
|
node = node_copy(node);
|
|
|
|
|
|
node->a = _expand_mvars(node->a, 1, err);
|
|
@@ -4090,7 +4148,7 @@ node_t *_expand_mvars(node_t *node, int expr, mvar_expand_err_t *err) {
|
|
|
if (err->code != 0) return NULL;
|
|
|
|
|
|
return node;
|
|
|
- } else if (node->tag == N_PROGRAM || node->tag == N_LIST || node->tag == N_TUPLE) {
|
|
|
+ } else if (node->tag == N_PROGRAM || node->tag == N_BLOCK || node->tag == N_LIST || node->tag == N_TUPLE) {
|
|
|
node = node_copy(node);
|
|
|
node->l = list_copy(node->l);
|
|
|
|
|
@@ -5148,6 +5206,7 @@ char *compile(char *source, list_t *required) {
|
|
|
buffer_t *buf = buffer_new();
|
|
|
|
|
|
compile_into("const __QIC = \"" QIC_VERSION "\"", gbuf, buf, ctx, ltab, lstk, sstk, lbl);
|
|
|
+ compile_into("macro E(x)$:E(x)", gbuf, buf, ctx, ltab, lstk, sstk, lbl);
|
|
|
|
|
|
if (required && required->length)
|
|
|
for (size_t i = 0; i < required->length; i++)
|