jscript: Use compiler for handling if statement.
[wine] / dlls / jscript / engine.c
1 /*
2  * Copyright 2008 Jacek Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include "config.h"
20 #include "wine/port.h"
21
22 #include <math.h>
23 #include <assert.h>
24
25 #include "jscript.h"
26 #include "engine.h"
27
28 #include "wine/debug.h"
29
30 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
31
32 #define EXPR_NOVAL   0x0001
33
34 static const WCHAR booleanW[] = {'b','o','o','l','e','a','n',0};
35 static const WCHAR functionW[] = {'f','u','n','c','t','i','o','n',0};
36 static const WCHAR numberW[] = {'n','u','m','b','e','r',0};
37 static const WCHAR objectW[] = {'o','b','j','e','c','t',0};
38 static const WCHAR stringW[] = {'s','t','r','i','n','g',0};
39 static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
40 static const WCHAR unknownW[] = {'u','n','k','n','o','w','n',0};
41
42 struct _return_type_t {
43     enum{
44         RT_NORMAL,
45         RT_RETURN,
46         RT_BREAK,
47         RT_CONTINUE
48     } type;
49     jsexcept_t ei;
50 };
51
52 static inline HRESULT stat_eval(script_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
53 {
54     return stat->eval(ctx, stat, rt, ret);
55 }
56
57 static HRESULT expr_eval(script_ctx_t*,expression_t*,DWORD,jsexcept_t*,VARIANT*);
58
59 static HRESULT stack_push(exec_ctx_t *ctx, VARIANT *v)
60 {
61     if(!ctx->stack_size) {
62         ctx->stack = heap_alloc(16*sizeof(VARIANT));
63         if(!ctx->stack)
64             return E_OUTOFMEMORY;
65         ctx->stack_size = 16;
66     }else if(ctx->stack_size == ctx->top) {
67         VARIANT *new_stack;
68
69         new_stack = heap_realloc(ctx->stack, ctx->stack_size*2*sizeof(VARIANT));
70         if(!new_stack) {
71             VariantClear(v);
72             return E_OUTOFMEMORY;
73         }
74
75         ctx->stack = new_stack;
76         ctx->stack_size *= 2;
77     }
78
79     ctx->stack[ctx->top++] = *v;
80     return S_OK;
81 }
82
83 static HRESULT stack_push_bool(exec_ctx_t *ctx, BOOL b)
84 {
85     VARIANT v;
86
87     V_VT(&v) = VT_BOOL;
88     V_BOOL(&v) = b ? VARIANT_TRUE : VARIANT_FALSE;
89     return stack_push(ctx, &v);
90 }
91
92 static inline HRESULT stack_push_number(exec_ctx_t *ctx, double number)
93 {
94     VARIANT v;
95
96     num_set_val(&v, number);
97     return stack_push(ctx, &v);
98 }
99
100 static inline HRESULT stack_push_int(exec_ctx_t *ctx, INT n)
101 {
102     VARIANT v;
103
104     V_VT(&v) = VT_I4;
105     V_I4(&v) = n;
106     return stack_push(ctx, &v);
107 }
108
109 static inline HRESULT stack_push_string(exec_ctx_t *ctx, const WCHAR *str)
110 {
111     VARIANT v;
112
113     V_VT(&v) = VT_BSTR;
114     V_BSTR(&v) = SysAllocString(str);
115     return V_BSTR(&v) ? stack_push(ctx, &v) : E_OUTOFMEMORY;
116 }
117
118 static HRESULT stack_push_objid(exec_ctx_t *ctx, IDispatch *disp, DISPID id)
119 {
120     VARIANT v;
121     HRESULT hres;
122
123     V_VT(&v) = VT_DISPATCH;
124     V_DISPATCH(&v) = disp;
125     hres = stack_push(ctx, &v);
126     if(FAILED(hres))
127         return hres;
128
129     V_VT(&v) = VT_INT;
130     V_INT(&v) = id;
131     return stack_push(ctx, &v);
132 }
133
134 static inline VARIANT *stack_top(exec_ctx_t *ctx)
135 {
136     assert(ctx->top);
137     return ctx->stack + ctx->top-1;
138 }
139
140 static inline VARIANT *stack_topn(exec_ctx_t *ctx, unsigned n)
141 {
142     assert(ctx->top > n);
143     return ctx->stack + ctx->top-1-n;
144 }
145
146 static inline VARIANT *stack_pop(exec_ctx_t *ctx)
147 {
148     assert(ctx->top);
149     return ctx->stack + --ctx->top;
150 }
151
152 static void stack_popn(exec_ctx_t *ctx, unsigned n)
153 {
154     while(n--)
155         VariantClear(stack_pop(ctx));
156 }
157
158 static HRESULT stack_pop_number(exec_ctx_t *ctx, VARIANT *r)
159 {
160     VARIANT *v;
161     HRESULT hres;
162
163     v = stack_pop(ctx);
164     hres = to_number(ctx->parser->script, v, ctx->ei, r);
165     VariantClear(v);
166     return hres;
167 }
168
169 static HRESULT stack_pop_object(exec_ctx_t *ctx, IDispatch **r)
170 {
171     VARIANT *v;
172     HRESULT hres;
173
174     v = stack_pop(ctx);
175     if(V_VT(v) == VT_DISPATCH) {
176         if(!V_DISPATCH(v))
177             return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_REQUIRED, NULL);
178         *r = V_DISPATCH(v);
179         return S_OK;
180     }
181
182     hres = to_object(ctx->parser->script, v, r);
183     VariantClear(v);
184     return hres;
185 }
186
187 static inline HRESULT stack_pop_int(exec_ctx_t *ctx, INT *r)
188 {
189     return to_int32(ctx->parser->script, stack_pop(ctx), ctx->ei, r);
190 }
191
192 static inline HRESULT stack_pop_uint(exec_ctx_t *ctx, DWORD *r)
193 {
194     return to_uint32(ctx->parser->script, stack_pop(ctx), ctx->ei, r);
195 }
196
197 static inline IDispatch *stack_pop_objid(exec_ctx_t *ctx, DISPID *id)
198 {
199     assert(V_VT(stack_top(ctx)) == VT_INT && V_VT(stack_topn(ctx, 1)) == VT_DISPATCH);
200
201     *id = V_INT(stack_pop(ctx));
202     return V_DISPATCH(stack_pop(ctx));
203 }
204
205 static inline IDispatch *stack_topn_objid(exec_ctx_t *ctx, unsigned n, DISPID *id)
206 {
207     assert(V_VT(stack_topn(ctx, n)) == VT_INT && V_VT(stack_topn(ctx, n+1)) == VT_DISPATCH);
208
209     *id = V_INT(stack_topn(ctx, n));
210     return V_DISPATCH(stack_topn(ctx, n+1));
211 }
212
213 static void exprval_release(exprval_t *val)
214 {
215     switch(val->type) {
216     case EXPRVAL_VARIANT:
217         if(V_VT(&val->u.var) != VT_EMPTY)
218             VariantClear(&val->u.var);
219         return;
220     case EXPRVAL_IDREF:
221         if(val->u.idref.disp)
222             IDispatch_Release(val->u.idref.disp);
223         return;
224     case EXPRVAL_INVALID:
225         SysFreeString(val->u.identifier);
226     }
227 }
228
229 /* ECMA-262 3rd Edition    8.7.1 */
230 static HRESULT exprval_value(script_ctx_t *ctx, exprval_t *val, jsexcept_t *ei, VARIANT *ret)
231 {
232     V_VT(ret) = VT_EMPTY;
233
234     switch(val->type) {
235     case EXPRVAL_VARIANT:
236         return VariantCopy(ret, &val->u.var);
237     case EXPRVAL_IDREF:
238         if(!val->u.idref.disp) {
239             FIXME("throw ReferenceError\n");
240             return E_FAIL;
241         }
242
243         return disp_propget(ctx, val->u.idref.disp, val->u.idref.id, ret, ei, NULL/*FIXME*/);
244     case EXPRVAL_INVALID:
245         return throw_type_error(ctx, ei, JS_E_UNDEFINED_VARIABLE, val->u.identifier);
246     }
247
248     ERR("type %d\n", val->type);
249     return E_FAIL;
250 }
251
252 static HRESULT exprval_to_value(script_ctx_t *ctx, exprval_t *val, jsexcept_t *ei, VARIANT *ret)
253 {
254     if(val->type == EXPRVAL_VARIANT) {
255         *ret = val->u.var;
256         V_VT(&val->u.var) = VT_EMPTY;
257         return S_OK;
258     }
259
260     return exprval_value(ctx, val, ei, ret);
261 }
262
263 static void exprval_set_idref(exprval_t *val, IDispatch *disp, DISPID id)
264 {
265     val->type = EXPRVAL_IDREF;
266     val->u.idref.disp = disp;
267     val->u.idref.id = id;
268
269     if(disp)
270         IDispatch_AddRef(disp);
271 }
272
273 HRESULT scope_push(scope_chain_t *scope, jsdisp_t *obj, scope_chain_t **ret)
274 {
275     scope_chain_t *new_scope;
276
277     new_scope = heap_alloc(sizeof(scope_chain_t));
278     if(!new_scope)
279         return E_OUTOFMEMORY;
280
281     new_scope->ref = 1;
282
283     jsdisp_addref(obj);
284     new_scope->obj = obj;
285
286     if(scope) {
287         scope_addref(scope);
288         new_scope->next = scope;
289     }else {
290         new_scope->next = NULL;
291     }
292
293     *ret = new_scope;
294     return S_OK;
295 }
296
297 static void scope_pop(scope_chain_t **scope)
298 {
299     scope_chain_t *tmp;
300
301     tmp = *scope;
302     *scope = tmp->next;
303     scope_release(tmp);
304 }
305
306 void scope_release(scope_chain_t *scope)
307 {
308     if(--scope->ref)
309         return;
310
311     if(scope->next)
312         scope_release(scope->next);
313
314     jsdisp_release(scope->obj);
315     heap_free(scope);
316 }
317
318 HRESULT create_exec_ctx(script_ctx_t *script_ctx, IDispatch *this_obj, jsdisp_t *var_disp,
319         scope_chain_t *scope, BOOL is_global, exec_ctx_t **ret)
320 {
321     exec_ctx_t *ctx;
322
323     ctx = heap_alloc_zero(sizeof(exec_ctx_t));
324     if(!ctx)
325         return E_OUTOFMEMORY;
326
327     ctx->ref = 1;
328     ctx->is_global = is_global;
329
330     if(this_obj)
331         ctx->this_obj = this_obj;
332     else if(script_ctx->host_global)
333         ctx->this_obj = script_ctx->host_global;
334     else
335         ctx->this_obj = to_disp(script_ctx->global);
336     IDispatch_AddRef(ctx->this_obj);
337
338     jsdisp_addref(var_disp);
339     ctx->var_disp = var_disp;
340
341     if(scope) {
342         scope_addref(scope);
343         ctx->scope_chain = scope;
344     }
345
346     *ret = ctx;
347     return S_OK;
348 }
349
350 void exec_release(exec_ctx_t *ctx)
351 {
352     if(--ctx->ref)
353         return;
354
355     if(ctx->scope_chain)
356         scope_release(ctx->scope_chain);
357     if(ctx->var_disp)
358         jsdisp_release(ctx->var_disp);
359     if(ctx->this_obj)
360         IDispatch_Release(ctx->this_obj);
361     heap_free(ctx->stack);
362     heap_free(ctx);
363 }
364
365 static HRESULT disp_get_id(script_ctx_t *ctx, IDispatch *disp, BSTR name, DWORD flags, DISPID *id)
366 {
367     IDispatchEx *dispex;
368     HRESULT hres;
369
370     hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
371     if(FAILED(hres)) {
372         TRACE("unsing IDispatch\n");
373
374         *id = 0;
375         return IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, id);
376     }
377
378     *id = 0;
379     hres = IDispatchEx_GetDispID(dispex, name, make_grfdex(ctx, flags|fdexNameCaseSensitive), id);
380     IDispatchEx_Release(dispex);
381     return hres;
382 }
383
384 /* ECMA-262 3rd Edition    8.7.2 */
385 static HRESULT put_value(script_ctx_t *ctx, exprval_t *ref, VARIANT *v, jsexcept_t *ei)
386 {
387     if(ref->type != EXPRVAL_IDREF)
388         return throw_reference_error(ctx, ei, JS_E_ILLEGAL_ASSIGN, NULL);
389
390     return disp_propput(ctx, ref->u.idref.disp, ref->u.idref.id, v, ei, NULL/*FIXME*/);
391 }
392
393 static inline BOOL is_null(const VARIANT *v)
394 {
395     return V_VT(v) == VT_NULL || (V_VT(v) == VT_DISPATCH && !V_DISPATCH(v));
396 }
397
398 static HRESULT disp_cmp(IDispatch *disp1, IDispatch *disp2, BOOL *ret)
399 {
400     IObjectIdentity *identity;
401     IUnknown *unk1, *unk2;
402     HRESULT hres;
403
404     if(disp1 == disp2) {
405         *ret = TRUE;
406         return S_OK;
407     }
408
409     if(!disp1 || !disp2) {
410         *ret = FALSE;
411         return S_OK;
412     }
413
414     hres = IDispatch_QueryInterface(disp1, &IID_IUnknown, (void**)&unk1);
415     if(FAILED(hres))
416         return hres;
417
418     hres = IDispatch_QueryInterface(disp2, &IID_IUnknown, (void**)&unk2);
419     if(FAILED(hres)) {
420         IUnknown_Release(unk1);
421         return hres;
422     }
423
424     if(unk1 == unk2) {
425         *ret = TRUE;
426     }else {
427         hres = IUnknown_QueryInterface(unk1, &IID_IObjectIdentity, (void**)&identity);
428         if(SUCCEEDED(hres)) {
429             hres = IObjectIdentity_IsEqualObject(identity, unk2);
430             IObjectIdentity_Release(identity);
431             *ret = hres == S_OK;
432         }else {
433             *ret = FALSE;
434         }
435     }
436
437     IUnknown_Release(unk1);
438     IUnknown_Release(unk2);
439     return S_OK;
440 }
441
442 /* ECMA-262 3rd Edition    11.9.6 */
443 static HRESULT equal2_values(VARIANT *lval, VARIANT *rval, BOOL *ret)
444 {
445     TRACE("\n");
446
447     if(V_VT(lval) != V_VT(rval)) {
448         if(is_num_vt(V_VT(lval)) && is_num_vt(V_VT(rval)))
449             *ret = num_val(lval) == num_val(rval);
450         else if(is_null(lval))
451             *ret = is_null(rval);
452         else
453             *ret = FALSE;
454         return S_OK;
455     }
456
457     switch(V_VT(lval)) {
458     case VT_EMPTY:
459     case VT_NULL:
460         *ret = VARIANT_TRUE;
461         break;
462     case VT_I4:
463         *ret = V_I4(lval) == V_I4(rval);
464         break;
465     case VT_R8:
466         *ret = V_R8(lval) == V_R8(rval);
467         break;
468     case VT_BSTR:
469         if(!V_BSTR(lval))
470             *ret = SysStringLen(V_BSTR(rval))?FALSE:TRUE;
471         else if(!V_BSTR(rval))
472             *ret = SysStringLen(V_BSTR(lval))?FALSE:TRUE;
473         else
474             *ret = !strcmpW(V_BSTR(lval), V_BSTR(rval));
475         break;
476     case VT_DISPATCH:
477         return disp_cmp(V_DISPATCH(lval), V_DISPATCH(rval), ret);
478     case VT_BOOL:
479         *ret = !V_BOOL(lval) == !V_BOOL(rval);
480         break;
481     default:
482         FIXME("unimplemented vt %d\n", V_VT(lval));
483         return E_NOTIMPL;
484     }
485
486     return S_OK;
487 }
488
489 static BOOL lookup_global_members(script_ctx_t *ctx, BSTR identifier, exprval_t *ret)
490 {
491     named_item_t *item;
492     DISPID id;
493     HRESULT hres;
494
495     for(item = ctx->named_items; item; item = item->next) {
496         if(item->flags & SCRIPTITEM_GLOBALMEMBERS) {
497             hres = disp_get_id(ctx, item->disp, identifier, 0, &id);
498             if(SUCCEEDED(hres)) {
499                 if(ret)
500                     exprval_set_idref(ret, item->disp, id);
501                 return TRUE;
502             }
503         }
504     }
505
506     return FALSE;
507 }
508
509 HRESULT exec_source(exec_ctx_t *ctx, parser_ctx_t *parser, source_elements_t *source, BOOL from_eval,
510         jsexcept_t *ei, VARIANT *retv)
511 {
512     script_ctx_t *script = parser->script;
513     function_declaration_t *func;
514     parser_ctx_t *prev_parser;
515     var_list_t *var;
516     VARIANT val;
517     exec_ctx_t *prev_ctx;
518     return_type_t rt;
519     HRESULT hres = S_OK;
520
521     for(func = source->functions; func; func = func->next) {
522         jsdisp_t *func_obj;
523         VARIANT var;
524
525         hres = create_source_function(parser, func->expr->parameter_list, func->expr->source_elements,
526                 ctx->scope_chain, func->expr->src_str, func->expr->src_len, &func_obj);
527         if(FAILED(hres))
528             return hres;
529
530         var_set_jsdisp(&var, func_obj);
531         hres = jsdisp_propput_name(ctx->var_disp, func->expr->identifier, &var, ei, NULL);
532         jsdisp_release(func_obj);
533         if(FAILED(hres))
534             return hres;
535     }
536
537     for(var = source->variables; var; var = var->next) {
538         DISPID id = 0;
539         BSTR name;
540
541         name = SysAllocString(var->identifier);
542         if(!name)
543             return E_OUTOFMEMORY;
544
545         if(!ctx->is_global || !lookup_global_members(parser->script, name, NULL))
546             hres = jsdisp_get_id(ctx->var_disp, var->identifier, fdexNameEnsure, &id);
547         SysFreeString(name);
548         if(FAILED(hres))
549             return hres;
550     }
551
552     prev_ctx = script->exec_ctx;
553     script->exec_ctx = ctx;
554
555     prev_parser = ctx->parser;
556     ctx->parser = parser;
557
558     V_VT(&val) = VT_EMPTY;
559     memset(&rt, 0, sizeof(rt));
560     rt.type = RT_NORMAL;
561
562     if(source->statement) {
563         if(source->statement->instr_off == -1)
564             hres = compile_subscript_stat(ctx->parser, source->statement, TRUE, &source->statement->instr_off);
565         if(SUCCEEDED(hres))
566             hres = compiled_statement_eval(script, source->statement, &rt, &val);
567     }
568
569     script->exec_ctx = prev_ctx;
570     ctx->parser = prev_parser;
571
572     if(rt.type != RT_NORMAL && rt.type != RT_RETURN) {
573         FIXME("wrong rt %d\n", rt.type);
574         hres = E_FAIL;
575     }
576
577     *ei = rt.ei;
578     if(FAILED(hres)) {
579         VariantClear(&val);
580         return hres;
581     }
582
583     if(!retv || (!from_eval && rt.type != RT_RETURN))
584         VariantClear(&val);
585     if(retv)
586         *retv = val;
587     return S_OK;
588 }
589
590 /* ECMA-262 3rd Edition    10.1.4 */
591 static HRESULT identifier_eval(script_ctx_t *ctx, BSTR identifier, DWORD flags, jsexcept_t *ei, exprval_t *ret)
592 {
593     scope_chain_t *scope;
594     named_item_t *item;
595     DISPID id = 0;
596     HRESULT hres;
597
598     TRACE("%s\n", debugstr_w(identifier));
599
600     for(scope = ctx->exec_ctx->scope_chain; scope; scope = scope->next) {
601         hres = jsdisp_get_id(scope->obj, identifier, 0, &id);
602         if(SUCCEEDED(hres)) {
603             exprval_set_idref(ret, to_disp(scope->obj), id);
604             return S_OK;
605         }
606     }
607
608     hres = jsdisp_get_id(ctx->global, identifier, 0, &id);
609     if(SUCCEEDED(hres)) {
610         exprval_set_idref(ret, to_disp(ctx->global), id);
611         return S_OK;
612     }
613
614     for(item = ctx->named_items; item; item = item->next) {
615         if((item->flags & SCRIPTITEM_ISVISIBLE) && !strcmpW(item->name, identifier)) {
616             if(!item->disp) {
617                 IUnknown *unk;
618
619                 if(!ctx->site)
620                     break;
621
622                 hres = IActiveScriptSite_GetItemInfo(ctx->site, identifier,
623                                                      SCRIPTINFO_IUNKNOWN, &unk, NULL);
624                 if(FAILED(hres)) {
625                     WARN("GetItemInfo failed: %08x\n", hres);
626                     break;
627                 }
628
629                 hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&item->disp);
630                 IUnknown_Release(unk);
631                 if(FAILED(hres)) {
632                     WARN("object does not implement IDispatch\n");
633                     break;
634                 }
635             }
636
637             ret->type = EXPRVAL_VARIANT;
638             V_VT(&ret->u.var) = VT_DISPATCH;
639             V_DISPATCH(&ret->u.var) = item->disp;
640             IDispatch_AddRef(item->disp);
641             return S_OK;
642         }
643     }
644
645     if(lookup_global_members(ctx, identifier, ret))
646         return S_OK;
647
648     if(flags & fdexNameEnsure) {
649         hres = jsdisp_get_id(ctx->global, identifier, fdexNameEnsure, &id);
650         if(FAILED(hres))
651             return hres;
652
653         exprval_set_idref(ret, to_disp(ctx->global), id);
654         return S_OK;
655     }
656
657     ret->type = EXPRVAL_INVALID;
658     ret->u.identifier = SysAllocString(identifier);
659     if(!ret->u.identifier)
660         return E_OUTOFMEMORY;
661
662     return S_OK;
663 }
664
665 /* ECMA-262 3rd Edition    12.2 */
666 static HRESULT variable_list_eval(script_ctx_t *ctx, variable_declaration_t *var_list, jsexcept_t *ei)
667 {
668     variable_declaration_t *iter;
669     HRESULT hres = S_OK;
670
671     for(iter = var_list; iter; iter = iter->next) {
672         VARIANT val;
673
674         if(!iter->expr)
675             continue;
676
677         hres = expr_eval(ctx, iter->expr, 0, ei, &val);
678         if(FAILED(hres))
679             break;
680
681         hres = jsdisp_propput_name(ctx->exec_ctx->var_disp, iter->identifier, &val, ei, NULL/*FIXME*/);
682         VariantClear(&val);
683         if(FAILED(hres))
684             break;
685     }
686
687     return hres;
688 }
689
690 /* ECMA-262 3rd Edition    12.2 */
691 HRESULT var_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
692 {
693     var_statement_t *stat = (var_statement_t*)_stat;
694     HRESULT hres;
695
696     TRACE("\n");
697
698     hres = variable_list_eval(ctx, stat->variable_list, &rt->ei);
699     if(FAILED(hres))
700         return hres;
701
702     V_VT(ret) = VT_EMPTY;
703     return S_OK;
704 }
705
706 /* ECMA-262 3rd Edition    12.3 */
707 HRESULT empty_statement_eval(script_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
708 {
709     TRACE("\n");
710
711     V_VT(ret) = VT_EMPTY;
712     return S_OK;
713 }
714
715 /* ECMA-262 3rd Edition    12.6.2 */
716 HRESULT while_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
717 {
718     while_statement_t *stat = (while_statement_t*)_stat;
719     VARIANT val, tmp;
720     VARIANT_BOOL b;
721     BOOL test_expr;
722     HRESULT hres;
723
724     TRACE("\n");
725
726     V_VT(&val) = VT_EMPTY;
727     test_expr = !stat->do_while;
728
729     while(1) {
730         if(test_expr) {
731             hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &tmp);
732             if(FAILED(hres))
733                 break;
734
735             hres = to_boolean(&tmp, &b);
736             VariantClear(&tmp);
737             if(FAILED(hres) || !b)
738                 break;
739         }else {
740             test_expr = TRUE;
741         }
742
743         hres = stat_eval(ctx, stat->statement, rt, &tmp);
744         if(FAILED(hres))
745             break;
746
747         VariantClear(&val);
748         val = tmp;
749
750         if(rt->type == RT_CONTINUE)
751             rt->type = RT_NORMAL;
752         if(rt->type != RT_NORMAL)
753             break;
754     }
755
756     if(FAILED(hres)) {
757         VariantClear(&val);
758         return hres;
759     }
760
761     if(rt->type == RT_BREAK)
762         rt->type = RT_NORMAL;
763
764     *ret = val;
765     return S_OK;
766 }
767
768 /* ECMA-262 3rd Edition    12.6.3 */
769 HRESULT for_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
770 {
771     for_statement_t *stat = (for_statement_t*)_stat;
772     VARIANT val, tmp, retv;
773     VARIANT_BOOL b;
774     HRESULT hres;
775
776     TRACE("\n");
777
778     if(stat->variable_list) {
779         hres = variable_list_eval(ctx, stat->variable_list, &rt->ei);
780         if(FAILED(hres))
781             return hres;
782     }else if(stat->begin_expr) {
783         hres = expr_eval(ctx, stat->begin_expr, 0, &rt->ei, &val);
784         if(FAILED(hres))
785             return hres;
786
787         VariantClear(&val);
788     }
789
790     V_VT(&retv) = VT_EMPTY;
791
792     while(1) {
793         if(stat->expr) {
794             hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &tmp);
795             if(FAILED(hres))
796                 break;
797
798             hres = to_boolean(&tmp, &b);
799             VariantClear(&tmp);
800             if(FAILED(hres) || !b)
801                 break;
802         }
803
804         hres = stat_eval(ctx, stat->statement, rt, &tmp);
805         if(FAILED(hres))
806             break;
807
808         VariantClear(&retv);
809         retv = tmp;
810
811         if(rt->type == RT_CONTINUE)
812             rt->type = RT_NORMAL;
813         else if(rt->type != RT_NORMAL)
814             break;
815
816         if(stat->end_expr) {
817             hres = expr_eval(ctx, stat->end_expr, 0, &rt->ei, &val);
818             if(FAILED(hres))
819                 break;
820
821             VariantClear(&val);
822         }
823     }
824
825     if(FAILED(hres)) {
826         VariantClear(&retv);
827         return hres;
828     }
829
830     if(rt->type == RT_BREAK)
831         rt->type = RT_NORMAL;
832
833     *ret = retv;
834     return S_OK;
835 }
836
837 static HRESULT array_expression_eval(script_ctx_t*,expression_t*,jsexcept_t*,exprval_t*);
838 static HRESULT member_expression_eval(script_ctx_t*,expression_t*,jsexcept_t*,exprval_t*);
839 static HRESULT identifier_expression_eval(script_ctx_t*,expression_t*,jsexcept_t*,exprval_t*);
840
841 /* ECMA-262 3rd Edition    12.6.4 */
842 HRESULT forin_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
843 {
844     forin_statement_t *stat = (forin_statement_t*)_stat;
845     VARIANT val, name, retv, tmp;
846     DISPID id = DISPID_STARTENUM;
847     BSTR str, identifier = NULL;
848     IDispatchEx *in_obj;
849     exprval_t exprval;
850     HRESULT hres;
851
852     TRACE("\n");
853
854     if(stat->variable) {
855         hres = variable_list_eval(ctx, stat->variable, &rt->ei);
856         if(FAILED(hres))
857             return hres;
858     }
859
860     hres = expr_eval(ctx, stat->in_expr, 0, &rt->ei, &val);
861     if(FAILED(hres))
862         return hres;
863
864     if(V_VT(&val) != VT_DISPATCH) {
865         TRACE("in vt %d\n", V_VT(&val));
866         VariantClear(&val);
867         V_VT(ret) = VT_EMPTY;
868         return S_OK;
869     }
870
871     hres = IDispatch_QueryInterface(V_DISPATCH(&val), &IID_IDispatchEx, (void**)&in_obj);
872     IDispatch_Release(V_DISPATCH(&val));
873     if(FAILED(hres)) {
874         TRACE("Object doesn't support IDispatchEx\n");
875         V_VT(ret) = VT_EMPTY;
876         return S_OK;
877     }
878
879     V_VT(&retv) = VT_EMPTY;
880
881     if(stat->variable)
882         identifier = SysAllocString(stat->variable->identifier);
883
884     while(1) {
885         hres = IDispatchEx_GetNextDispID(in_obj, fdexEnumDefault, id, &id);
886         if(FAILED(hres) || hres == S_FALSE)
887             break;
888
889         hres = IDispatchEx_GetMemberName(in_obj, id, &str);
890         if(FAILED(hres))
891             break;
892
893         TRACE("iter %s\n", debugstr_w(str));
894
895         if(stat->variable) {
896             hres = identifier_eval(ctx, identifier, 0, NULL, &exprval);
897         }else {
898             switch(stat->expr->type) {
899             case EXPR_ARRAY:
900                 hres = array_expression_eval(ctx, stat->expr, &rt->ei, &exprval);
901                 break;
902             case EXPR_IDENT:
903                 hres = identifier_expression_eval(ctx, stat->expr, &rt->ei, &exprval);
904                 break;
905             case EXPR_MEMBER:
906                 hres = member_expression_eval(ctx, stat->expr, &rt->ei, &exprval);
907                 break;
908             default:
909                 hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &tmp);
910                 if(FAILED(hres))
911                     break;
912
913                 VariantClear(&tmp);
914                 hres = throw_reference_error(ctx, &rt->ei, JS_E_ILLEGAL_ASSIGN, NULL);
915                 break;
916             }
917         }
918         if(SUCCEEDED(hres)) {
919             V_VT(&name) = VT_BSTR;
920             V_BSTR(&name) = str;
921             hres = put_value(ctx, &exprval, &name, &rt->ei);
922             exprval_release(&exprval);
923         }
924         SysFreeString(str);
925         if(FAILED(hres))
926             break;
927
928         hres = stat_eval(ctx, stat->statement, rt, &tmp);
929         if(FAILED(hres))
930             break;
931
932         VariantClear(&retv);
933         retv = tmp;
934
935         if(rt->type == RT_CONTINUE)
936             rt->type = RT_NORMAL;
937         else if(rt->type != RT_NORMAL)
938             break;
939     }
940
941     SysFreeString(identifier);
942     IDispatchEx_Release(in_obj);
943     if(FAILED(hres)) {
944         VariantClear(&retv);
945         return hres;
946     }
947
948     if(rt->type == RT_BREAK)
949         rt->type = RT_NORMAL;
950
951     *ret = retv;
952     return S_OK;
953 }
954
955 /* ECMA-262 3rd Edition    12.7 */
956 HRESULT continue_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
957 {
958     branch_statement_t *stat = (branch_statement_t*)_stat;
959
960     TRACE("\n");
961
962     if(stat->identifier) {
963         FIXME("indentifier not implemented\n");
964         return E_NOTIMPL;
965     }
966
967     rt->type = RT_CONTINUE;
968     V_VT(ret) = VT_EMPTY;
969     return S_OK;
970 }
971
972 /* ECMA-262 3rd Edition    12.8 */
973 HRESULT break_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
974 {
975     branch_statement_t *stat = (branch_statement_t*)_stat;
976
977     TRACE("\n");
978
979     if(stat->identifier) {
980         FIXME("indentifier not implemented\n");
981         return E_NOTIMPL;
982     }
983
984     rt->type = RT_BREAK;
985     V_VT(ret) = VT_EMPTY;
986     return S_OK;
987 }
988
989 /* ECMA-262 3rd Edition    12.9 */
990 HRESULT return_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
991 {
992     expression_statement_t *stat = (expression_statement_t*)_stat;
993     HRESULT hres;
994
995     TRACE("\n");
996
997     if(stat->expr) {
998         hres = expr_eval(ctx, stat->expr, 0, &rt->ei, ret);
999         if(FAILED(hres))
1000             return hres;
1001     }else {
1002         V_VT(ret) = VT_EMPTY;
1003     }
1004
1005     TRACE("= %s\n", debugstr_variant(ret));
1006     rt->type = RT_RETURN;
1007     return S_OK;
1008 }
1009
1010 /* ECMA-262 3rd Edition    12.10 */
1011 HRESULT with_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1012 {
1013     with_statement_t *stat = (with_statement_t*)_stat;
1014     IDispatch *disp;
1015     jsdisp_t *obj;
1016     VARIANT val;
1017     HRESULT hres;
1018
1019     TRACE("\n");
1020
1021     hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &val);
1022     if(FAILED(hres))
1023         return hres;
1024
1025     hres = to_object(ctx, &val, &disp);
1026     VariantClear(&val);
1027     if(FAILED(hres))
1028         return hres;
1029
1030     obj = iface_to_jsdisp((IUnknown*)disp);
1031     IDispatch_Release(disp);
1032     if(!obj) {
1033         FIXME("disp id not jsdisp\n");
1034         return E_NOTIMPL;
1035     }
1036
1037     hres = scope_push(ctx->exec_ctx->scope_chain, obj, &ctx->exec_ctx->scope_chain);
1038     jsdisp_release(obj);
1039     if(FAILED(hres))
1040         return hres;
1041
1042     hres = stat_eval(ctx, stat->statement, rt, ret);
1043
1044     scope_pop(&ctx->exec_ctx->scope_chain);
1045     return hres;
1046 }
1047
1048 /* ECMA-262 3rd Edition    12.12 */
1049 HRESULT labelled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
1050 {
1051     FIXME("\n");
1052     return E_NOTIMPL;
1053 }
1054
1055 /* ECMA-262 3rd Edition    12.13 */
1056 HRESULT switch_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1057 {
1058     switch_statement_t *stat = (switch_statement_t*)_stat;
1059     case_clausule_t *iter, *default_clausule = NULL;
1060     statement_t *stat_iter;
1061     VARIANT val, cval;
1062     BOOL b;
1063     HRESULT hres;
1064
1065     TRACE("\n");
1066
1067     hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &val);
1068     if(FAILED(hres))
1069         return hres;
1070
1071     for(iter = stat->case_list; iter; iter = iter->next) {
1072         if(!iter->expr) {
1073             default_clausule = iter;
1074             continue;
1075         }
1076
1077         hres = expr_eval(ctx, iter->expr, 0, &rt->ei, &cval);
1078         if(FAILED(hres))
1079             break;
1080
1081         hres = equal2_values(&val, &cval, &b);
1082         VariantClear(&cval);
1083         if(FAILED(hres) || b)
1084             break;
1085     }
1086
1087     VariantClear(&val);
1088     if(FAILED(hres))
1089         return hres;
1090
1091     if(!iter)
1092         iter = default_clausule;
1093
1094     V_VT(&val) = VT_EMPTY;
1095     if(iter) {
1096         VARIANT tmp;
1097
1098         for(stat_iter = iter->stat; stat_iter; stat_iter = stat_iter->next) {
1099             hres = stat_eval(ctx, stat_iter, rt, &tmp);
1100             if(FAILED(hres))
1101                 break;
1102
1103             VariantClear(&val);
1104             val = tmp;
1105
1106             if(rt->type != RT_NORMAL)
1107                 break;
1108         }
1109     }
1110
1111     if(FAILED(hres)) {
1112         VariantClear(&val);
1113         return hres;
1114     }
1115
1116     if(rt->type == RT_BREAK)
1117         rt->type = RT_NORMAL;
1118
1119     *ret = val;
1120     return S_OK;
1121 }
1122
1123 /* ECMA-262 3rd Edition    12.13 */
1124 HRESULT throw_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1125 {
1126     expression_statement_t *stat = (expression_statement_t*)_stat;
1127     VARIANT val;
1128     HRESULT hres;
1129
1130     TRACE("\n");
1131
1132     hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &val);
1133     if(FAILED(hres))
1134         return hres;
1135
1136     rt->ei.var = val;
1137     return DISP_E_EXCEPTION;
1138 }
1139
1140 static HRESULT interp_throw(exec_ctx_t *ctx)
1141 {
1142     const HRESULT arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1143
1144     TRACE("%08x\n", arg);
1145
1146     return throw_reference_error(ctx->parser->script, ctx->ei, arg, NULL);
1147 }
1148
1149 static HRESULT interp_throw_type(exec_ctx_t *ctx)
1150 {
1151     const HRESULT hres = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1152     const WCHAR *str = ctx->parser->code->instrs[ctx->ip].arg2.str;
1153
1154     TRACE("%08x %s\n", hres, debugstr_w(str));
1155
1156     return throw_type_error(ctx->parser->script, ctx->ei, hres, str);
1157 }
1158
1159 /* ECMA-262 3rd Edition    12.14 */
1160 static HRESULT catch_eval(script_ctx_t *ctx, catch_block_t *block, return_type_t *rt, VARIANT *ret)
1161 {
1162     jsdisp_t *var_disp;
1163     VARIANT ex, val;
1164     HRESULT hres;
1165
1166     ex = rt->ei.var;
1167     memset(&rt->ei, 0, sizeof(jsexcept_t));
1168
1169     hres = create_dispex(ctx, NULL, NULL, &var_disp);
1170     if(SUCCEEDED(hres)) {
1171         hres = jsdisp_propput_name(var_disp, block->identifier, &ex, &rt->ei, NULL/*FIXME*/);
1172         if(SUCCEEDED(hres)) {
1173             hres = scope_push(ctx->exec_ctx->scope_chain, var_disp, &ctx->exec_ctx->scope_chain);
1174             if(SUCCEEDED(hres)) {
1175                 hres = stat_eval(ctx, block->statement, rt, &val);
1176                 scope_pop(&ctx->exec_ctx->scope_chain);
1177             }
1178         }
1179
1180         jsdisp_release(var_disp);
1181     }
1182
1183     VariantClear(&ex);
1184     if(FAILED(hres))
1185         return hres;
1186
1187     *ret = val;
1188     return S_OK;
1189 }
1190
1191 /* ECMA-262 3rd Edition    12.14 */
1192 HRESULT try_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1193 {
1194     try_statement_t *stat = (try_statement_t*)_stat;
1195     VARIANT val;
1196     HRESULT hres;
1197
1198     TRACE("\n");
1199
1200     hres = stat_eval(ctx, stat->try_statement, rt, &val);
1201     if(FAILED(hres)) {
1202         TRACE("EXCEPTION\n");
1203         if(!stat->catch_block)
1204             return hres;
1205
1206         hres = catch_eval(ctx, stat->catch_block, rt, &val);
1207         if(FAILED(hres))
1208             return hres;
1209     }
1210
1211     if(stat->finally_statement) {
1212         VariantClear(&val);
1213         hres = stat_eval(ctx, stat->finally_statement, rt, &val);
1214         if(FAILED(hres))
1215             return hres;
1216     }
1217
1218     *ret = val;
1219     return S_OK;
1220 }
1221
1222 /* ECMA-262 3rd Edition    13 */
1223 static HRESULT interp_func(exec_ctx_t *ctx)
1224 {
1225     function_expression_t *expr = ctx->parser->code->instrs[ctx->ip].arg1.func;
1226     jsdisp_t *dispex;
1227     VARIANT v;
1228     HRESULT hres;
1229
1230     TRACE("\n");
1231
1232     hres = create_source_function(ctx->parser, expr->parameter_list, expr->source_elements, ctx->scope_chain,
1233             expr->src_str, expr->src_len, &dispex);
1234     if(FAILED(hres))
1235         return hres;
1236
1237     var_set_jsdisp(&v, dispex);
1238     return stack_push(ctx, &v);
1239 }
1240
1241 /* ECMA-262 3rd Edition    11.2.1 */
1242 static HRESULT array_expression_eval(script_ctx_t *ctx, expression_t *_expr, jsexcept_t *ei, exprval_t *ret)
1243 {
1244     binary_expression_t *expr = (binary_expression_t*)_expr;
1245     VARIANT member, val;
1246     DISPID id;
1247     BSTR str;
1248     IDispatch *obj = NULL;
1249     HRESULT hres;
1250
1251     TRACE("\n");
1252
1253     hres = expr_eval(ctx, expr->expression1, 0, ei, &member);
1254     if(FAILED(hres))
1255         return hres;
1256
1257     hres = expr_eval(ctx, expr->expression2, 0, ei, &val);
1258     if(SUCCEEDED(hres)) {
1259         hres = to_object(ctx, &member, &obj);
1260         if(FAILED(hres))
1261             VariantClear(&val);
1262     }
1263     VariantClear(&member);
1264     if(SUCCEEDED(hres)) {
1265         hres = to_string(ctx, &val, ei, &str);
1266         VariantClear(&val);
1267         if(SUCCEEDED(hres)) {
1268             hres = disp_get_id(ctx, obj, str, fdexNameEnsure, &id);
1269             SysFreeString(str);
1270         }
1271
1272         if(SUCCEEDED(hres))
1273             exprval_set_idref(ret, obj, id);
1274
1275         IDispatch_Release(obj);
1276     }
1277
1278     return hres;
1279 }
1280
1281 /* ECMA-262 3rd Edition    11.2.1 */
1282 static HRESULT interp_array(exec_ctx_t *ctx)
1283 {
1284     VARIANT v, *namev;
1285     IDispatch *obj;
1286     DISPID id;
1287     BSTR name;
1288     HRESULT hres;
1289
1290     TRACE("\n");
1291
1292     namev = stack_pop(ctx);
1293
1294     hres = stack_pop_object(ctx, &obj);
1295     if(FAILED(hres)) {
1296         VariantClear(namev);
1297         return hres;
1298     }
1299
1300     hres = to_string(ctx->parser->script, namev, ctx->ei, &name);
1301     VariantClear(namev);
1302     if(FAILED(hres)) {
1303         IDispatch_Release(obj);
1304         return hres;
1305     }
1306
1307     hres = disp_get_id(ctx->parser->script, obj, name, 0, &id);
1308     SysFreeString(name);
1309     if(SUCCEEDED(hres)) {
1310         hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
1311     }else if(hres == DISP_E_UNKNOWNNAME) {
1312         V_VT(&v) = VT_EMPTY;
1313         hres = S_OK;
1314     }
1315     IDispatch_Release(obj);
1316     if(FAILED(hres))
1317         return hres;
1318
1319     return stack_push(ctx, &v);
1320 }
1321
1322 /* ECMA-262 3rd Edition    11.2.1 */
1323 static HRESULT member_expression_eval(script_ctx_t *ctx, expression_t *_expr, jsexcept_t *ei, exprval_t *ret)
1324 {
1325     member_expression_t *expr = (member_expression_t*)_expr;
1326     IDispatch *obj = NULL;
1327     VARIANT member;
1328     DISPID id;
1329     BSTR str;
1330     HRESULT hres;
1331
1332     TRACE("\n");
1333
1334     hres = expr_eval(ctx, expr->expression, 0, ei, &member);
1335     if(FAILED(hres))
1336         return hres;
1337
1338     hres = to_object(ctx, &member, &obj);
1339     VariantClear(&member);
1340     if(FAILED(hres))
1341         return hres;
1342
1343     str = SysAllocString(expr->identifier);
1344     if(!str) {
1345         IDispatch_Release(obj);
1346         return E_OUTOFMEMORY;
1347     }
1348
1349     hres = disp_get_id(ctx, obj, str, fdexNameEnsure, &id);
1350     SysFreeString(str);
1351     if(SUCCEEDED(hres))
1352         exprval_set_idref(ret, obj, id);
1353
1354     IDispatch_Release(obj);
1355     return hres;
1356 }
1357
1358 /* ECMA-262 3rd Edition    11.2.1 */
1359 static HRESULT interp_member(exec_ctx_t *ctx)
1360 {
1361     const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1362     IDispatch *obj;
1363     VARIANT v;
1364     DISPID id;
1365     HRESULT hres;
1366
1367     TRACE("\n");
1368
1369     hres = stack_pop_object(ctx, &obj);
1370     if(FAILED(hres))
1371         return hres;
1372
1373     hres = disp_get_id(ctx->parser->script, obj, arg, 0, &id);
1374     if(SUCCEEDED(hres)) {
1375         V_VT(&v) = VT_EMPTY;
1376         hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
1377     }else if(hres == DISP_E_UNKNOWNNAME) {
1378         V_VT(&v) = VT_EMPTY;
1379         hres = S_OK;
1380     }
1381     IDispatch_Release(obj);
1382     if(FAILED(hres))
1383         return hres;
1384
1385     return stack_push(ctx, &v);
1386 }
1387
1388 /* ECMA-262 3rd Edition    11.2.1 */
1389 static HRESULT interp_memberid(exec_ctx_t *ctx)
1390 {
1391     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1392     VARIANT *objv, *namev;
1393     IDispatch *obj;
1394     BSTR name;
1395     DISPID id;
1396     HRESULT hres;
1397
1398     TRACE("%x\n", arg);
1399
1400     namev = stack_pop(ctx);
1401     objv = stack_pop(ctx);
1402
1403     hres = to_object(ctx->parser->script, objv, &obj);
1404     VariantClear(objv);
1405     if(SUCCEEDED(hres)) {
1406         hres = to_string(ctx->parser->script, namev, ctx->ei, &name);
1407         if(FAILED(hres))
1408             IDispatch_Release(obj);
1409     }
1410     VariantClear(namev);
1411     if(FAILED(hres))
1412         return hres;
1413
1414     hres = disp_get_id(ctx->parser->script, obj, name, arg, &id);
1415     SysFreeString(name);
1416     if(FAILED(hres)) {
1417         IDispatch_Release(obj);
1418         if(hres == DISP_E_UNKNOWNNAME && !(arg & fdexNameEnsure)) {
1419             obj = NULL;
1420             id = JS_E_INVALID_PROPERTY;
1421         }else {
1422             return hres;
1423         }
1424     }
1425
1426     return stack_push_objid(ctx, obj, id);
1427 }
1428
1429 /* ECMA-262 3rd Edition    11.2.1 */
1430 static HRESULT interp_refval(exec_ctx_t *ctx)
1431 {
1432     IDispatch *disp;
1433     VARIANT v;
1434     DISPID id;
1435     HRESULT hres;
1436
1437     TRACE("\n");
1438
1439     disp = stack_topn_objid(ctx, 0, &id);
1440     if(!disp)
1441         return throw_reference_error(ctx->parser->script, ctx->ei, JS_E_ILLEGAL_ASSIGN, NULL);
1442
1443     hres = disp_propget(ctx->parser->script, disp, id, &v, ctx->ei, NULL/*FIXME*/);
1444     if(FAILED(hres))
1445         return hres;
1446
1447     return stack_push(ctx, &v);
1448 }
1449
1450 static void jsstack_to_dp(exec_ctx_t *ctx, unsigned arg_cnt, DISPPARAMS *dp)
1451 {
1452     VARIANT tmp;
1453     unsigned i;
1454
1455     dp->cArgs = arg_cnt;
1456     dp->rgdispidNamedArgs = NULL;
1457     dp->cNamedArgs = 0;
1458
1459     assert(ctx->top >= arg_cnt);
1460
1461     for(i=1; i*2 <= arg_cnt; i++) {
1462         tmp = ctx->stack[ctx->top-i];
1463         ctx->stack[ctx->top-i] = ctx->stack[ctx->top-arg_cnt+i-1];
1464         ctx->stack[ctx->top-arg_cnt+i-1] = tmp;
1465     }
1466
1467     dp->rgvarg = ctx->stack + ctx->top-arg_cnt;
1468 }
1469
1470 /* ECMA-262 3rd Edition    11.2.2 */
1471 static HRESULT interp_new(exec_ctx_t *ctx)
1472 {
1473     const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1474     VARIANT *constr, v;
1475     DISPPARAMS dp;
1476     HRESULT hres;
1477
1478     TRACE("%d\n", arg);
1479
1480     constr = stack_topn(ctx, arg);
1481
1482     /* NOTE: Should use to_object here */
1483
1484     if(V_VT(constr) == VT_NULL)
1485         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
1486     else if(V_VT(constr) != VT_DISPATCH)
1487         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_INVALID_ACTION, NULL);
1488     else if(!V_DISPATCH(constr))
1489         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_INVALID_PROPERTY, NULL);
1490
1491     jsstack_to_dp(ctx, arg, &dp);
1492     hres = disp_call(ctx->parser->script, V_DISPATCH(constr), DISPID_VALUE,
1493             DISPATCH_CONSTRUCT, &dp, &v, ctx->ei, NULL/*FIXME*/);
1494     if(FAILED(hres))
1495         return hres;
1496
1497     stack_popn(ctx, arg+1);
1498     return stack_push(ctx, &v);
1499 }
1500
1501 /* ECMA-262 3rd Edition    11.2.3 */
1502 static HRESULT interp_call(exec_ctx_t *ctx)
1503 {
1504     const unsigned argn = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1505     const int do_ret = ctx->parser->code->instrs[ctx->ip].arg2.lng;
1506     VARIANT v, *objv;
1507     DISPPARAMS dp;
1508     HRESULT hres;
1509
1510     TRACE("%d %d\n", argn, do_ret);
1511
1512     objv = stack_topn(ctx, argn);
1513     if(V_VT(objv) != VT_DISPATCH)
1514         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_INVALID_PROPERTY, NULL);
1515
1516     jsstack_to_dp(ctx, argn, &dp);
1517     hres = disp_call(ctx->parser->script, V_DISPATCH(objv), DISPID_VALUE, DISPATCH_METHOD, &dp,
1518             do_ret ? &v : NULL, ctx->ei, NULL/*FIXME*/);
1519     if(FAILED(hres))
1520         return hres;
1521
1522     stack_popn(ctx, argn+1);
1523     return do_ret ? stack_push(ctx, &v) : S_OK;
1524
1525 }
1526
1527 /* ECMA-262 3rd Edition    11.2.3 */
1528 static HRESULT interp_call_member(exec_ctx_t *ctx)
1529 {
1530     const unsigned argn = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1531     const int do_ret = ctx->parser->code->instrs[ctx->ip].arg2.lng;
1532     IDispatch *obj;
1533     DISPPARAMS dp;
1534     VARIANT v;
1535     DISPID id;
1536     HRESULT hres;
1537
1538     TRACE("%d %d\n", argn, do_ret);
1539
1540     obj = stack_topn_objid(ctx, argn, &id);
1541     if(!obj)
1542         return throw_type_error(ctx->parser->script, ctx->ei, id, NULL);
1543
1544     jsstack_to_dp(ctx, argn, &dp);
1545     hres = disp_call(ctx->parser->script, obj, id, DISPATCH_METHOD, &dp, do_ret ? &v : NULL, ctx->ei, NULL/*FIXME*/);
1546     if(FAILED(hres))
1547         return hres;
1548
1549     stack_popn(ctx, argn+2);
1550     return do_ret ? stack_push(ctx, &v) : S_OK;
1551
1552 }
1553
1554 /* ECMA-262 3rd Edition    11.1.1 */
1555 static HRESULT interp_this(exec_ctx_t *ctx)
1556 {
1557     VARIANT v;
1558
1559     TRACE("\n");
1560
1561     V_VT(&v) = VT_DISPATCH;
1562     V_DISPATCH(&v) = ctx->this_obj;
1563     IDispatch_AddRef(ctx->this_obj);
1564     return stack_push(ctx, &v);
1565 }
1566
1567 /* ECMA-262 3rd Edition    10.1.4 */
1568 static HRESULT identifier_expression_eval(script_ctx_t *ctx, expression_t *_expr, jsexcept_t *ei, exprval_t *ret)
1569 {
1570     identifier_expression_t *expr = (identifier_expression_t*)_expr;
1571     BSTR identifier;
1572     HRESULT hres;
1573
1574     TRACE("\n");
1575
1576     identifier = SysAllocString(expr->identifier);
1577     if(!identifier)
1578         return E_OUTOFMEMORY;
1579
1580     hres = identifier_eval(ctx, identifier, fdexNameEnsure, ei, ret);
1581
1582     SysFreeString(identifier);
1583     return hres;
1584 }
1585
1586 /* ECMA-262 3rd Edition    10.1.4 */
1587 static HRESULT interp_ident(exec_ctx_t *ctx)
1588 {
1589     const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1590     exprval_t exprval;
1591     VARIANT v;
1592     HRESULT hres;
1593
1594     TRACE("%s\n", debugstr_w(arg));
1595
1596     hres = identifier_eval(ctx->parser->script, arg, 0, ctx->ei, &exprval);
1597     if(FAILED(hres))
1598         return hres;
1599
1600     hres = exprval_to_value(ctx->parser->script, &exprval, ctx->ei, &v);
1601     exprval_release(&exprval);
1602     if(FAILED(hres))
1603         return hres;
1604
1605     return stack_push(ctx, &v);
1606 }
1607
1608 /* ECMA-262 3rd Edition    10.1.4 */
1609 static HRESULT interp_identid(exec_ctx_t *ctx)
1610 {
1611     const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1612     const unsigned flags = ctx->parser->code->instrs[ctx->ip].arg2.uint;
1613     exprval_t exprval;
1614     HRESULT hres;
1615
1616     TRACE("%s %x\n", debugstr_w(arg), flags);
1617
1618     hres = identifier_eval(ctx->parser->script, arg, flags, ctx->ei, &exprval);
1619     if(FAILED(hres))
1620         return hres;
1621
1622     if(exprval.type != EXPRVAL_IDREF) {
1623         WARN("invalid ref\n");
1624         exprval_release(&exprval);
1625         return stack_push_objid(ctx, NULL, JS_E_OBJECT_EXPECTED);
1626     }
1627
1628     return stack_push_objid(ctx, exprval.u.idref.disp, exprval.u.idref.id);
1629 }
1630
1631 /* ECMA-262 3rd Edition    7.8.1 */
1632 static HRESULT interp_null(exec_ctx_t *ctx)
1633 {
1634     VARIANT v;
1635
1636     TRACE("\n");
1637
1638     V_VT(&v) = VT_NULL;
1639     return stack_push(ctx, &v);
1640 }
1641
1642 /* ECMA-262 3rd Edition    7.8.2 */
1643 static HRESULT interp_bool(exec_ctx_t *ctx)
1644 {
1645     const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1646
1647     TRACE("%s\n", arg ? "true" : "false");
1648
1649     return stack_push_bool(ctx, arg);
1650 }
1651
1652 /* ECMA-262 3rd Edition    7.8.3 */
1653 static HRESULT interp_int(exec_ctx_t *ctx)
1654 {
1655     const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1656     VARIANT v;
1657
1658     TRACE("%d\n", arg);
1659
1660     V_VT(&v) = VT_I4;
1661     V_I4(&v) = arg;
1662     return stack_push(ctx, &v);
1663 }
1664
1665 /* ECMA-262 3rd Edition    7.8.3 */
1666 static HRESULT interp_double(exec_ctx_t *ctx)
1667 {
1668     const double arg = *ctx->parser->code->instrs[ctx->ip].arg1.dbl;
1669     VARIANT v;
1670
1671     TRACE("%lf\n", arg);
1672
1673     V_VT(&v) = VT_R8;
1674     V_R8(&v) = arg;
1675     return stack_push(ctx, &v);
1676 }
1677
1678 /* ECMA-262 3rd Edition    7.8.4 */
1679 static HRESULT interp_str(exec_ctx_t *ctx)
1680 {
1681     const WCHAR *str = ctx->parser->code->instrs[ctx->ip].arg1.str;
1682     VARIANT v;
1683
1684     TRACE("%s\n", debugstr_w(str));
1685
1686     V_VT(&v) = VT_BSTR;
1687     V_BSTR(&v) = SysAllocString(str);
1688     if(!V_BSTR(&v))
1689         return E_OUTOFMEMORY;
1690
1691     return stack_push(ctx, &v);
1692 }
1693
1694 /* ECMA-262 3rd Edition    7.8 */
1695 static HRESULT interp_regexp(exec_ctx_t *ctx)
1696 {
1697     const WCHAR *source = ctx->parser->code->instrs[ctx->ip].arg1.str;
1698     const LONG flags = ctx->parser->code->instrs[ctx->ip].arg2.lng;
1699     jsdisp_t *regexp;
1700     VARIANT v;
1701     HRESULT hres;
1702
1703     TRACE("%s %x\n", debugstr_w(source), flags);
1704
1705     hres = create_regexp(ctx->parser->script, source, strlenW(source), flags, &regexp);
1706     if(FAILED(hres))
1707         return hres;
1708
1709     var_set_jsdisp(&v, regexp);
1710     return stack_push(ctx, &v);
1711 }
1712
1713 /* ECMA-262 3rd Edition    11.1.4 */
1714 static HRESULT interp_carray(exec_ctx_t *ctx)
1715 {
1716     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1717     jsdisp_t *array;
1718     VARIANT *v, r;
1719     unsigned i;
1720     HRESULT hres;
1721
1722     TRACE("%u\n", arg);
1723
1724     hres = create_array(ctx->parser->script, arg, &array);
1725     if(FAILED(hres))
1726         return hres;
1727
1728     i = arg;
1729     while(i--) {
1730         v = stack_pop(ctx);
1731         hres = jsdisp_propput_idx(array, i, v, ctx->ei, NULL/*FIXME*/);
1732         VariantClear(v);
1733         if(FAILED(hres)) {
1734             jsdisp_release(array);
1735             return hres;
1736         }
1737     }
1738
1739     var_set_jsdisp(&r, array);
1740     return stack_push(ctx, &r);
1741 }
1742
1743 /* ECMA-262 3rd Edition    11.1.5 */
1744 HRESULT interp_new_obj(exec_ctx_t *ctx)
1745 {
1746     jsdisp_t *obj;
1747     VARIANT v;
1748     HRESULT hres;
1749
1750     TRACE("\n");
1751
1752     hres = create_object(ctx->parser->script, NULL, &obj);
1753     if(FAILED(hres))
1754         return hres;
1755
1756     var_set_jsdisp(&v, obj);
1757     return stack_push(ctx, &v);
1758 }
1759
1760 /* ECMA-262 3rd Edition    11.1.5 */
1761 HRESULT interp_obj_prop(exec_ctx_t *ctx)
1762 {
1763     const BSTR name = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1764     jsdisp_t *obj;
1765     VARIANT *v;
1766     HRESULT hres;
1767
1768     TRACE("%s\n", debugstr_w(name));
1769
1770     v = stack_pop(ctx);
1771
1772     assert(V_VT(stack_top(ctx)) == VT_DISPATCH);
1773     obj = as_jsdisp(V_DISPATCH(stack_top(ctx)));
1774
1775     hres = jsdisp_propput_name(obj, name, v, ctx->ei, NULL/*FIXME*/);
1776     VariantClear(v);
1777     return hres;
1778 }
1779
1780 /* ECMA-262 3rd Edition    11.11 */
1781 static HRESULT interp_jmp_nz(exec_ctx_t *ctx)
1782 {
1783     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1784     VARIANT_BOOL b;
1785     HRESULT hres;
1786
1787     TRACE("\n");
1788
1789     hres = to_boolean(stack_top(ctx), &b);
1790     if(FAILED(hres))
1791         return hres;
1792
1793     if(b) {
1794         ctx->ip = arg;
1795     }else {
1796         stack_popn(ctx, 1);
1797         ctx->ip++;
1798     }
1799     return S_OK;
1800 }
1801
1802 /* ECMA-262 3rd Edition    11.11 */
1803 static HRESULT interp_jmp_z(exec_ctx_t *ctx)
1804 {
1805     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1806     VARIANT_BOOL b;
1807     HRESULT hres;
1808
1809     TRACE("\n");
1810
1811     hres = to_boolean(stack_top(ctx), &b);
1812     if(FAILED(hres))
1813         return hres;
1814
1815     if(b) {
1816         stack_popn(ctx, 1);
1817         ctx->ip++;
1818     }else {
1819         ctx->ip = arg;
1820     }
1821     return S_OK;
1822 }
1823
1824 /* ECMA-262 3rd Edition    11.10 */
1825 static HRESULT interp_or(exec_ctx_t *ctx)
1826 {
1827     INT l, r;
1828     HRESULT hres;
1829
1830     TRACE("\n");
1831
1832     hres = stack_pop_int(ctx, &r);
1833     if(FAILED(hres))
1834         return hres;
1835
1836     hres = stack_pop_int(ctx, &l);
1837     if(FAILED(hres))
1838         return hres;
1839
1840     return stack_push_int(ctx, l|r);
1841 }
1842
1843 /* ECMA-262 3rd Edition    11.10 */
1844 static HRESULT interp_xor(exec_ctx_t *ctx)
1845 {
1846     INT l, r;
1847     HRESULT hres;
1848
1849     TRACE("\n");
1850
1851     hres = stack_pop_int(ctx, &r);
1852     if(FAILED(hres))
1853         return hres;
1854
1855     hres = stack_pop_int(ctx, &l);
1856     if(FAILED(hres))
1857         return hres;
1858
1859     return stack_push_int(ctx, l^r);
1860 }
1861
1862 /* ECMA-262 3rd Edition    11.10 */
1863 static HRESULT interp_and(exec_ctx_t *ctx)
1864 {
1865     INT l, r;
1866     HRESULT hres;
1867
1868     TRACE("\n");
1869
1870     hres = stack_pop_int(ctx, &r);
1871     if(FAILED(hres))
1872         return hres;
1873
1874     hres = stack_pop_int(ctx, &l);
1875     if(FAILED(hres))
1876         return hres;
1877
1878     return stack_push_int(ctx, l&r);
1879 }
1880
1881 /* ECMA-262 3rd Edition    11.8.6 */
1882 static HRESULT interp_instanceof(exec_ctx_t *ctx)
1883 {
1884     jsdisp_t *obj, *iter, *tmp = NULL;
1885     VARIANT prot, *v;
1886     BOOL ret = FALSE;
1887     HRESULT hres;
1888
1889     static const WCHAR prototypeW[] = {'p','r','o','t','o','t', 'y', 'p','e',0};
1890
1891     v = stack_pop(ctx);
1892     if(V_VT(v) != VT_DISPATCH || !V_DISPATCH(v)) {
1893         VariantClear(v);
1894         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_FUNCTION_EXPECTED, NULL);
1895     }
1896
1897     obj = iface_to_jsdisp((IUnknown*)V_DISPATCH(v));
1898     IDispatch_Release(V_DISPATCH(v));
1899     if(!obj) {
1900         FIXME("non-jsdisp objects not supported\n");
1901         return E_FAIL;
1902     }
1903
1904     if(is_class(obj, JSCLASS_FUNCTION)) {
1905         hres = jsdisp_propget_name(obj, prototypeW, &prot, ctx->ei, NULL/*FIXME*/);
1906     }else {
1907         hres = throw_type_error(ctx->parser->script, ctx->ei, JS_E_FUNCTION_EXPECTED, NULL);
1908     }
1909     jsdisp_release(obj);
1910     if(FAILED(hres))
1911         return hres;
1912
1913     v = stack_pop(ctx);
1914
1915     if(V_VT(&prot) == VT_DISPATCH) {
1916         if(V_VT(v) == VT_DISPATCH)
1917             tmp = iface_to_jsdisp((IUnknown*)V_DISPATCH(v));
1918         for(iter = tmp; !ret && iter; iter = iter->prototype) {
1919             hres = disp_cmp(V_DISPATCH(&prot), to_disp(iter), &ret);
1920             if(FAILED(hres))
1921                 break;
1922         }
1923
1924         if(tmp)
1925             jsdisp_release(tmp);
1926     }else {
1927         FIXME("prototype is not an object\n");
1928         hres = E_FAIL;
1929     }
1930
1931     VariantClear(&prot);
1932     VariantClear(v);
1933     if(FAILED(hres))
1934         return hres;
1935
1936     return stack_push_bool(ctx, ret);
1937 }
1938
1939 /* ECMA-262 3rd Edition    11.8.7 */
1940 static HRESULT interp_in(exec_ctx_t *ctx)
1941 {
1942     VARIANT *obj, *v;
1943     DISPID id = 0;
1944     BOOL ret;
1945     BSTR str;
1946     HRESULT hres;
1947
1948     TRACE("\n");
1949
1950     obj = stack_pop(ctx);
1951     v = stack_pop(ctx);
1952
1953     if(V_VT(obj) != VT_DISPATCH || !V_DISPATCH(obj)) {
1954         VariantClear(obj);
1955         VariantClear(v);
1956         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
1957     }
1958
1959     hres = to_string(ctx->parser->script, v, ctx->ei, &str);
1960     VariantClear(v);
1961     if(FAILED(hres)) {
1962         IDispatch_Release(V_DISPATCH(obj));
1963         return hres;
1964     }
1965
1966     hres = disp_get_id(ctx->parser->script, V_DISPATCH(obj), str, 0, &id);
1967     IDispatch_Release(V_DISPATCH(obj));
1968     SysFreeString(str);
1969     if(SUCCEEDED(hres))
1970         ret = TRUE;
1971     else if(hres == DISP_E_UNKNOWNNAME)
1972         ret = FALSE;
1973     else
1974         return hres;
1975
1976     return stack_push_bool(ctx, ret);
1977 }
1978
1979 /* ECMA-262 3rd Edition    11.6.1 */
1980 static HRESULT add_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
1981 {
1982     VARIANT r, l;
1983     HRESULT hres;
1984
1985     hres = to_primitive(ctx, lval, ei, &l, NO_HINT);
1986     if(FAILED(hres))
1987         return hres;
1988
1989     hres = to_primitive(ctx, rval, ei, &r, NO_HINT);
1990     if(FAILED(hres)) {
1991         VariantClear(&l);
1992         return hres;
1993     }
1994
1995     if(V_VT(&l) == VT_BSTR || V_VT(&r) == VT_BSTR) {
1996         BSTR lstr = NULL, rstr = NULL;
1997
1998         if(V_VT(&l) == VT_BSTR)
1999             lstr = V_BSTR(&l);
2000         else
2001             hres = to_string(ctx, &l, ei, &lstr);
2002
2003         if(SUCCEEDED(hres)) {
2004             if(V_VT(&r) == VT_BSTR)
2005                 rstr = V_BSTR(&r);
2006             else
2007                 hres = to_string(ctx, &r, ei, &rstr);
2008         }
2009
2010         if(SUCCEEDED(hres)) {
2011             int len1, len2;
2012
2013             len1 = SysStringLen(lstr);
2014             len2 = SysStringLen(rstr);
2015
2016             V_VT(retv) = VT_BSTR;
2017             V_BSTR(retv) = SysAllocStringLen(NULL, len1+len2);
2018             memcpy(V_BSTR(retv), lstr, len1*sizeof(WCHAR));
2019             memcpy(V_BSTR(retv)+len1, rstr, (len2+1)*sizeof(WCHAR));
2020         }
2021
2022         if(V_VT(&l) != VT_BSTR)
2023             SysFreeString(lstr);
2024         if(V_VT(&r) != VT_BSTR)
2025             SysFreeString(rstr);
2026     }else {
2027         VARIANT nl, nr;
2028
2029         hres = to_number(ctx, &l, ei, &nl);
2030         if(SUCCEEDED(hres)) {
2031             hres = to_number(ctx, &r, ei, &nr);
2032             if(SUCCEEDED(hres))
2033                 num_set_val(retv, num_val(&nl) + num_val(&nr));
2034         }
2035     }
2036
2037     VariantClear(&r);
2038     VariantClear(&l);
2039     return hres;
2040 }
2041
2042 /* ECMA-262 3rd Edition    11.6.1 */
2043 static HRESULT interp_add(exec_ctx_t *ctx)
2044 {
2045     VARIANT *l, *r, ret;
2046     HRESULT hres;
2047
2048     r = stack_pop(ctx);
2049     l = stack_pop(ctx);
2050
2051     TRACE("%s + %s\n", debugstr_variant(l), debugstr_variant(r));
2052
2053     hres = add_eval(ctx->parser->script, l, r, ctx->ei, &ret);
2054     VariantClear(l);
2055     VariantClear(r);
2056     if(FAILED(hres))
2057         return hres;
2058
2059     return stack_push(ctx, &ret);
2060 }
2061
2062 /* ECMA-262 3rd Edition    11.6.2 */
2063 static HRESULT interp_sub(exec_ctx_t *ctx)
2064 {
2065     VARIANT l, r;
2066     HRESULT hres;
2067
2068     TRACE("\n");
2069
2070     hres = stack_pop_number(ctx, &r);
2071     if(FAILED(hres))
2072         return hres;
2073
2074     hres = stack_pop_number(ctx, &l);
2075     if(FAILED(hres))
2076         return hres;
2077
2078     return stack_push_number(ctx, num_val(&l)-num_val(&r));
2079 }
2080
2081 /* ECMA-262 3rd Edition    11.5.1 */
2082 static HRESULT interp_mul(exec_ctx_t *ctx)
2083 {
2084     VARIANT l, r;
2085     HRESULT hres;
2086
2087     TRACE("\n");
2088
2089     hres = stack_pop_number(ctx, &r);
2090     if(FAILED(hres))
2091         return hres;
2092
2093     hres = stack_pop_number(ctx, &l);
2094     if(FAILED(hres))
2095         return hres;
2096
2097     return stack_push_number(ctx, num_val(&l)*num_val(&r));
2098 }
2099
2100 /* ECMA-262 3rd Edition    11.5.2 */
2101 static HRESULT interp_div(exec_ctx_t *ctx)
2102 {
2103     VARIANT l, r;
2104     HRESULT hres;
2105
2106     TRACE("\n");
2107
2108     hres = stack_pop_number(ctx, &r);
2109     if(FAILED(hres))
2110         return hres;
2111
2112     hres = stack_pop_number(ctx, &l);
2113     if(FAILED(hres))
2114         return hres;
2115
2116     return stack_push_number(ctx, num_val(&l)/num_val(&r));
2117 }
2118
2119 /* ECMA-262 3rd Edition    11.5.3 */
2120 static HRESULT interp_mod(exec_ctx_t *ctx)
2121 {
2122     VARIANT l, r;
2123     HRESULT hres;
2124
2125     TRACE("\n");
2126
2127     hres = stack_pop_number(ctx, &r);
2128     if(FAILED(hres))
2129         return hres;
2130
2131     hres = stack_pop_number(ctx, &l);
2132     if(FAILED(hres))
2133         return hres;
2134
2135     return stack_push_number(ctx, fmod(num_val(&l), num_val(&r)));
2136 }
2137
2138 /* ECMA-262 3rd Edition    11.4.2 */
2139 static HRESULT interp_delete(exec_ctx_t *ctx)
2140 {
2141     VARIANT *obj_var, *name_var;
2142     IDispatchEx *dispex;
2143     IDispatch *obj;
2144     BSTR name;
2145     BOOL ret;
2146     HRESULT hres;
2147
2148     TRACE("\n");
2149
2150     name_var = stack_pop(ctx);
2151     obj_var = stack_pop(ctx);
2152
2153     hres = to_object(ctx->parser->script, obj_var, &obj);
2154     VariantClear(obj_var);
2155     if(FAILED(hres)) {
2156         VariantClear(name_var);
2157         return hres;
2158     }
2159
2160     hres = to_string(ctx->parser->script, name_var, ctx->ei, &name);
2161     VariantClear(name_var);
2162     if(FAILED(hres)) {
2163         IDispatch_Release(obj);
2164         return hres;
2165     }
2166
2167     hres = IDispatch_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex);
2168     if(SUCCEEDED(hres)) {
2169         hres = IDispatchEx_DeleteMemberByName(dispex, name, make_grfdex(ctx->parser->script, fdexNameCaseSensitive));
2170         ret = TRUE;
2171         IDispatchEx_Release(dispex);
2172     }else {
2173         hres = S_OK;
2174         ret = FALSE;
2175     }
2176
2177     IDispatch_Release(obj);
2178     SysFreeString(name);
2179     if(FAILED(hres))
2180         return hres;
2181
2182     return stack_push_bool(ctx, ret);
2183 }
2184
2185 /* ECMA-262 3rd Edition    11.4.2 */
2186 static HRESULT interp_delete_ident(exec_ctx_t *ctx)
2187 {
2188     const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
2189     IDispatchEx *dispex;
2190     exprval_t exprval;
2191     BOOL ret = FALSE;
2192     HRESULT hres;
2193
2194     TRACE("%s\n", debugstr_w(arg));
2195
2196     hres = identifier_eval(ctx->parser->script, arg, 0, ctx->ei, &exprval);
2197     if(FAILED(hres))
2198         return hres;
2199
2200     if(exprval.type != EXPRVAL_IDREF) {
2201         FIXME("Unsupported exprval\n");
2202         exprval_release(&exprval);
2203         return E_NOTIMPL;
2204     }
2205
2206     hres = IDispatch_QueryInterface(exprval.u.idref.disp, &IID_IDispatchEx, (void**)&dispex);
2207     IDispatch_Release(exprval.u.idref.disp);
2208     if(SUCCEEDED(hres)) {
2209         hres = IDispatchEx_DeleteMemberByDispID(dispex, exprval.u.idref.id);
2210         IDispatchEx_Release(dispex);
2211         if(FAILED(hres))
2212             return hres;
2213
2214         ret = TRUE;
2215     }
2216
2217     return stack_push_bool(ctx, ret);
2218 }
2219
2220 /* ECMA-262 3rd Edition    11.4.2 */
2221 static HRESULT interp_void(exec_ctx_t *ctx)
2222 {
2223     VARIANT v;
2224
2225     TRACE("\n");
2226
2227     stack_popn(ctx, 1);
2228
2229     V_VT(&v) = VT_EMPTY;
2230     return stack_push(ctx, &v);
2231 }
2232
2233 /* ECMA-262 3rd Edition    11.4.3 */
2234 static HRESULT typeof_string(VARIANT *v, const WCHAR **ret)
2235 {
2236     switch(V_VT(v)) {
2237     case VT_EMPTY:
2238         *ret = undefinedW;
2239         break;
2240     case VT_NULL:
2241         *ret = objectW;
2242         break;
2243     case VT_BOOL:
2244         *ret = booleanW;
2245         break;
2246     case VT_I4:
2247     case VT_R8:
2248         *ret = numberW;
2249         break;
2250     case VT_BSTR:
2251         *ret = stringW;
2252         break;
2253     case VT_DISPATCH: {
2254         jsdisp_t *dispex;
2255
2256         if(V_DISPATCH(v) && (dispex = iface_to_jsdisp((IUnknown*)V_DISPATCH(v)))) {
2257             *ret = is_class(dispex, JSCLASS_FUNCTION) ? functionW : objectW;
2258             jsdisp_release(dispex);
2259         }else {
2260             *ret = objectW;
2261         }
2262         break;
2263     }
2264     default:
2265         FIXME("unhandled vt %d\n", V_VT(v));
2266         return E_NOTIMPL;
2267     }
2268
2269     return S_OK;
2270 }
2271
2272 /* ECMA-262 3rd Edition    11.4.3 */
2273 static HRESULT interp_typeofid(exec_ctx_t *ctx)
2274 {
2275     const WCHAR *ret;
2276     IDispatch *obj;
2277     VARIANT v;
2278     DISPID id;
2279     HRESULT hres;
2280
2281     static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
2282
2283     TRACE("\n");
2284
2285     obj = stack_pop_objid(ctx, &id);
2286     if(!obj)
2287         return stack_push_string(ctx, undefinedW);
2288
2289     V_VT(&v) = VT_EMPTY;
2290     hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
2291     IDispatch_Release(obj);
2292     if(FAILED(hres))
2293         return stack_push_string(ctx, unknownW);
2294
2295     hres = typeof_string(&v, &ret);
2296     VariantClear(&v);
2297     if(FAILED(hres))
2298         return hres;
2299
2300     return stack_push_string(ctx, ret);
2301 }
2302
2303 /* ECMA-262 3rd Edition    11.4.3 */
2304 static HRESULT interp_typeofident(exec_ctx_t *ctx)
2305 {
2306     const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
2307     exprval_t exprval;
2308     const WCHAR *ret;
2309     VARIANT v;
2310     HRESULT hres;
2311
2312     TRACE("%s\n", debugstr_w(arg));
2313
2314     hres = identifier_eval(ctx->parser->script, arg, 0, ctx->ei, &exprval);
2315     if(FAILED(hres))
2316         return hres;
2317
2318     if(exprval.type == EXPRVAL_INVALID) {
2319         hres = stack_push_string(ctx, undefinedW);
2320         exprval_release(&exprval);
2321         return hres;
2322     }
2323
2324     hres = exprval_to_value(ctx->parser->script, &exprval, ctx->ei, &v);
2325     exprval_release(&exprval);
2326     if(FAILED(hres))
2327         return hres;
2328
2329     hres = typeof_string(&v, &ret);
2330     VariantClear(&v);
2331     if(FAILED(hres))
2332         return hres;
2333
2334     return stack_push_string(ctx, ret);
2335 }
2336
2337 /* ECMA-262 3rd Edition    11.4.3 */
2338 static HRESULT interp_typeof(exec_ctx_t *ctx)
2339 {
2340     const WCHAR *ret;
2341     VARIANT *v;
2342     HRESULT hres;
2343
2344     TRACE("\n");
2345
2346     v = stack_pop(ctx);
2347     hres = typeof_string(v, &ret);
2348     VariantClear(v);
2349     if(FAILED(hres))
2350         return hres;
2351
2352     return stack_push_string(ctx, ret);
2353 }
2354
2355 /* ECMA-262 3rd Edition    11.4.7 */
2356 static HRESULT interp_minus(exec_ctx_t *ctx)
2357 {
2358     VARIANT n;
2359     HRESULT hres;
2360
2361     TRACE("\n");
2362
2363     hres = stack_pop_number(ctx, &n);
2364     if(FAILED(hres))
2365         return hres;
2366
2367     return stack_push_number(ctx, -num_val(&n));
2368 }
2369
2370 /* ECMA-262 3rd Edition    11.4.6 */
2371 static HRESULT interp_tonum(exec_ctx_t *ctx)
2372 {
2373     VARIANT *v, num;
2374     HRESULT hres;
2375
2376     TRACE("\n");
2377
2378     v = stack_pop(ctx);
2379     hres = to_number(ctx->parser->script, v, ctx->ei, &num);
2380     VariantClear(v);
2381     if(FAILED(hres))
2382         return hres;
2383
2384     return stack_push(ctx, &num);
2385 }
2386
2387 /* ECMA-262 3rd Edition    11.3.1 */
2388 static HRESULT interp_postinc(exec_ctx_t *ctx)
2389 {
2390     const int arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
2391     IDispatch *obj;
2392     DISPID id;
2393     VARIANT v;
2394     HRESULT hres;
2395
2396     TRACE("%d\n", arg);
2397
2398     obj = stack_pop_objid(ctx, &id);
2399     if(!obj)
2400         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
2401
2402     hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
2403     if(SUCCEEDED(hres)) {
2404         VARIANT n, inc;
2405
2406         hres = to_number(ctx->parser->script, &v, ctx->ei, &n);
2407         if(SUCCEEDED(hres)) {
2408             num_set_val(&inc, num_val(&n)+(double)arg);
2409             hres = disp_propput(ctx->parser->script, obj, id, &inc, ctx->ei, NULL/*FIXME*/);
2410         }
2411         if(FAILED(hres))
2412             VariantClear(&v);
2413     }
2414     IDispatch_Release(obj);
2415     if(FAILED(hres))
2416         return hres;
2417
2418     return stack_push(ctx, &v);
2419 }
2420
2421 /* ECMA-262 3rd Edition    11.4.4, 11.4.5 */
2422 static HRESULT interp_preinc(exec_ctx_t *ctx)
2423 {
2424     const int arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
2425     IDispatch *obj;
2426     DISPID id;
2427     VARIANT v;
2428     HRESULT hres;
2429
2430     TRACE("%d\n", arg);
2431
2432     obj = stack_pop_objid(ctx, &id);
2433     if(!obj)
2434         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
2435
2436     hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
2437     if(SUCCEEDED(hres)) {
2438         VARIANT n;
2439
2440         hres = to_number(ctx->parser->script, &v, ctx->ei, &n);
2441         VariantClear(&v);
2442         if(SUCCEEDED(hres)) {
2443             num_set_val(&v, num_val(&n)+(double)arg);
2444             hres = disp_propput(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
2445         }
2446     }
2447     IDispatch_Release(obj);
2448     if(FAILED(hres))
2449         return hres;
2450
2451     return stack_push(ctx, &v);
2452 }
2453
2454 /* ECMA-262 3rd Edition    11.9.3 */
2455 static HRESULT equal_values(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, BOOL *ret)
2456 {
2457     if(V_VT(lval) == V_VT(rval) || (is_num_vt(V_VT(lval)) && is_num_vt(V_VT(rval))))
2458        return equal2_values(lval, rval, ret);
2459
2460     /* FIXME: NULL disps should be handled in more general way */
2461     if(V_VT(lval) == VT_DISPATCH && !V_DISPATCH(lval)) {
2462         VARIANT v;
2463         V_VT(&v) = VT_NULL;
2464         return equal_values(ctx, &v, rval, ei, ret);
2465     }
2466
2467     if(V_VT(rval) == VT_DISPATCH && !V_DISPATCH(rval)) {
2468         VARIANT v;
2469         V_VT(&v) = VT_NULL;
2470         return equal_values(ctx, lval, &v, ei, ret);
2471     }
2472
2473     if((V_VT(lval) == VT_NULL && V_VT(rval) == VT_EMPTY) ||
2474        (V_VT(lval) == VT_EMPTY && V_VT(rval) == VT_NULL)) {
2475         *ret = TRUE;
2476         return S_OK;
2477     }
2478
2479     if(V_VT(lval) == VT_BSTR && is_num_vt(V_VT(rval))) {
2480         VARIANT v;
2481         HRESULT hres;
2482
2483         hres = to_number(ctx, lval, ei, &v);
2484         if(FAILED(hres))
2485             return hres;
2486
2487         return equal_values(ctx, &v, rval, ei, ret);
2488     }
2489
2490     if(V_VT(rval) == VT_BSTR && is_num_vt(V_VT(lval))) {
2491         VARIANT v;
2492         HRESULT hres;
2493
2494         hres = to_number(ctx, rval, ei, &v);
2495         if(FAILED(hres))
2496             return hres;
2497
2498         return equal_values(ctx, lval, &v, ei, ret);
2499     }
2500
2501     if(V_VT(rval) == VT_BOOL) {
2502         VARIANT v;
2503
2504         V_VT(&v) = VT_I4;
2505         V_I4(&v) = V_BOOL(rval) ? 1 : 0;
2506         return equal_values(ctx, lval, &v, ei, ret);
2507     }
2508
2509     if(V_VT(lval) == VT_BOOL) {
2510         VARIANT v;
2511
2512         V_VT(&v) = VT_I4;
2513         V_I4(&v) = V_BOOL(lval) ? 1 : 0;
2514         return equal_values(ctx, &v, rval, ei, ret);
2515     }
2516
2517
2518     if(V_VT(rval) == VT_DISPATCH && (V_VT(lval) == VT_BSTR || is_num_vt(V_VT(lval)))) {
2519         VARIANT v;
2520         HRESULT hres;
2521
2522         hres = to_primitive(ctx, rval, ei, &v, NO_HINT);
2523         if(FAILED(hres))
2524             return hres;
2525
2526         hres = equal_values(ctx, lval, &v, ei, ret);
2527
2528         VariantClear(&v);
2529         return hres;
2530     }
2531
2532
2533     if(V_VT(lval) == VT_DISPATCH && (V_VT(rval) == VT_BSTR || is_num_vt(V_VT(rval)))) {
2534         VARIANT v;
2535         HRESULT hres;
2536
2537         hres = to_primitive(ctx, lval, ei, &v, NO_HINT);
2538         if(FAILED(hres))
2539             return hres;
2540
2541         hres = equal_values(ctx, &v, rval, ei, ret);
2542
2543         VariantClear(&v);
2544         return hres;
2545     }
2546
2547
2548     *ret = FALSE;
2549     return S_OK;
2550 }
2551
2552 /* ECMA-262 3rd Edition    11.9.1 */
2553 static HRESULT interp_eq(exec_ctx_t *ctx)
2554 {
2555     VARIANT *l, *r;
2556     BOOL b;
2557     HRESULT hres;
2558
2559     r = stack_pop(ctx);
2560     l = stack_pop(ctx);
2561
2562     TRACE("%s == %s\n", debugstr_variant(l), debugstr_variant(r));
2563
2564     hres = equal_values(ctx->parser->script, l, r, ctx->ei, &b);
2565     VariantClear(l);
2566     VariantClear(r);
2567     if(FAILED(hres))
2568         return hres;
2569
2570     return stack_push_bool(ctx, b);
2571 }
2572
2573 /* ECMA-262 3rd Edition    11.9.2 */
2574 static HRESULT interp_neq(exec_ctx_t *ctx)
2575 {
2576     VARIANT *l, *r;
2577     BOOL b;
2578     HRESULT hres;
2579
2580     r = stack_pop(ctx);
2581     l = stack_pop(ctx);
2582
2583     TRACE("%s != %s\n", debugstr_variant(l), debugstr_variant(r));
2584
2585     hres = equal_values(ctx->parser->script, l, r, ctx->ei, &b);
2586     VariantClear(l);
2587     VariantClear(r);
2588     if(FAILED(hres))
2589         return hres;
2590
2591     return stack_push_bool(ctx, !b);
2592 }
2593
2594 /* ECMA-262 3rd Edition    11.9.4 */
2595 static HRESULT interp_eq2(exec_ctx_t *ctx)
2596 {
2597     VARIANT *l, *r;
2598     BOOL b;
2599     HRESULT hres;
2600
2601     TRACE("\n");
2602
2603     r = stack_pop(ctx);
2604     l = stack_pop(ctx);
2605
2606     hres = equal2_values(r, l, &b);
2607     VariantClear(l);
2608     VariantClear(r);
2609     if(FAILED(hres))
2610         return hres;
2611
2612     return stack_push_bool(ctx, b);
2613 }
2614
2615 /* ECMA-262 3rd Edition    11.9.5 */
2616 static HRESULT interp_neq2(exec_ctx_t *ctx)
2617 {
2618     VARIANT *l, *r;
2619     BOOL b;
2620     HRESULT hres;
2621
2622     TRACE("\n");
2623
2624     r = stack_pop(ctx);
2625     l = stack_pop(ctx);
2626
2627     hres = equal2_values(r, l, &b);
2628     VariantClear(l);
2629     VariantClear(r);
2630     if(FAILED(hres))
2631         return hres;
2632
2633     return stack_push_bool(ctx, !b);
2634 }
2635
2636 /* ECMA-262 3rd Edition    11.8.5 */
2637 static HRESULT less_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, BOOL greater, jsexcept_t *ei, BOOL *ret)
2638 {
2639     VARIANT l, r, ln, rn;
2640     HRESULT hres;
2641
2642     hres = to_primitive(ctx, lval, ei, &l, NO_HINT);
2643     if(FAILED(hres))
2644         return hres;
2645
2646     hres = to_primitive(ctx, rval, ei, &r, NO_HINT);
2647     if(FAILED(hres)) {
2648         VariantClear(&l);
2649         return hres;
2650     }
2651
2652     if(V_VT(&l) == VT_BSTR && V_VT(&r) == VT_BSTR) {
2653         *ret = (strcmpW(V_BSTR(&l), V_BSTR(&r)) < 0) ^ greater;
2654         SysFreeString(V_BSTR(&l));
2655         SysFreeString(V_BSTR(&r));
2656         return S_OK;
2657     }
2658
2659     hres = to_number(ctx, &l, ei, &ln);
2660     VariantClear(&l);
2661     if(SUCCEEDED(hres))
2662         hres = to_number(ctx, &r, ei, &rn);
2663     VariantClear(&r);
2664     if(FAILED(hres))
2665         return hres;
2666
2667     if(V_VT(&ln) == VT_I4 && V_VT(&rn) == VT_I4) {
2668         *ret = (V_I4(&ln) < V_I4(&rn)) ^ greater;
2669     }else  {
2670         DOUBLE ld = num_val(&ln);
2671         DOUBLE rd = num_val(&rn);
2672
2673         *ret = !isnan(ld) && !isnan(rd) && ((ld < rd) ^ greater);
2674     }
2675
2676     return S_OK;
2677 }
2678
2679 /* ECMA-262 3rd Edition    11.8.1 */
2680 static HRESULT interp_lt(exec_ctx_t *ctx)
2681 {
2682     VARIANT *l, *r;
2683     BOOL b;
2684     HRESULT hres;
2685
2686     r = stack_pop(ctx);
2687     l = stack_pop(ctx);
2688
2689     TRACE("%s < %s\n", debugstr_variant(l), debugstr_variant(r));
2690
2691     hres = less_eval(ctx->parser->script, l, r, FALSE, ctx->ei, &b);
2692     VariantClear(l);
2693     VariantClear(r);
2694     if(FAILED(hres))
2695         return hres;
2696
2697     return stack_push_bool(ctx, b);
2698 }
2699
2700 /* ECMA-262 3rd Edition    11.8.1 */
2701 static HRESULT interp_lteq(exec_ctx_t *ctx)
2702 {
2703     VARIANT *l, *r;
2704     BOOL b;
2705     HRESULT hres;
2706
2707     r = stack_pop(ctx);
2708     l = stack_pop(ctx);
2709
2710     TRACE("%s <= %s\n", debugstr_variant(l), debugstr_variant(r));
2711
2712     hres = less_eval(ctx->parser->script, r, l, TRUE, ctx->ei, &b);
2713     VariantClear(l);
2714     VariantClear(r);
2715     if(FAILED(hres))
2716         return hres;
2717
2718     return stack_push_bool(ctx, b);
2719 }
2720
2721 /* ECMA-262 3rd Edition    11.8.2 */
2722 static HRESULT interp_gt(exec_ctx_t *ctx)
2723 {
2724     VARIANT *l, *r;
2725     BOOL b;
2726     HRESULT hres;
2727
2728     r = stack_pop(ctx);
2729     l = stack_pop(ctx);
2730
2731     TRACE("%s > %s\n", debugstr_variant(l), debugstr_variant(r));
2732
2733     hres = less_eval(ctx->parser->script, r, l, FALSE, ctx->ei, &b);
2734     VariantClear(l);
2735     VariantClear(r);
2736     if(FAILED(hres))
2737         return hres;
2738
2739     return stack_push_bool(ctx, b);
2740 }
2741
2742 /* ECMA-262 3rd Edition    11.8.4 */
2743 static HRESULT interp_gteq(exec_ctx_t *ctx)
2744 {
2745     VARIANT *l, *r;
2746     BOOL b;
2747     HRESULT hres;
2748
2749     r = stack_pop(ctx);
2750     l = stack_pop(ctx);
2751
2752     TRACE("%s >= %s\n", debugstr_variant(l), debugstr_variant(r));
2753
2754     hres = less_eval(ctx->parser->script, l, r, TRUE, ctx->ei, &b);
2755     VariantClear(l);
2756     VariantClear(r);
2757     if(FAILED(hres))
2758         return hres;
2759
2760     return stack_push_bool(ctx, b);
2761 }
2762
2763 /* ECMA-262 3rd Edition    11.4.8 */
2764 static HRESULT interp_bneg(exec_ctx_t *ctx)
2765 {
2766     VARIANT *v, r;
2767     INT i;
2768     HRESULT hres;
2769
2770     TRACE("\n");
2771
2772     v = stack_pop(ctx);
2773     hres = to_int32(ctx->parser->script, v, ctx->ei, &i);
2774     VariantClear(v);
2775     if(FAILED(hres))
2776         return hres;
2777
2778     V_VT(&r) = VT_I4;
2779     V_I4(&r) = ~i;
2780     return stack_push(ctx, &r);
2781 }
2782
2783 /* ECMA-262 3rd Edition    11.4.9 */
2784 static HRESULT interp_neg(exec_ctx_t *ctx)
2785 {
2786     VARIANT *v;
2787     VARIANT_BOOL b;
2788     HRESULT hres;
2789
2790     TRACE("\n");
2791
2792     v = stack_pop(ctx);
2793     hres = to_boolean(v, &b);
2794     VariantClear(v);
2795     if(FAILED(hres))
2796         return hres;
2797
2798     return stack_push_bool(ctx, !b);
2799 }
2800
2801 /* ECMA-262 3rd Edition    11.7.1 */
2802 static HRESULT interp_lshift(exec_ctx_t *ctx)
2803 {
2804     DWORD r;
2805     INT l;
2806     HRESULT hres;
2807
2808     hres = stack_pop_uint(ctx, &r);
2809     if(FAILED(hres))
2810         return hres;
2811
2812     hres = stack_pop_int(ctx, &l);
2813     if(FAILED(hres))
2814         return hres;
2815
2816     return stack_push_int(ctx, l << (r&0x1f));
2817 }
2818
2819 /* ECMA-262 3rd Edition    11.7.2 */
2820 static HRESULT interp_rshift(exec_ctx_t *ctx)
2821 {
2822     DWORD r;
2823     INT l;
2824     HRESULT hres;
2825
2826     hres = stack_pop_uint(ctx, &r);
2827     if(FAILED(hres))
2828         return hres;
2829
2830     hres = stack_pop_int(ctx, &l);
2831     if(FAILED(hres))
2832         return hres;
2833
2834     return stack_push_int(ctx, l >> (r&0x1f));
2835 }
2836
2837 /* ECMA-262 3rd Edition    11.7.3 */
2838 static HRESULT interp_rshift2(exec_ctx_t *ctx)
2839 {
2840     DWORD r, l;
2841     HRESULT hres;
2842
2843     hres = stack_pop_uint(ctx, &r);
2844     if(FAILED(hres))
2845         return hres;
2846
2847     hres = stack_pop_uint(ctx, &l);
2848     if(FAILED(hres))
2849         return hres;
2850
2851     return stack_push_int(ctx, l >> (r&0x1f));
2852 }
2853
2854 /* ECMA-262 3rd Edition    11.13.1 */
2855 static HRESULT interp_assign(exec_ctx_t *ctx)
2856 {
2857     IDispatch *disp;
2858     DISPID id;
2859     VARIANT *v;
2860     HRESULT hres;
2861
2862     TRACE("\n");
2863
2864     v = stack_pop(ctx);
2865     disp = stack_pop_objid(ctx, &id);
2866
2867     if(!disp)
2868         return throw_reference_error(ctx->parser->script, ctx->ei, JS_E_ILLEGAL_ASSIGN, NULL);
2869
2870     hres = disp_propput(ctx->parser->script, disp, id, v, ctx->ei, NULL/*FIXME*/);
2871     IDispatch_Release(disp);
2872     if(FAILED(hres)) {
2873         VariantClear(v);
2874         return hres;
2875     }
2876
2877     return stack_push(ctx, v);
2878 }
2879
2880 static HRESULT interp_undefined(exec_ctx_t *ctx)
2881 {
2882     VARIANT v;
2883
2884     TRACE("\n");
2885
2886     V_VT(&v) = VT_EMPTY;
2887     return stack_push(ctx, &v);
2888 }
2889
2890 static HRESULT interp_jmp(exec_ctx_t *ctx)
2891 {
2892     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
2893
2894     TRACE("\n");
2895
2896     ctx->ip = arg;
2897     return S_OK;
2898 }
2899
2900 static HRESULT interp_pop(exec_ctx_t *ctx)
2901 {
2902     TRACE("\n");
2903
2904     stack_popn(ctx, 1);
2905     return S_OK;
2906 }
2907
2908 static HRESULT interp_ret(exec_ctx_t *ctx)
2909 {
2910     TRACE("\n");
2911
2912     ctx->ip = -1;
2913     return S_OK;
2914 }
2915
2916 static HRESULT interp_tree(exec_ctx_t *ctx)
2917 {
2918     instr_t *instr = ctx->parser->code->instrs+ctx->ip;
2919     VARIANT v;
2920     HRESULT hres;
2921
2922     TRACE("\n");
2923
2924     hres = stat_eval(ctx->parser->script, instr->arg1.stat, ctx->rt, &v);
2925     if(FAILED(hres))
2926         return hres;
2927
2928     return stack_push(ctx, &v);
2929 }
2930
2931 typedef HRESULT (*op_func_t)(exec_ctx_t*);
2932
2933 static const op_func_t op_funcs[] = {
2934 #define X(x,a,b,c) interp_##x,
2935 OP_LIST
2936 #undef X
2937 };
2938
2939 static const unsigned op_move[] = {
2940 #define X(a,x,b,c) x,
2941 OP_LIST
2942 #undef X
2943 };
2944
2945 HRESULT compiled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
2946 {
2947     exec_ctx_t *exec_ctx = ctx->exec_ctx;
2948     unsigned prev_ip, prev_top;
2949     return_type_t *prev_rt;
2950     jsexcept_t *prev_ei;
2951     jsop_t op;
2952     HRESULT hres = S_OK;
2953
2954     TRACE("\n");
2955
2956     if(stat->instr_off == -1) {
2957         hres = compile_subscript_stat(exec_ctx->parser, stat, FALSE, &stat->instr_off);
2958         if(FAILED(hres))
2959             return hres;
2960     }
2961
2962     prev_rt = exec_ctx->rt;
2963     prev_top = exec_ctx->top;
2964     prev_ip = exec_ctx->ip;
2965     prev_ei = exec_ctx->ei;
2966     exec_ctx->ip = stat->instr_off;
2967     exec_ctx->rt = rt;
2968     exec_ctx->ei = &rt->ei;
2969
2970     while(exec_ctx->ip != -1 && exec_ctx->rt->type == RT_NORMAL) {
2971         op = exec_ctx->parser->code->instrs[exec_ctx->ip].op;
2972         hres = op_funcs[op](exec_ctx);
2973         if(FAILED(hres))
2974             break;
2975         exec_ctx->ip += op_move[op];
2976     }
2977
2978     exec_ctx->rt = prev_rt;
2979     exec_ctx->ip = prev_ip;
2980     exec_ctx->ei = prev_ei;
2981
2982     if(FAILED(hres)) {
2983         stack_popn(exec_ctx, exec_ctx->top-prev_top);
2984         return hres;
2985     }
2986
2987     assert(exec_ctx->top == prev_top+1 || exec_ctx->top == prev_top);
2988
2989     if(exec_ctx->top == prev_top)
2990         V_VT(ret) = VT_EMPTY;
2991     else
2992         *ret = *stack_pop(exec_ctx);
2993     return S_OK;
2994 }
2995
2996 static HRESULT expr_eval(script_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, VARIANT *ret)
2997 {
2998     exec_ctx_t *exec_ctx = ctx->exec_ctx;
2999     unsigned prev_ip, prev_top;
3000     jsexcept_t *prev_ei;
3001     jsop_t op;
3002     HRESULT hres = S_OK;
3003
3004     TRACE("\n");
3005
3006     if(expr->instr_off == -1) {
3007         hres = compile_subscript(ctx->exec_ctx->parser, expr, !(flags & EXPR_NOVAL), &expr->instr_off);
3008         if(FAILED(hres))
3009             return hres;
3010     }
3011
3012     prev_top = exec_ctx->top;
3013     prev_ip = exec_ctx->ip;
3014     prev_ei = exec_ctx->ei;
3015     exec_ctx->ip = expr->instr_off;
3016     exec_ctx->ei = ei;
3017
3018     while(exec_ctx->ip != -1) {
3019         op = exec_ctx->parser->code->instrs[exec_ctx->ip].op;
3020         hres = op_funcs[op](exec_ctx);
3021         if(FAILED(hres))
3022             break;
3023         exec_ctx->ip += op_move[op];
3024     }
3025
3026     exec_ctx->ip = prev_ip;
3027     exec_ctx->ei = prev_ei;
3028
3029     if(FAILED(hres)) {
3030         stack_popn(exec_ctx, exec_ctx->top-prev_top);
3031         return hres;
3032     }
3033
3034     assert(exec_ctx->top == prev_top+1 || ((flags&EXPR_NOVAL) && exec_ctx->top == prev_top));
3035
3036     if(exec_ctx->top == prev_top)
3037         V_VT(ret) = VT_EMPTY;
3038     else
3039         *ret = *stack_pop(exec_ctx);
3040     return S_OK;
3041 }