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