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