typedef struct njs_generator_patch_s njs_generator_patch_t;
+typedef enum {
+ NJS_GENERATOR_LOOP = 1,
+ NJS_GENERATOR_SWITCH = 2,
+ NJS_GENERATOR_BLOCK = 4,
+ NJS_GENERATOR_TRY = 8,
+#define NJS_GENERATOR_ALL (NJS_GENERATOR_LOOP | NJS_GENERATOR_SWITCH)
+} njs_generator_block_type_t;
+
+
struct njs_generator_patch_s {
/*
* The jump_offset field points to jump offset field which contains a small
};
-typedef enum {
- NJS_GENERATOR_LOOP = 1,
- NJS_GENERATOR_SWITCH = 2,
- NJS_GENERATOR_BLOCK = 4,
- NJS_GENERATOR_TRY = 8,
-#define NJS_GENERATOR_ALL (NJS_GENERATOR_LOOP | NJS_GENERATOR_SWITCH)
-} njs_generator_block_type_t;
-
-
struct njs_generator_block_s {
njs_generator_block_type_t type; /* 4 bits */
njs_str_t label;
};
-static njs_int_t njs_generator(njs_vm_t *vm, njs_generator_t *generator,
- njs_parser_node_t *node);
+typedef struct {
+ njs_generator_state_func_t state;
+ njs_queue_link_t link;
+ njs_parser_node_t *node;
+ void *context;
+} njs_generator_stack_entry_t;
+
+
+typedef struct {
+ njs_generator_patch_t *patch;
+ njs_generator_patch_t **last;
+ njs_vmcode_jump_t *jump;
+ njs_jump_off_t jump_offset;
+ njs_index_t index;
+} njs_generator_switch_ctx_t;
+
+
+typedef struct {
+ njs_jump_off_t jump_offset;
+ njs_jump_off_t loop_offset;
+ njs_vmcode_jump_t *jump;
+ njs_variable_t *var;
+ njs_index_t index;
+} njs_generator_loop_ctx_t;
+
+
+typedef struct {
+ njs_index_t exception_index;
+ njs_jump_off_t try_offset;
+ njs_jump_off_t catch_offset;
+ njs_generator_block_t *try_block;
+ njs_generator_block_t *catch_block;
+ njs_str_t try_cont_label;
+ njs_str_t try_exit_label;
+ njs_str_t catch_cont_label;
+ njs_str_t catch_exit_label;
+} njs_generator_try_ctx_t;
+
+
static u_char *njs_generate_reserve(njs_vm_t *vm, njs_generator_t *generator,
size_t size);
static njs_int_t njs_generate_code_map(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node, u_char *code);
+
static njs_int_t njs_generate_name(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node);
static njs_int_t njs_generate_variable(njs_vm_t *vm, njs_generator_t *generator,
njs_variable_t **retvar);
static njs_int_t njs_generate_var_statement(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_var_statement_after(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_let(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node, njs_variable_t *var);
static njs_int_t njs_generate_if_statement(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_if_statement_cond(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_if_statement_then(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_if_statement_else(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_cond_expression(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_cond_expression_handler(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_cond_expression_true(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_cond_expression_false(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_switch_statement(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_switch_expression(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *swtch);
+static njs_int_t njs_generate_switch_case(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *swtch);
+static njs_int_t njs_generate_switch_case_after(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *branch);
+static njs_int_t njs_generate_switch_case_end(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *branch);
+static njs_int_t njs_generate_switch_default(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *branch);
+static njs_int_t njs_generate_switch_end(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *swtch);
static njs_int_t njs_generate_while_statement(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_while_condition(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_while_end(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_do_while_statement(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_do_while_condition(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_do_while_end(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_for_statement(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_for_init(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node);
+static njs_int_t njs_generate_for_body(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node);
+static njs_int_t njs_generate_for_update(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_for_end(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node);
static njs_int_t njs_generate_for_let_update(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node, size_t depth);
static njs_int_t njs_generate_for_resolve_closure(njs_vm_t *vm,
njs_parser_node_t *node, size_t depth);
static njs_int_t njs_generate_for_in_statement(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_for_in_object(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_for_in_body(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_start_block(njs_vm_t *vm,
njs_generator_t *generator, njs_generator_block_type_t type,
const njs_str_t *label);
njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_block_statement(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_block_statement_end(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_children(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node);
static njs_int_t njs_generate_stop_statement(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_stop_statement_end(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_comma_expression(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_comma_expression_end(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_assignment(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_assignment_name(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_assignment_prop(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_assignment_end(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_operation_assignment(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_operation_assignment_name(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_operation_assignment_prop(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_operation_assignment_end(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_object(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node);
static njs_int_t njs_generate_property_accessor(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_property_accessor_end(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_array(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node);
static njs_int_t njs_generate_function_expression(njs_vm_t *vm,
njs_parser_node_t *node);
static njs_int_t njs_generate_template_literal(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_template_literal_end(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_test_jump_expression(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_test_jump_expression_after(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_test_jump_expression_end(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_3addr_operation(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node, njs_bool_t swap);
+static njs_int_t njs_generate_3addr_operation_name(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_3addr_operation_end(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_2addr_operation(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_2addr_operation_end(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_typeof_operation(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_typeof_operation_end(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_inc_dec_operation(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node, njs_bool_t post);
+static njs_int_t njs_generate_inc_dec_operation_prop(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_function_declaration(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_function_scope(njs_vm_t *vm,
njs_function_lambda_t *lambda, njs_parser_node_t *node,
const njs_str_t *name);
+static njs_int_t njs_generate_scope_end(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static int64_t njs_generate_lambda_variables(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_return_statement(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_return_statement_end(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_function_call(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_function_call_arguments(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_function_call_end(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_method_call(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_method_call_arguments(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_method_call_end(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_call(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node);
static njs_int_t njs_generate_move_arguments(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_try_statement(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_try_left(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node);
+static njs_int_t njs_generate_try_catch(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_try_finally(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_try_end(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node);
static njs_int_t njs_generate_throw_statement(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_throw_end(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_import_statement(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_import_statement_end(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_export_statement(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_export_statement_end(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_wo_dest(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_wo_dest_after(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_global_reference(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node, njs_bool_t exception);
+static njs_int_t njs_generate_reference_error(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
+
static njs_index_t njs_generate_dest_index(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
static njs_index_t njs_generate_object_dest_index(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_children_indexes_release(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_children_indexes_release_pop(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_node_index_release(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_node_index_release_pop(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_index_release(njs_vm_t *vm,
njs_generator_t *generator, njs_index_t index);
-static njs_int_t njs_generate_global_reference(njs_vm_t *vm,
- njs_generator_t *generator, njs_parser_node_t *node, njs_bool_t exception);
-static njs_int_t njs_generate_reference_error(njs_vm_t *vm,
- njs_generator_t *generator, njs_parser_node_t *node);
#define njs_generate_code(generator, type, _code, _op, nargs, nd) \
static const njs_str_t undef_label = { 0xffffffff, (u_char *) "" };
+njs_inline void
+njs_generator_next(njs_generator_t *generator, njs_generator_state_func_t state,
+ njs_parser_node_t *node)
+{
+ generator->state = state;
+ generator->node = node;
+}
+
+
+njs_inline njs_int_t
+njs_generator_after(njs_vm_t *vm, njs_generator_t *generator,
+ njs_queue_link_t *link, njs_parser_node_t *node,
+ njs_generator_state_func_t state, void *ctx, size_t size)
+{
+ njs_generator_stack_entry_t *entry;
+
+ entry = njs_mp_alloc(vm->mem_pool, sizeof(njs_parser_stack_entry_t));
+ if (njs_slow_path(entry == NULL)) {
+ return NJS_ERROR;
+ }
+
+ entry->state = state;
+ entry->node = node;
+ entry->context = ctx;
+
+ njs_queue_insert_before(link, &entry->link);
+
+ if (size > 0) {
+ entry->context = njs_mp_alloc(vm->mem_pool, size);
+ if (njs_slow_path(entry->context == NULL)) {
+ return NJS_ERROR;
+ }
+
+ memcpy(entry->context, ctx, size);
+ }
+
+ return NJS_OK;
+}
+
+
+njs_inline njs_int_t
+njs_generator_stack_pop(njs_vm_t *vm, njs_generator_t *generator, void *ctx)
+{
+ njs_queue_link_t *link;
+ njs_generator_stack_entry_t *entry;
+
+ entry = njs_queue_link_data(njs_queue_first(&generator->stack),
+ njs_generator_stack_entry_t, link);
+
+ link = njs_queue_first(&generator->stack);
+ njs_queue_remove(link);
+
+ if (ctx != NULL) {
+ njs_mp_free(vm->mem_pool, ctx);
+ }
+
+ generator->context = entry->context;
+
+ njs_generator_next(generator, entry->state, entry->node);
+
+ njs_mp_free(vm->mem_pool, entry);
+
+ return NJS_OK;
+}
+
+
static njs_int_t
njs_generate(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node)
{
if (node == NULL) {
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
}
switch (node->token_type) {
return NJS_ERROR;
}
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
case NJS_TOKEN_OBJECT_VALUE:
node->index = node->u.object->index;
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
case NJS_TOKEN_OBJECT:
return njs_generate_object(vm, generator, node);
return njs_generate_template_literal(vm, generator, node);
case NJS_TOKEN_EXTERNAL:
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
case NJS_TOKEN_NAME:
case NJS_TOKEN_ARGUMENTS:
}
-njs_inline njs_int_t
-njs_generator(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node)
-{
- njs_int_t ret;
-
- if (njs_slow_path(generator->count++ > NJS_GENERATE_MAX_DEPTH)) {
- njs_range_error(vm, "Maximum call stack size exceeded");
- return NJS_ERROR;
- }
-
- ret = njs_generate(vm, generator, node);
-
- generator->count--;
-
- return ret;
-}
-
-
static njs_int_t
-njs_generate_wo_dest(njs_vm_t *vm, njs_generator_t *generator,
+njs_generator_pop(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
{
- njs_int_t ret;
- njs_parser_scope_t *scope;
-
- scope = njs_function_scope(node->scope);
-
- scope->dest_disable = 1;
-
- ret = njs_generator(vm, generator, node);
-
- scope->dest_disable = 0;
-
- return ret;
+ return njs_generator_stack_pop(vm, generator, NULL);
}
njs_generate_name(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
{
+ njs_int_t ret;
njs_variable_t *var;
njs_parser_scope_t *scope;
njs_vmcode_variable_t *variable;
var = njs_variable_reference(vm, node);
if (njs_slow_path(var == NULL)) {
- return njs_generate_global_reference(vm, generator, node, 1);
+ ret = njs_generate_global_reference(vm, generator, node, 1);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
+
+ return njs_generator_stack_pop(vm, generator, NULL);
}
if (var->function && var->type == NJS_VARIABLE_FUNCTION) {
}
if (var->init) {
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
}
if (var->type == NJS_VARIABLE_LET || var->type == NJS_VARIABLE_CONST) {
}
}
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
}
njs_int_t ret;
njs_variable_t *var;
njs_parser_node_t *lvalue, *expr;
- njs_vmcode_move_t *move;
lvalue = node->left;
var->init = 1;
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
}
if (var->type == NJS_VARIABLE_LET || var->type == NJS_VARIABLE_CONST) {
return ret;
}
- ret = njs_generate_let(vm, generator, node, var);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
-
} else {
expr->dest = lvalue;
- ret = njs_generator(vm, generator, expr);
+ njs_generator_next(generator, njs_generate, expr);
+ }
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_var_statement_after, var, 0);
+}
+
+
+static njs_int_t
+njs_generate_var_statement_after(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_int_t ret;
+ njs_variable_t *var;
+ njs_parser_node_t *lvalue, *expr;
+ njs_vmcode_move_t *move;
+
+ lvalue = node->left;
+ expr = node->right;
+ var = generator->context;
+
+ if (var->type == NJS_VARIABLE_LET || var->type == NJS_VARIABLE_CONST) {
+ ret = njs_generate_let(vm, generator, node, var);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
node->index = expr->index;
node->temporary = expr->temporary;
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
}
njs_generate_if_statement(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
{
- njs_int_t ret;
- njs_jump_off_t jump_offset, label_offset;
- njs_vmcode_jump_t *jump;
- njs_vmcode_cond_jump_t *cond_jump;
-
/* The condition expression. */
- ret = njs_generator(vm, generator, node->left);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ njs_generator_next(generator, njs_generate, node->left);
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_if_statement_cond, NULL, 0);
+}
+
+
+static njs_int_t
+njs_generate_if_statement_cond(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_int_t ret;
+ njs_jump_off_t jump_offset;
+ njs_vmcode_cond_jump_t *cond_jump;
njs_generate_code(generator, njs_vmcode_cond_jump_t, cond_jump,
NJS_VMCODE_IF_FALSE_JUMP, 2, node);
}
jump_offset = njs_code_offset(generator, cond_jump);
- label_offset = jump_offset + offsetof(njs_vmcode_cond_jump_t, offset);
if (node->right != NULL && node->right->token_type == NJS_TOKEN_BRANCHING) {
node = node->right;
- ret = njs_generator(vm, generator, node->left);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
-
- ret = njs_generate_node_index_release(vm, generator, node->left);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
-
- njs_generate_code_jump(generator, jump, 0);
-
- njs_code_set_offset(generator, label_offset, jump_offset);
+ njs_generator_next(generator, njs_generate, node->left);
- jump_offset = njs_code_offset(generator, jump);
- label_offset = jump_offset + offsetof(njs_vmcode_jump_t, offset);
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_if_statement_then,
+ &jump_offset, sizeof(njs_jump_off_t));
}
/*
* or the "else" branch in a case of "if/then/else" statement.
*/
- ret = njs_generator(vm, generator, node->right);
+ njs_generator_next(generator, njs_generate, node->right);
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_if_statement_else,
+ &jump_offset, sizeof(njs_jump_off_t));
+}
+
+
+static njs_int_t
+njs_generate_if_statement_then(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_int_t ret;
+ njs_jump_off_t *jump_offset, label_offset;
+ njs_vmcode_jump_t *jump;
+
+ ret = njs_generate_node_index_release(vm, generator, node->left);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
+ jump_offset = (njs_jump_off_t *) generator->context;
+ label_offset = *jump_offset + offsetof(njs_vmcode_cond_jump_t, offset);
+
+ njs_generate_code_jump(generator, jump, 0);
+ njs_code_set_offset(generator, label_offset, *jump_offset);
+
+ *jump_offset = njs_code_offset(generator, jump);
+
+ njs_generator_next(generator, njs_generate, node->right);
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_if_statement_else,
+ jump_offset, 0);
+}
+
+
+static njs_int_t
+njs_generate_if_statement_else(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_int_t ret;
+ njs_jump_off_t *jump_offset, label_offset;
+
+ jump_offset = (njs_jump_off_t *) generator->context;
+ label_offset = *jump_offset + offsetof(njs_vmcode_cond_jump_t, offset);
+
ret = njs_generate_node_index_release(vm, generator, node->right);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
- njs_code_set_offset(generator, label_offset, jump_offset);
+ njs_code_set_offset(generator, label_offset, *jump_offset);
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, generator->context);
}
njs_generate_cond_expression(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
{
- njs_int_t ret;
- njs_jump_off_t jump_offset, cond_jump_offset;
- njs_parser_node_t *branch;
- njs_vmcode_move_t *move;
- njs_vmcode_jump_t *jump;
- njs_vmcode_cond_jump_t *cond_jump;
+ njs_generator_next(generator, njs_generate, node->left);
- /* The condition expression. */
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_cond_expression_handler, NULL, 0);
+}
- ret = njs_generator(vm, generator, node->left);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+
+static njs_int_t
+njs_generate_cond_expression_handler(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_jump_off_t jump_offset;
+ njs_vmcode_cond_jump_t *cond_jump;
njs_generate_code(generator, njs_vmcode_cond_jump_t, cond_jump,
NJS_VMCODE_IF_FALSE_JUMP, 2, node);
- cond_jump_offset = njs_code_offset(generator, cond_jump);
+ jump_offset = njs_code_offset(generator, cond_jump);
cond_jump->cond = node->left->index;
node->index = njs_generate_dest_index(vm, generator, node);
if (njs_slow_path(node->index == NJS_INDEX_ERROR)) {
- return node->index;
+ return NJS_ERROR;
}
- branch = node->right;
+ njs_generator_next(generator, njs_generate, node->right->left);
- /* The "true" branch. */
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_cond_expression_true,
+ &jump_offset, sizeof(njs_jump_off_t));
+}
- ret = njs_generator(vm, generator, branch->left);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+
+static njs_int_t
+njs_generate_cond_expression_true(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_int_t ret;
+ njs_jump_off_t jump_offset;
+ njs_parser_node_t *branch;
+ njs_vmcode_move_t *move;
+ njs_vmcode_jump_t *jump;
+
+ branch = node->right;
/*
* Branches usually uses node->index as destination, however,
jump_offset = njs_code_offset(generator, jump);
njs_code_set_jump_offset(generator, njs_vmcode_cond_jump_t,
- cond_jump_offset);
+ *((njs_jump_off_t *) generator->context));
- /* The "false" branch. */
+ njs_generator_next(generator, njs_generate, branch->right);
- ret = njs_generator(vm, generator, branch->right);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_cond_expression_false,
+ &jump_offset, sizeof(njs_jump_off_t));
+}
+
+
+static njs_int_t
+njs_generate_cond_expression_false(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_int_t ret;
+ njs_parser_node_t *branch;
+ njs_vmcode_move_t *move;
+
+ branch = node->right;
if (node->index != branch->right->index) {
njs_generate_code_move(generator, move, node->index,
branch->right->index, node);
}
- njs_code_set_jump_offset(generator, njs_vmcode_cond_jump_t, jump_offset);
+ njs_code_set_jump_offset(generator, njs_vmcode_cond_jump_t,
+ *((njs_jump_off_t *) generator->context));
ret = njs_generate_node_index_release(vm, generator, branch->right);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, generator->context);
}
njs_generate_switch_statement(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *swtch)
{
- njs_int_t ret;
- njs_jump_off_t jump_offset;
- njs_index_t index;
- njs_parser_node_t *node, *expr, *branch;
- njs_vmcode_move_t *move;
- njs_vmcode_jump_t *jump;
- njs_generator_patch_t *patch, *next, *patches, **last;
- njs_vmcode_equal_jump_t *equal;
+ njs_generator_switch_ctx_t ctx;
/* The "switch" expression. */
- expr = swtch->left;
+ njs_generator_next(generator, njs_generate, swtch->left);
- ret = njs_generator(vm, generator, expr);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), swtch,
+ njs_generate_switch_expression,
+ &ctx, sizeof(njs_generator_switch_ctx_t));
+}
+
+
+static njs_int_t
+njs_generate_switch_expression(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *swtch)
+{
+ njs_int_t ret;
+ njs_parser_node_t *expr;
+ njs_vmcode_move_t *move;
+ njs_generator_switch_ctx_t *ctx;
- index = expr->index;
+ ctx = generator->context;
+
+ expr = swtch->left;
+ ctx->index = expr->index;
if (!expr->temporary) {
- index = njs_generate_temp_index_get(vm, generator, swtch);
- if (njs_slow_path(index == NJS_INDEX_ERROR)) {
+ ctx->index = njs_generate_temp_index_get(vm, generator, swtch);
+ if (njs_slow_path(ctx->index == NJS_INDEX_ERROR)) {
return NJS_ERROR;
}
- njs_generate_code_move(generator, move, index, expr->index, swtch);
+ njs_generate_code_move(generator, move, ctx->index, expr->index, swtch);
}
ret = njs_generate_start_block(vm, generator, NJS_GENERATOR_SWITCH,
return ret;
}
- patches = NULL;
- last = &patches;
+ ctx->patch = NULL;
+ ctx->last = &ctx->patch;
- for (branch = swtch->right; branch != NULL; branch = branch->left) {
+ if (swtch->right != NULL) {
- if (branch->token_type != NJS_TOKEN_DEFAULT) {
+ /* The "case" expression. */
- /* The "case" expression. */
+ njs_generator_next(generator, njs_generate_switch_case, swtch->right);
- node = branch->right;
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), swtch,
+ njs_generate_switch_case_end, ctx, 0);
+ }
- ret = njs_generator(vm, generator, node->left);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ return njs_generate_switch_case_end(vm, generator, swtch);
+}
- njs_generate_code(generator, njs_vmcode_equal_jump_t, equal,
- NJS_VMCODE_IF_EQUAL_JUMP, 3, branch);
- equal->offset = offsetof(njs_vmcode_equal_jump_t, offset);
- equal->value1 = index;
- equal->value2 = node->left->index;
- ret = njs_generate_node_index_release(vm, generator, node->left);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+static njs_int_t
+njs_generate_switch_case(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *branch)
+{
+ if (branch->token_type == NJS_TOKEN_DEFAULT) {
+ if (branch->left == NULL) {
+ return njs_generator_stack_pop(vm, generator, NULL);
+ }
- patch = njs_mp_alloc(vm->mem_pool, sizeof(njs_generator_patch_t));
- if (njs_slow_path(patch == NULL)) {
- return NJS_ERROR;
- }
+ branch = branch->left;
+ }
+
+ njs_generator_next(generator, njs_generate, branch->right->left);
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), branch,
+ njs_generate_switch_case_after,
+ generator->context, 0);
+}
+
+
+static njs_int_t
+njs_generate_switch_case_after(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *branch)
+{
+ njs_int_t ret;
+ njs_parser_node_t *node;
+ njs_generator_patch_t *patch;
+ njs_vmcode_equal_jump_t *equal;
+ njs_generator_switch_ctx_t *ctx;
+
+ ctx = generator->context;
+ node = branch->right;
+
+ njs_generate_code(generator, njs_vmcode_equal_jump_t, equal,
+ NJS_VMCODE_IF_EQUAL_JUMP, 3, branch);
+ equal->offset = offsetof(njs_vmcode_equal_jump_t, offset);
+ equal->value1 = ctx->index;
+ equal->value2 = node->left->index;
+
+ ret = njs_generate_node_index_release(vm, generator, node->left);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
+
+ patch = njs_mp_alloc(vm->mem_pool, sizeof(njs_generator_patch_t));
+ if (njs_slow_path(patch == NULL)) {
+ return NJS_ERROR;
+ }
+
+ patch->jump_offset = njs_code_offset(generator, equal)
+ + offsetof(njs_vmcode_equal_jump_t, offset);
+ patch->label = no_label;
+
+ *ctx->last = patch;
+ ctx->last = &patch->next;
- patch->jump_offset = njs_code_offset(generator, equal)
- + offsetof(njs_vmcode_equal_jump_t, offset);
- patch->label = no_label;
+ if (branch->left == NULL) {
+ return njs_generator_stack_pop(vm, generator, NULL);
+ }
+
+ branch = branch->left;
- *last = patch;
- last = &patch->next;
+ if (branch->token_type == NJS_TOKEN_DEFAULT) {
+ branch = branch->left;
+
+ if (branch == NULL) {
+ return njs_generator_stack_pop(vm, generator, NULL);
}
}
+ njs_generator_next(generator, njs_generate, branch->right->left);
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), branch,
+ njs_generate_switch_case_after, ctx, 0);
+}
+
+static njs_int_t
+njs_generate_switch_case_end(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *swtch)
+{
+ njs_int_t ret;
+ njs_parser_node_t *branch;
+ njs_generator_switch_ctx_t *ctx;
+
+ ctx = generator->context;
+
/* Release either temporary index or temporary expr->index. */
- ret = njs_generate_index_release(vm, generator, index);
+ ret = njs_generate_index_release(vm, generator, ctx->index);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
- njs_generate_code_jump(generator, jump,
+ njs_generate_code_jump(generator, ctx->jump,
offsetof(njs_vmcode_jump_t, offset));
- jump_offset = njs_code_offset(generator, jump);
+ ctx->jump_offset = njs_code_offset(generator, ctx->jump);
+
+ branch = swtch->right;
+
+ if (branch != NULL) {
+ njs_generator_next(generator, njs_generate_switch_default, branch);
- patch = patches;
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), swtch,
+ njs_generate_switch_end, ctx, 0);
+ }
- for (branch = swtch->right; branch != NULL; branch = branch->left) {
+ return njs_generate_switch_end(vm, generator, swtch);
+}
- if (branch->token_type == NJS_TOKEN_DEFAULT) {
- njs_code_set_jump_offset(generator, njs_vmcode_jump_t, jump_offset);
- jump = NULL;
- node = branch;
- } else {
- njs_code_update_offset(generator, patch);
+static njs_int_t
+njs_generate_switch_default(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *branch)
+{
+ njs_parser_node_t *node;
+ njs_generator_patch_t *next;
+ njs_generator_switch_ctx_t *ctx;
- next = patch->next;
+ ctx = generator->context;
- njs_mp_free(vm->mem_pool, patch);
+ if (branch->token_type == NJS_TOKEN_DEFAULT) {
+ njs_code_set_jump_offset(generator, njs_vmcode_jump_t,
+ ctx->jump_offset);
+ ctx->jump = NULL;
+ node = branch;
- patch = next;
- node = branch->right;
- }
+ } else {
+ njs_code_update_offset(generator, ctx->patch);
- /* The "case/default" statements. */
+ next = ctx->patch->next;
- ret = njs_generator(vm, generator, node->right);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ njs_mp_free(vm->mem_pool, ctx->patch);
+
+ ctx->patch = next;
+ node = branch->right;
+ }
+
+ njs_generator_next(generator, njs_generate, node->right);
+
+ branch = branch->left;
+
+ if (branch == NULL) {
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), branch,
+ njs_generator_pop, NULL, 0);
}
- if (jump != NULL) {
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), branch,
+ njs_generate_switch_default, ctx, 0);
+}
+
+
+static njs_int_t
+njs_generate_switch_end(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *swtch)
+{
+ njs_generator_switch_ctx_t *ctx;
+
+ ctx = generator->context;
+
+ if (ctx->jump != NULL) {
/* A "switch" without default case. */
- njs_code_set_jump_offset(generator, njs_vmcode_jump_t, jump_offset);
+ njs_code_set_jump_offset(generator, njs_vmcode_jump_t,
+ ctx->jump_offset);
}
/* Patch "break" statements offsets. */
njs_generate_patch_block_exit(vm, generator);
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, ctx);
}
njs_generate_while_statement(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
{
- njs_int_t ret;
- njs_jump_off_t jump_offset, loop_offset;
- njs_parser_node_t *condition;
- njs_vmcode_jump_t *jump;
- njs_vmcode_cond_jump_t *cond_jump;
+ njs_int_t ret;
+ njs_vmcode_jump_t *jump;
+ njs_generator_loop_ctx_t ctx;
/*
* Set a jump to the loop condition. This jump is executed once just on
*/
njs_generate_code_jump(generator, jump, 0);
- jump_offset = njs_code_offset(generator, jump);
-
- /* The loop body. */
+ ctx.jump_offset = njs_code_offset(generator, jump);
ret = njs_generate_start_block(vm, generator, NJS_GENERATOR_LOOP,
&node->name);
return ret;
}
- loop_offset = njs_code_offset(generator, generator->code_end);
+ ctx.loop_offset = njs_code_offset(generator, generator->code_end);
- ret = njs_generator(vm, generator, node->left);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ njs_generator_next(generator, njs_generate, node->left);
- /* The loop condition. */
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_while_condition,
+ &ctx, sizeof(njs_generator_loop_ctx_t));
+}
+
+
+static njs_int_t
+njs_generate_while_condition(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_generator_loop_ctx_t *ctx;
+
+ ctx = generator->context;
njs_generate_patch_block(vm, generator, generator->block->continuation);
- njs_code_set_jump_offset(generator, njs_vmcode_jump_t, jump_offset);
+ njs_code_set_jump_offset(generator, njs_vmcode_jump_t, ctx->jump_offset);
- condition = node->right;
+ njs_generator_next(generator, njs_generate, node->right);
- ret = njs_generator(vm, generator, condition);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_while_end, ctx, 0);
+}
+
+
+static njs_int_t
+njs_generate_while_end(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_int_t ret;
+ njs_vmcode_cond_jump_t *cond_jump;
+ njs_generator_loop_ctx_t *ctx;
+
+ ctx = generator->context;
njs_generate_code(generator, njs_vmcode_cond_jump_t, cond_jump,
- NJS_VMCODE_IF_TRUE_JUMP, 2, condition);
- cond_jump->offset = loop_offset - njs_code_offset(generator, cond_jump);
- cond_jump->cond = condition->index;
+ NJS_VMCODE_IF_TRUE_JUMP, 2, node->right);
+ cond_jump->offset = ctx->loop_offset - njs_code_offset(generator,
+ cond_jump);
+ cond_jump->cond = node->right->index;
njs_generate_patch_block_exit(vm, generator);
- return njs_generate_node_index_release(vm, generator, condition);
+ ret = njs_generate_node_index_release(vm, generator, node->right);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
+
+ return njs_generator_stack_pop(vm, generator, ctx);
}
njs_generate_do_while_statement(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
{
- njs_int_t ret;
- njs_jump_off_t loop_offset;
- njs_parser_node_t *condition;
- njs_vmcode_cond_jump_t *cond_jump;
-
- /* The loop body. */
+ njs_int_t ret;
+ njs_generator_loop_ctx_t ctx;
ret = njs_generate_start_block(vm, generator, NJS_GENERATOR_LOOP,
&node->name);
return ret;
}
- loop_offset = njs_code_offset(generator, generator->code_end);
+ ctx.loop_offset = njs_code_offset(generator, generator->code_end);
- ret = njs_generator(vm, generator, node->left);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ njs_generator_next(generator, njs_generate, node->left);
- /* The loop condition. */
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_do_while_condition,
+ &ctx, sizeof(njs_generator_loop_ctx_t));
+}
+
+static njs_int_t
+njs_generate_do_while_condition(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
njs_generate_patch_block(vm, generator, generator->block->continuation);
- condition = node->right;
+ njs_generator_next(generator, njs_generate, node->right);
- ret = njs_generator(vm, generator, condition);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_do_while_end,
+ generator->context, 0);
+}
+
+
+static njs_int_t
+njs_generate_do_while_end(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_int_t ret;
+ njs_vmcode_cond_jump_t *cond_jump;
+ njs_generator_loop_ctx_t *ctx;
+
+ ctx = generator->context;
njs_generate_code(generator, njs_vmcode_cond_jump_t, cond_jump,
- NJS_VMCODE_IF_TRUE_JUMP, 2, condition);
- cond_jump->offset = loop_offset - njs_code_offset(generator, cond_jump);
- cond_jump->cond = condition->index;
+ NJS_VMCODE_IF_TRUE_JUMP, 2, node->right);
+ cond_jump->offset = ctx->loop_offset
+ - njs_code_offset(generator, cond_jump);
+ cond_jump->cond = node->right->index;
njs_generate_patch_block_exit(vm, generator);
- return njs_generate_node_index_release(vm, generator, condition);
+ ret = njs_generate_node_index_release(vm, generator, node->right);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
+
+ return njs_generator_stack_pop(vm, generator, ctx);
}
njs_generate_for_statement(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
{
- njs_int_t ret;
- njs_jump_off_t jump_offset, loop_offset;
- njs_parser_node_t *condition, *update, *init;
- njs_vmcode_jump_t *jump;
- njs_vmcode_cond_jump_t *cond_jump;
+ njs_int_t ret;
+ njs_generator_loop_ctx_t ctx;
ret = njs_generate_start_block(vm, generator, NJS_GENERATOR_LOOP,
&node->name);
return ret;
}
- jump = NULL;
+ ctx.jump = NULL;
- /* The loop initialization. */
+ njs_generator_next(generator, njs_generate, node->left);
- ret = njs_generator(vm, generator, node->left);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_for_init,
+ &ctx, sizeof(njs_generator_loop_ctx_t));
+}
+
+
+static njs_int_t
+njs_generate_for_init(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_int_t ret;
+ njs_parser_node_t *condition;
+ njs_generator_loop_ctx_t *ctx;
+
+ ctx = generator->context;
ret = njs_generate_node_index_release(vm, generator, node->left);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
- init = node->left;
- node = node->right;
- condition = node->left;
+ condition = node->right->left;
/*
* Closures can occur in conditional and loop updates. This must be
return ret;
}
- /* GCC complains about uninitialized jump_offset. */
- jump_offset = 0;
+ ctx->jump_offset = 0;
if (condition != NULL) {
/*
* executed once just after the loop initialization and eliminates
* execution of one additional jump inside the loop per each iteration.
*/
- njs_generate_code_jump(generator, jump, 0);
- jump_offset = njs_code_offset(generator, jump);
+ njs_generate_code_jump(generator, ctx->jump, 0);
+ ctx->jump_offset = njs_code_offset(generator, ctx->jump);
}
/* The loop body. */
- loop_offset = njs_code_offset(generator, generator->code_end);
+ ctx->loop_offset = njs_code_offset(generator, generator->code_end);
- node = node->right;
+ njs_generator_next(generator, njs_generate, node->right->right->left);
- ret = njs_generator(vm, generator, node->left);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_for_body, ctx, 0);
+}
+
+
+static njs_int_t
+njs_generate_for_body(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_int_t ret;
+ njs_parser_node_t *update, *init;
+ njs_generator_loop_ctx_t *ctx;
+
+ ctx = generator->context;
/* The loop update. */
- update = node->right;
+ init = node->left;
+ update = node->right->right->right;
ret = njs_generate_for_resolve_closure(vm, update, generator->count);
if (njs_slow_path(ret != NJS_OK)) {
njs_generate_patch_block(vm, generator, generator->block->continuation);
- ret = njs_generator(vm, generator, update);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ njs_generator_next(generator, njs_generate, update);
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_for_update, ctx, 0);
+}
+
+
+static njs_int_t
+njs_generate_for_update(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_int_t ret;
+ njs_parser_node_t *condition, *update;
+ njs_generator_loop_ctx_t *ctx;
+
+ ctx = generator->context;
+
+ update = node->right->right->right;
+ condition = node->right->left;
ret = njs_generate_node_index_release(vm, generator, update);
if (njs_slow_path(ret != NJS_OK)) {
/* The loop condition. */
if (condition != NULL) {
- njs_code_set_jump_offset(generator, njs_vmcode_jump_t, jump_offset);
+ njs_code_set_jump_offset(generator, njs_vmcode_jump_t,
+ ctx->jump_offset);
+
+ njs_generator_next(generator, njs_generate, condition);
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_for_end, ctx, 0);
+ }
+
+ return njs_generate_for_end(vm, generator, node);
+}
- ret = njs_generator(vm, generator, condition);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+static njs_int_t
+njs_generate_for_end(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_int_t ret;
+ njs_parser_node_t *condition;
+ njs_vmcode_cond_jump_t *cond_jump;
+ njs_generator_loop_ctx_t *ctx;
+
+ ctx = generator->context;
+
+ condition = node->right->left;
+
+ if (condition != NULL) {
njs_generate_code(generator, njs_vmcode_cond_jump_t, cond_jump,
NJS_VMCODE_IF_TRUE_JUMP, 2, condition);
- cond_jump->offset = loop_offset - njs_code_offset(generator, cond_jump);
+ cond_jump->offset = ctx->loop_offset
+ - njs_code_offset(generator, cond_jump);
cond_jump->cond = condition->index;
njs_generate_patch_block_exit(vm, generator);
- return njs_generate_node_index_release(vm, generator, condition);
+ ret = njs_generate_node_index_release(vm, generator, condition);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
+
+ return njs_generator_stack_pop(vm, generator, ctx);
}
- njs_generate_code_jump(generator, jump,
- loop_offset - njs_code_offset(generator, jump));
+ njs_generate_code_jump(generator, ctx->jump,
+ ctx->loop_offset - njs_code_offset(generator,
+ ctx->jump));
njs_generate_patch_block_exit(vm, generator);
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, ctx);
}
njs_generate_for_in_statement(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
{
- njs_int_t ret;
- njs_index_t index;
- njs_variable_t *var;
- njs_jump_off_t loop_offset, prop_offset;
- njs_parser_node_t *foreach, *name;
- njs_vmcode_prop_next_t *prop_next;
- njs_vmcode_prop_foreach_t *prop_foreach;
+ njs_int_t ret;
+ njs_parser_node_t *foreach, *name;
+ njs_generator_loop_ctx_t ctx;
ret = njs_generate_start_block(vm, generator, NJS_GENERATOR_LOOP,
&node->name);
name = name->left;
ret = njs_generate_variable_wo_dest(vm, generator, name,
- NJS_DECLARATION, &var);
+ NJS_DECLARATION, &ctx.var);
if (njs_slow_path(ret != NJS_OK)) {
return NJS_ERROR;
}
foreach->left->index = name->index;
- ret = njs_generator(vm, generator, foreach->right);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ njs_generator_next(generator, njs_generate, foreach->right);
- var->init = 1;
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_for_in_object,
+ &ctx, sizeof(njs_generator_loop_ctx_t));
+ }
- } else {
- ret = njs_generator(vm, generator, foreach->left);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ njs_generator_next(generator, njs_generate, foreach->left);
- ret = njs_generator(vm, generator, foreach->right);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ ret = njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_for_in_object,
+ &ctx, sizeof(njs_generator_loop_ctx_t));
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack),
+ foreach->right, njs_generate, NULL, 0);
+}
+
+
+static njs_int_t
+njs_generate_for_in_object(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_parser_node_t *foreach, *name;
+ njs_generator_loop_ctx_t *ctx;
+ njs_vmcode_prop_foreach_t *prop_foreach;
+
+ ctx = generator->context;
+
+ foreach = node->left;
+ name = foreach->left->right;
+
+ if (name != NULL) {
+ ctx->var->init = 1;
}
njs_generate_code(generator, njs_vmcode_prop_foreach_t, prop_foreach,
NJS_VMCODE_PROPERTY_FOREACH, 2, foreach);
- prop_offset = njs_code_offset(generator, prop_foreach);
+ ctx->jump_offset = njs_code_offset(generator, prop_foreach);
prop_foreach->object = foreach->right->index;
- index = njs_generate_temp_index_get(vm, generator, foreach->right);
- if (njs_slow_path(index == NJS_INDEX_ERROR)) {
+ ctx->index = njs_generate_temp_index_get(vm, generator, foreach->right);
+ if (njs_slow_path(ctx->index == NJS_INDEX_ERROR)) {
return NJS_ERROR;
}
- prop_foreach->next = index;
+ prop_foreach->next = ctx->index;
/* The loop body. */
- loop_offset = njs_code_offset(generator, generator->code_end);
+ ctx->loop_offset = njs_code_offset(generator, generator->code_end);
- ret = njs_generator(vm, generator, node->right);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ njs_generator_next(generator, njs_generate, node->right);
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_for_in_body, ctx, 0);
+}
+
+
+static njs_int_t
+njs_generate_for_in_body(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_int_t ret;
+ njs_jump_off_t prop_offset;
+ njs_parser_node_t *foreach, *name;
+ njs_vmcode_prop_next_t *prop_next;
+ njs_generator_loop_ctx_t *ctx;
+
+ ctx = generator->context;
+
+ foreach = node->left;
+ name = foreach->left->right;
/* The loop iterator. */
njs_generate_patch_block(vm, generator, generator->block->continuation);
- njs_code_set_jump_offset(generator, njs_vmcode_prop_foreach_t, prop_offset);
+ njs_code_set_jump_offset(generator, njs_vmcode_prop_foreach_t,
+ ctx->jump_offset);
njs_generate_code(generator, njs_vmcode_prop_next_t, prop_next,
NJS_VMCODE_PROPERTY_NEXT, 3, node->left->left);
prop_offset = njs_code_offset(generator, prop_next);
prop_next->retval = foreach->left->index;
prop_next->object = foreach->right->index;
- prop_next->next = index;
- prop_next->offset = loop_offset - prop_offset;
+ prop_next->next = ctx->index;
+ prop_next->offset = ctx->loop_offset - prop_offset;
njs_generate_patch_block_exit(vm, generator);
return ret;
}
- return njs_generate_index_release(vm, generator, index);
+ ret = njs_generate_index_release(vm, generator, ctx->index);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
+
+ return njs_generator_stack_pop(vm, generator, ctx);
}
return NJS_ERROR;
}
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
syntax_error:
return NJS_ERROR;
}
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
syntax_error:
return debugger->retval;
}
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
}
{
njs_int_t ret;
njs_variable_t *var;
+ njs_queue_link_t *link;
njs_parser_node_t *right;
njs_vmcode_variable_t *code;
}
if (node->left == NULL) {
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
}
node = node->left;
statement:
- ret = njs_generate_children(vm, generator, node);
+ link = njs_queue_first(&generator->stack);
- if (njs_fast_path(ret == NJS_OK)) {
- return njs_generate_node_index_release(vm, generator, right);
+ ret = njs_generate_children(vm, generator, node);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
}
- return ret;
+ return njs_generator_after(vm, generator, link, right,
+ njs_generate_node_index_release_pop, NULL, 0);
}
-
static njs_int_t
njs_generate_block_statement(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
{
- njs_int_t ret;
+ njs_int_t ret;
+ njs_queue_link_t *link;
ret = njs_generate_start_block(vm, generator, NJS_GENERATOR_BLOCK,
&node->name);
return ret;
}
+ link = njs_queue_first(&generator->stack);
+
ret = njs_generate_statement(vm, generator, node);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
+ return njs_generator_after(vm, generator, link, node,
+ njs_generate_block_statement_end, NULL, 0);
+}
+
+
+static njs_int_t
+njs_generate_block_statement_end(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
njs_generate_patch_block_exit(vm, generator);
- return ret;
+ return njs_generator_stack_pop(vm, generator, NULL);
}
{
njs_int_t ret;
- ret = njs_generator(vm, generator, node->left);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ njs_generator_next(generator, njs_generate, node->left);
- ret = njs_generate_node_index_release(vm, generator, node->left);
+ ret = njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node->right,
+ njs_generate, NULL, 0);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
- return njs_generator(vm, generator, node->right);
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node->left,
+ njs_generate_node_index_release_pop, NULL, 0);
}
njs_parser_node_t *node)
{
njs_int_t ret;
- njs_index_t index;
- njs_vmcode_stop_t *stop;
+ njs_queue_link_t *link;
+
+ link = njs_queue_first(&generator->stack);
ret = njs_generate_children(vm, generator, node);
+ if (njs_fast_path(ret != NJS_OK)) {
+ return ret;
+ }
- if (njs_fast_path(ret == NJS_OK)) {
- njs_generate_code(generator, njs_vmcode_stop_t, stop,
- NJS_VMCODE_STOP, 1, node);
+ return njs_generator_after(vm, generator, link, node,
+ njs_generate_stop_statement_end, NULL, 0);
+}
- index = njs_scope_undefined_index(vm, 0);
- node = node->right;
- if (node != NULL) {
- if ((node->index != NJS_INDEX_NONE
- && node->token_type != NJS_TOKEN_FUNCTION_DECLARATION)
- || node->token_type == NJS_TOKEN_THIS)
- {
- index = node->index;
- }
- }
+static njs_int_t
+njs_generate_stop_statement_end(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_index_t index;
+ njs_vmcode_stop_t *stop;
+
+ njs_generate_code(generator, njs_vmcode_stop_t, stop,
+ NJS_VMCODE_STOP, 1, node);
- stop->retval = index;
+ index = njs_scope_undefined_index(vm, 0);
+ node = node->right;
+
+ if (node != NULL) {
+ if ((node->index != NJS_INDEX_NONE
+ && node->token_type != NJS_TOKEN_FUNCTION_DECLARATION)
+ || node->token_type == NJS_TOKEN_THIS)
+ {
+ index = node->index;
+ }
}
- return ret;
+ stop->retval = index;
+
+ return njs_generator_stack_pop(vm, generator, NULL);
}
njs_generate_comma_expression(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
{
- njs_int_t ret;
+ njs_int_t ret;
+ njs_queue_link_t *link;
- ret = njs_generate_children(vm, generator, node);
+ link = njs_queue_first(&generator->stack);
- if (njs_fast_path(ret == NJS_OK)) {
- node->index = node->right->index;
+ ret = njs_generate_children(vm, generator, node);
+ if (njs_fast_path(ret != NJS_OK)) {
+ return ret;
}
- return ret;
+ return njs_generator_after(vm, generator, link, node,
+ njs_generate_comma_expression_end, NULL, 0);
+}
+
+
+static njs_int_t
+njs_generate_comma_expression_end(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ node->index = node->right->index;
+
+ return njs_generator_stack_pop(vm, generator, NULL);
}
njs_parser_node_t *node)
{
njs_int_t ret;
- njs_index_t index, src;
njs_variable_t *var;
- njs_parser_node_t *lvalue, *expr, *object, *property;
- njs_vmcode_move_t *move;
+ njs_parser_node_t *lvalue, *expr;
njs_vmcode_variable_t *var_code;
- njs_vmcode_prop_set_t *prop_set;
lvalue = node->left;
expr = node->right;
NJS_VMCODE_ASSIGNMENT_ERROR, 0, node);
var_code->dst = var->index;
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
}
expr->dest = lvalue;
- ret = njs_generator(vm, generator, expr);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
-
- /*
- * lvalue and expression indexes are equal if the expression is an
- * empty object or expression result is stored directly in variable.
- */
- if (lvalue->index != expr->index) {
- njs_generate_code_move(generator, move, lvalue->index, expr->index,
- expr);
- }
-
- node->index = expr->index;
- node->temporary = expr->temporary;
+ njs_generator_next(generator, njs_generate, expr);
- return NJS_OK;
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_assignment_name, NULL, 0);
}
/* lvalue->token == NJS_TOKEN_PROPERTY(_INIT) */
/* Object. */
- object = lvalue->left;
+ njs_generator_next(generator, njs_generate, lvalue->left);
- ret = njs_generator(vm, generator, object);
+ ret = njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_assignment_prop, NULL, 0);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
/* Property. */
- property = lvalue->right;
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack),
+ lvalue->right, njs_generate, NULL, 0);
+}
- ret = njs_generator(vm, generator, property);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
+
+static njs_int_t
+njs_generate_assignment_name(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_parser_node_t *lvalue, *expr;
+ njs_vmcode_move_t *move;
+
+ lvalue = node->left;
+ expr = node->right;
+
+ /*
+ * lvalue and expression indexes are equal if the expression is an
+ * empty object or expression result is stored directly in variable.
+ */
+ if (lvalue->index != expr->index) {
+ njs_generate_code_move(generator, move, lvalue->index, expr->index,
+ expr);
}
+ node->index = expr->index;
+ node->temporary = expr->temporary;
+
+ return njs_generator_stack_pop(vm, generator, NULL);
+}
+
+
+static njs_int_t
+njs_generate_assignment_prop(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_index_t index, src;
+ njs_parser_node_t *lvalue, *expr, *object, *property;
+ njs_vmcode_move_t *move;
+
+ lvalue = node->left;
+ expr = node->right;
+
+ object = lvalue->left;
+ property = lvalue->right;
+
if (njs_slow_path(njs_parser_has_side_effect(expr))) {
/*
* Preserve object and property values stored in variables in a case
}
}
- ret = njs_generator(vm, generator, expr);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ njs_generator_next(generator, njs_generate, expr);
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_assignment_end, NULL, 0);
+}
+
+
+static njs_int_t
+njs_generate_assignment_end(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_parser_node_t *lvalue, *expr, *object, *property;
+ njs_vmcode_prop_set_t *prop_set;
+
+ lvalue = node->left;
+ expr = node->right;
+
+ object = lvalue->left;
+ property = lvalue->right;
switch (lvalue->token_type) {
case NJS_TOKEN_PROPERTY_INIT:
node->index = expr->index;
node->temporary = expr->temporary;
- return njs_generate_children_indexes_release(vm, generator, lvalue);
+ return njs_generate_children_indexes_release_pop(vm, generator, lvalue);
}
njs_parser_node_t *node)
{
njs_int_t ret;
- njs_index_t index, src;
+ njs_index_t index;
njs_variable_t *var;
- njs_parser_node_t *lvalue, *expr, *object, *property;
+ njs_parser_node_t *lvalue, *expr;
njs_vmcode_move_t *move;
- njs_vmcode_3addr_t *code;
njs_vmcode_variable_t *var_code;
- njs_vmcode_prop_get_t *prop_get;
- njs_vmcode_prop_set_t *prop_set;
lvalue = node->left;
NJS_VMCODE_ASSIGNMENT_ERROR, 0, node);
var_code->dst = var->index;
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
}
index = lvalue->index;
move->dst = index;
}
- ret = njs_generator(vm, generator, expr);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
-
- njs_generate_code(generator, njs_vmcode_3addr_t, code,
- node->u.operation, 3, expr);
- code->dst = lvalue->index;
- code->src1 = index;
- code->src2 = expr->index;
-
- node->index = lvalue->index;
+ njs_generator_next(generator, njs_generate, expr);
- if (lvalue->index != index) {
- ret = njs_generate_index_release(vm, generator, index);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
- }
-
- return njs_generate_node_index_release(vm, generator, expr);
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_operation_assignment_name,
+ &index, sizeof(njs_index_t));
}
/* lvalue->token == NJS_TOKEN_PROPERTY */
/* Object. */
- object = lvalue->left;
+ njs_generator_next(generator, njs_generate, lvalue->left);
- ret = njs_generator(vm, generator, object);
+ ret = njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_operation_assignment_prop, NULL, 0);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
/* Property. */
- property = lvalue->right;
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack),
+ lvalue->right, njs_generate, NULL, 0);
+}
- ret = njs_generator(vm, generator, property);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
+
+static njs_int_t
+njs_generate_operation_assignment_name(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_int_t ret;
+ njs_index_t index;
+ njs_parser_node_t *lvalue, *expr;
+ njs_vmcode_3addr_t *code;
+
+ lvalue = node->left;
+ expr = node->right;
+
+ index = *((njs_index_t *) generator->context);
+
+ njs_generate_code(generator, njs_vmcode_3addr_t, code,
+ node->u.operation, 3, expr);
+ code->dst = lvalue->index;
+ code->src1 = index;
+ code->src2 = expr->index;
+
+ node->index = lvalue->index;
+
+ if (lvalue->index != index) {
+ ret = njs_generate_index_release(vm, generator, index);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
}
+ njs_mp_free(vm->mem_pool, generator->context);
+
+ return njs_generate_node_index_release_pop(vm, generator, expr);
+}
+
+
+static njs_int_t
+njs_generate_operation_assignment_prop(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_index_t index, src;
+ njs_parser_node_t *lvalue, *object, *property;
+ njs_vmcode_move_t *move;
+ njs_vmcode_prop_get_t *prop_get;
+
+ lvalue = node->left;
+ object = lvalue->left;
+ property = lvalue->right;
+
if (njs_slow_path(njs_parser_has_side_effect(node->right))) {
/*
* Preserve object and property values stored in variables in a case
prop_get->object = object->index;
prop_get->property = property->index;
- expr = node->right;
+ njs_generator_next(generator, njs_generate, node->right);
- ret = njs_generator(vm, generator, expr);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_operation_assignment_end, NULL, 0);
+}
+
+
+static njs_int_t
+njs_generate_operation_assignment_end(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_int_t ret;
+ njs_parser_node_t *lvalue, *expr;
+ njs_vmcode_3addr_t *code;
+ njs_vmcode_prop_set_t *prop_set;
+
+ lvalue = node->left;
+ expr = node->right;
njs_generate_code(generator, njs_vmcode_3addr_t, code,
node->u.operation, 3, expr);
njs_generate_code(generator, njs_vmcode_prop_set_t, prop_set,
NJS_VMCODE_PROPERTY_SET, 3, expr);
prop_set->value = node->index;
- prop_set->object = object->index;
- prop_set->property = property->index;
+ prop_set->object = lvalue->left->index;
+ prop_set->property = lvalue->right->index;
ret = njs_generate_children_indexes_release(vm, generator, lvalue);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
- return njs_generate_node_index_release(vm, generator, expr);
+ return njs_generate_node_index_release_pop(vm, generator, expr);
}
object->retval = node->index;
/* Initialize object. */
- return njs_generator(vm, generator, node->left);
+
+ njs_generator_next(generator, njs_generate, node->left);
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack),
+ NULL, njs_generator_pop, NULL, 0);
}
njs_generate_property_accessor(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
{
- njs_int_t ret;
- njs_parser_node_t *lvalue, *function, *object, *property;
- njs_vmcode_prop_accessor_t *accessor;
+ njs_int_t ret;
- lvalue = node->left;
- function = node->right;
-
- object = lvalue->left;
+ njs_generator_next(generator, njs_generate, node->left->left);
- ret = njs_generator(vm, generator, object);
+ ret = njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_property_accessor_end, NULL, 0);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
- property = lvalue->right;
-
- ret = njs_generator(vm, generator, property);
+ ret = njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack),
+ node->right, njs_generate, NULL, 0);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
- ret = njs_generator(vm, generator, function);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack),
+ node->left->right, njs_generate, NULL, 0);
+}
+
+
+static njs_int_t
+njs_generate_property_accessor_end(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_parser_node_t *lvalue, *function;
+ njs_vmcode_prop_accessor_t *accessor;
+
+ lvalue = node->left;
+ function = node->right;
njs_generate_code(generator, njs_vmcode_prop_accessor_t, accessor,
NJS_VMCODE_PROPERTY_ACCESSOR, 3, function);
accessor->value = function->index;
- accessor->object = object->index;
- accessor->property = property->index;
+ accessor->object = lvalue->left->index;
+ accessor->property = lvalue->right->index;
accessor->type = (node->token_type == NJS_TOKEN_PROPERTY_GETTER)
? NJS_OBJECT_PROP_GETTER : NJS_OBJECT_PROP_SETTER;
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
}
array->length = node->u.length;
/* Initialize array. */
- return njs_generator(vm, generator, node->left);
+
+ njs_generator_next(generator, njs_generate, node->left);
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack),
+ NULL, njs_generator_pop, NULL, 0);
}
var = njs_variable_reference(vm, node->left);
if (njs_slow_path(var == NULL)) {
- return njs_generate_reference_error(vm, generator, node->left);
+ ret = njs_generate_reference_error(vm, generator, node->left);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
+
+ return njs_generator_stack_pop(vm, generator, NULL);
}
lambda = node->u.value.data.u.lambda;
function->retval = node->index;
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
}
function->retval = node->index;
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
}
regexp->retval = node->index;
regexp->pattern = node->u.value.data.u.data;
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
}
njs_generate_template_literal(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
{
- njs_int_t ret;
- njs_vmcode_template_literal_t *code;
+ njs_generator_next(generator, njs_generate, node->left);
- ret = njs_generator(vm, generator, node->left);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_template_literal_end, NULL, 0);
+}
+
+
+static njs_int_t
+njs_generate_template_literal_end(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_vmcode_template_literal_t *code;
njs_generate_code(generator, njs_vmcode_template_literal_t, code,
NJS_VMCODE_TEMPLATE_LITERAL, 1, node);
node->index = node->left->index;
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
}
njs_generate_test_jump_expression(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
{
- njs_int_t ret;
+ njs_generator_next(generator, njs_generate, node->left);
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_test_jump_expression_after,
+ NULL, 0);
+}
+
+
+static njs_int_t
+njs_generate_test_jump_expression_after(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node)
+{
njs_jump_off_t jump_offset;
- njs_vmcode_move_t *move;
njs_vmcode_test_jump_t *test_jump;
- ret = njs_generator(vm, generator, node->left);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
-
njs_generate_code(generator, njs_vmcode_test_jump_t, test_jump,
node->u.operation, 2, node);
jump_offset = njs_code_offset(generator, test_jump);
test_jump->retval = node->index;
- ret = njs_generator(vm, generator, node->right);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ njs_generator_next(generator, njs_generate, node->right);
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_test_jump_expression_end,
+ &jump_offset, sizeof(njs_jump_off_t));
+}
+
+
+static njs_int_t
+njs_generate_test_jump_expression_end(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_int_t ret;
+ njs_vmcode_move_t *move;
/*
* The right expression usually uses node->index as destination,
node->right->index, node);
}
- njs_code_set_jump_offset(generator, njs_vmcode_test_jump_t, jump_offset);
+ njs_code_set_jump_offset(generator, njs_vmcode_test_jump_t,
+ *((njs_jump_off_t *) generator->context));
- return njs_generate_children_indexes_release(vm, generator, node);
+ ret = njs_generate_children_indexes_release(vm, generator, node);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
+
+ return njs_generator_stack_pop(vm, generator, generator->context);
}
njs_generate_3addr_operation(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node, njs_bool_t swap)
{
- njs_int_t ret;
- njs_index_t index;
- njs_parser_node_t *left, *right;
- njs_vmcode_move_t *move;
- njs_vmcode_3addr_t *code;
+ njs_int_t ret;
+ njs_parser_node_t *left, *right;
left = node->left;
+ right = node->right;
+
+ njs_generator_next(generator, njs_generate, left);
- ret = njs_generator(vm, generator, left);
+ if (left->token_type == NJS_TOKEN_NAME) {
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_3addr_operation_name,
+ &swap, sizeof(njs_bool_t));
+ }
+
+ ret = njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_3addr_operation_end, &swap,
+ sizeof(njs_bool_t));
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
- right = node->right;
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), right,
+ njs_generate, NULL, 0);
+}
- if (left->token_type == NJS_TOKEN_NAME) {
- if (njs_slow_path(njs_parser_has_side_effect(right))) {
- njs_generate_code(generator, njs_vmcode_move_t, move,
- NJS_VMCODE_MOVE, 2, node);
- move->src = left->index;
+static njs_int_t
+njs_generate_3addr_operation_name(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_index_t index;
+ njs_parser_node_t *left;
+ njs_vmcode_move_t *move;
- index = njs_generate_node_temp_index_get(vm, generator, left);
- if (njs_slow_path(index == NJS_INDEX_ERROR)) {
- return NJS_ERROR;
- }
+ left = node->left;
- move->dst = index;
+ if (njs_slow_path(njs_parser_has_side_effect(node->right))) {
+ njs_generate_code(generator, njs_vmcode_move_t, move,
+ NJS_VMCODE_MOVE, 2, node);
+ move->src = left->index;
+
+ index = njs_generate_node_temp_index_get(vm, generator, left);
+ if (njs_slow_path(index == NJS_INDEX_ERROR)) {
+ return NJS_ERROR;
}
- }
- ret = njs_generator(vm, generator, right);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
+ move->dst = index;
}
+ njs_generator_next(generator, njs_generate, node->right);
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_3addr_operation_end,
+ generator->context, 0);
+}
+
+
+static njs_int_t
+njs_generate_3addr_operation_end(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_bool_t swap;
+ njs_parser_node_t *left, *right;
+ njs_vmcode_3addr_t *code;
+
+ left = node->left;
+ right = node->right;
+
njs_generate_code(generator, njs_vmcode_3addr_t, code,
node->u.operation, 3, node);
+ swap = *((njs_bool_t *) generator->context);
+
if (!swap) {
code->src1 = left->index;
code->src2 = right->index;
njs_thread_log_debug("CODE3 %p, %p, %p",
code->dst, code->src1, code->src2);
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, generator->context);
}
njs_generate_2addr_operation(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
{
- njs_int_t ret;
- njs_vmcode_2addr_t *code;
+ njs_generator_next(generator, njs_generate, node->left);
- ret = njs_generator(vm, generator, node->left);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_2addr_operation_end, NULL, 0);
+}
+
+
+static njs_int_t
+njs_generate_2addr_operation_end(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_vmcode_2addr_t *code;
njs_generate_code(generator, njs_vmcode_2addr_t, code,
node->u.operation, 2, node);
njs_thread_log_debug("CODE2 %p, %p", code->dst, code->src);
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
}
njs_generate_typeof_operation(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
{
- njs_int_t ret;
- njs_parser_node_t *expr;
- njs_vmcode_2addr_t *code;
+ njs_int_t ret;
+ njs_parser_node_t *expr;
expr = node->left;
- if (expr->token_type == NJS_TOKEN_NAME) {
- ret = njs_generate_variable(vm, generator, expr, NJS_TYPEOF, NULL);
- if (njs_slow_path(ret != NJS_OK)) {
- return NJS_ERROR;
- }
+ if (expr->token_type != NJS_TOKEN_NAME) {
+ njs_generator_next(generator, njs_generate, node->left);
- } else {
- ret = njs_generator(vm, generator, node->left);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_typeof_operation_end, NULL, 0);
+ }
+
+ ret = njs_generate_variable(vm, generator, expr, NJS_TYPEOF, NULL);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return NJS_ERROR;
}
+ return njs_generate_typeof_operation_end(vm, generator, node);
+}
+
+
+static njs_int_t
+njs_generate_typeof_operation_end(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_vmcode_2addr_t *code;
+
njs_generate_code(generator, njs_vmcode_2addr_t, code,
- node->u.operation, 2, expr);
+ node->u.operation, 2, node->left);
code->src = node->left->index;
node->index = njs_generate_dest_index(vm, generator, node);
njs_thread_log_debug("CODE2 %p, %p", code->dst, code->src);
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
}
njs_parser_node_t *node, njs_bool_t post)
{
njs_int_t ret;
- njs_index_t index, dest_index;
+ njs_index_t index;
njs_variable_t *var;
njs_parser_node_t *lvalue;
njs_vmcode_3addr_t *code;
njs_vmcode_variable_t *var_code;
- njs_vmcode_prop_get_t *prop_get;
- njs_vmcode_prop_set_t *prop_set;
lvalue = node->left;
NJS_VMCODE_ASSIGNMENT_ERROR, 0, node);
var_code->dst = var->index;
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
}
index = njs_generate_dest_index(vm, generator, node);
code->src1 = lvalue->index;
code->src2 = lvalue->index;
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
}
/* lvalue->token == NJS_TOKEN_PROPERTY */
/* Object. */
- ret = njs_generator(vm, generator, lvalue->left);
+ njs_generator_next(generator, njs_generate, lvalue->left);
+
+ ret = njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_inc_dec_operation_prop,
+ &post, sizeof(njs_bool_t));
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
/* Property. */
- ret = njs_generator(vm, generator, lvalue->right);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack),
+ lvalue->right, njs_generate, NULL, 0);
+}
+
+
+static njs_int_t
+njs_generate_inc_dec_operation_prop(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_int_t ret;
+ njs_bool_t post;
+ njs_index_t index, dest_index;
+ njs_parser_node_t *lvalue;
+ njs_vmcode_3addr_t *code;
+ njs_vmcode_prop_get_t *prop_get;
+ njs_vmcode_prop_set_t *prop_set;
+
+ lvalue = node->left;
if (node->dest != NULL) {
dest_index = node->dest->index;
found:
+ post = *((njs_bool_t *) generator->context);
+
index = post ? njs_generate_temp_index_get(vm, generator, node)
: dest_index;
}
}
- return njs_generate_children_indexes_release(vm, generator, lvalue);
+ njs_mp_free(vm->mem_pool, generator->context);
+
+ return njs_generate_children_indexes_release_pop(vm, generator, lvalue);
}
var = njs_variable_reference(vm, node);
if (njs_slow_path(var == NULL)) {
- return njs_generate_reference_error(vm, generator, node);
+ ret = njs_generate_reference_error(vm, generator, node);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
+
+ return njs_generator_stack_pop(vm, generator, NULL);
}
if (njs_is_function(&var->value)) {
njs_set_function(&var->value, function);
- return ret;
+ return njs_generator_stack_pop(vm, generator, NULL);
}
{
u_char *p;
int64_t nargs;
+ njs_int_t ret;
njs_uint_t index;
njs_vm_code_t *code;
scope->closures = generator->closures;
- if (njs_slow_path(njs_generator(vm, generator, scope->top) != NJS_OK)) {
+ njs_queue_init(&generator->stack);
+
+ njs_generator_next(generator, njs_generate, scope->top);
+
+ ret = njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), NULL,
+ njs_generate_scope_end, NULL, 0);
+ if (njs_slow_path(ret != NJS_OK)) {
return NULL;
}
+ do {
+ ret = generator->state(vm, generator, generator->node);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return NULL;
+ }
+
+ } while (generator->state != NULL);
+
code = njs_arr_item(vm->codes, index);
code->start = generator->code_start;
code->end = generator->code_end;
}
+static njs_int_t
+njs_generate_scope_end(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ generator->state = NULL;
+ return NJS_OK;
+}
+
+
static int64_t
njs_generate_lambda_variables(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
njs_generate_return_statement(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
{
- njs_int_t ret;
+ njs_generator_next(generator, njs_generate, node->right);
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_return_statement_end, NULL, 0);
+}
+
+
+static njs_int_t
+njs_generate_return_statement_end(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
njs_index_t index;
const njs_str_t *dest;
njs_vmcode_return_t *code;
njs_generator_block_t *block, *immediate, *top;
njs_vmcode_try_return_t *try_return;
- ret = njs_generator(vm, generator, node->right);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
-
if (node->right != NULL) {
index = node->right->index;
code->retval = index;
node->index = index;
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
}
if (immediate->type == NJS_GENERATOR_TRY && immediate->exit != NULL) {
return NJS_ERROR;
}
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
}
njs_generate_function_call(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
{
- njs_int_t ret, nargs;
- njs_jump_off_t func_offset;
- njs_variable_t *var;
- njs_parser_node_t *name;
- njs_vmcode_function_frame_t *func;
+ njs_int_t ret;
+ njs_variable_t *var;
var = NULL;
if (node->left != NULL) {
/* Generate function code in function expression. */
- ret = njs_generator(vm, generator, node->left);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
- name = node->left;
+ njs_generator_next(generator, njs_generate, node->left);
- } else {
- ret = njs_generate_variable(vm, generator, node, NJS_REFERENCE, &var);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_function_call_arguments,
+ NULL, 0);
+ }
- name = node;
+ ret = njs_generate_variable(vm, generator, node, NJS_REFERENCE, &var);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
+
+ return njs_generate_function_call_arguments(vm, generator, node);
+}
+
+
+static njs_int_t
+njs_generate_function_call_arguments(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_int_t ret;
+ njs_jump_off_t func_offset;
+ njs_parser_node_t *name;
+ njs_vmcode_function_frame_t *func;
+
+ name = node;
+
+ if (node->left != NULL) {
+ name = node->left;
}
njs_generate_code(generator, njs_vmcode_function_frame_t, func,
func_offset = njs_code_offset(generator, func);
func->ctor = node->ctor;
func->name = name->index;
+ func->nargs = 0;
- nargs = njs_generate_move_arguments(vm, generator, node);
- if (njs_slow_path(nargs < 0)) {
- return nargs;
- }
-
- func = njs_code_ptr(generator, njs_vmcode_function_frame_t, func_offset);
- func->nargs = nargs;
+ njs_generator_next(generator, njs_generate,
+ (node->right != NULL ? node->right->left : NULL));
- ret = njs_generate_call(vm, generator, node);
- if (njs_fast_path(ret != NJS_OK)) {
+ ret = njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_function_call_end, NULL, 0);
+ if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
- return NJS_OK;
+ if (node->right == NULL) {
+ return NJS_OK;
+ }
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node->right,
+ njs_generate_move_arguments,
+ &func_offset, sizeof(njs_jump_off_t));
}
static njs_int_t
-njs_generate_method_call(njs_vm_t *vm, njs_generator_t *generator,
+njs_generate_function_call_end(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
{
- njs_int_t ret, nargs;
- njs_jump_off_t method_offset;
- njs_parser_node_t *prop;
- njs_vmcode_method_frame_t *method;
+ njs_int_t ret;
+
+ ret = njs_generate_call(vm, generator, node);
+ if (njs_fast_path(ret != NJS_OK)) {
+ return ret;
+ }
+
+ return njs_generator_stack_pop(vm, generator, generator->context);
+}
+
+
+static njs_int_t
+njs_generate_method_call(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_int_t ret;
+ njs_parser_node_t *prop;
prop = node->left;
/* Object. */
- ret = njs_generator(vm, generator, prop->left);
+ njs_generator_next(generator, njs_generate, prop->left);
+
+ ret = njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_method_call_arguments, NULL, 0);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
/* Method name. */
- ret = njs_generator(vm, generator, prop->right);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), prop->right,
+ njs_generate, NULL, 0);
+}
+
+
+static njs_int_t
+njs_generate_method_call_arguments(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_int_t ret;
+ njs_jump_off_t method_offset;
+ njs_parser_node_t *prop;
+ njs_vmcode_method_frame_t *method;
+
+ prop = node->left;
njs_generate_code(generator, njs_vmcode_method_frame_t, method,
NJS_VMCODE_METHOD_FRAME, 3, prop);
method->ctor = node->ctor;
method->object = prop->left->index;
method->method = prop->right->index;
+ method->nargs = 0;
+
+ njs_generator_next(generator, njs_generate,
+ (node->right != NULL ? node->right->left : node->right));
+
+ ret = njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_method_call_end, NULL, 0);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
- nargs = njs_generate_move_arguments(vm, generator, node);
- if (njs_slow_path(nargs < 0)) {
- return nargs;
+ if (node->right == NULL) {
+ return NJS_OK;
}
- method = njs_code_ptr(generator, njs_vmcode_method_frame_t, method_offset);
- method->nargs = nargs;
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node->right,
+ njs_generate_move_arguments,
+ &method_offset, sizeof(njs_jump_off_t));
+}
+
+
+static njs_int_t
+njs_generate_method_call_end(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_int_t ret;
ret = njs_generate_call(vm, generator, node);
if (njs_fast_path(ret != NJS_OK)) {
return ret;
}
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, generator->context);
}
njs_generate_move_arguments(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
{
- njs_int_t ret;
- njs_uint_t nargs;
- njs_parser_node_t *arg;
- njs_vmcode_move_arg_t *move_arg;
+ njs_jump_off_t func_offset;
+ njs_vmcode_move_arg_t *move_arg;
+ njs_vmcode_function_frame_t *func;
- nargs = 0;
+ if (node == NULL) {
+ return njs_generator_stack_pop(vm, generator, generator->context);
+ }
- for (arg = node->right; arg != NULL; arg = arg->right) {
- ret = njs_generator(vm, generator, arg->left);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ njs_generate_code(generator, njs_vmcode_move_arg_t, move_arg,
+ NJS_VMCODE_MOVE_ARG, 0, node);
+ move_arg->src = node->left->index;
+
+ func_offset = *((njs_jump_off_t *) generator->context);
+ func = njs_code_ptr(generator, njs_vmcode_function_frame_t, func_offset);
- njs_generate_code(generator, njs_vmcode_move_arg_t, move_arg,
- NJS_VMCODE_MOVE_ARG, 0, node);
- move_arg->src = arg->left->index;
- move_arg->dst = nargs;
+ move_arg->dst = (njs_uint_t) func->nargs;
- nargs++;
+ func->nargs++;
+
+ if (node->right == NULL) {
+ return njs_generator_stack_pop(vm, generator, generator->context);
}
- return nargs;
+ njs_generator_next(generator, njs_generate, node->right->left);
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node->right,
+ njs_generate_move_arguments,
+ generator->context, 0);
}
njs_generate_try_statement(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
{
- njs_int_t ret;
- njs_str_t try_cont_label, try_exit_label,
- catch_cont_label, catch_exit_label;
- njs_index_t exception_index, exit_index, catch_index;
- njs_jump_off_t try_offset, try_end_offset, catch_offset,
- catch_end_offset;
- njs_variable_t *var;
- const njs_str_t *dest_label;
- njs_vmcode_catch_t *catch;
- njs_vmcode_finally_t *finally;
- njs_vmcode_try_end_t *try_end, *catch_end;
- njs_generator_patch_t *patch;
- njs_generator_block_t *block, *try_block, *catch_block;
- njs_vmcode_try_start_t *try_start;
- njs_vmcode_try_trampoline_t *try_break, *try_continue;
+ njs_int_t ret;
+ njs_index_t exception_index, exit_index;
+ njs_vmcode_try_start_t *try_start;
+ njs_generator_try_ctx_t ctx;
+
+ njs_memzero(&ctx, sizeof(njs_generator_try_ctx_t));
njs_generate_code(generator, njs_vmcode_try_start_t, try_start,
NJS_VMCODE_TRY_START, 2, node);
- try_offset = njs_code_offset(generator, try_start);
+ ctx.try_offset = njs_code_offset(generator, try_start);
exception_index = njs_generate_temp_index_get(vm, generator, node);
if (njs_slow_path(exception_index == NJS_INDEX_ERROR)) {
return ret;
}
- try_block = generator->block;
- try_block->index = exit_index;
+ ctx.try_block = generator->block;
+ ctx.try_block->index = exit_index;
+ ctx.exception_index = exception_index;
- ret = njs_generator(vm, generator, node->left);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ ctx.catch_cont_label = undef_label;
+ ctx.catch_exit_label = undef_label;
+ ctx.try_cont_label = undef_label;
+ ctx.try_exit_label = undef_label;
+
+ njs_generator_next(generator, njs_generate, node->left);
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_try_left,
+ &ctx, sizeof(njs_generator_try_ctx_t));
+}
- try_exit_label = undef_label;
- try_cont_label = undef_label;
+
+static njs_int_t
+njs_generate_try_left(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_int_t ret;
+ njs_index_t exit_index, catch_index;
+ njs_jump_off_t try_end_offset;
+ njs_variable_t *var;
+ njs_vmcode_catch_t *catch;
+ njs_vmcode_try_end_t *try_end;
+ njs_generator_block_t *try_block;
+ njs_generator_try_ctx_t *ctx;
+ njs_vmcode_try_trampoline_t *try_break, *try_continue;
+
+ ctx = generator->context;
+
+ try_block = ctx->try_block;
+ exit_index = try_block->index;
njs_generate_code(generator, njs_vmcode_try_end_t, try_end,
NJS_VMCODE_TRY_END, 0, NULL);
try_end_offset = njs_code_offset(generator, try_end);
if (try_block->exit != NULL) {
- try_exit_label = try_block->exit->label;
+ ctx->try_exit_label = try_block->exit->label;
njs_generate_patch_block(vm, generator, try_block->exit);
}
if (try_block->continuation != NULL) {
- try_cont_label = try_block->continuation->label;
+ ctx->try_cont_label = try_block->continuation->label;
njs_generate_patch_block(vm, generator, try_block->continuation);
generator->block = try_block->next;
- njs_code_set_jump_offset(generator, njs_vmcode_try_start_t, try_offset);
- try_offset = try_end_offset;
+ njs_code_set_jump_offset(generator, njs_vmcode_try_start_t,
+ ctx->try_offset);
+ ctx->try_offset = try_end_offset;
node = node->right;
- catch_exit_label = undef_label;
- catch_cont_label = undef_label;
-
if (node->token_type == NJS_TOKEN_CATCH) {
/* A "try/catch" case. */
njs_generate_code_catch(generator, catch, catch_index, node);
- ret = njs_generator(vm, generator, node->right);
+ njs_generator_next(generator, njs_generate, node->right);
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_try_catch, ctx, 0);
+ }
+
+ if (node->left != NULL) {
+ /* A try/catch/finally case. */
+
+ var = njs_variable_reference(vm, node->left->left);
+ if (njs_slow_path(var == NULL)) {
+ return NJS_ERROR;
+ }
+
+ catch_index = node->left->left->index;
+
+ njs_generate_code_catch(generator, catch, catch_index, node);
+ ctx->catch_offset = njs_code_offset(generator, catch);
+
+ ret = njs_generate_start_block(vm, generator, NJS_GENERATOR_TRY,
+ &no_label);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
- njs_code_set_jump_offset(generator, njs_vmcode_try_end_t, try_offset);
+ ctx->catch_block = generator->block;
+ ctx->catch_block->index = exit_index;
+
+ njs_generator_next(generator, njs_generate, node->left->right);
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_try_finally, ctx, 0);
+ }
+
+ /* A try/finally case. */
+
+ njs_generate_code_catch(generator, catch, ctx->exception_index, NULL);
+
+ ctx->catch_block = NULL;
+
+ njs_code_set_jump_offset(generator, njs_vmcode_try_end_t,
+ ctx->try_offset);
+
+ njs_generator_next(generator, njs_generate, node->right);
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_try_end, ctx, 0);
+}
+
+
+static njs_int_t
+njs_generate_try_catch(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_int_t ret;
+ njs_index_t exit_index;
+ njs_vmcode_finally_t *finally;
+ njs_generator_patch_t *patch;
+ njs_generator_block_t *block, *try_block;
+ njs_generator_try_ctx_t *ctx;
+
+ ctx = generator->context;
+
+ try_block = ctx->try_block;
+ exit_index = try_block->index;
+
+ njs_code_set_jump_offset(generator, njs_vmcode_try_end_t,
+ ctx->try_offset);
+
+ if (try_block->continuation != NULL || try_block->exit != NULL) {
+ njs_generate_code_finally(generator, finally, ctx->exception_index,
+ exit_index, NULL);
+
+ if (try_block->continuation != NULL) {
+ /*
+ * block != NULL is checked
+ * by njs_generate_continue_statement()
+ */
+ block = njs_generate_find_block(generator->block,
+ NJS_GENERATOR_LOOP,
+ &ctx->try_cont_label);
- if (try_block->continuation != NULL || try_block->exit != NULL) {
- njs_generate_code_finally(generator, finally, exception_index,
- exit_index, NULL);
+ patch = njs_generate_make_continuation_patch(vm, block,
+ &ctx->try_cont_label,
+ njs_code_offset(generator, finally)
+ + offsetof(njs_vmcode_finally_t, continue_offset));
+ if (njs_slow_path(patch == NULL)) {
+ return NJS_ERROR;
+ }
+ }
- if (try_block->continuation != NULL) {
- /*
- * block != NULL is checked
- * by njs_generate_continue_statement()
- */
- block = njs_generate_find_block(generator->block,
- NJS_GENERATOR_LOOP,
- &try_cont_label);
+ if (try_block->exit != NULL) {
+ block = njs_generate_find_block(generator->block,
+ NJS_GENERATOR_ALL,
+ &ctx->try_exit_label);
- patch = njs_generate_make_continuation_patch(vm, block,
- &try_cont_label,
+ if (block != NULL) {
+ patch = njs_generate_make_exit_patch(vm, block,
+ &ctx->try_exit_label,
njs_code_offset(generator, finally)
- + offsetof(njs_vmcode_finally_t, continue_offset));
+ + offsetof(njs_vmcode_finally_t, break_offset));
if (njs_slow_path(patch == NULL)) {
return NJS_ERROR;
}
}
-
- if (try_block->exit != NULL) {
- block = njs_generate_find_block(generator->block,
- NJS_GENERATOR_ALL,
- &try_exit_label);
-
- if (block != NULL) {
- patch = njs_generate_make_exit_patch(vm, block,
- &try_exit_label,
- njs_code_offset(generator, finally)
- + offsetof(njs_vmcode_finally_t, break_offset));
- if (njs_slow_path(patch == NULL)) {
- return NJS_ERROR;
- }
- }
- }
}
+ }
- /* TODO: release exception variable index. */
+ /* TODO: release exception variable index. */
- } else {
- if (node->left != NULL) {
- /* A try/catch/finally case. */
+ ret = njs_generate_index_release(vm, generator, ctx->exception_index);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
- var = njs_variable_reference(vm, node->left->left);
- if (njs_slow_path(var == NULL)) {
- return NJS_ERROR;
- }
+ return njs_generator_stack_pop(vm, generator, ctx);
+}
- catch_index = node->left->left->index;
- njs_generate_code_catch(generator, catch, catch_index, node);
- catch_offset = njs_code_offset(generator, catch);
+static njs_int_t
+njs_generate_try_finally(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_index_t exit_index;
+ njs_jump_off_t catch_end_offset;
+ njs_vmcode_catch_t *catch;
+ njs_vmcode_try_end_t *catch_end;
+ njs_generator_block_t *try_block, *catch_block;
+ njs_generator_try_ctx_t *ctx;
+ njs_vmcode_try_trampoline_t *try_break, *try_continue;
- ret = njs_generate_start_block(vm, generator, NJS_GENERATOR_TRY,
- &no_label);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ ctx = generator->context;
- catch_block = generator->block;
- catch_block->index = exit_index;
+ try_block = ctx->try_block;
+ exit_index = try_block->index;
+ catch_block = ctx->catch_block;
- ret = njs_generator(vm, generator, node->left->right);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ njs_generate_code(generator, njs_vmcode_try_end_t, catch_end,
+ NJS_VMCODE_TRY_END, 0, node->left->right);
+ catch_end_offset = njs_code_offset(generator, catch_end);
- njs_generate_code(generator, njs_vmcode_try_end_t, catch_end,
- NJS_VMCODE_TRY_END, 0, node->left->right);
- catch_end_offset = njs_code_offset(generator, catch_end);
+ if (catch_block->exit != NULL) {
+ ctx->catch_exit_label = catch_block->exit->label;
- if (catch_block->exit != NULL) {
- catch_exit_label = catch_block->exit->label;
+ njs_generate_patch_block(vm, generator, catch_block->exit);
- njs_generate_patch_block(vm, generator, catch_block->exit);
+ njs_generate_code(generator, njs_vmcode_try_trampoline_t,
+ try_break, NJS_VMCODE_TRY_BREAK, 1, NULL);
- njs_generate_code(generator, njs_vmcode_try_trampoline_t,
- try_break, NJS_VMCODE_TRY_BREAK, 1, NULL);
+ try_break->exit_value = exit_index;
- try_break->exit_value = exit_index;
+ try_break->offset = -sizeof(njs_vmcode_try_end_t);
- try_break->offset = -sizeof(njs_vmcode_try_end_t);
+ } else {
+ try_break = NULL;
+ }
- } else {
- try_break = NULL;
- }
+ if (catch_block->continuation != NULL) {
+ ctx->catch_cont_label = catch_block->continuation->label;
- if (catch_block->continuation != NULL) {
- catch_cont_label = catch_block->continuation->label;
+ njs_generate_patch_block(vm, generator,
+ catch_block->continuation);
- njs_generate_patch_block(vm, generator,
- catch_block->continuation);
+ njs_generate_code(generator, njs_vmcode_try_trampoline_t,
+ try_continue, NJS_VMCODE_TRY_CONTINUE, 1,
+ NULL);
- njs_generate_code(generator, njs_vmcode_try_trampoline_t,
- try_continue, NJS_VMCODE_TRY_CONTINUE, 1,
- NULL);
+ try_continue->exit_value = exit_index;
- try_continue->exit_value = exit_index;
+ try_continue->offset = -sizeof(njs_vmcode_try_end_t);
- try_continue->offset = -sizeof(njs_vmcode_try_end_t);
+ if (try_break != NULL) {
+ try_continue->offset -= sizeof(njs_vmcode_try_trampoline_t);
+ }
+ }
- if (try_break != NULL) {
- try_continue->offset -= sizeof(njs_vmcode_try_trampoline_t);
- }
- }
+ generator->block = catch_block->next;
+
+ njs_code_set_jump_offset(generator, njs_vmcode_catch_t,
+ ctx->catch_offset);
- generator->block = catch_block->next;
+ /* TODO: release exception variable index. */
- njs_code_set_jump_offset(generator, njs_vmcode_catch_t,
- catch_offset);
+ njs_generate_code_catch(generator, catch, ctx->exception_index, NULL);
- /* TODO: release exception variable index. */
+ njs_code_set_jump_offset(generator, njs_vmcode_try_end_t,
+ catch_end_offset);
- njs_generate_code_catch(generator, catch, exception_index, NULL);
+ njs_code_set_jump_offset(generator, njs_vmcode_try_end_t,
+ ctx->try_offset);
- njs_code_set_jump_offset(generator, njs_vmcode_try_end_t,
- catch_end_offset);
+ njs_generator_next(generator, njs_generate, node->right);
- } else {
- /* A try/finally case. */
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_try_end, ctx, 0);
+}
- njs_generate_code_catch(generator, catch, exception_index, NULL);
- catch_block = NULL;
- }
+static njs_int_t
+njs_generate_try_end(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_int_t ret;
+ njs_index_t exit_index;
+ const njs_str_t *dest_label;
+ njs_vmcode_finally_t *finally;
+ njs_generator_patch_t *patch;
+ njs_generator_block_t *block, *try_block, *catch_block;
+ njs_generator_try_ctx_t *ctx;
- njs_code_set_jump_offset(generator, njs_vmcode_try_end_t, try_offset);
+ ctx = generator->context;
- ret = njs_generator(vm, generator, node->right);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
+ try_block = ctx->try_block;
+ exit_index = try_block->index;
+ catch_block = ctx->catch_block;
+
+ njs_generate_code_finally(generator, finally, ctx->exception_index,
+ exit_index, node);
+
+ if (try_block->continuation != NULL
+ || (catch_block && catch_block->continuation != NULL))
+ {
+ dest_label = njs_generate_jump_destination(vm, generator->block,
+ "try continue",
+ NJS_GENERATOR_LOOP,
+ &ctx->try_cont_label,
+ &ctx->catch_cont_label);
+ if (njs_slow_path(dest_label == NULL)) {
+ return NJS_ERROR;
}
- njs_generate_code_finally(generator, finally, exception_index,
- exit_index, node);
+ /*
+ * block != NULL is checked
+ * by njs_generate_continue_statement()
+ */
+ block = njs_generate_find_block(generator->block,
+ NJS_GENERATOR_LOOP, dest_label);
- if (try_block->continuation != NULL
- || (catch_block && catch_block->continuation != NULL))
- {
- dest_label = njs_generate_jump_destination(vm, generator->block,
- "try continue",
- NJS_GENERATOR_LOOP,
- &try_cont_label,
- &catch_cont_label);
- if (njs_slow_path(dest_label == NULL)) {
- return NJS_ERROR;
- }
+ patch = njs_generate_make_continuation_patch(vm, block, dest_label,
+ njs_code_offset(generator, finally)
+ + offsetof(njs_vmcode_finally_t, continue_offset));
+ if (njs_slow_path(patch == NULL)) {
+ return NJS_ERROR;
+ }
+ }
- /*
- * block != NULL is checked
- * by njs_generate_continue_statement()
- */
- block = njs_generate_find_block(generator->block,
- NJS_GENERATOR_LOOP, dest_label);
+ if (try_block->exit != NULL
+ || (catch_block != NULL && catch_block->exit != NULL))
+ {
+ dest_label = njs_generate_jump_destination(vm, generator->block,
+ "try break/return",
+ NJS_GENERATOR_ALL
+ | NJS_GENERATOR_TRY,
+ &ctx->try_exit_label,
+ &ctx->catch_exit_label);
+ if (njs_slow_path(dest_label == NULL)) {
+ return NJS_ERROR;
+ }
- patch = njs_generate_make_continuation_patch(vm, block, dest_label,
- njs_code_offset(generator, finally)
- + offsetof(njs_vmcode_finally_t, continue_offset));
+ /*
+ * block can be NULL for "return" instruction in
+ * outermost try-catch block.
+ */
+ block = njs_generate_find_block(generator->block,
+ NJS_GENERATOR_ALL
+ | NJS_GENERATOR_TRY, dest_label);
+ if (block != NULL) {
+ patch = njs_generate_make_exit_patch(vm, block, dest_label,
+ njs_code_offset(generator, finally)
+ + offsetof(njs_vmcode_finally_t, break_offset));
if (njs_slow_path(patch == NULL)) {
return NJS_ERROR;
}
}
+ }
- if (try_block->exit != NULL
- || (catch_block != NULL && catch_block->exit != NULL))
- {
- dest_label = njs_generate_jump_destination(vm, generator->block,
- "try break/return",
- NJS_GENERATOR_ALL
- | NJS_GENERATOR_TRY,
- &try_exit_label,
- &catch_exit_label);
- if (njs_slow_path(dest_label == NULL)) {
- return NJS_ERROR;
- }
-
- /*
- * block can be NULL for "return" instruction in
- * outermost try-catch block.
- */
- block = njs_generate_find_block(generator->block,
- NJS_GENERATOR_ALL
- | NJS_GENERATOR_TRY, dest_label);
- if (block != NULL) {
- patch = njs_generate_make_exit_patch(vm, block, dest_label,
- njs_code_offset(generator, finally)
- + offsetof(njs_vmcode_finally_t, break_offset));
- if (njs_slow_path(patch == NULL)) {
- return NJS_ERROR;
- }
- }
- }
+ ret = njs_generate_index_release(vm, generator, ctx->exception_index);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
}
- return njs_generate_index_release(vm, generator, exception_index);
+ return njs_generator_stack_pop(vm, generator, ctx);
}
njs_generate_throw_statement(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
{
- njs_int_t ret;
- njs_vmcode_throw_t *throw;
+ njs_generator_next(generator, njs_generate, node->right);
- ret = njs_generator(vm, generator, node->right);
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_throw_end, NULL, 0);
+}
- if (njs_fast_path(ret == NJS_OK)) {
- njs_generate_code(generator, njs_vmcode_throw_t, throw,
- NJS_VMCODE_THROW, 1, node);
+static njs_int_t
+njs_generate_throw_end(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_vmcode_throw_t *throw;
- node->index = node->right->index;
- throw->retval = node->index;
- }
+ njs_generate_code(generator, njs_vmcode_throw_t, throw,
+ NJS_VMCODE_THROW, 1, node);
- return ret;
+ node->index = node->right->index;
+ throw->retval = node->index;
+
+ return njs_generator_stack_pop(vm, generator, NULL);
}
njs_generate_import_statement(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
{
- njs_int_t ret;
- njs_index_t index;
- njs_module_t *module;
- njs_variable_t *var;
- njs_parser_node_t *lvalue, *expr;
- njs_vmcode_object_copy_t *copy;
+ njs_variable_t *var;
+ njs_parser_node_t *lvalue, *expr;
lvalue = node->left;
expr = node->right;
return NJS_ERROR;
}
- index = lvalue->index;
-
if (expr->left != NULL) {
- ret = njs_generator(vm, generator, expr->left);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
+ njs_generator_next(generator, njs_generate, expr->left);
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_import_statement_end, NULL, 0);
}
+ return njs_generate_import_statement_end(vm, generator, node);
+}
+
+
+static njs_int_t
+njs_generate_import_statement_end(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_module_t *module;
+ njs_parser_node_t *expr;
+ njs_vmcode_object_copy_t *copy;
+
+ expr = node->right;
+
module = (njs_module_t *) expr->index;
njs_generate_code(generator, njs_vmcode_object_copy_t, copy,
NJS_VMCODE_OBJECT_COPY, 2, node);
- copy->retval = index;
+ copy->retval = node->left->index;
copy->object = module->index;
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
}
njs_generate_export_statement(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
{
- njs_int_t ret;
+ njs_generator_next(generator, njs_generate, node->right);
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_export_statement_end, NULL, 0);
+}
+
+
+static njs_int_t
+njs_generate_export_statement_end(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
njs_parser_node_t *obj;
njs_vmcode_return_t *code;
obj = node->right;
- ret = njs_generator(vm, generator, obj);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
-
njs_generate_code(generator, njs_vmcode_return_t, code,
NJS_VMCODE_RETURN, 1, NULL);
code->retval = obj->index;
node->index = obj->index;
- return NJS_OK;
+ return njs_generator_stack_pop(vm, generator, NULL);
+}
+
+
+static njs_int_t
+njs_generate_wo_dest(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_parser_scope_t *scope;
+
+ scope = njs_function_scope(node->scope);
+
+ scope->dest_disable = 1;
+
+ njs_generator_next(generator, njs_generate, node);
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), node,
+ njs_generate_wo_dest_after, NULL, 0);
+}
+
+
+static njs_int_t
+njs_generate_wo_dest_after(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_parser_scope_t *scope;
+
+ scope = njs_function_scope(node->scope);
+
+ scope->dest_disable = 0;
+
+ return njs_generator_stack_pop(vm, generator, NULL);
+}
+
+
+static njs_int_t
+njs_generate_global_reference(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node, njs_bool_t exception)
+{
+ njs_int_t ret;
+ njs_index_t index;
+ njs_value_t property;
+ njs_vmcode_prop_get_t *prop_get;
+ const njs_lexer_entry_t *lex_entry;
+
+ index = njs_generate_temp_index_get(vm, generator, node);
+ if (njs_slow_path(index == NJS_INDEX_ERROR)) {
+ return NJS_ERROR;
+ }
+
+ njs_generate_code(generator, njs_vmcode_prop_get_t, prop_get,
+ exception ? NJS_VMCODE_GLOBAL_GET: NJS_VMCODE_PROPERTY_GET,
+ 3, node);
+
+ prop_get->value = index;
+
+ prop_get->object = njs_scope_global_this_index();
+ if (njs_slow_path(prop_get->object == NJS_INDEX_ERROR)) {
+ return NJS_ERROR;
+ }
+
+ lex_entry = njs_lexer_entry(node->u.reference.unique_id);
+ if (njs_slow_path(lex_entry == NULL)) {
+ return NJS_ERROR;
+ }
+
+ ret = njs_string_set(vm, &property, lex_entry->name.start,
+ lex_entry->name.length);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return NJS_ERROR;
+ }
+
+ prop_get->property = njs_scope_global_index(vm, &property,
+ generator->runtime);
+ if (njs_slow_path(prop_get->property == NJS_INDEX_ERROR)) {
+ return NJS_ERROR;
+ }
+
+ node->index = index;
+
+ if (!exception) {
+ return NJS_OK;
+ }
+
+ return njs_generate_reference_error(vm, generator, node);
+}
+
+
+static njs_int_t
+njs_generate_reference_error(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_vmcode_error_t *ref_err;
+ const njs_lexer_entry_t *lex_entry;
+
+ if (njs_slow_path(!node->u.reference.not_defined)) {
+ njs_internal_error(vm, "variable is not defined but not_defined "
+ "is not set");
+ return NJS_ERROR;
+ }
+
+ njs_generate_code(generator, njs_vmcode_error_t, ref_err, NJS_VMCODE_ERROR,
+ 0, NULL);
+
+ ref_err->type = NJS_OBJ_TYPE_REF_ERROR;
+ lex_entry = njs_lexer_entry(node->u.reference.unique_id);
+ if (njs_slow_path(lex_entry == NULL)) {
+ return NJS_ERROR;
+ }
+
+ return njs_name_copy(vm, &ref_err->u.name, &lex_entry->name);
}
}
+static njs_int_t
+njs_generate_children_indexes_release_pop(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node)
+{
+ njs_int_t ret;
+
+ ret = njs_generate_node_index_release(vm, generator, node->left);
+
+ if (njs_fast_path(ret == NJS_OK)) {
+ return njs_generate_node_index_release_pop(vm, generator, node->right);
+ }
+
+ return ret;
+}
+
+
static njs_int_t
njs_generate_node_index_release(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
return NJS_OK;
}
+static njs_int_t
+njs_generate_node_index_release_pop(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_int_t ret;
+
+ if (node != NULL && node->temporary) {
+ ret = njs_generate_index_release(vm, generator, node->index);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
+ }
+
+ return njs_generator_stack_pop(vm, generator, NULL);
+}
+
static njs_int_t
njs_generate_index_release(njs_vm_t *vm, njs_generator_t *generator,
return NJS_ERROR;
}
-
-
-static njs_int_t
-njs_generate_global_reference(njs_vm_t *vm, njs_generator_t *generator,
- njs_parser_node_t *node, njs_bool_t exception)
-{
- njs_int_t ret;
- njs_index_t index;
- njs_value_t property;
- njs_vmcode_prop_get_t *prop_get;
- const njs_lexer_entry_t *lex_entry;
-
- index = njs_generate_temp_index_get(vm, generator, node);
- if (njs_slow_path(index == NJS_INDEX_ERROR)) {
- return NJS_ERROR;
- }
-
- njs_generate_code(generator, njs_vmcode_prop_get_t, prop_get,
- exception ? NJS_VMCODE_GLOBAL_GET: NJS_VMCODE_PROPERTY_GET,
- 3, node);
-
- prop_get->value = index;
-
- prop_get->object = njs_scope_global_this_index();
- if (njs_slow_path(prop_get->object == NJS_INDEX_ERROR)) {
- return NJS_ERROR;
- }
-
- lex_entry = njs_lexer_entry(node->u.reference.unique_id);
- if (njs_slow_path(lex_entry == NULL)) {
- return NJS_ERROR;
- }
-
- ret = njs_string_set(vm, &property, lex_entry->name.start,
- lex_entry->name.length);
- if (njs_slow_path(ret != NJS_OK)) {
- return NJS_ERROR;
- }
-
- prop_get->property = njs_scope_global_index(vm, &property,
- generator->runtime);
- if (njs_slow_path(prop_get->property == NJS_INDEX_ERROR)) {
- return NJS_ERROR;
- }
-
- node->index = index;
-
- if (!exception) {
- return NJS_OK;
- }
-
- return njs_generate_reference_error(vm, generator, node);
-}
-
-
-static njs_int_t
-njs_generate_reference_error(njs_vm_t *vm, njs_generator_t *generator,
- njs_parser_node_t *node)
-{
- njs_vmcode_error_t *ref_err;
- const njs_lexer_entry_t *lex_entry;
-
- if (njs_slow_path(!node->u.reference.not_defined)) {
- njs_internal_error(vm, "variable is not defined but not_defined "
- "is not set");
- return NJS_ERROR;
- }
-
- njs_generate_code(generator, njs_vmcode_error_t, ref_err, NJS_VMCODE_ERROR,
- 0, NULL);
-
- ref_err->type = NJS_OBJ_TYPE_REF_ERROR;
- lex_entry = njs_lexer_entry(node->u.reference.unique_id);
- if (njs_slow_path(lex_entry == NULL)) {
- return NJS_ERROR;
- }
-
- return njs_name_copy(vm, &ref_err->u.name, &lex_entry->name);
-}