txlyre 4 天之前
父节点
当前提交
a998927ec5
共有 1 个文件被更改,包括 52 次插入1 次删除
  1. 52 1
      qic.c

+ 52 - 1
qic.c

@@ -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");