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