]> git.kaiwu.me - njs.git/commitdiff
Comma expressions, statement sequences, and njs_vmcode_stop
authorIgor Sysoev <igor@sysoev.ru>
Tue, 15 Dec 2015 13:45:56 +0000 (16:45 +0300)
committerIgor Sysoev <igor@sysoev.ru>
Tue, 15 Dec 2015 13:45:56 +0000 (16:45 +0300)
changes.

njs/njs_generator.c
njs/njs_parser.c
njs/test/njs_unit_test.c

index 8f9b05487a3539dea299661c29a491f96af0521f..96343f63e1f03e93b72e211bed0136dfb49b5866 100644 (file)
@@ -37,6 +37,14 @@ static nxt_int_t njs_generate_for_statement(njs_vm_t *vm, njs_parser_t *parser,
     njs_parser_node_t *node);
 static nxt_int_t njs_generate_for_in_statement(njs_vm_t *vm,
     njs_parser_t *parser, njs_parser_node_t *node);
+static nxt_int_t njs_generate_statement(njs_vm_t *vm, njs_parser_t *parser,
+    njs_parser_node_t *node);
+static nxt_int_t njs_generate_children(njs_vm_t *vm, njs_parser_t *parser,
+    njs_parser_node_t *node);
+static nxt_int_t njs_generate_stop_statement(njs_vm_t *vm, njs_parser_t *parser,
+    njs_parser_node_t *node);
+static nxt_int_t njs_generate_comma_expression(njs_vm_t *vm,
+    njs_parser_t *parser, njs_parser_node_t *node);
 static nxt_int_t njs_generate_assignment(njs_vm_t *vm, njs_parser_t *parser,
     njs_parser_node_t *node);
 static nxt_int_t njs_generate_operation_assignment(njs_vm_t *vm,
@@ -93,7 +101,6 @@ nxt_inline nxt_bool_t njs_generator_is_constant(njs_parser_node_t *node);
 static nxt_int_t
 njs_generator(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *node)
 {
-    nxt_int_t          ret;
     njs_parser_node_t  *left;
 
     if (node == NULL) {
@@ -121,28 +128,13 @@ njs_generator(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *node)
         return njs_generate_for_in_statement(vm, parser, node);
 
     case NJS_TOKEN_STATEMENT:
-    case NJS_TOKEN_COMMA:
-
-        if (node->left != NULL) {
-            ret = njs_generator(vm, parser, node->left);
-            if (nxt_slow_path(ret != NXT_OK)) {
-                return ret;
-            }
-
-            ret = njs_generator_node_index_release(vm, parser, node->left);
-            if (nxt_slow_path(ret != NXT_OK)) {
-                return ret;
-            }
-        }
-
-        ret = njs_generator(vm, parser, node->right);
-        if (nxt_slow_path(ret != NXT_OK)) {
-            return ret;
-        }
+        return njs_generate_statement(vm, parser, node);
 
-        node->index = node->right->index;
+    case NJS_TOKEN_END:
+        return njs_generate_stop_statement(vm, parser, node);
 
-        return njs_generator_node_index_release(vm, parser, node->right);
+    case NJS_TOKEN_COMMA:
+        return njs_generate_comma_expression(vm, parser, node);
 
     case NJS_TOKEN_ASSIGNMENT:
         return njs_generate_assignment(vm, parser, node);
@@ -736,6 +728,91 @@ njs_generate_for_in_statement(njs_vm_t *vm, njs_parser_t *parser,
 }
 
 
+static nxt_int_t
+njs_generate_statement(njs_vm_t *vm, njs_parser_t *parser,
+    njs_parser_node_t *node)
+{
+    nxt_int_t  ret;
+
+    ret = njs_generate_children(vm, parser, node);
+
+    if (nxt_fast_path(ret == NXT_OK)) {
+        return njs_generator_node_index_release(vm, parser, node->right);
+    }
+
+    return ret;
+}
+
+
+static nxt_int_t
+njs_generate_children(njs_vm_t *vm, njs_parser_t *parser,
+    njs_parser_node_t *node)
+{
+    nxt_int_t  ret;
+
+    ret = njs_generator(vm, parser, node->left);
+    if (nxt_slow_path(ret != NXT_OK)) {
+        return ret;
+    }
+
+    ret = njs_generator_node_index_release(vm, parser, node->left);
+    if (nxt_slow_path(ret != NXT_OK)) {
+        return ret;
+    }
+
+    return njs_generator(vm, parser, node->right);
+}
+
+
+static nxt_int_t
+njs_generate_stop_statement(njs_vm_t *vm, njs_parser_t *parser,
+    njs_parser_node_t *node)
+{
+    nxt_int_t          ret;
+    njs_index_t        index;
+    njs_vmcode_stop_t  *stop;
+
+    ret = njs_generate_children(vm, parser, node);
+
+    if (nxt_fast_path(ret == NXT_OK)) {
+        njs_generate_code(parser, njs_vmcode_stop_t, stop);
+        stop->code.operation = njs_vmcode_stop;
+        stop->code.operands = NJS_VMCODE_1OPERAND;
+        stop->code.retval = NJS_VMCODE_NO_RETVAL;
+
+        index = NJS_INDEX_NONE;
+
+        if (node->right != NULL) {
+            index = node->right->index;
+        }
+
+        if (index == NJS_INDEX_NONE) {
+            index = njs_value_index(vm, parser, &njs_value_void);
+        }
+
+        stop->retval = index;
+    }
+
+    return ret;
+}
+
+
+static nxt_int_t
+njs_generate_comma_expression(njs_vm_t *vm, njs_parser_t *parser,
+    njs_parser_node_t *node)
+{
+    nxt_int_t  ret;
+
+    ret = njs_generate_children(vm, parser, node);
+
+    if (nxt_fast_path(ret == NXT_OK)) {
+        node->index = node->right->index;
+    }
+
+    return ret;
+}
+
+
 static nxt_int_t
 njs_generate_assignment(njs_vm_t *vm, njs_parser_t *parser,
     njs_parser_node_t *node)
@@ -1386,14 +1463,12 @@ njs_generate_function_scope(njs_vm_t *vm, njs_function_lambda_t *lambda,
 nxt_int_t
 njs_generate_scope(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *node)
 {
-    u_char             *p;
-    size_t             code_size, size;
-    uintptr_t          scope_size;
-    nxt_uint_t         n;
-    njs_index_t        index;
-    njs_value_t        *value;
-    njs_vm_code_t      *code;
-    njs_vmcode_stop_t  *stop;
+    u_char         *p;
+    size_t         code_size, size;
+    uintptr_t      scope_size;
+    nxt_uint_t     n;
+    njs_value_t    *value;
+    njs_vm_code_t  *code;
 
     p = nxt_mem_cache_alloc(vm->mem_cache_pool, parser->code_size);
     if (nxt_slow_path(p == NULL)) {
@@ -1403,26 +1478,8 @@ njs_generate_scope(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *node)
     parser->code_start = p;
     parser->code_end = p;
 
-    if (node != NULL) {
-        if (nxt_slow_path(njs_generator(vm, parser, node) != NXT_OK)) {
-            return NXT_ERROR;
-        }
-    }
-
-    if (parser->scope == NJS_SCOPE_GLOBAL) {
-        njs_generate_code(parser, njs_vmcode_stop_t, stop);
-        stop->code.operation = njs_vmcode_stop;
-        stop->code.operands = NJS_VMCODE_1OPERAND;
-        stop->code.retval = NJS_VMCODE_NO_RETVAL;
-
-        if (node->index != 0) {
-            index = node->index;
-
-        } else {
-            index = njs_value_index(vm, parser, &njs_value_void);
-        }
-
-        stop->retval = index;
+    if (nxt_slow_path(njs_generator(vm, parser, node) != NXT_OK)) {
+        return NXT_ERROR;
     }
 
     code_size = parser->code_end - parser->code_start;
index d2b407e9ddd760357a15ca9428c18dee5f75a9d8..f2d9216a0f85810a19a6b382f076ebff39f7bec5 100644 (file)
@@ -34,6 +34,8 @@
  * is treated as a single expiression.
  */
 
+static njs_token_t njs_parser_statement_link(njs_vm_t *vm, njs_parser_t *parser,
+    njs_token_t token);
 static njs_token_t njs_parser_statement(njs_vm_t *vm, njs_parser_t *parser,
     njs_token_t token);
 static njs_token_t njs_parser_block(njs_vm_t *vm, njs_parser_t *parser);
@@ -72,63 +74,74 @@ njs_parser_node_t *
 njs_parser(njs_vm_t *vm, njs_parser_t *parser)
 {
     njs_token_t        token;
-    njs_parser_node_t  *node, *left;
+    njs_parser_node_t  *node;
 
     token = njs_parser_token(parser);
 
-    if (nxt_slow_path(token <= NJS_TOKEN_END)) {
+    while (token != NJS_TOKEN_END) {
 
-        if (vm->exception == NULL) {
-            vm->exception = &njs_exception_syntax_error;
+        token = njs_parser_statement_link(vm, parser, token);
+        if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
+            return NULL;
         }
 
-        return NULL;
-    }
-
-    left = NULL;
+        if (token == NJS_TOKEN_CLOSE_BRACE) {
+            parser->lexer->start--;
 
-    for ( ;; ) {
-        token = njs_parser_statement(vm, parser, token);
+            return parser->node;
+        }
+    }
 
-        if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
+    node = parser->node;
 
-            if (vm->exception == NULL) {
-                vm->exception = &njs_exception_syntax_error;
-            }
+    if (node == NULL) {
+        /* Empty string, just semicolons or variables declarations. */
 
-            nxt_thread_log_error(NXT_LOG_ERR, "ERROR");
+        node = njs_parser_node_alloc(vm);
+        if (nxt_slow_path(node == NULL)) {
             return NULL;
         }
+    }
+
+    node->token = NJS_TOKEN_END;
+
+    return node;
+}
 
-        if (parser->node != NULL && parser->node != left) {
+
+static njs_token_t
+njs_parser_statement_link(njs_vm_t *vm, njs_parser_t *parser,
+    njs_token_t token)
+{
+    njs_parser_node_t  *node, *last;
+
+    last = parser->node;
+
+    token = njs_parser_statement(vm, parser, token);
+
+    if (nxt_fast_path(token > NJS_TOKEN_ILLEGAL)) {
+
+        if (parser->node != last) {
             /*
              * The statement is not empty block, not just semicolon,
-             * and not a "var" declaration without initialization.
+             * and not variables declaration without initialization.
              */
             node = njs_parser_node_alloc(vm);
             if (nxt_slow_path(node == NULL)) {
-                return NULL;
+                return NJS_TOKEN_ERROR;
             }
 
             node->token = NJS_TOKEN_STATEMENT;
-            node->left = left;
+            node->left = last;
             node->right = parser->node;
             parser->node = node;
-
-            left = node;
         }
 
-        if (token == NJS_TOKEN_CLOSE_BRACE) {
-            parser->lexer->start--;
-            break;
-        }
-
-        if (token == NJS_TOKEN_END) {
-            break;
-        }
+    } else if (vm->exception == NULL) {
+        vm->exception = &njs_exception_syntax_error;
     }
 
-    return parser->node;
+    return token;
 }
 
 
@@ -210,37 +223,20 @@ njs_parser_statement(njs_vm_t *vm, njs_parser_t *parser,
 static njs_token_t
 njs_parser_block(njs_vm_t *vm, njs_parser_t *parser)
 {
-    njs_token_t        token;
-    njs_parser_node_t  *node, *left;
+    njs_token_t  token;
 
     token = njs_parser_token(parser);
     if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
         return token;
     }
 
-    left = NULL;
+    parser->node = NULL;
 
     while (token != NJS_TOKEN_CLOSE_BRACE) {
-        token = njs_parser_statement(vm, parser, token);
+        token = njs_parser_statement_link(vm, parser, token);
         if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
             return token;
         }
-
-        if (parser->node != NULL) {
-            /* The statement is not empty block and is not just semicolon. */
-
-            node = njs_parser_node_alloc(vm);
-            if (nxt_slow_path(node == NULL)) {
-                return NJS_TOKEN_ERROR;
-            }
-
-            node->token = NJS_TOKEN_STATEMENT;
-            node->left = left;
-            node->right = parser->node;
-            parser->node = node;
-
-            left = node;
-        }
     }
 
     return njs_parser_token(parser);
index 9f6529057ff9adb6f5bf04e11bb82c9edca81a60..73b7eb8af9699b1963a18d6b78735d697017cf51 100644 (file)
@@ -25,6 +25,40 @@ typedef struct {
 
 static njs_unit_test_t  njs_test[] =
 {
+    /* Variable declarations. */
+
+    { nxt_string("var x"),
+      nxt_string("undefined") },
+
+    { nxt_string("var x;"),
+      nxt_string("undefined") },
+
+    { nxt_string("var x;;"),
+      nxt_string("undefined") },
+
+    { nxt_string("var x = 0"),
+      nxt_string("undefined") },
+
+    { nxt_string("var x = 0;"),
+      nxt_string("undefined") },
+
+    { nxt_string("var x = 0;;"),
+      nxt_string("undefined") },
+
+    { nxt_string("var; a"),
+      nxt_string("SyntaxError") },
+
+    { nxt_string("var \n a \n = 1; a"),
+      nxt_string("1") },
+
+    { nxt_string("var \n a, \n b; b"),
+      nxt_string("undefined") },
+
+    { nxt_string("var a = 1; var b; a"),
+      nxt_string("1") },
+
+    /* Numbers. */
+
     { nxt_string("999999999999999999999"),
       nxt_string("1e+21") },
 
@@ -46,10 +80,13 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("1") },
 
     { nxt_string(""),
-      nxt_string("SyntaxError") },
+      nxt_string("undefined") },
 
     { nxt_string("\n"),
-      nxt_string("SyntaxError") },
+      nxt_string("undefined") },
+
+    { nxt_string(";"),
+      nxt_string("undefined") },
 
     { nxt_string("\n +1"),
       nxt_string("1") },
@@ -1284,7 +1321,7 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("SyntaxError") },
 
     { nxt_string("var a = a + 1"),
-      nxt_string("NaN") },
+      nxt_string("undefined") },
 
     { nxt_string("a = b + 1; var b = 1; a +' '+ b"),
       nxt_string("NaN 1") },
@@ -1308,10 +1345,10 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("ReferenceError") },
 
     { nxt_string("a += 1; var a = 2"),
-      nxt_string("2") },
+      nxt_string("undefined") },
 
     { nxt_string("var a = 1"),
-      nxt_string("1") },
+      nxt_string("undefined") },
 
     { nxt_string("var a = 1; a = (a = 2) + a"),
       nxt_string("4") },
@@ -1337,19 +1374,6 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("a = 3; if (true) if (false); else; a = 2; a"),
       nxt_string("2") },
 
-    /* var statements. */
-
-    { nxt_string("var; a"),
-      nxt_string("SyntaxError") },
-
-    { nxt_string("var \n a \n = 1; a"),
-      nxt_string("1") },
-
-    { nxt_string("var \n a, \n b; b"),
-      nxt_string("undefined") },
-
-    /**/
-
     { nxt_string("for (i = 0; i < 10; i++) { i += 1 } i"),
       nxt_string("10") },
 
@@ -3186,7 +3210,7 @@ static njs_unit_test_t  njs_test[] =
     /* es5id: 8.2_A1_T2 */
 
     { nxt_string("var x = null;"),
-      nxt_string("") },
+      nxt_string("undefined") },
 
     /* es5id: 8.2_A2 */