Commit abffe88e authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

jscript: Added bytecode version of with statement.

parent 17fedc44
......@@ -1097,6 +1097,40 @@ static HRESULT compile_for_statement(compiler_ctx_t *ctx, for_statement_t *stat)
return S_OK;
}
/* ECMA-262 3rd Edition 12.10 */
static HRESULT compile_with_statement(compiler_ctx_t *ctx, with_statement_t *stat)
{
unsigned off_backup;
BOOL prev_no_fallback;
HRESULT hres;
off_backup = ctx->code_off;
hres = compile_expression(ctx, stat->expr);
if(FAILED(hres))
return hres;
if(push_instr(ctx, OP_push_scope) == -1)
return E_OUTOFMEMORY;
prev_no_fallback = ctx->no_fallback;
ctx->no_fallback = TRUE;
hres = compile_statement(ctx, stat->statement);
ctx->no_fallback = prev_no_fallback;
if(hres == E_NOTIMPL) {
ctx->code_off = off_backup;
stat->stat.eval = with_statement_eval;
return compile_interp_fallback(ctx, &stat->stat);
}
if(FAILED(hres))
return hres;
if(push_instr(ctx, OP_pop_scope) == -1)
return E_OUTOFMEMORY;
return S_OK;
}
static HRESULT compile_statement(compiler_ctx_t *ctx, statement_t *stat)
{
switch(stat->type) {
......@@ -1114,6 +1148,8 @@ static HRESULT compile_statement(compiler_ctx_t *ctx, statement_t *stat)
return compile_var_statement(ctx, (var_statement_t*)stat);
case STAT_WHILE:
return compile_while_statement(ctx, (while_statement_t*)stat);
case STAT_WITH:
return compile_with_statement(ctx, (with_statement_t*)stat);
default:
return compile_interp_fallback(ctx, stat);
}
......
......@@ -837,6 +837,11 @@ jsdisp_t *as_jsdisp(IDispatch *disp)
return impl_from_IDispatchEx((IDispatchEx*)disp);
}
jsdisp_t *to_jsdisp(IDispatch *disp)
{
return disp->lpVtbl == (IDispatchVtbl*)&DispatchExVtbl ? impl_from_IDispatchEx((IDispatchEx*)disp) : NULL;
}
HRESULT init_dispex(jsdisp_t *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, jsdisp_t *prototype)
{
TRACE("%p (%p)\n", dispex, prototype);
......
......@@ -1029,6 +1029,43 @@ HRESULT with_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t
return hres;
}
/* ECMA-262 3rd Edition 12.10 */
HRESULT interp_push_scope(exec_ctx_t *ctx)
{
IDispatch *disp;
jsdisp_t *obj;
VARIANT *v;
HRESULT hres;
TRACE("\n");
v = stack_pop(ctx);
hres = to_object(ctx->parser->script, v, &disp);
VariantClear(v);
if(FAILED(hres))
return hres;
obj = to_jsdisp(disp);
if(!obj) {
IDispatch_Release(disp);
FIXME("disp is not jsdisp\n");
return E_NOTIMPL;
}
hres = scope_push(ctx->scope_chain, obj, &ctx->scope_chain);
jsdisp_release(obj);
return hres;
}
/* ECMA-262 3rd Edition 12.10 */
HRESULT interp_pop_scope(exec_ctx_t *ctx)
{
TRACE("\n");
scope_pop(&ctx->scope_chain);
return S_OK;
}
/* ECMA-262 3rd Edition 12.12 */
HRESULT labelled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
{
......@@ -2955,6 +2992,7 @@ HRESULT compiled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_typ
{
exec_ctx_t *exec_ctx = ctx->exec_ctx;
unsigned prev_ip, prev_top;
scope_chain_t *prev_scope;
return_type_t *prev_rt;
jsexcept_t *prev_ei;
jsop_t op;
......@@ -2970,6 +3008,7 @@ HRESULT compiled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_typ
prev_rt = exec_ctx->rt;
prev_top = exec_ctx->top;
prev_scope = exec_ctx->scope_chain;
prev_ip = exec_ctx->ip;
prev_ei = exec_ctx->ei;
exec_ctx->ip = stat->instr_off;
......@@ -2990,10 +3029,13 @@ HRESULT compiled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_typ
if(FAILED(hres)) {
stack_popn(exec_ctx, exec_ctx->top-prev_top);
while(exec_ctx->scope_chain != prev_scope)
scope_pop(&exec_ctx->scope_chain);
return hres;
}
assert(exec_ctx->top == prev_top+1 || exec_ctx->top == prev_top);
assert(exec_ctx->scope_chain == prev_scope);
if(exec_ctx->top == prev_top)
V_VT(ret) = VT_EMPTY;
......
......@@ -87,8 +87,10 @@ typedef struct _func_stack {
X(obj_prop, 1, ARG_BSTR, 0) \
X(or, 1, 0,0) \
X(pop, 1, 0,0) \
X(pop_scope, 1, 0,0) \
X(postinc, 1, ARG_INT, 0) \
X(preinc, 1, ARG_INT, 0) \
X(push_scope, 1, 0,0) \
X(regexp, 1, ARG_STR, ARG_INT) \
X(rshift, 1, 0,0) \
X(rshift2, 1, 0,0) \
......
......@@ -190,6 +190,7 @@ static inline IDispatch *to_disp(jsdisp_t *jsdisp)
}
jsdisp_t *as_jsdisp(IDispatch*);
jsdisp_t *to_jsdisp(IDispatch*);
static inline void jsdisp_addref(jsdisp_t *jsdisp)
{
......
......@@ -851,7 +851,7 @@ static const statement_eval_t stat_eval_table[] = {
try_statement_eval,
compiled_statement_eval,
compiled_statement_eval,
with_statement_eval
compiled_statement_eval
};
static void *new_statement(parser_ctx_t *ctx, statement_type_t type, size_t size)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment