blob: e7bfa7c84e1a01dff053b5c941810af6c4efc0d3 [file] [log] [blame]
/*
* Copyright (C) Alexander Borisov
* Copyright (C) NGINX, Inc.
*/
#ifndef _NJS_SCOPE_H_INCLUDED_
#define _NJS_SCOPE_H_INCLUDED_
#define NJS_SCOPE_VAR_SIZE 4
#define NJS_SCOPE_TYPE_OFFSET (NJS_SCOPE_VAR_SIZE + 4)
#define NJS_SCOPE_VALUE_OFFSET (NJS_SCOPE_TYPE_OFFSET + 1)
#define NJS_SCOPE_VALUE_MAX ((1 << (32 - NJS_SCOPE_VALUE_OFFSET)) - 1)
#define NJS_SCOPE_TYPE_MASK ((NJS_SCOPE_VALUE_MAX) << NJS_SCOPE_VAR_SIZE)
#define NJS_INDEX_NONE ((njs_index_t) 0)
#define NJS_INDEX_ERROR ((njs_index_t) -1)
njs_index_t njs_scope_temp_index(njs_parser_scope_t *scope);
njs_value_t *njs_scope_create_index_value(njs_vm_t *vm, njs_index_t index);
njs_value_t **njs_scope_make(njs_vm_t *vm, uint32_t count);
njs_index_t njs_scope_global_index(njs_vm_t *vm, const njs_value_t *src,
njs_uint_t runtime);
njs_value_t *njs_scope_value_get(njs_vm_t *vm, njs_index_t index);
njs_inline njs_index_t
njs_scope_index(njs_scope_t scope, njs_index_t index, njs_level_type_t type,
njs_variable_type_t var_type)
{
if (index > NJS_SCOPE_VALUE_MAX || type >= NJS_LEVEL_MAX
|| (scope != NJS_SCOPE_GLOBAL && scope != NJS_SCOPE_FUNCTION))
{
return NJS_INDEX_ERROR;
}
if (scope == NJS_SCOPE_GLOBAL && type == NJS_LEVEL_LOCAL) {
type = NJS_LEVEL_GLOBAL;
}
return (index << NJS_SCOPE_VALUE_OFFSET) | (type << NJS_SCOPE_VAR_SIZE)
| var_type;
}
njs_inline njs_variable_type_t
njs_scope_index_var(njs_index_t index)
{
return (njs_variable_type_t) (index & ~NJS_SCOPE_TYPE_MASK);
}
njs_inline njs_level_type_t
njs_scope_index_type(njs_index_t index)
{
return (njs_level_type_t) ((index >> NJS_SCOPE_VAR_SIZE)
& ~NJS_SCOPE_TYPE_MASK);
}
njs_inline uint32_t
njs_scope_index_value(njs_index_t index)
{
return (uint32_t) (index >> NJS_SCOPE_VALUE_OFFSET);
}
njs_inline njs_value_t *
njs_scope_value(njs_vm_t *vm, njs_index_t index)
{
return vm->levels[njs_scope_index_type(index)]
[njs_scope_index_value(index)];
}
njs_inline njs_value_t *
njs_scope_valid_value(njs_vm_t *vm, njs_index_t index)
{
njs_value_t *value;
value = njs_scope_value(vm, index);
if (!njs_is_valid(value)) {
if (njs_scope_index_var(index) <= NJS_VARIABLE_LET) {
njs_reference_error(vm, "cannot access variable "
"before initialization");
return NULL;
}
njs_set_undefined(value);
}
return value;
}
njs_inline void
njs_scope_value_set(njs_vm_t *vm, njs_index_t index, njs_value_t *value)
{
vm->levels[njs_scope_index_type(index)]
[njs_scope_index_value(index)] = value;
}
njs_inline njs_value_t *
njs_scope_value_clone(njs_vm_t *vm, njs_index_t index, njs_value_t *value)
{
njs_value_t *newval;
newval = njs_mp_alloc(vm->mem_pool, sizeof(njs_value_t));
if (njs_slow_path(newval == NULL)) {
njs_memory_error(vm);
return NULL;
}
*newval = *value;
njs_scope_value_set(vm, index, newval);
return newval;
}
njs_inline njs_index_t
njs_scope_undefined_index(njs_vm_t *vm, njs_uint_t runtime)
{
return njs_scope_global_index(vm, &njs_value_undefined, runtime);
}
njs_inline njs_index_t
njs_scope_global_this_index()
{
return njs_scope_index(NJS_SCOPE_GLOBAL, 0, NJS_LEVEL_LOCAL,
NJS_VARIABLE_VAR);
}
#endif /* _NJS_PARSER_H_INCLUDED_ */