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