|
@@ -1097,6 +1097,9 @@ struct _node_t {
|
|
N_UNARY_PLUS,
|
|
N_UNARY_PLUS,
|
|
N_BNOT,
|
|
N_BNOT,
|
|
|
|
|
|
|
|
+ N_REFERENCE,
|
|
|
|
+ N_DEREFERENCE,
|
|
|
|
+
|
|
N_LITERAL,
|
|
N_LITERAL,
|
|
N_LIST,
|
|
N_LIST,
|
|
N_LISTGEN,
|
|
N_LISTGEN,
|
|
@@ -1566,7 +1569,11 @@ char *unescape(char *s);
|
|
node_t *parse_primary(list_t *tokens, size_t *pos) {
|
|
node_t *parse_primary(list_t *tokens, size_t *pos) {
|
|
if (MATCH(MVAR))
|
|
if (MATCH(MVAR))
|
|
return NODET(MVAR, tokens->data[(*pos) - 1]);
|
|
return NODET(MVAR, tokens->data[(*pos) - 1]);
|
|
- else if (MATCH(CATCH)) {
|
|
|
|
|
|
+ else if (AT(AND) && ATP(NAME, 1)) {
|
|
|
|
+ MATCH(AND);
|
|
|
|
+
|
|
|
|
+ return NODET(REFERENCE, tokens->data[(*pos)++]);
|
|
|
|
+ } else if (MATCH(CATCH)) {
|
|
node_t *a = parse_expr(tokens, pos);
|
|
node_t *a = parse_expr(tokens, pos);
|
|
|
|
|
|
return NODE1(CATCH, a);
|
|
return NODE1(CATCH, a);
|
|
@@ -1909,6 +1916,10 @@ node_t *parse_unary(list_t *tokens, size_t *pos) {
|
|
node_t *a = parse_unary(tokens, pos);
|
|
node_t *a = parse_unary(tokens, pos);
|
|
|
|
|
|
return NODE1(BNOT, a);
|
|
return NODE1(BNOT, a);
|
|
|
|
+ } else if (MATCH(RAISE)) {
|
|
|
|
+ node_t *a = parse_unary(tokens, pos);
|
|
|
|
+
|
|
|
|
+ return NODE1(DEREFERENCE, a);
|
|
} else if (MATCH(PLUSPLUS)) {
|
|
} else if (MATCH(PLUSPLUS)) {
|
|
node_t *a = parse_postfix(tokens, pos);
|
|
node_t *a = parse_postfix(tokens, pos);
|
|
|
|
|
|
@@ -2129,10 +2140,16 @@ node_t *parse_bitand(list_t *tokens, size_t *pos) {
|
|
node_t *parse_bitxor(list_t *tokens, size_t *pos) {
|
|
node_t *parse_bitxor(list_t *tokens, size_t *pos) {
|
|
node_t *a = parse_bitand(tokens, pos);
|
|
node_t *a = parse_bitand(tokens, pos);
|
|
|
|
|
|
|
|
+ if (CLIFF)
|
|
|
|
+ return a;
|
|
|
|
+
|
|
while (MATCH(RAISE)) {
|
|
while (MATCH(RAISE)) {
|
|
node_t *b = parse_bitand(tokens, pos);
|
|
node_t *b = parse_bitand(tokens, pos);
|
|
|
|
|
|
a = NODE2(XOR, a, b);
|
|
a = NODE2(XOR, a, b);
|
|
|
|
+
|
|
|
|
+ if (CLIFF)
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
|
|
|
|
return a;
|
|
return a;
|
|
@@ -2422,12 +2439,20 @@ node_t *parse_func(list_t *tokens, size_t *pos, int is_expr) {
|
|
captured = table_new();
|
|
captured = table_new();
|
|
|
|
|
|
do {
|
|
do {
|
|
|
|
+ int is_ref = 0;
|
|
|
|
+
|
|
|
|
+ if (MATCH(AND))
|
|
|
|
+ is_ref = 1;
|
|
|
|
+
|
|
if (!AT(NAME))
|
|
if (!AT(NAME))
|
|
PARSE_ERROR("expected identifier");
|
|
PARSE_ERROR("expected identifier");
|
|
|
|
|
|
token_t *name = tokens->data[(*pos)++];
|
|
token_t *name = tokens->data[(*pos)++];
|
|
|
|
|
|
- table_set(captured, name->text, NODET(LITERAL, name));
|
|
|
|
|
|
+ if (is_ref)
|
|
|
|
+ table_set(captured, name->text, NODET(REFERENCE, name));
|
|
|
|
+ else
|
|
|
|
+ table_set(captured, name->text, NODET(LITERAL, name));
|
|
} while (MATCH(COMMA));
|
|
} while (MATCH(COMMA));
|
|
|
|
|
|
EXPECT(RPAR, ")");
|
|
EXPECT(RPAR, ")");
|
|
@@ -3274,6 +3299,12 @@ node_t *parse(char *source) {
|
|
buffer_fmt(buf, ", qi_make_string(state, \"%s\"), ", (lhs)->t->text); \
|
|
buffer_fmt(buf, ", qi_make_string(state, \"%s\"), ", (lhs)->t->text); \
|
|
rhs; \
|
|
rhs; \
|
|
buffer_fmt(buf, ")"); \
|
|
buffer_fmt(buf, ")"); \
|
|
|
|
+ } else if ((lhs)->tag == N_DEREFERENCE) { \
|
|
|
|
+ buffer_fmt(buf, "qi_set_ref(state, " #prefix ", "); \
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, (lhs)->a); \
|
|
|
|
+ buffer_fmt(buf, ", "); \
|
|
|
|
+ rhs; \
|
|
|
|
+ buffer_fmt(buf, ")"); \
|
|
} else \
|
|
} else \
|
|
COMPILE_ERROR("illegal assignment left-hand side"); \
|
|
COMPILE_ERROR("illegal assignment left-hand side"); \
|
|
}
|
|
}
|
|
@@ -6760,9 +6791,20 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
UNOP("bnot");
|
|
UNOP("bnot");
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case N_REFERENCE:
|
|
|
|
+ EMIT("qi_make_ref(state, \"%s\")", node->t->text);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case N_DEREFERENCE:
|
|
|
|
+ EMIT("qi_deref(state, ");
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
|
|
+ EMIT(")");
|
|
|
|
+ break;
|
|
|
|
+
|
|
case N_MACRO_CALL:
|
|
case N_MACRO_CALL:
|
|
compile_macro_call(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node, 1);
|
|
compile_macro_call(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node, 1);
|
|
break;
|
|
break;
|
|
|
|
+
|
|
case N_MVAR:
|
|
case N_MVAR:
|
|
COMPILE_ERROR("macro variable outside of a macro");
|
|
COMPILE_ERROR("macro variable outside of a macro");
|
|
|
|
|