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