}
+nxt_inline njs_variable_t *
+njs_parser_variable_add(njs_vm_t *vm, njs_parser_t *parser,
+ njs_variable_type_t type)
+{
+ return njs_variable_add(vm, parser->scope, &parser->lexer->text,
+ parser->lexer->key_hash, type);
+}
+
+nxt_inline njs_ret_t
+njs_parser_variable_reference(njs_vm_t *vm, njs_parser_t *parser,
+ njs_parser_node_t *node, njs_variable_reference_t type)
+{
+ return njs_variable_reference(vm, parser->scope, node, &parser->lexer->text,
+ parser->lexer->key_hash, type);
+}
+
+
static njs_token_t
njs_parser_function_declaration(njs_vm_t *vm, njs_parser_t *parser)
{
return NJS_TOKEN_ILLEGAL;
}
- var = njs_variable_add(vm, parser, NJS_VARIABLE_FUNCTION);
+ var = njs_parser_variable_add(vm, parser, NJS_VARIABLE_FUNCTION);
if (nxt_slow_path(var == NULL)) {
return NJS_TOKEN_ERROR;
}
- ret = njs_variable_reference(vm, parser, node, NJS_DECLARATION);
+ ret = njs_parser_variable_reference(vm, parser, node, NJS_DECLARATION);
if (nxt_slow_path(ret != NXT_OK)) {
return NJS_TOKEN_ERROR;
}
}
if (token == NJS_TOKEN_NAME) {
- var = njs_variable_add(vm, parser, NJS_VARIABLE_SHIM);
+ var = njs_parser_variable_add(vm, parser, NJS_VARIABLE_SHIM);
if (nxt_slow_path(var == NULL)) {
return NJS_TOKEN_ERROR;
}
return NJS_TOKEN_ILLEGAL;
}
- arg = njs_variable_add(vm, parser, NJS_VARIABLE_VAR);
+ arg = njs_parser_variable_add(vm, parser, NJS_VARIABLE_VAR);
if (nxt_slow_path(arg == NULL)) {
return NJS_TOKEN_ERROR;
}
return NJS_TOKEN_ILLEGAL;
}
- var = njs_variable_add(vm, parser, NJS_VARIABLE_VAR);
+ var = njs_parser_variable_add(vm, parser, NJS_VARIABLE_VAR);
if (nxt_slow_path(var == NULL)) {
return NJS_TOKEN_ERROR;
}
name->token = NJS_TOKEN_NAME;
- ret = njs_variable_reference(vm, parser, name, NJS_DECLARATION);
+ ret = njs_parser_variable_reference(vm, parser, name, NJS_DECLARATION);
if (nxt_slow_path(ret != NXT_OK)) {
return NJS_TOKEN_ERROR;
}
return NJS_TOKEN_ILLEGAL;
}
- var = njs_variable_add(vm, parser, NJS_VARIABLE_VAR);
+ var = njs_parser_variable_add(vm, parser, NJS_VARIABLE_VAR);
if (nxt_slow_path(var == NULL)) {
return NJS_TOKEN_ERROR;
}
name->token = NJS_TOKEN_NAME;
- ret = njs_variable_reference(vm, parser, name, NJS_DECLARATION);
+ ret = njs_parser_variable_reference(vm, parser, name, NJS_DECLARATION);
if (nxt_slow_path(ret != NXT_OK)) {
return NJS_TOKEN_ERROR;
}
return NJS_TOKEN_ERROR;
}
- var = njs_variable_add(vm, parser, NJS_VARIABLE_CATCH);
+ var = njs_parser_variable_add(vm, parser, NJS_VARIABLE_CATCH);
if (nxt_slow_path(var == NULL)) {
return NJS_TOKEN_ERROR;
}
node->token = NJS_TOKEN_NAME;
- ret = njs_variable_reference(vm, parser, node, NJS_DECLARATION);
+ ret = njs_parser_variable_reference(vm, parser, node, NJS_DECLARATION);
if (nxt_slow_path(ret != NXT_OK)) {
return NJS_TOKEN_ERROR;
}
break;
}
- ret = njs_variable_reference(vm, parser, node, NJS_REFERENCE);
+ ret = njs_parser_variable_reference(vm, parser, node, NJS_REFERENCE);
if (nxt_slow_path(ret != NXT_OK)) {
return NJS_TOKEN_ERROR;
}
njs_parser_builtin_object(njs_vm_t *vm, njs_parser_t *parser,
njs_parser_node_t *node)
{
- njs_ret_t ret;
- nxt_uint_t index;
- njs_variable_t *var;
+ uint32_t hash;
+ nxt_str_t *name;
+ njs_ret_t ret;
+ nxt_uint_t index;
+ njs_variable_t *var;
+ njs_parser_scope_t *scope;
+
+ scope = parser->scope;
- var = njs_builtin_add(vm, parser);
+ while (scope->type != NJS_SCOPE_GLOBAL) {
+ scope = scope->parent;
+ }
+
+ hash = parser->lexer->key_hash;
+ name = &parser->lexer->text;
+
+ var = njs_variable_add(vm, scope, name, hash, NJS_VARIABLE_VAR);
if (nxt_slow_path(var == NULL)) {
return NJS_TOKEN_ERROR;
}
var->value.type = NJS_OBJECT;
var->value.data.truth = 1;
- ret = njs_variable_reference(vm, parser, node, NJS_REFERENCE);
+ ret = njs_variable_reference(vm, scope, node, name, hash, NJS_REFERENCE);
if (nxt_slow_path(ret != NXT_OK)) {
return NJS_TOKEN_ERROR;
}
njs_parser_builtin_function(njs_vm_t *vm, njs_parser_t *parser,
njs_parser_node_t *node)
{
- njs_ret_t ret;
- nxt_uint_t index;
- njs_variable_t *var;
+ uint32_t hash;
+ nxt_str_t *name;
+ njs_ret_t ret;
+ nxt_uint_t index;
+ njs_variable_t *var;
+ njs_parser_scope_t *scope;
+
+ scope = parser->scope;
+
+ while (scope->type != NJS_SCOPE_GLOBAL) {
+ scope = scope->parent;
+ }
+
+ hash = parser->lexer->key_hash;
+ name = &parser->lexer->text;
- var = njs_builtin_add(vm, parser);
+ var = njs_variable_add(vm, scope, name, hash, NJS_VARIABLE_VAR);
if (nxt_slow_path(var == NULL)) {
return NJS_TOKEN_ERROR;
}
var->value.type = NJS_FUNCTION;
var->value.data.truth = 1;
- ret = njs_variable_reference(vm, parser, node, NJS_REFERENCE);
+ ret = njs_variable_reference(vm, scope, node, name, hash, NJS_REFERENCE);
if (nxt_slow_path(ret != NXT_OK)) {
return NJS_TOKEN_ERROR;
}
};
-typedef struct njs_parser_node_s njs_parser_node_t;
-
struct njs_parser_node_s {
njs_token_t token:16;
uint8_t ctor:1;
njs_token_t njs_parser_property_token(njs_parser_t *parser);
njs_token_t njs_parser_token(njs_parser_t *parser);
nxt_int_t njs_parser_string_create(njs_vm_t *vm, njs_value_t *value);
-njs_ret_t njs_variable_reference(njs_vm_t *vm, njs_parser_t *parser,
- njs_parser_node_t *node, njs_variable_reference_t reference);
+njs_ret_t njs_variable_reference(njs_vm_t *vm, njs_parser_scope_t *scope,
+ njs_parser_node_t *node, nxt_str_t *name, uint32_t hash,
+ njs_variable_reference_t reference);
njs_variable_t *njs_variable_get(njs_vm_t *vm, njs_parser_node_t *node);
njs_index_t njs_variable_typeof(njs_vm_t *vm, njs_parser_node_t *node);
njs_index_t njs_variable_index(njs_vm_t *vm, njs_parser_node_t *node);
/*
* Copyright (C) Igor Sysoev
+ * Copyright (C) Dmitry Volyntsev
* Copyright (C) NGINX, Inc.
*/
} njs_variable_scope_t;
-static njs_ret_t njs_variable_find(njs_vm_t *vm, njs_parser_node_t *node,
- njs_variable_scope_t *vs);
+static njs_ret_t njs_variable_find(njs_vm_t *vm, njs_parser_scope_t *scope,
+ njs_variable_scope_t *vs, nxt_str_t *name, uint32_t hash);
static njs_variable_t *njs_variable_alloc(njs_vm_t *vm, nxt_str_t *name,
njs_variable_type_t type);
njs_variable_t *
-njs_builtin_add(njs_vm_t *vm, njs_parser_t *parser)
+njs_variable_add(njs_vm_t *vm, njs_parser_scope_t *scope, nxt_str_t *name,
+ uint32_t hash, njs_variable_type_t type)
{
nxt_int_t ret;
njs_variable_t *var;
- njs_parser_scope_t *scope;
nxt_lvlhsh_query_t lhq;
- lhq.key_hash = parser->lexer->key_hash;
- lhq.key = parser->lexer->text;
- lhq.proto = &njs_variables_hash_proto;
-
- scope = parser->scope;
-
- while (scope->type != NJS_SCOPE_GLOBAL) {
- scope = scope->parent;
- }
-
- if (nxt_lvlhsh_find(&scope->variables, &lhq) == NXT_OK) {
- var = lhq.value;
-
- return var;
- }
-
- var = njs_variable_alloc(vm, &lhq.key, NJS_VARIABLE_VAR);
- if (nxt_slow_path(var == NULL)) {
- return var;
- }
-
- lhq.replace = 0;
- lhq.value = var;
- lhq.pool = vm->mem_cache_pool;
-
- ret = nxt_lvlhsh_insert(&scope->variables, &lhq);
-
- if (nxt_fast_path(ret == NXT_OK)) {
- return var;
- }
-
- njs_internal_error(vm, "lvlhsh insert failed");
-
- nxt_mem_cache_free(vm->mem_cache_pool, var->name.start);
- nxt_mem_cache_free(vm->mem_cache_pool, var);
-
- return NULL;
-}
-
-
-njs_variable_t *
-njs_variable_add(njs_vm_t *vm, njs_parser_t *parser, njs_variable_type_t type)
-{
- nxt_int_t ret;
- njs_variable_t *var;
- njs_parser_scope_t *scope;
- nxt_lvlhsh_query_t lhq;
-
- lhq.key_hash = parser->lexer->key_hash;
- lhq.key = parser->lexer->text;
+ lhq.key_hash = hash;
+ lhq.key = *name;
lhq.proto = &njs_variables_hash_proto;
- scope = parser->scope;
-
if (type >= NJS_VARIABLE_VAR) {
/*
* A "var" and "function" declarations are
njs_ret_t
-njs_variable_reference(njs_vm_t *vm, njs_parser_t *parser,
- njs_parser_node_t *node, njs_variable_reference_t reference)
+njs_variable_reference(njs_vm_t *vm, njs_parser_scope_t *scope,
+ njs_parser_node_t *node, nxt_str_t *name, uint32_t hash,
+ njs_variable_reference_t reference)
{
njs_ret_t ret;
nxt_lvlhsh_query_t lhq;
- ret = njs_name_copy(vm, &node->u.variable_name, &parser->lexer->text);
+ ret = njs_name_copy(vm, &node->u.variable_name, name);
if (nxt_fast_path(ret == NXT_OK)) {
- node->variable_name_hash = parser->lexer->key_hash;
- node->scope = parser->scope;
+ node->variable_name_hash = hash;
+ node->scope = scope;
node->reference = reference;
lhq.key_hash = node->variable_name_hash;
lhq.value = node;
lhq.pool = vm->mem_cache_pool;
- ret = nxt_lvlhsh_insert(&parser->scope->references, &lhq);
+ ret = nxt_lvlhsh_insert(&scope->references, &lhq);
if (nxt_slow_path(ret != NXT_ERROR)) {
ret = NXT_OK;
}
if (!local_scope) {
- ret = njs_variable_find(vm, node, &vs);
+ ret = njs_variable_find(vm, node->scope, &vs,
+ &node->u.variable_name,
+ node->variable_name_hash);
if (nxt_slow_path(ret != NXT_OK)) {
continue;
}
return node->index;
}
- ret = njs_variable_find(vm, node, &vs);
+ ret = njs_variable_find(vm, node->scope, &vs, &node->u.variable_name,
+ node->variable_name_hash);
if (nxt_fast_path(ret == NXT_OK)) {
return vs.variable->index;
njs_variable_t *var;
njs_variable_scope_t vs;
- ret = njs_variable_find(vm, node, &vs);
+ ret = njs_variable_find(vm, node->scope, &vs, &node->u.variable_name,
+ node->variable_name_hash);
if (nxt_slow_path(ret != NXT_OK)) {
goto not_found;
static njs_ret_t
-njs_variable_find(njs_vm_t *vm, njs_parser_node_t *node,
- njs_variable_scope_t *vs)
+njs_variable_find(njs_vm_t *vm, njs_parser_scope_t *scope,
+ njs_variable_scope_t *vs, nxt_str_t *name, uint32_t hash)
{
- njs_parser_scope_t *scope, *parent, *previous;
+ njs_parser_scope_t *parent, *previous;
- vs->lhq.key_hash = node->variable_name_hash;
- vs->lhq.key = node->u.variable_name;
+ vs->lhq.key_hash = hash;
+ vs->lhq.key = *name;
vs->lhq.proto = &njs_variables_hash_proto;
previous = NULL;
- scope = node->scope;
for ( ;; ) {
if (nxt_lvlhsh_find(&scope->variables, &vs->lhq) == NXT_OK) {
nxt_mem_cache_free(vm->mem_cache_pool, var);
+ njs_memory_error(vm);
+
return NULL;
}
+ njs_scope_offset((var)->index) - NJS_INDEX_GLOBAL_OFFSET)
-njs_variable_t *njs_builtin_add(njs_vm_t *vm, njs_parser_t *parser);
-njs_variable_t *njs_variable_add(njs_vm_t *vm, njs_parser_t *parser,
- njs_variable_type_t type);
+njs_variable_t *njs_variable_add(njs_vm_t *vm, njs_parser_scope_t *scope,
+ nxt_str_t *name, uint32_t hash, njs_variable_type_t type);
+njs_ret_t njs_variable_reference(njs_vm_t *vm, njs_parser_scope_t *scope,
+ njs_parser_node_t *node, nxt_str_t *name, uint32_t hash,
+ njs_variable_reference_t reference);
njs_ret_t njs_variables_scope_reference(njs_vm_t *vm,
njs_parser_scope_t *scope);
njs_ret_t njs_name_copy(njs_vm_t *vm, nxt_str_t *dst, nxt_str_t *src);
typedef struct njs_native_frame_s njs_native_frame_t;
typedef struct njs_property_next_s njs_property_next_t;
typedef struct njs_parser_scope_s njs_parser_scope_t;
+typedef struct njs_parser_node_s njs_parser_node_t;
union njs_value_s {