jscript: Added bytecode version of try 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 with_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1072 {
1073     with_statement_t *stat = (with_statement_t*)_stat;
1074     IDispatch *disp;
1075     jsdisp_t *obj;
1076     VARIANT val;
1077     HRESULT hres;
1078
1079     TRACE("\n");
1080
1081     hres = expr_eval(ctx, stat->expr, &rt->ei, &val);
1082     if(FAILED(hres))
1083         return hres;
1084
1085     hres = to_object(ctx, &val, &disp);
1086     VariantClear(&val);
1087     if(FAILED(hres))
1088         return hres;
1089
1090     obj = iface_to_jsdisp((IUnknown*)disp);
1091     IDispatch_Release(disp);
1092     if(!obj) {
1093         FIXME("disp id not jsdisp\n");
1094         return E_NOTIMPL;
1095     }
1096
1097     hres = scope_push(ctx->exec_ctx->scope_chain, obj, &ctx->exec_ctx->scope_chain);
1098     jsdisp_release(obj);
1099     if(FAILED(hres))
1100         return hres;
1101
1102     hres = stat_eval(ctx, stat->statement, rt, ret);
1103
1104     scope_pop(&ctx->exec_ctx->scope_chain);
1105     return hres;
1106 }
1107
1108 /* ECMA-262 3rd Edition    12.10 */
1109 HRESULT interp_push_scope(exec_ctx_t *ctx)
1110 {
1111     IDispatch *disp;
1112     jsdisp_t *obj;
1113     VARIANT *v;
1114     HRESULT hres;
1115
1116     TRACE("\n");
1117
1118     v = stack_pop(ctx);
1119     hres = to_object(ctx->parser->script, v, &disp);
1120     VariantClear(v);
1121     if(FAILED(hres))
1122         return hres;
1123
1124     obj = to_jsdisp(disp);
1125     if(!obj) {
1126         IDispatch_Release(disp);
1127         FIXME("disp is not jsdisp\n");
1128         return E_NOTIMPL;
1129     }
1130
1131     hres = scope_push(ctx->scope_chain, obj, &ctx->scope_chain);
1132     jsdisp_release(obj);
1133     return hres;
1134 }
1135
1136 /* ECMA-262 3rd Edition    12.10 */
1137 HRESULT interp_pop_scope(exec_ctx_t *ctx)
1138 {
1139     TRACE("\n");
1140
1141     scope_pop(&ctx->scope_chain);
1142     return S_OK;
1143 }
1144
1145 /* ECMA-262 3rd Edition    12.12 */
1146 HRESULT interp_label(exec_ctx_t *ctx)
1147 {
1148     FIXME("\n");
1149     return E_NOTIMPL;
1150 }
1151
1152 /* ECMA-262 3rd Edition    12.13 */
1153 static HRESULT interp_case(exec_ctx_t *ctx)
1154 {
1155     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1156     VARIANT *v;
1157     BOOL b;
1158     HRESULT hres;
1159
1160     TRACE("\n");
1161
1162     v = stack_pop(ctx);
1163     hres = equal2_values(stack_top(ctx), v, &b);
1164     VariantClear(v);
1165     if(FAILED(hres))
1166         return hres;
1167
1168     if(b) {
1169         stack_popn(ctx, 1);
1170         ctx->ip = arg;
1171     }else {
1172         ctx->ip++;
1173     }
1174     return S_OK;
1175 }
1176
1177 /* ECMA-262 3rd Edition    12.13 */
1178 HRESULT switch_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1179 {
1180     switch_statement_t *stat = (switch_statement_t*)_stat;
1181     case_clausule_t *iter, *default_clausule = NULL;
1182     statement_t *stat_iter;
1183     VARIANT val, cval;
1184     BOOL b;
1185     HRESULT hres;
1186
1187     TRACE("\n");
1188
1189     hres = expr_eval(ctx, stat->expr, &rt->ei, &val);
1190     if(FAILED(hres))
1191         return hres;
1192
1193     for(iter = stat->case_list; iter; iter = iter->next) {
1194         if(!iter->expr) {
1195             default_clausule = iter;
1196             continue;
1197         }
1198
1199         hres = expr_eval(ctx, iter->expr, &rt->ei, &cval);
1200         if(FAILED(hres))
1201             break;
1202
1203         hres = equal2_values(&val, &cval, &b);
1204         VariantClear(&cval);
1205         if(FAILED(hres) || b)
1206             break;
1207     }
1208
1209     VariantClear(&val);
1210     if(FAILED(hres))
1211         return hres;
1212
1213     if(!iter)
1214         iter = default_clausule;
1215
1216     V_VT(&val) = VT_EMPTY;
1217     if(iter) {
1218         VARIANT tmp;
1219
1220         for(stat_iter = iter->stat; stat_iter; stat_iter = stat_iter->next) {
1221             hres = stat_eval(ctx, stat_iter, rt, &tmp);
1222             if(FAILED(hres))
1223                 break;
1224
1225             VariantClear(&val);
1226             val = tmp;
1227
1228             if(rt->type != RT_NORMAL)
1229                 break;
1230         }
1231     }
1232
1233     if(FAILED(hres)) {
1234         VariantClear(&val);
1235         return hres;
1236     }
1237
1238     if(rt->type == RT_BREAK)
1239         rt->type = RT_NORMAL;
1240
1241     *ret = val;
1242     return S_OK;
1243 }
1244
1245 /* ECMA-262 3rd Edition    12.13 */
1246 static HRESULT interp_throw(exec_ctx_t *ctx)
1247 {
1248     TRACE("\n");
1249
1250     ctx->rt->ei.var = *stack_pop(ctx);
1251     return DISP_E_EXCEPTION;
1252 }
1253
1254 static HRESULT interp_throw_ref(exec_ctx_t *ctx)
1255 {
1256     const HRESULT arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1257
1258     TRACE("%08x\n", arg);
1259
1260     return throw_reference_error(ctx->parser->script, ctx->ei, arg, NULL);
1261 }
1262
1263 static HRESULT interp_throw_type(exec_ctx_t *ctx)
1264 {
1265     const HRESULT hres = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1266     const WCHAR *str = ctx->parser->code->instrs[ctx->ip].arg2.str;
1267
1268     TRACE("%08x %s\n", hres, debugstr_w(str));
1269
1270     return throw_type_error(ctx->parser->script, ctx->ei, hres, str);
1271 }
1272
1273 /* ECMA-262 3rd Edition    12.14 */
1274 static HRESULT catch_eval(script_ctx_t *ctx, catch_block_t *block, return_type_t *rt, VARIANT *ret)
1275 {
1276     jsdisp_t *var_disp;
1277     VARIANT ex, val;
1278     HRESULT hres;
1279
1280     ex = rt->ei.var;
1281     memset(&rt->ei, 0, sizeof(jsexcept_t));
1282
1283     hres = create_dispex(ctx, NULL, NULL, &var_disp);
1284     if(SUCCEEDED(hres)) {
1285         hres = jsdisp_propput_name(var_disp, block->identifier, &ex, &rt->ei, NULL/*FIXME*/);
1286         if(SUCCEEDED(hres)) {
1287             hres = scope_push(ctx->exec_ctx->scope_chain, var_disp, &ctx->exec_ctx->scope_chain);
1288             if(SUCCEEDED(hres)) {
1289                 hres = stat_eval(ctx, block->statement, rt, &val);
1290                 scope_pop(&ctx->exec_ctx->scope_chain);
1291             }
1292         }
1293
1294         jsdisp_release(var_disp);
1295     }
1296
1297     VariantClear(&ex);
1298     if(FAILED(hres))
1299         return hres;
1300
1301     *ret = val;
1302     return S_OK;
1303 }
1304
1305 /* ECMA-262 3rd Edition    12.14 */
1306 HRESULT try_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1307 {
1308     try_statement_t *stat = (try_statement_t*)_stat;
1309     VARIANT val;
1310     HRESULT hres;
1311
1312     TRACE("\n");
1313
1314     hres = stat_eval(ctx, stat->try_statement, rt, &val);
1315     if(FAILED(hres)) {
1316         TRACE("EXCEPTION\n");
1317         if(!stat->catch_block)
1318             return hres;
1319
1320         hres = catch_eval(ctx, stat->catch_block, rt, &val);
1321         if(FAILED(hres))
1322             return hres;
1323     }
1324
1325     if(stat->finally_statement) {
1326         VariantClear(&val);
1327         hres = stat_eval(ctx, stat->finally_statement, rt, &val);
1328         if(FAILED(hres))
1329             return hres;
1330     }
1331
1332     *ret = val;
1333     return S_OK;
1334 }
1335
1336 /* ECMA-262 3rd Edition    12.14 */
1337 static HRESULT interp_push_except(exec_ctx_t *ctx)
1338 {
1339     const unsigned arg1 = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1340     const BSTR arg2 = ctx->parser->code->instrs[ctx->ip].arg2.bstr;
1341     except_frame_t *except;
1342     unsigned stack_top;
1343
1344     TRACE("\n");
1345
1346     stack_top = ctx->top;
1347
1348     if(!arg2) {
1349         HRESULT hres;
1350
1351         hres = stack_push_bool(ctx, TRUE);
1352         if(FAILED(hres))
1353             return hres;
1354     }
1355
1356     except = heap_alloc(sizeof(*except));
1357     if(!except)
1358         return E_OUTOFMEMORY;
1359
1360     except->stack_top = stack_top;
1361     except->scope = ctx->scope_chain;
1362     except->catch_off = arg1;
1363     except->ident = arg2;
1364     except->next = ctx->except_frame;
1365     ctx->except_frame = except;
1366     return S_OK;
1367 }
1368
1369 /* ECMA-262 3rd Edition    12.14 */
1370 static HRESULT interp_pop_except(exec_ctx_t *ctx)
1371 {
1372     except_frame_t *except;
1373
1374     TRACE("\n");
1375
1376     except = ctx->except_frame;
1377     assert(except != NULL);
1378
1379     ctx->except_frame = except->next;
1380     heap_free(except);
1381     return S_OK;
1382 }
1383
1384 /* ECMA-262 3rd Edition    12.14 */
1385 static HRESULT interp_end_finally(exec_ctx_t *ctx)
1386 {
1387     VARIANT *v;
1388
1389     TRACE("\n");
1390
1391     v = stack_pop(ctx);
1392
1393     assert(V_VT(stack_top(ctx)) == VT_BOOL);
1394     if(!V_BOOL(stack_top(ctx))) {
1395         TRACE("passing exception\n");
1396
1397         VariantClear(v);
1398         stack_popn(ctx, 1);
1399         ctx->rt->ei.var = *stack_pop(ctx);
1400         return DISP_E_EXCEPTION;
1401     }
1402
1403     *stack_top(ctx) = *v;
1404     return S_OK;
1405 }
1406
1407 /* ECMA-262 3rd Edition    13 */
1408 static HRESULT interp_func(exec_ctx_t *ctx)
1409 {
1410     function_expression_t *expr = ctx->parser->code->instrs[ctx->ip].arg1.func;
1411     jsdisp_t *dispex;
1412     VARIANT v;
1413     HRESULT hres;
1414
1415     TRACE("\n");
1416
1417     hres = create_source_function(ctx->parser, expr->parameter_list, expr->source_elements, ctx->scope_chain,
1418             expr->src_str, expr->src_len, &dispex);
1419     if(FAILED(hres))
1420         return hres;
1421
1422     var_set_jsdisp(&v, dispex);
1423     return stack_push(ctx, &v);
1424 }
1425
1426 /* ECMA-262 3rd Edition    11.2.1 */
1427 static HRESULT array_expression_eval(script_ctx_t *ctx, expression_t *_expr, jsexcept_t *ei, exprval_t *ret)
1428 {
1429     binary_expression_t *expr = (binary_expression_t*)_expr;
1430     VARIANT member, val;
1431     DISPID id;
1432     BSTR str;
1433     IDispatch *obj = NULL;
1434     HRESULT hres;
1435
1436     TRACE("\n");
1437
1438     hres = expr_eval(ctx, expr->expression1, ei, &member);
1439     if(FAILED(hres))
1440         return hres;
1441
1442     hres = expr_eval(ctx, expr->expression2, ei, &val);
1443     if(SUCCEEDED(hres)) {
1444         hres = to_object(ctx, &member, &obj);
1445         if(FAILED(hres))
1446             VariantClear(&val);
1447     }
1448     VariantClear(&member);
1449     if(SUCCEEDED(hres)) {
1450         hres = to_string(ctx, &val, ei, &str);
1451         VariantClear(&val);
1452         if(SUCCEEDED(hres)) {
1453             hres = disp_get_id(ctx, obj, str, fdexNameEnsure, &id);
1454             SysFreeString(str);
1455         }
1456
1457         if(SUCCEEDED(hres))
1458             exprval_set_idref(ret, obj, id);
1459
1460         IDispatch_Release(obj);
1461     }
1462
1463     return hres;
1464 }
1465
1466 /* ECMA-262 3rd Edition    11.2.1 */
1467 static HRESULT interp_array(exec_ctx_t *ctx)
1468 {
1469     VARIANT v, *namev;
1470     IDispatch *obj;
1471     DISPID id;
1472     BSTR name;
1473     HRESULT hres;
1474
1475     TRACE("\n");
1476
1477     namev = stack_pop(ctx);
1478
1479     hres = stack_pop_object(ctx, &obj);
1480     if(FAILED(hres)) {
1481         VariantClear(namev);
1482         return hres;
1483     }
1484
1485     hres = to_string(ctx->parser->script, namev, ctx->ei, &name);
1486     VariantClear(namev);
1487     if(FAILED(hres)) {
1488         IDispatch_Release(obj);
1489         return hres;
1490     }
1491
1492     hres = disp_get_id(ctx->parser->script, obj, name, 0, &id);
1493     SysFreeString(name);
1494     if(SUCCEEDED(hres)) {
1495         hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
1496     }else if(hres == DISP_E_UNKNOWNNAME) {
1497         V_VT(&v) = VT_EMPTY;
1498         hres = S_OK;
1499     }
1500     IDispatch_Release(obj);
1501     if(FAILED(hres))
1502         return hres;
1503
1504     return stack_push(ctx, &v);
1505 }
1506
1507 /* ECMA-262 3rd Edition    11.2.1 */
1508 static HRESULT member_expression_eval(script_ctx_t *ctx, expression_t *_expr, jsexcept_t *ei, exprval_t *ret)
1509 {
1510     member_expression_t *expr = (member_expression_t*)_expr;
1511     IDispatch *obj = NULL;
1512     VARIANT member;
1513     DISPID id;
1514     BSTR str;
1515     HRESULT hres;
1516
1517     TRACE("\n");
1518
1519     hres = expr_eval(ctx, expr->expression, ei, &member);
1520     if(FAILED(hres))
1521         return hres;
1522
1523     hres = to_object(ctx, &member, &obj);
1524     VariantClear(&member);
1525     if(FAILED(hres))
1526         return hres;
1527
1528     str = SysAllocString(expr->identifier);
1529     if(!str) {
1530         IDispatch_Release(obj);
1531         return E_OUTOFMEMORY;
1532     }
1533
1534     hres = disp_get_id(ctx, obj, str, fdexNameEnsure, &id);
1535     SysFreeString(str);
1536     if(SUCCEEDED(hres))
1537         exprval_set_idref(ret, obj, id);
1538
1539     IDispatch_Release(obj);
1540     return hres;
1541 }
1542
1543 /* ECMA-262 3rd Edition    11.2.1 */
1544 static HRESULT interp_member(exec_ctx_t *ctx)
1545 {
1546     const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1547     IDispatch *obj;
1548     VARIANT v;
1549     DISPID id;
1550     HRESULT hres;
1551
1552     TRACE("\n");
1553
1554     hres = stack_pop_object(ctx, &obj);
1555     if(FAILED(hres))
1556         return hres;
1557
1558     hres = disp_get_id(ctx->parser->script, obj, arg, 0, &id);
1559     if(SUCCEEDED(hres)) {
1560         V_VT(&v) = VT_EMPTY;
1561         hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
1562     }else if(hres == DISP_E_UNKNOWNNAME) {
1563         V_VT(&v) = VT_EMPTY;
1564         hres = S_OK;
1565     }
1566     IDispatch_Release(obj);
1567     if(FAILED(hres))
1568         return hres;
1569
1570     return stack_push(ctx, &v);
1571 }
1572
1573 /* ECMA-262 3rd Edition    11.2.1 */
1574 static HRESULT interp_memberid(exec_ctx_t *ctx)
1575 {
1576     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1577     VARIANT *objv, *namev;
1578     IDispatch *obj;
1579     BSTR name;
1580     DISPID id;
1581     HRESULT hres;
1582
1583     TRACE("%x\n", arg);
1584
1585     namev = stack_pop(ctx);
1586     objv = stack_pop(ctx);
1587
1588     hres = to_object(ctx->parser->script, objv, &obj);
1589     VariantClear(objv);
1590     if(SUCCEEDED(hres)) {
1591         hres = to_string(ctx->parser->script, namev, ctx->ei, &name);
1592         if(FAILED(hres))
1593             IDispatch_Release(obj);
1594     }
1595     VariantClear(namev);
1596     if(FAILED(hres))
1597         return hres;
1598
1599     hres = disp_get_id(ctx->parser->script, obj, name, arg, &id);
1600     SysFreeString(name);
1601     if(FAILED(hres)) {
1602         IDispatch_Release(obj);
1603         if(hres == DISP_E_UNKNOWNNAME && !(arg & fdexNameEnsure)) {
1604             obj = NULL;
1605             id = JS_E_INVALID_PROPERTY;
1606         }else {
1607             return hres;
1608         }
1609     }
1610
1611     return stack_push_objid(ctx, obj, id);
1612 }
1613
1614 /* ECMA-262 3rd Edition    11.2.1 */
1615 static HRESULT interp_refval(exec_ctx_t *ctx)
1616 {
1617     IDispatch *disp;
1618     VARIANT v;
1619     DISPID id;
1620     HRESULT hres;
1621
1622     TRACE("\n");
1623
1624     disp = stack_topn_objid(ctx, 0, &id);
1625     if(!disp)
1626         return throw_reference_error(ctx->parser->script, ctx->ei, JS_E_ILLEGAL_ASSIGN, NULL);
1627
1628     hres = disp_propget(ctx->parser->script, disp, id, &v, ctx->ei, NULL/*FIXME*/);
1629     if(FAILED(hres))
1630         return hres;
1631
1632     return stack_push(ctx, &v);
1633 }
1634
1635 static void jsstack_to_dp(exec_ctx_t *ctx, unsigned arg_cnt, DISPPARAMS *dp)
1636 {
1637     VARIANT tmp;
1638     unsigned i;
1639
1640     dp->cArgs = arg_cnt;
1641     dp->rgdispidNamedArgs = NULL;
1642     dp->cNamedArgs = 0;
1643
1644     assert(ctx->top >= arg_cnt);
1645
1646     for(i=1; i*2 <= arg_cnt; i++) {
1647         tmp = ctx->stack[ctx->top-i];
1648         ctx->stack[ctx->top-i] = ctx->stack[ctx->top-arg_cnt+i-1];
1649         ctx->stack[ctx->top-arg_cnt+i-1] = tmp;
1650     }
1651
1652     dp->rgvarg = ctx->stack + ctx->top-arg_cnt;
1653 }
1654
1655 /* ECMA-262 3rd Edition    11.2.2 */
1656 static HRESULT interp_new(exec_ctx_t *ctx)
1657 {
1658     const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1659     VARIANT *constr, v;
1660     DISPPARAMS dp;
1661     HRESULT hres;
1662
1663     TRACE("%d\n", arg);
1664
1665     constr = stack_topn(ctx, arg);
1666
1667     /* NOTE: Should use to_object here */
1668
1669     if(V_VT(constr) == VT_NULL)
1670         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
1671     else if(V_VT(constr) != VT_DISPATCH)
1672         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_INVALID_ACTION, NULL);
1673     else if(!V_DISPATCH(constr))
1674         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_INVALID_PROPERTY, NULL);
1675
1676     jsstack_to_dp(ctx, arg, &dp);
1677     hres = disp_call(ctx->parser->script, V_DISPATCH(constr), DISPID_VALUE,
1678             DISPATCH_CONSTRUCT, &dp, &v, ctx->ei, NULL/*FIXME*/);
1679     if(FAILED(hres))
1680         return hres;
1681
1682     stack_popn(ctx, arg+1);
1683     return stack_push(ctx, &v);
1684 }
1685
1686 /* ECMA-262 3rd Edition    11.2.3 */
1687 static HRESULT interp_call(exec_ctx_t *ctx)
1688 {
1689     const unsigned argn = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1690     const int do_ret = ctx->parser->code->instrs[ctx->ip].arg2.lng;
1691     VARIANT v, *objv;
1692     DISPPARAMS dp;
1693     HRESULT hres;
1694
1695     TRACE("%d %d\n", argn, do_ret);
1696
1697     objv = stack_topn(ctx, argn);
1698     if(V_VT(objv) != VT_DISPATCH)
1699         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_INVALID_PROPERTY, NULL);
1700
1701     jsstack_to_dp(ctx, argn, &dp);
1702     hres = disp_call(ctx->parser->script, V_DISPATCH(objv), DISPID_VALUE, DISPATCH_METHOD, &dp,
1703             do_ret ? &v : NULL, ctx->ei, NULL/*FIXME*/);
1704     if(FAILED(hres))
1705         return hres;
1706
1707     stack_popn(ctx, argn+1);
1708     return do_ret ? stack_push(ctx, &v) : S_OK;
1709
1710 }
1711
1712 /* ECMA-262 3rd Edition    11.2.3 */
1713 static HRESULT interp_call_member(exec_ctx_t *ctx)
1714 {
1715     const unsigned argn = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1716     const int do_ret = ctx->parser->code->instrs[ctx->ip].arg2.lng;
1717     IDispatch *obj;
1718     DISPPARAMS dp;
1719     VARIANT v;
1720     DISPID id;
1721     HRESULT hres;
1722
1723     TRACE("%d %d\n", argn, do_ret);
1724
1725     obj = stack_topn_objid(ctx, argn, &id);
1726     if(!obj)
1727         return throw_type_error(ctx->parser->script, ctx->ei, id, NULL);
1728
1729     jsstack_to_dp(ctx, argn, &dp);
1730     hres = disp_call(ctx->parser->script, obj, id, DISPATCH_METHOD, &dp, do_ret ? &v : NULL, ctx->ei, NULL/*FIXME*/);
1731     if(FAILED(hres))
1732         return hres;
1733
1734     stack_popn(ctx, argn+2);
1735     return do_ret ? stack_push(ctx, &v) : S_OK;
1736
1737 }
1738
1739 /* ECMA-262 3rd Edition    11.1.1 */
1740 static HRESULT interp_this(exec_ctx_t *ctx)
1741 {
1742     VARIANT v;
1743
1744     TRACE("\n");
1745
1746     V_VT(&v) = VT_DISPATCH;
1747     V_DISPATCH(&v) = ctx->this_obj;
1748     IDispatch_AddRef(ctx->this_obj);
1749     return stack_push(ctx, &v);
1750 }
1751
1752 /* ECMA-262 3rd Edition    10.1.4 */
1753 static HRESULT identifier_expression_eval(script_ctx_t *ctx, expression_t *_expr, jsexcept_t *ei, exprval_t *ret)
1754 {
1755     identifier_expression_t *expr = (identifier_expression_t*)_expr;
1756     BSTR identifier;
1757     HRESULT hres;
1758
1759     TRACE("\n");
1760
1761     identifier = SysAllocString(expr->identifier);
1762     if(!identifier)
1763         return E_OUTOFMEMORY;
1764
1765     hres = identifier_eval(ctx, identifier, fdexNameEnsure, ei, ret);
1766
1767     SysFreeString(identifier);
1768     return hres;
1769 }
1770
1771 /* ECMA-262 3rd Edition    10.1.4 */
1772 static HRESULT interp_ident(exec_ctx_t *ctx)
1773 {
1774     const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1775     exprval_t exprval;
1776     VARIANT v;
1777     HRESULT hres;
1778
1779     TRACE("%s\n", debugstr_w(arg));
1780
1781     hres = identifier_eval(ctx->parser->script, arg, 0, ctx->ei, &exprval);
1782     if(FAILED(hres))
1783         return hres;
1784
1785     if(exprval.type == EXPRVAL_INVALID)
1786         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_UNDEFINED_VARIABLE, arg);
1787
1788     hres = exprval_to_value(ctx->parser->script, &exprval, ctx->ei, &v);
1789     exprval_release(&exprval);
1790     if(FAILED(hres))
1791         return hres;
1792
1793     return stack_push(ctx, &v);
1794 }
1795
1796 /* ECMA-262 3rd Edition    10.1.4 */
1797 static HRESULT interp_identid(exec_ctx_t *ctx)
1798 {
1799     const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1800     const unsigned flags = ctx->parser->code->instrs[ctx->ip].arg2.uint;
1801     exprval_t exprval;
1802     HRESULT hres;
1803
1804     TRACE("%s %x\n", debugstr_w(arg), flags);
1805
1806     hres = identifier_eval(ctx->parser->script, arg, flags, ctx->ei, &exprval);
1807     if(FAILED(hres))
1808         return hres;
1809
1810     if(exprval.type != EXPRVAL_IDREF) {
1811         WARN("invalid ref\n");
1812         exprval_release(&exprval);
1813         return stack_push_objid(ctx, NULL, JS_E_OBJECT_EXPECTED);
1814     }
1815
1816     return stack_push_objid(ctx, exprval.u.idref.disp, exprval.u.idref.id);
1817 }
1818
1819 /* ECMA-262 3rd Edition    7.8.1 */
1820 static HRESULT interp_null(exec_ctx_t *ctx)
1821 {
1822     VARIANT v;
1823
1824     TRACE("\n");
1825
1826     V_VT(&v) = VT_NULL;
1827     return stack_push(ctx, &v);
1828 }
1829
1830 /* ECMA-262 3rd Edition    7.8.2 */
1831 static HRESULT interp_bool(exec_ctx_t *ctx)
1832 {
1833     const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1834
1835     TRACE("%s\n", arg ? "true" : "false");
1836
1837     return stack_push_bool(ctx, arg);
1838 }
1839
1840 /* ECMA-262 3rd Edition    7.8.3 */
1841 static HRESULT interp_int(exec_ctx_t *ctx)
1842 {
1843     const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1844     VARIANT v;
1845
1846     TRACE("%d\n", arg);
1847
1848     V_VT(&v) = VT_I4;
1849     V_I4(&v) = arg;
1850     return stack_push(ctx, &v);
1851 }
1852
1853 /* ECMA-262 3rd Edition    7.8.3 */
1854 static HRESULT interp_double(exec_ctx_t *ctx)
1855 {
1856     const double arg = *ctx->parser->code->instrs[ctx->ip].arg1.dbl;
1857     VARIANT v;
1858
1859     TRACE("%lf\n", arg);
1860
1861     V_VT(&v) = VT_R8;
1862     V_R8(&v) = arg;
1863     return stack_push(ctx, &v);
1864 }
1865
1866 /* ECMA-262 3rd Edition    7.8.4 */
1867 static HRESULT interp_str(exec_ctx_t *ctx)
1868 {
1869     const WCHAR *str = ctx->parser->code->instrs[ctx->ip].arg1.str;
1870     VARIANT v;
1871
1872     TRACE("%s\n", debugstr_w(str));
1873
1874     V_VT(&v) = VT_BSTR;
1875     V_BSTR(&v) = SysAllocString(str);
1876     if(!V_BSTR(&v))
1877         return E_OUTOFMEMORY;
1878
1879     return stack_push(ctx, &v);
1880 }
1881
1882 /* ECMA-262 3rd Edition    7.8 */
1883 static HRESULT interp_regexp(exec_ctx_t *ctx)
1884 {
1885     const WCHAR *source = ctx->parser->code->instrs[ctx->ip].arg1.str;
1886     const LONG flags = ctx->parser->code->instrs[ctx->ip].arg2.lng;
1887     jsdisp_t *regexp;
1888     VARIANT v;
1889     HRESULT hres;
1890
1891     TRACE("%s %x\n", debugstr_w(source), flags);
1892
1893     hres = create_regexp(ctx->parser->script, source, strlenW(source), flags, &regexp);
1894     if(FAILED(hres))
1895         return hres;
1896
1897     var_set_jsdisp(&v, regexp);
1898     return stack_push(ctx, &v);
1899 }
1900
1901 /* ECMA-262 3rd Edition    11.1.4 */
1902 static HRESULT interp_carray(exec_ctx_t *ctx)
1903 {
1904     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1905     jsdisp_t *array;
1906     VARIANT *v, r;
1907     unsigned i;
1908     HRESULT hres;
1909
1910     TRACE("%u\n", arg);
1911
1912     hres = create_array(ctx->parser->script, arg, &array);
1913     if(FAILED(hres))
1914         return hres;
1915
1916     i = arg;
1917     while(i--) {
1918         v = stack_pop(ctx);
1919         hres = jsdisp_propput_idx(array, i, v, ctx->ei, NULL/*FIXME*/);
1920         VariantClear(v);
1921         if(FAILED(hres)) {
1922             jsdisp_release(array);
1923             return hres;
1924         }
1925     }
1926
1927     var_set_jsdisp(&r, array);
1928     return stack_push(ctx, &r);
1929 }
1930
1931 /* ECMA-262 3rd Edition    11.1.5 */
1932 HRESULT interp_new_obj(exec_ctx_t *ctx)
1933 {
1934     jsdisp_t *obj;
1935     VARIANT v;
1936     HRESULT hres;
1937
1938     TRACE("\n");
1939
1940     hres = create_object(ctx->parser->script, NULL, &obj);
1941     if(FAILED(hres))
1942         return hres;
1943
1944     var_set_jsdisp(&v, obj);
1945     return stack_push(ctx, &v);
1946 }
1947
1948 /* ECMA-262 3rd Edition    11.1.5 */
1949 HRESULT interp_obj_prop(exec_ctx_t *ctx)
1950 {
1951     const BSTR name = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1952     jsdisp_t *obj;
1953     VARIANT *v;
1954     HRESULT hres;
1955
1956     TRACE("%s\n", debugstr_w(name));
1957
1958     v = stack_pop(ctx);
1959
1960     assert(V_VT(stack_top(ctx)) == VT_DISPATCH);
1961     obj = as_jsdisp(V_DISPATCH(stack_top(ctx)));
1962
1963     hres = jsdisp_propput_name(obj, name, v, ctx->ei, NULL/*FIXME*/);
1964     VariantClear(v);
1965     return hres;
1966 }
1967
1968 /* ECMA-262 3rd Edition    11.11 */
1969 static HRESULT interp_cnd_nz(exec_ctx_t *ctx)
1970 {
1971     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1972     VARIANT_BOOL b;
1973     HRESULT hres;
1974
1975     TRACE("\n");
1976
1977     hres = to_boolean(stack_top(ctx), &b);
1978     if(FAILED(hres))
1979         return hres;
1980
1981     if(b) {
1982         ctx->ip = arg;
1983     }else {
1984         stack_popn(ctx, 1);
1985         ctx->ip++;
1986     }
1987     return S_OK;
1988 }
1989
1990 /* ECMA-262 3rd Edition    11.11 */
1991 static HRESULT interp_cnd_z(exec_ctx_t *ctx)
1992 {
1993     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1994     VARIANT_BOOL b;
1995     HRESULT hres;
1996
1997     TRACE("\n");
1998
1999     hres = to_boolean(stack_top(ctx), &b);
2000     if(FAILED(hres))
2001         return hres;
2002
2003     if(b) {
2004         stack_popn(ctx, 1);
2005         ctx->ip++;
2006     }else {
2007         ctx->ip = arg;
2008     }
2009     return S_OK;
2010 }
2011
2012 /* ECMA-262 3rd Edition    11.10 */
2013 static HRESULT interp_or(exec_ctx_t *ctx)
2014 {
2015     INT l, r;
2016     HRESULT hres;
2017
2018     TRACE("\n");
2019
2020     hres = stack_pop_int(ctx, &r);
2021     if(FAILED(hres))
2022         return hres;
2023
2024     hres = stack_pop_int(ctx, &l);
2025     if(FAILED(hres))
2026         return hres;
2027
2028     return stack_push_int(ctx, l|r);
2029 }
2030
2031 /* ECMA-262 3rd Edition    11.10 */
2032 static HRESULT interp_xor(exec_ctx_t *ctx)
2033 {
2034     INT l, r;
2035     HRESULT hres;
2036
2037     TRACE("\n");
2038
2039     hres = stack_pop_int(ctx, &r);
2040     if(FAILED(hres))
2041         return hres;
2042
2043     hres = stack_pop_int(ctx, &l);
2044     if(FAILED(hres))
2045         return hres;
2046
2047     return stack_push_int(ctx, l^r);
2048 }
2049
2050 /* ECMA-262 3rd Edition    11.10 */
2051 static HRESULT interp_and(exec_ctx_t *ctx)
2052 {
2053     INT l, r;
2054     HRESULT hres;
2055
2056     TRACE("\n");
2057
2058     hres = stack_pop_int(ctx, &r);
2059     if(FAILED(hres))
2060         return hres;
2061
2062     hres = stack_pop_int(ctx, &l);
2063     if(FAILED(hres))
2064         return hres;
2065
2066     return stack_push_int(ctx, l&r);
2067 }
2068
2069 /* ECMA-262 3rd Edition    11.8.6 */
2070 static HRESULT interp_instanceof(exec_ctx_t *ctx)
2071 {
2072     jsdisp_t *obj, *iter, *tmp = NULL;
2073     VARIANT prot, *v;
2074     BOOL ret = FALSE;
2075     HRESULT hres;
2076
2077     static const WCHAR prototypeW[] = {'p','r','o','t','o','t', 'y', 'p','e',0};
2078
2079     v = stack_pop(ctx);
2080     if(V_VT(v) != VT_DISPATCH || !V_DISPATCH(v)) {
2081         VariantClear(v);
2082         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_FUNCTION_EXPECTED, NULL);
2083     }
2084
2085     obj = iface_to_jsdisp((IUnknown*)V_DISPATCH(v));
2086     IDispatch_Release(V_DISPATCH(v));
2087     if(!obj) {
2088         FIXME("non-jsdisp objects not supported\n");
2089         return E_FAIL;
2090     }
2091
2092     if(is_class(obj, JSCLASS_FUNCTION)) {
2093         hres = jsdisp_propget_name(obj, prototypeW, &prot, ctx->ei, NULL/*FIXME*/);
2094     }else {
2095         hres = throw_type_error(ctx->parser->script, ctx->ei, JS_E_FUNCTION_EXPECTED, NULL);
2096     }
2097     jsdisp_release(obj);
2098     if(FAILED(hres))
2099         return hres;
2100
2101     v = stack_pop(ctx);
2102
2103     if(V_VT(&prot) == VT_DISPATCH) {
2104         if(V_VT(v) == VT_DISPATCH)
2105             tmp = iface_to_jsdisp((IUnknown*)V_DISPATCH(v));
2106         for(iter = tmp; !ret && iter; iter = iter->prototype) {
2107             hres = disp_cmp(V_DISPATCH(&prot), to_disp(iter), &ret);
2108             if(FAILED(hres))
2109                 break;
2110         }
2111
2112         if(tmp)
2113             jsdisp_release(tmp);
2114     }else {
2115         FIXME("prototype is not an object\n");
2116         hres = E_FAIL;
2117     }
2118
2119     VariantClear(&prot);
2120     VariantClear(v);
2121     if(FAILED(hres))
2122         return hres;
2123
2124     return stack_push_bool(ctx, ret);
2125 }
2126
2127 /* ECMA-262 3rd Edition    11.8.7 */
2128 static HRESULT interp_in(exec_ctx_t *ctx)
2129 {
2130     VARIANT *obj, *v;
2131     DISPID id = 0;
2132     BOOL ret;
2133     BSTR str;
2134     HRESULT hres;
2135
2136     TRACE("\n");
2137
2138     obj = stack_pop(ctx);
2139     v = stack_pop(ctx);
2140
2141     if(V_VT(obj) != VT_DISPATCH || !V_DISPATCH(obj)) {
2142         VariantClear(obj);
2143         VariantClear(v);
2144         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
2145     }
2146
2147     hres = to_string(ctx->parser->script, v, ctx->ei, &str);
2148     VariantClear(v);
2149     if(FAILED(hres)) {
2150         IDispatch_Release(V_DISPATCH(obj));
2151         return hres;
2152     }
2153
2154     hres = disp_get_id(ctx->parser->script, V_DISPATCH(obj), str, 0, &id);
2155     IDispatch_Release(V_DISPATCH(obj));
2156     SysFreeString(str);
2157     if(SUCCEEDED(hres))
2158         ret = TRUE;
2159     else if(hres == DISP_E_UNKNOWNNAME)
2160         ret = FALSE;
2161     else
2162         return hres;
2163
2164     return stack_push_bool(ctx, ret);
2165 }
2166
2167 /* ECMA-262 3rd Edition    11.6.1 */
2168 static HRESULT add_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
2169 {
2170     VARIANT r, l;
2171     HRESULT hres;
2172
2173     hres = to_primitive(ctx, lval, ei, &l, NO_HINT);
2174     if(FAILED(hres))
2175         return hres;
2176
2177     hres = to_primitive(ctx, rval, ei, &r, NO_HINT);
2178     if(FAILED(hres)) {
2179         VariantClear(&l);
2180         return hres;
2181     }
2182
2183     if(V_VT(&l) == VT_BSTR || V_VT(&r) == VT_BSTR) {
2184         BSTR lstr = NULL, rstr = NULL;
2185
2186         if(V_VT(&l) == VT_BSTR)
2187             lstr = V_BSTR(&l);
2188         else
2189             hres = to_string(ctx, &l, ei, &lstr);
2190
2191         if(SUCCEEDED(hres)) {
2192             if(V_VT(&r) == VT_BSTR)
2193                 rstr = V_BSTR(&r);
2194             else
2195                 hres = to_string(ctx, &r, ei, &rstr);
2196         }
2197
2198         if(SUCCEEDED(hres)) {
2199             int len1, len2;
2200
2201             len1 = SysStringLen(lstr);
2202             len2 = SysStringLen(rstr);
2203
2204             V_VT(retv) = VT_BSTR;
2205             V_BSTR(retv) = SysAllocStringLen(NULL, len1+len2);
2206             memcpy(V_BSTR(retv), lstr, len1*sizeof(WCHAR));
2207             memcpy(V_BSTR(retv)+len1, rstr, (len2+1)*sizeof(WCHAR));
2208         }
2209
2210         if(V_VT(&l) != VT_BSTR)
2211             SysFreeString(lstr);
2212         if(V_VT(&r) != VT_BSTR)
2213             SysFreeString(rstr);
2214     }else {
2215         VARIANT nl, nr;
2216
2217         hres = to_number(ctx, &l, ei, &nl);
2218         if(SUCCEEDED(hres)) {
2219             hres = to_number(ctx, &r, ei, &nr);
2220             if(SUCCEEDED(hres))
2221                 num_set_val(retv, num_val(&nl) + num_val(&nr));
2222         }
2223     }
2224
2225     VariantClear(&r);
2226     VariantClear(&l);
2227     return hres;
2228 }
2229
2230 /* ECMA-262 3rd Edition    11.6.1 */
2231 static HRESULT interp_add(exec_ctx_t *ctx)
2232 {
2233     VARIANT *l, *r, ret;
2234     HRESULT hres;
2235
2236     r = stack_pop(ctx);
2237     l = stack_pop(ctx);
2238
2239     TRACE("%s + %s\n", debugstr_variant(l), debugstr_variant(r));
2240
2241     hres = add_eval(ctx->parser->script, l, r, ctx->ei, &ret);
2242     VariantClear(l);
2243     VariantClear(r);
2244     if(FAILED(hres))
2245         return hres;
2246
2247     return stack_push(ctx, &ret);
2248 }
2249
2250 /* ECMA-262 3rd Edition    11.6.2 */
2251 static HRESULT interp_sub(exec_ctx_t *ctx)
2252 {
2253     VARIANT l, r;
2254     HRESULT hres;
2255
2256     TRACE("\n");
2257
2258     hres = stack_pop_number(ctx, &r);
2259     if(FAILED(hres))
2260         return hres;
2261
2262     hres = stack_pop_number(ctx, &l);
2263     if(FAILED(hres))
2264         return hres;
2265
2266     return stack_push_number(ctx, num_val(&l)-num_val(&r));
2267 }
2268
2269 /* ECMA-262 3rd Edition    11.5.1 */
2270 static HRESULT interp_mul(exec_ctx_t *ctx)
2271 {
2272     VARIANT l, r;
2273     HRESULT hres;
2274
2275     TRACE("\n");
2276
2277     hres = stack_pop_number(ctx, &r);
2278     if(FAILED(hres))
2279         return hres;
2280
2281     hres = stack_pop_number(ctx, &l);
2282     if(FAILED(hres))
2283         return hres;
2284
2285     return stack_push_number(ctx, num_val(&l)*num_val(&r));
2286 }
2287
2288 /* ECMA-262 3rd Edition    11.5.2 */
2289 static HRESULT interp_div(exec_ctx_t *ctx)
2290 {
2291     VARIANT l, r;
2292     HRESULT hres;
2293
2294     TRACE("\n");
2295
2296     hres = stack_pop_number(ctx, &r);
2297     if(FAILED(hres))
2298         return hres;
2299
2300     hres = stack_pop_number(ctx, &l);
2301     if(FAILED(hres))
2302         return hres;
2303
2304     return stack_push_number(ctx, num_val(&l)/num_val(&r));
2305 }
2306
2307 /* ECMA-262 3rd Edition    11.5.3 */
2308 static HRESULT interp_mod(exec_ctx_t *ctx)
2309 {
2310     VARIANT l, r;
2311     HRESULT hres;
2312
2313     TRACE("\n");
2314
2315     hres = stack_pop_number(ctx, &r);
2316     if(FAILED(hres))
2317         return hres;
2318
2319     hres = stack_pop_number(ctx, &l);
2320     if(FAILED(hres))
2321         return hres;
2322
2323     return stack_push_number(ctx, fmod(num_val(&l), num_val(&r)));
2324 }
2325
2326 /* ECMA-262 3rd Edition    11.4.2 */
2327 static HRESULT interp_delete(exec_ctx_t *ctx)
2328 {
2329     VARIANT *obj_var, *name_var;
2330     IDispatchEx *dispex;
2331     IDispatch *obj;
2332     BSTR name;
2333     BOOL ret;
2334     HRESULT hres;
2335
2336     TRACE("\n");
2337
2338     name_var = stack_pop(ctx);
2339     obj_var = stack_pop(ctx);
2340
2341     hres = to_object(ctx->parser->script, obj_var, &obj);
2342     VariantClear(obj_var);
2343     if(FAILED(hres)) {
2344         VariantClear(name_var);
2345         return hres;
2346     }
2347
2348     hres = to_string(ctx->parser->script, name_var, ctx->ei, &name);
2349     VariantClear(name_var);
2350     if(FAILED(hres)) {
2351         IDispatch_Release(obj);
2352         return hres;
2353     }
2354
2355     hres = IDispatch_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex);
2356     if(SUCCEEDED(hres)) {
2357         hres = IDispatchEx_DeleteMemberByName(dispex, name, make_grfdex(ctx->parser->script, fdexNameCaseSensitive));
2358         ret = TRUE;
2359         IDispatchEx_Release(dispex);
2360     }else {
2361         hres = S_OK;
2362         ret = FALSE;
2363     }
2364
2365     IDispatch_Release(obj);
2366     SysFreeString(name);
2367     if(FAILED(hres))
2368         return hres;
2369
2370     return stack_push_bool(ctx, ret);
2371 }
2372
2373 /* ECMA-262 3rd Edition    11.4.2 */
2374 static HRESULT interp_delete_ident(exec_ctx_t *ctx)
2375 {
2376     const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
2377     IDispatchEx *dispex;
2378     exprval_t exprval;
2379     BOOL ret = FALSE;
2380     HRESULT hres;
2381
2382     TRACE("%s\n", debugstr_w(arg));
2383
2384     hres = identifier_eval(ctx->parser->script, arg, 0, ctx->ei, &exprval);
2385     if(FAILED(hres))
2386         return hres;
2387
2388     if(exprval.type != EXPRVAL_IDREF) {
2389         FIXME("Unsupported exprval\n");
2390         exprval_release(&exprval);
2391         return E_NOTIMPL;
2392     }
2393
2394     hres = IDispatch_QueryInterface(exprval.u.idref.disp, &IID_IDispatchEx, (void**)&dispex);
2395     IDispatch_Release(exprval.u.idref.disp);
2396     if(SUCCEEDED(hres)) {
2397         hres = IDispatchEx_DeleteMemberByDispID(dispex, exprval.u.idref.id);
2398         IDispatchEx_Release(dispex);
2399         if(FAILED(hres))
2400             return hres;
2401
2402         ret = TRUE;
2403     }
2404
2405     return stack_push_bool(ctx, ret);
2406 }
2407
2408 /* ECMA-262 3rd Edition    11.4.2 */
2409 static HRESULT interp_void(exec_ctx_t *ctx)
2410 {
2411     VARIANT v;
2412
2413     TRACE("\n");
2414
2415     stack_popn(ctx, 1);
2416
2417     V_VT(&v) = VT_EMPTY;
2418     return stack_push(ctx, &v);
2419 }
2420
2421 /* ECMA-262 3rd Edition    11.4.3 */
2422 static HRESULT typeof_string(VARIANT *v, const WCHAR **ret)
2423 {
2424     switch(V_VT(v)) {
2425     case VT_EMPTY:
2426         *ret = undefinedW;
2427         break;
2428     case VT_NULL:
2429         *ret = objectW;
2430         break;
2431     case VT_BOOL:
2432         *ret = booleanW;
2433         break;
2434     case VT_I4:
2435     case VT_R8:
2436         *ret = numberW;
2437         break;
2438     case VT_BSTR:
2439         *ret = stringW;
2440         break;
2441     case VT_DISPATCH: {
2442         jsdisp_t *dispex;
2443
2444         if(V_DISPATCH(v) && (dispex = iface_to_jsdisp((IUnknown*)V_DISPATCH(v)))) {
2445             *ret = is_class(dispex, JSCLASS_FUNCTION) ? functionW : objectW;
2446             jsdisp_release(dispex);
2447         }else {
2448             *ret = objectW;
2449         }
2450         break;
2451     }
2452     default:
2453         FIXME("unhandled vt %d\n", V_VT(v));
2454         return E_NOTIMPL;
2455     }
2456
2457     return S_OK;
2458 }
2459
2460 /* ECMA-262 3rd Edition    11.4.3 */
2461 static HRESULT interp_typeofid(exec_ctx_t *ctx)
2462 {
2463     const WCHAR *ret;
2464     IDispatch *obj;
2465     VARIANT v;
2466     DISPID id;
2467     HRESULT hres;
2468
2469     static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
2470
2471     TRACE("\n");
2472
2473     obj = stack_pop_objid(ctx, &id);
2474     if(!obj)
2475         return stack_push_string(ctx, undefinedW);
2476
2477     V_VT(&v) = VT_EMPTY;
2478     hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
2479     IDispatch_Release(obj);
2480     if(FAILED(hres))
2481         return stack_push_string(ctx, unknownW);
2482
2483     hres = typeof_string(&v, &ret);
2484     VariantClear(&v);
2485     if(FAILED(hres))
2486         return hres;
2487
2488     return stack_push_string(ctx, ret);
2489 }
2490
2491 /* ECMA-262 3rd Edition    11.4.3 */
2492 static HRESULT interp_typeofident(exec_ctx_t *ctx)
2493 {
2494     const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
2495     exprval_t exprval;
2496     const WCHAR *ret;
2497     VARIANT v;
2498     HRESULT hres;
2499
2500     TRACE("%s\n", debugstr_w(arg));
2501
2502     hres = identifier_eval(ctx->parser->script, arg, 0, ctx->ei, &exprval);
2503     if(FAILED(hres))
2504         return hres;
2505
2506     if(exprval.type == EXPRVAL_INVALID) {
2507         hres = stack_push_string(ctx, undefinedW);
2508         exprval_release(&exprval);
2509         return hres;
2510     }
2511
2512     hres = exprval_to_value(ctx->parser->script, &exprval, ctx->ei, &v);
2513     exprval_release(&exprval);
2514     if(FAILED(hres))
2515         return hres;
2516
2517     hres = typeof_string(&v, &ret);
2518     VariantClear(&v);
2519     if(FAILED(hres))
2520         return hres;
2521
2522     return stack_push_string(ctx, ret);
2523 }
2524
2525 /* ECMA-262 3rd Edition    11.4.3 */
2526 static HRESULT interp_typeof(exec_ctx_t *ctx)
2527 {
2528     const WCHAR *ret;
2529     VARIANT *v;
2530     HRESULT hres;
2531
2532     TRACE("\n");
2533
2534     v = stack_pop(ctx);
2535     hres = typeof_string(v, &ret);
2536     VariantClear(v);
2537     if(FAILED(hres))
2538         return hres;
2539
2540     return stack_push_string(ctx, ret);
2541 }
2542
2543 /* ECMA-262 3rd Edition    11.4.7 */
2544 static HRESULT interp_minus(exec_ctx_t *ctx)
2545 {
2546     VARIANT n;
2547     HRESULT hres;
2548
2549     TRACE("\n");
2550
2551     hres = stack_pop_number(ctx, &n);
2552     if(FAILED(hres))
2553         return hres;
2554
2555     return stack_push_number(ctx, -num_val(&n));
2556 }
2557
2558 /* ECMA-262 3rd Edition    11.4.6 */
2559 static HRESULT interp_tonum(exec_ctx_t *ctx)
2560 {
2561     VARIANT *v, num;
2562     HRESULT hres;
2563
2564     TRACE("\n");
2565
2566     v = stack_pop(ctx);
2567     hres = to_number(ctx->parser->script, v, ctx->ei, &num);
2568     VariantClear(v);
2569     if(FAILED(hres))
2570         return hres;
2571
2572     return stack_push(ctx, &num);
2573 }
2574
2575 /* ECMA-262 3rd Edition    11.3.1 */
2576 static HRESULT interp_postinc(exec_ctx_t *ctx)
2577 {
2578     const int arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
2579     IDispatch *obj;
2580     DISPID id;
2581     VARIANT v;
2582     HRESULT hres;
2583
2584     TRACE("%d\n", arg);
2585
2586     obj = stack_pop_objid(ctx, &id);
2587     if(!obj)
2588         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
2589
2590     hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
2591     if(SUCCEEDED(hres)) {
2592         VARIANT n, inc;
2593
2594         hres = to_number(ctx->parser->script, &v, ctx->ei, &n);
2595         if(SUCCEEDED(hres)) {
2596             num_set_val(&inc, num_val(&n)+(double)arg);
2597             hres = disp_propput(ctx->parser->script, obj, id, &inc, ctx->ei, NULL/*FIXME*/);
2598         }
2599         if(FAILED(hres))
2600             VariantClear(&v);
2601     }
2602     IDispatch_Release(obj);
2603     if(FAILED(hres))
2604         return hres;
2605
2606     return stack_push(ctx, &v);
2607 }
2608
2609 /* ECMA-262 3rd Edition    11.4.4, 11.4.5 */
2610 static HRESULT interp_preinc(exec_ctx_t *ctx)
2611 {
2612     const int arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
2613     IDispatch *obj;
2614     DISPID id;
2615     VARIANT v;
2616     HRESULT hres;
2617
2618     TRACE("%d\n", arg);
2619
2620     obj = stack_pop_objid(ctx, &id);
2621     if(!obj)
2622         return throw_type_error(ctx->parser->script, ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
2623
2624     hres = disp_propget(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
2625     if(SUCCEEDED(hres)) {
2626         VARIANT n;
2627
2628         hres = to_number(ctx->parser->script, &v, ctx->ei, &n);
2629         VariantClear(&v);
2630         if(SUCCEEDED(hres)) {
2631             num_set_val(&v, num_val(&n)+(double)arg);
2632             hres = disp_propput(ctx->parser->script, obj, id, &v, ctx->ei, NULL/*FIXME*/);
2633         }
2634     }
2635     IDispatch_Release(obj);
2636     if(FAILED(hres))
2637         return hres;
2638
2639     return stack_push(ctx, &v);
2640 }
2641
2642 /* ECMA-262 3rd Edition    11.9.3 */
2643 static HRESULT equal_values(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, BOOL *ret)
2644 {
2645     if(V_VT(lval) == V_VT(rval) || (is_num_vt(V_VT(lval)) && is_num_vt(V_VT(rval))))
2646        return equal2_values(lval, rval, ret);
2647
2648     /* FIXME: NULL disps should be handled in more general way */
2649     if(V_VT(lval) == VT_DISPATCH && !V_DISPATCH(lval)) {
2650         VARIANT v;
2651         V_VT(&v) = VT_NULL;
2652         return equal_values(ctx, &v, rval, ei, ret);
2653     }
2654
2655     if(V_VT(rval) == VT_DISPATCH && !V_DISPATCH(rval)) {
2656         VARIANT v;
2657         V_VT(&v) = VT_NULL;
2658         return equal_values(ctx, lval, &v, ei, ret);
2659     }
2660
2661     if((V_VT(lval) == VT_NULL && V_VT(rval) == VT_EMPTY) ||
2662        (V_VT(lval) == VT_EMPTY && V_VT(rval) == VT_NULL)) {
2663         *ret = TRUE;
2664         return S_OK;
2665     }
2666
2667     if(V_VT(lval) == VT_BSTR && is_num_vt(V_VT(rval))) {
2668         VARIANT v;
2669         HRESULT hres;
2670
2671         hres = to_number(ctx, lval, ei, &v);
2672         if(FAILED(hres))
2673             return hres;
2674
2675         return equal_values(ctx, &v, rval, ei, ret);
2676     }
2677
2678     if(V_VT(rval) == VT_BSTR && is_num_vt(V_VT(lval))) {
2679         VARIANT v;
2680         HRESULT hres;
2681
2682         hres = to_number(ctx, rval, ei, &v);
2683         if(FAILED(hres))
2684             return hres;
2685
2686         return equal_values(ctx, lval, &v, ei, ret);
2687     }
2688
2689     if(V_VT(rval) == VT_BOOL) {
2690         VARIANT v;
2691
2692         V_VT(&v) = VT_I4;
2693         V_I4(&v) = V_BOOL(rval) ? 1 : 0;
2694         return equal_values(ctx, lval, &v, ei, ret);
2695     }
2696
2697     if(V_VT(lval) == VT_BOOL) {
2698         VARIANT v;
2699
2700         V_VT(&v) = VT_I4;
2701         V_I4(&v) = V_BOOL(lval) ? 1 : 0;
2702         return equal_values(ctx, &v, rval, ei, ret);
2703     }
2704
2705
2706     if(V_VT(rval) == VT_DISPATCH && (V_VT(lval) == VT_BSTR || is_num_vt(V_VT(lval)))) {
2707         VARIANT v;
2708         HRESULT hres;
2709
2710         hres = to_primitive(ctx, rval, ei, &v, NO_HINT);
2711         if(FAILED(hres))
2712             return hres;
2713
2714         hres = equal_values(ctx, lval, &v, ei, ret);
2715
2716         VariantClear(&v);
2717         return hres;
2718     }
2719
2720
2721     if(V_VT(lval) == VT_DISPATCH && (V_VT(rval) == VT_BSTR || is_num_vt(V_VT(rval)))) {
2722         VARIANT v;
2723         HRESULT hres;
2724
2725         hres = to_primitive(ctx, lval, ei, &v, NO_HINT);
2726         if(FAILED(hres))
2727             return hres;
2728
2729         hres = equal_values(ctx, &v, rval, ei, ret);
2730
2731         VariantClear(&v);
2732         return hres;
2733     }
2734
2735
2736     *ret = FALSE;
2737     return S_OK;
2738 }
2739
2740 /* ECMA-262 3rd Edition    11.9.1 */
2741 static HRESULT interp_eq(exec_ctx_t *ctx)
2742 {
2743     VARIANT *l, *r;
2744     BOOL b;
2745     HRESULT hres;
2746
2747     r = stack_pop(ctx);
2748     l = stack_pop(ctx);
2749
2750     TRACE("%s == %s\n", debugstr_variant(l), debugstr_variant(r));
2751
2752     hres = equal_values(ctx->parser->script, l, r, ctx->ei, &b);
2753     VariantClear(l);
2754     VariantClear(r);
2755     if(FAILED(hres))
2756         return hres;
2757
2758     return stack_push_bool(ctx, b);
2759 }
2760
2761 /* ECMA-262 3rd Edition    11.9.2 */
2762 static HRESULT interp_neq(exec_ctx_t *ctx)
2763 {
2764     VARIANT *l, *r;
2765     BOOL b;
2766     HRESULT hres;
2767
2768     r = stack_pop(ctx);
2769     l = stack_pop(ctx);
2770
2771     TRACE("%s != %s\n", debugstr_variant(l), debugstr_variant(r));
2772
2773     hres = equal_values(ctx->parser->script, l, r, ctx->ei, &b);
2774     VariantClear(l);
2775     VariantClear(r);
2776     if(FAILED(hres))
2777         return hres;
2778
2779     return stack_push_bool(ctx, !b);
2780 }
2781
2782 /* ECMA-262 3rd Edition    11.9.4 */
2783 static HRESULT interp_eq2(exec_ctx_t *ctx)
2784 {
2785     VARIANT *l, *r;
2786     BOOL b;
2787     HRESULT hres;
2788
2789     TRACE("\n");
2790
2791     r = stack_pop(ctx);
2792     l = stack_pop(ctx);
2793
2794     hres = equal2_values(r, l, &b);
2795     VariantClear(l);
2796     VariantClear(r);
2797     if(FAILED(hres))
2798         return hres;
2799
2800     return stack_push_bool(ctx, b);
2801 }
2802
2803 /* ECMA-262 3rd Edition    11.9.5 */
2804 static HRESULT interp_neq2(exec_ctx_t *ctx)
2805 {
2806     VARIANT *l, *r;
2807     BOOL b;
2808     HRESULT hres;
2809
2810     TRACE("\n");
2811
2812     r = stack_pop(ctx);
2813     l = stack_pop(ctx);
2814
2815     hres = equal2_values(r, l, &b);
2816     VariantClear(l);
2817     VariantClear(r);
2818     if(FAILED(hres))
2819         return hres;
2820
2821     return stack_push_bool(ctx, !b);
2822 }
2823
2824 /* ECMA-262 3rd Edition    11.8.5 */
2825 static HRESULT less_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, BOOL greater, jsexcept_t *ei, BOOL *ret)
2826 {
2827     VARIANT l, r, ln, rn;
2828     HRESULT hres;
2829
2830     hres = to_primitive(ctx, lval, ei, &l, NO_HINT);
2831     if(FAILED(hres))
2832         return hres;
2833
2834     hres = to_primitive(ctx, rval, ei, &r, NO_HINT);
2835     if(FAILED(hres)) {
2836         VariantClear(&l);
2837         return hres;
2838     }
2839
2840     if(V_VT(&l) == VT_BSTR && V_VT(&r) == VT_BSTR) {
2841         *ret = (strcmpW(V_BSTR(&l), V_BSTR(&r)) < 0) ^ greater;
2842         SysFreeString(V_BSTR(&l));
2843         SysFreeString(V_BSTR(&r));
2844         return S_OK;
2845     }
2846
2847     hres = to_number(ctx, &l, ei, &ln);
2848     VariantClear(&l);
2849     if(SUCCEEDED(hres))
2850         hres = to_number(ctx, &r, ei, &rn);
2851     VariantClear(&r);
2852     if(FAILED(hres))
2853         return hres;
2854
2855     if(V_VT(&ln) == VT_I4 && V_VT(&rn) == VT_I4) {
2856         *ret = (V_I4(&ln) < V_I4(&rn)) ^ greater;
2857     }else  {
2858         DOUBLE ld = num_val(&ln);
2859         DOUBLE rd = num_val(&rn);
2860
2861         *ret = !isnan(ld) && !isnan(rd) && ((ld < rd) ^ greater);
2862     }
2863
2864     return S_OK;
2865 }
2866
2867 /* ECMA-262 3rd Edition    11.8.1 */
2868 static HRESULT interp_lt(exec_ctx_t *ctx)
2869 {
2870     VARIANT *l, *r;
2871     BOOL b;
2872     HRESULT hres;
2873
2874     r = stack_pop(ctx);
2875     l = stack_pop(ctx);
2876
2877     TRACE("%s < %s\n", debugstr_variant(l), debugstr_variant(r));
2878
2879     hres = less_eval(ctx->parser->script, l, r, FALSE, ctx->ei, &b);
2880     VariantClear(l);
2881     VariantClear(r);
2882     if(FAILED(hres))
2883         return hres;
2884
2885     return stack_push_bool(ctx, b);
2886 }
2887
2888 /* ECMA-262 3rd Edition    11.8.1 */
2889 static HRESULT interp_lteq(exec_ctx_t *ctx)
2890 {
2891     VARIANT *l, *r;
2892     BOOL b;
2893     HRESULT hres;
2894
2895     r = stack_pop(ctx);
2896     l = stack_pop(ctx);
2897
2898     TRACE("%s <= %s\n", debugstr_variant(l), debugstr_variant(r));
2899
2900     hres = less_eval(ctx->parser->script, r, l, TRUE, ctx->ei, &b);
2901     VariantClear(l);
2902     VariantClear(r);
2903     if(FAILED(hres))
2904         return hres;
2905
2906     return stack_push_bool(ctx, b);
2907 }
2908
2909 /* ECMA-262 3rd Edition    11.8.2 */
2910 static HRESULT interp_gt(exec_ctx_t *ctx)
2911 {
2912     VARIANT *l, *r;
2913     BOOL b;
2914     HRESULT hres;
2915
2916     r = stack_pop(ctx);
2917     l = stack_pop(ctx);
2918
2919     TRACE("%s > %s\n", debugstr_variant(l), debugstr_variant(r));
2920
2921     hres = less_eval(ctx->parser->script, r, l, FALSE, ctx->ei, &b);
2922     VariantClear(l);
2923     VariantClear(r);
2924     if(FAILED(hres))
2925         return hres;
2926
2927     return stack_push_bool(ctx, b);
2928 }
2929
2930 /* ECMA-262 3rd Edition    11.8.4 */
2931 static HRESULT interp_gteq(exec_ctx_t *ctx)
2932 {
2933     VARIANT *l, *r;
2934     BOOL b;
2935     HRESULT hres;
2936
2937     r = stack_pop(ctx);
2938     l = stack_pop(ctx);
2939
2940     TRACE("%s >= %s\n", debugstr_variant(l), debugstr_variant(r));
2941
2942     hres = less_eval(ctx->parser->script, l, r, TRUE, ctx->ei, &b);
2943     VariantClear(l);
2944     VariantClear(r);
2945     if(FAILED(hres))
2946         return hres;
2947
2948     return stack_push_bool(ctx, b);
2949 }
2950
2951 /* ECMA-262 3rd Edition    11.4.8 */
2952 static HRESULT interp_bneg(exec_ctx_t *ctx)
2953 {
2954     VARIANT *v, r;
2955     INT i;
2956     HRESULT hres;
2957
2958     TRACE("\n");
2959
2960     v = stack_pop(ctx);
2961     hres = to_int32(ctx->parser->script, v, ctx->ei, &i);
2962     VariantClear(v);
2963     if(FAILED(hres))
2964         return hres;
2965
2966     V_VT(&r) = VT_I4;
2967     V_I4(&r) = ~i;
2968     return stack_push(ctx, &r);
2969 }
2970
2971 /* ECMA-262 3rd Edition    11.4.9 */
2972 static HRESULT interp_neg(exec_ctx_t *ctx)
2973 {
2974     VARIANT *v;
2975     VARIANT_BOOL b;
2976     HRESULT hres;
2977
2978     TRACE("\n");
2979
2980     v = stack_pop(ctx);
2981     hres = to_boolean(v, &b);
2982     VariantClear(v);
2983     if(FAILED(hres))
2984         return hres;
2985
2986     return stack_push_bool(ctx, !b);
2987 }
2988
2989 /* ECMA-262 3rd Edition    11.7.1 */
2990 static HRESULT interp_lshift(exec_ctx_t *ctx)
2991 {
2992     DWORD r;
2993     INT l;
2994     HRESULT hres;
2995
2996     hres = stack_pop_uint(ctx, &r);
2997     if(FAILED(hres))
2998         return hres;
2999
3000     hres = stack_pop_int(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.7.2 */
3008 static HRESULT interp_rshift(exec_ctx_t *ctx)
3009 {
3010     DWORD r;
3011     INT l;
3012     HRESULT hres;
3013
3014     hres = stack_pop_uint(ctx, &r);
3015     if(FAILED(hres))
3016         return hres;
3017
3018     hres = stack_pop_int(ctx, &l);
3019     if(FAILED(hres))
3020         return hres;
3021
3022     return stack_push_int(ctx, l >> (r&0x1f));
3023 }
3024
3025 /* ECMA-262 3rd Edition    11.7.3 */
3026 static HRESULT interp_rshift2(exec_ctx_t *ctx)
3027 {
3028     DWORD r, l;
3029     HRESULT hres;
3030
3031     hres = stack_pop_uint(ctx, &r);
3032     if(FAILED(hres))
3033         return hres;
3034
3035     hres = stack_pop_uint(ctx, &l);
3036     if(FAILED(hres))
3037         return hres;
3038
3039     return stack_push_int(ctx, l >> (r&0x1f));
3040 }
3041
3042 /* ECMA-262 3rd Edition    11.13.1 */
3043 static HRESULT interp_assign(exec_ctx_t *ctx)
3044 {
3045     IDispatch *disp;
3046     DISPID id;
3047     VARIANT *v;
3048     HRESULT hres;
3049
3050     TRACE("\n");
3051
3052     v = stack_pop(ctx);
3053     disp = stack_pop_objid(ctx, &id);
3054
3055     if(!disp)
3056         return throw_reference_error(ctx->parser->script, ctx->ei, JS_E_ILLEGAL_ASSIGN, NULL);
3057
3058     hres = disp_propput(ctx->parser->script, disp, id, v, ctx->ei, NULL/*FIXME*/);
3059     IDispatch_Release(disp);
3060     if(FAILED(hres)) {
3061         VariantClear(v);
3062         return hres;
3063     }
3064
3065     return stack_push(ctx, v);
3066 }
3067
3068 static HRESULT interp_undefined(exec_ctx_t *ctx)
3069 {
3070     VARIANT v;
3071
3072     TRACE("\n");
3073
3074     V_VT(&v) = VT_EMPTY;
3075     return stack_push(ctx, &v);
3076 }
3077
3078 static HRESULT interp_jmp(exec_ctx_t *ctx)
3079 {
3080     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
3081
3082     TRACE("\n");
3083
3084     ctx->ip = arg;
3085     return S_OK;
3086 }
3087
3088 static HRESULT interp_jmp_z(exec_ctx_t *ctx)
3089 {
3090     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
3091     VARIANT_BOOL b;
3092     VARIANT *v;
3093     HRESULT hres;
3094
3095     TRACE("\n");
3096
3097     v = stack_pop(ctx);
3098     hres = to_boolean(v, &b);
3099     VariantClear(v);
3100     if(FAILED(hres))
3101         return hres;
3102
3103     if(b)
3104         ctx->ip++;
3105     else
3106         ctx->ip = arg;
3107     return S_OK;
3108 }
3109
3110 static HRESULT interp_pop(exec_ctx_t *ctx)
3111 {
3112     TRACE("\n");
3113
3114     stack_popn(ctx, 1);
3115     return S_OK;
3116 }
3117
3118 static HRESULT interp_ret(exec_ctx_t *ctx)
3119 {
3120     TRACE("\n");
3121
3122     ctx->ip = -1;
3123     return S_OK;
3124 }
3125
3126 static HRESULT interp_tree(exec_ctx_t *ctx)
3127 {
3128     instr_t *instr = ctx->parser->code->instrs+ctx->ip;
3129     VARIANT v;
3130     HRESULT hres;
3131
3132     TRACE("\n");
3133
3134     hres = stat_eval(ctx->parser->script, instr->arg1.stat, ctx->rt, &v);
3135     if(FAILED(hres))
3136         return hres;
3137
3138     return stack_push(ctx, &v);
3139 }
3140
3141 typedef HRESULT (*op_func_t)(exec_ctx_t*);
3142
3143 static const op_func_t op_funcs[] = {
3144 #define X(x,a,b,c) interp_##x,
3145 OP_LIST
3146 #undef X
3147 };
3148
3149 static const unsigned op_move[] = {
3150 #define X(a,x,b,c) x,
3151 OP_LIST
3152 #undef X
3153 };
3154
3155 static HRESULT unwind_exception(exec_ctx_t *ctx)
3156 {
3157     except_frame_t *except_frame;
3158     VARIANT except_val;
3159     BSTR ident;
3160     HRESULT hres;
3161
3162     except_frame = ctx->except_frame;
3163     ctx->except_frame = except_frame->next;
3164
3165     assert(except_frame->stack_top <= ctx->top);
3166     stack_popn(ctx, ctx->top - except_frame->stack_top);
3167
3168     while(except_frame->scope != ctx->scope_chain)
3169         scope_pop(&ctx->scope_chain);
3170
3171     ctx->ip = except_frame->catch_off;
3172
3173     assert(ctx->rt->type == RT_NORMAL);
3174     except_val = ctx->rt->ei.var;
3175     memset(&ctx->rt->ei, 0, sizeof(ctx->rt->ei));
3176
3177     ident = except_frame->ident;
3178     heap_free(except_frame);
3179
3180     if(ident) {
3181         jsdisp_t *scope_obj;
3182
3183         hres = create_dispex(ctx->parser->script, NULL, NULL, &scope_obj);
3184         if(SUCCEEDED(hres)) {
3185             hres = jsdisp_propput_name(scope_obj, ident, &except_val, &ctx->rt->ei, NULL/*FIXME*/);
3186             if(FAILED(hres))
3187                 jsdisp_release(scope_obj);
3188         }
3189         VariantClear(&except_val);
3190         if(FAILED(hres))
3191             return hres;
3192
3193         hres = scope_push(ctx->scope_chain, scope_obj, &ctx->scope_chain);
3194         jsdisp_release(scope_obj);
3195     }else {
3196         VARIANT v;
3197
3198         hres = stack_push(ctx, &except_val);
3199         if(FAILED(hres))
3200             return hres;
3201
3202         hres = stack_push_bool(ctx, FALSE);
3203         if(FAILED(hres))
3204             return hres;
3205
3206         V_VT(&v) = VT_EMPTY;
3207         hres = stack_push(ctx, &v);
3208     }
3209
3210     return hres;
3211 }
3212
3213 HRESULT compiled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
3214 {
3215     exec_ctx_t *exec_ctx = ctx->exec_ctx;
3216     except_frame_t *prev_except_frame;
3217     unsigned prev_ip, prev_top;
3218     scope_chain_t *prev_scope;
3219     return_type_t *prev_rt;
3220     jsexcept_t *prev_ei;
3221     jsop_t op;
3222     HRESULT hres = S_OK;
3223
3224     TRACE("\n");
3225
3226     if(stat->instr_off == -1) {
3227         hres = compile_subscript_stat(exec_ctx->parser, stat, FALSE, &stat->instr_off);
3228         if(FAILED(hres))
3229             return hres;
3230     }
3231
3232     prev_rt = exec_ctx->rt;
3233     prev_top = exec_ctx->top;
3234     prev_scope = exec_ctx->scope_chain;
3235     prev_except_frame = exec_ctx->except_frame;
3236     prev_ip = exec_ctx->ip;
3237     prev_ei = exec_ctx->ei;
3238     exec_ctx->ip = stat->instr_off;
3239     exec_ctx->rt = rt;
3240     exec_ctx->ei = &rt->ei;
3241     exec_ctx->except_frame = NULL;
3242
3243     while(exec_ctx->ip != -1 && exec_ctx->rt->type == RT_NORMAL) {
3244         op = exec_ctx->parser->code->instrs[exec_ctx->ip].op;
3245         hres = op_funcs[op](exec_ctx);
3246         if(FAILED(hres)) {
3247             TRACE("EXCEPTION\n");
3248
3249             if(!exec_ctx->except_frame)
3250                 break;
3251
3252             hres = unwind_exception(exec_ctx);
3253             if(FAILED(hres))
3254                 break;
3255         }else {
3256             exec_ctx->ip += op_move[op];
3257         }
3258     }
3259
3260     exec_ctx->rt = prev_rt;
3261     exec_ctx->ip = prev_ip;
3262     exec_ctx->ei = prev_ei;
3263     exec_ctx->except_frame = prev_except_frame;
3264
3265     if(FAILED(hres)) {
3266         stack_popn(exec_ctx, exec_ctx->top-prev_top);
3267         while(exec_ctx->scope_chain != prev_scope)
3268             scope_pop(&exec_ctx->scope_chain);
3269         return hres;
3270     }
3271
3272     assert(exec_ctx->top == prev_top+1 || exec_ctx->top == prev_top);
3273     assert(exec_ctx->scope_chain == prev_scope);
3274
3275     if(exec_ctx->top == prev_top)
3276         V_VT(ret) = VT_EMPTY;
3277     else
3278         *ret = *stack_pop(exec_ctx);
3279     return S_OK;
3280 }
3281
3282 static HRESULT expr_eval(script_ctx_t *ctx, expression_t *expr, jsexcept_t *ei, VARIANT *ret)
3283 {
3284     exec_ctx_t *exec_ctx = ctx->exec_ctx;
3285     unsigned prev_ip, prev_top;
3286     jsexcept_t *prev_ei;
3287     jsop_t op;
3288     HRESULT hres = S_OK;
3289
3290     TRACE("\n");
3291
3292     if(expr->instr_off == -1) {
3293         hres = compile_subscript(ctx->exec_ctx->parser, expr, &expr->instr_off);
3294         if(FAILED(hres))
3295             return hres;
3296     }
3297
3298     prev_top = exec_ctx->top;
3299     prev_ip = exec_ctx->ip;
3300     prev_ei = exec_ctx->ei;
3301     exec_ctx->ip = expr->instr_off;
3302     exec_ctx->ei = ei;
3303
3304     while(exec_ctx->ip != -1) {
3305         op = exec_ctx->parser->code->instrs[exec_ctx->ip].op;
3306         hres = op_funcs[op](exec_ctx);
3307         if(FAILED(hres))
3308             break;
3309         exec_ctx->ip += op_move[op];
3310     }
3311
3312     exec_ctx->ip = prev_ip;
3313     exec_ctx->ei = prev_ei;
3314
3315     if(FAILED(hres)) {
3316         stack_popn(exec_ctx, exec_ctx->top-prev_top);
3317         return hres;
3318     }
3319
3320     assert(exec_ctx->top == prev_top+1);
3321
3322     if(exec_ctx->top == prev_top)
3323         V_VT(ret) = VT_EMPTY;
3324     else
3325         *ret = *stack_pop(exec_ctx);
3326     return S_OK;
3327 }