|
@@ -384,6 +384,8 @@ typedef struct {
|
|
|
T_GOTO,
|
|
|
T_CLASS,
|
|
|
T_DEL,
|
|
|
+ T_WITH,
|
|
|
+ T_AS,
|
|
|
T_IS,
|
|
|
T_IN,
|
|
|
|
|
@@ -848,6 +850,10 @@ token_t *next_token(char *source, size_t *pos) {
|
|
|
return TK(DEL);
|
|
|
else if (strcmp(name, "is") == 0)
|
|
|
return TK(IS);
|
|
|
+ else if (strcmp(name, "with") == 0)
|
|
|
+ return TK(WITH);
|
|
|
+ else if (strcmp(name, "as") == 0)
|
|
|
+ return TK(AS);
|
|
|
else if (strcmp(name, "in") == 0)
|
|
|
return TK(IN);
|
|
|
else if (strcmp(name, "of") == 0)
|
|
@@ -1111,6 +1117,7 @@ struct _node_t {
|
|
|
N_GOTO,
|
|
|
N_CLASS,
|
|
|
N_DEL,
|
|
|
+ N_WITH,
|
|
|
|
|
|
N_INLINE,
|
|
|
N_HEADER,
|
|
@@ -2618,6 +2625,18 @@ node_t *_parse_stmt(list_t *tokens, size_t *pos, int allow_comma) {
|
|
|
node_t *a = parse_expr(tokens, pos);
|
|
|
|
|
|
return NODE1(DEL, a);
|
|
|
+ } else if (MATCH(WITH)) {
|
|
|
+ node_t *a = parse_expr(tokens, pos);
|
|
|
+
|
|
|
+ EXPECT(AS, "as");
|
|
|
+
|
|
|
+ if (!AT(NAME))
|
|
|
+ PARSE_ERROR("expected identifier");
|
|
|
+
|
|
|
+ token_t *t = tokens->data[(*pos)++];
|
|
|
+ node_t *b = STMT_OR_BLOCK();
|
|
|
+
|
|
|
+ return NODE2t(WITH, a, b, t);
|
|
|
} else if (MATCH(INLINE)) {
|
|
|
if (!AT(STRING))
|
|
|
PARSE_ERROR("expected string");
|
|
@@ -5681,6 +5700,38 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
|
EMIT(");");
|
|
|
break;
|
|
|
|
|
|
+ case N_WITH: {
|
|
|
+ NEWGID();
|
|
|
+ char *varname = tempvar();
|
|
|
+
|
|
|
+ buffer_fmt(gbuf, "qi_value_t *%s;\n", varname);
|
|
|
+
|
|
|
+ buffer_t *tbuf = buffer_new();
|
|
|
+ buffer_fmt(tbuf, "void __%s%d(qi_state_t *state) {\n", PREFIX, gid);
|
|
|
+ buffer_fmt(tbuf, "qi_call(state, qi_index(state, %s, qi_make_string(state, \"__leave\")), qi_list_push(qi_list_make(), %s));\n", varname, varname);
|
|
|
+ buffer_fmt(tbuf, "}\n");
|
|
|
+
|
|
|
+ buffer_appendb(gbuf, tbuf);
|
|
|
+
|
|
|
+ EMIT("%s = ", varname);
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
|
+ EMIT(";\n");
|
|
|
+
|
|
|
+ EMIT("qi_call(state, qi_index(state, %s, qi_make_string(state, \"__enter\")), qi_list_push(qi_list_make(), %s));\n", varname, varname);
|
|
|
+
|
|
|
+ CTXPUSH("scope");
|
|
|
+ EMIT("qi_new_scope(state);\n");
|
|
|
+
|
|
|
+ EMIT("qi_add_local_defer(state, 0, __%s%d);\n", PREFIX, gid);
|
|
|
+
|
|
|
+ EMIT("qi_decl(state, \"%s\", %s);\n", node->t->text, varname);
|
|
|
+
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->b);
|
|
|
+
|
|
|
+ CTXPOP();
|
|
|
+ EMIT("qi_old_scope(state);\n");
|
|
|
+ } break;
|
|
|
+
|
|
|
case N_TRY:
|
|
|
EMIT("qi_try(state, {\n");
|
|
|
LBPUSH();
|
|
@@ -5931,7 +5982,7 @@ void compile_into(char *source, buffer_t *gbuf, buffer_t *buf, list_t *ctx,
|
|
|
table_t *ltab, int_stack_t *lstk, int_stack_t *sstk,
|
|
|
list_t *lbl) {
|
|
|
node_t *n = parse(source);
|
|
|
- if (NEEDS_UTF8) {
|
|
|
+ if (NEEDS_UTF8 && !is_required("utf8")) {
|
|
|
NEEDS_UTF8 = 0;
|
|
|
|
|
|
require_once(gbuf, buf, ctx, ltab, lstk, sstk, lbl, "utf8");
|