jscript: Return VARIANT directly from expr_eval.
[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.1 */
671 HRESULT block_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
672 {
673     block_statement_t *stat = (block_statement_t*)_stat;
674     VARIANT val, tmp;
675     statement_t *iter;
676     HRESULT hres = S_OK;
677
678     TRACE("\n");
679
680     V_VT(&val) = VT_EMPTY;
681     for(iter = stat->stat_list; iter; iter = iter->next) {
682         hres = stat_eval(ctx, iter, rt, &tmp);
683         if(FAILED(hres))
684             break;
685
686         VariantClear(&val);
687         val = tmp;
688         if(rt->type != RT_NORMAL)
689             break;
690     }
691
692     if(FAILED(hres)) {
693         VariantClear(&val);
694         return hres;
695     }
696
697     *ret = val;
698     return S_OK;
699 }
700
701 /* ECMA-262 3rd Edition    12.2 */
702 static HRESULT variable_list_eval(script_ctx_t *ctx, variable_declaration_t *var_list, jsexcept_t *ei)
703 {
704     variable_declaration_t *iter;
705     HRESULT hres = S_OK;
706
707     for(iter = var_list; iter; iter = iter->next) {
708         VARIANT val;
709
710         if(!iter->expr)
711             continue;
712
713         hres = expr_eval(ctx, iter->expr, 0, ei, &val);
714         if(FAILED(hres))
715             break;
716
717         hres = jsdisp_propput_name(ctx->exec_ctx->var_disp, iter->identifier, &val, ei, NULL/*FIXME*/);
718         VariantClear(&val);
719         if(FAILED(hres))
720             break;
721     }
722
723     return hres;
724 }
725
726 /* ECMA-262 3rd Edition    12.2 */
727 HRESULT var_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
728 {
729     var_statement_t *stat = (var_statement_t*)_stat;
730     HRESULT hres;
731
732     TRACE("\n");
733
734     hres = variable_list_eval(ctx, stat->variable_list, &rt->ei);
735     if(FAILED(hres))
736         return hres;
737
738     V_VT(ret) = VT_EMPTY;
739     return S_OK;
740 }
741
742 /* ECMA-262 3rd Edition    12.3 */
743 HRESULT empty_statement_eval(script_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
744 {
745     TRACE("\n");
746
747     V_VT(ret) = VT_EMPTY;
748     return S_OK;
749 }
750
751 /* ECMA-262 3rd Edition    12.4 */
752 HRESULT expression_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
753 {
754     expression_statement_t *stat = (expression_statement_t*)_stat;
755     VARIANT val;
756     HRESULT hres;
757
758     TRACE("\n");
759
760     hres = expr_eval(ctx, stat->expr, EXPR_NOVAL, &rt->ei, &val);
761     if(FAILED(hres))
762         return hres;
763
764     *ret = val;
765     TRACE("= %s\n", debugstr_variant(ret));
766     return S_OK;
767 }
768
769 /* ECMA-262 3rd Edition    12.5 */
770 HRESULT if_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
771 {
772     if_statement_t *stat = (if_statement_t*)_stat;
773     VARIANT_BOOL b;
774     VARIANT v;
775     HRESULT hres;
776
777     TRACE("\n");
778
779     hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &v);
780     if(FAILED(hres))
781         return hres;
782
783     hres = to_boolean(&v, &b);
784     VariantClear(&v);
785     if(FAILED(hres))
786         return hres;
787
788     if(b)
789         hres = stat_eval(ctx, stat->if_stat, rt, ret);
790     else if(stat->else_stat)
791         hres = stat_eval(ctx, stat->else_stat, rt, ret);
792     else
793         V_VT(ret) = VT_EMPTY;
794
795     return hres;
796 }
797
798 /* ECMA-262 3rd Edition    12.6.2 */
799 HRESULT while_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
800 {
801     while_statement_t *stat = (while_statement_t*)_stat;
802     VARIANT val, tmp;
803     VARIANT_BOOL b;
804     BOOL test_expr;
805     HRESULT hres;
806
807     TRACE("\n");
808
809     V_VT(&val) = VT_EMPTY;
810     test_expr = !stat->do_while;
811
812     while(1) {
813         if(test_expr) {
814             hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &tmp);
815             if(FAILED(hres))
816                 break;
817
818             hres = to_boolean(&tmp, &b);
819             VariantClear(&tmp);
820             if(FAILED(hres) || !b)
821                 break;
822         }else {
823             test_expr = TRUE;
824         }
825
826         hres = stat_eval(ctx, stat->statement, rt, &tmp);
827         if(FAILED(hres))
828             break;
829
830         VariantClear(&val);
831         val = tmp;
832
833         if(rt->type == RT_CONTINUE)
834             rt->type = RT_NORMAL;
835         if(rt->type != RT_NORMAL)
836             break;
837     }
838
839     if(FAILED(hres)) {
840         VariantClear(&val);
841         return hres;
842     }
843
844     if(rt->type == RT_BREAK)
845         rt->type = RT_NORMAL;
846
847     *ret = val;
848     return S_OK;
849 }
850
851 /* ECMA-262 3rd Edition    12.6.3 */
852 HRESULT for_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
853 {
854     for_statement_t *stat = (for_statement_t*)_stat;
855     VARIANT val, tmp, retv;
856     VARIANT_BOOL b;
857     HRESULT hres;
858
859     TRACE("\n");
860
861     if(stat->variable_list) {
862         hres = variable_list_eval(ctx, stat->variable_list, &rt->ei);
863         if(FAILED(hres))
864             return hres;
865     }else if(stat->begin_expr) {
866         hres = expr_eval(ctx, stat->begin_expr, 0, &rt->ei, &val);
867         if(FAILED(hres))
868             return hres;
869
870         VariantClear(&val);
871     }
872
873     V_VT(&retv) = VT_EMPTY;
874
875     while(1) {
876         if(stat->expr) {
877             hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &tmp);
878             if(FAILED(hres))
879                 break;
880
881             hres = to_boolean(&tmp, &b);
882             VariantClear(&tmp);
883             if(FAILED(hres) || !b)
884                 break;
885         }
886
887         hres = stat_eval(ctx, stat->statement, rt, &tmp);
888         if(FAILED(hres))
889             break;
890
891         VariantClear(&retv);
892         retv = tmp;
893
894         if(rt->type == RT_CONTINUE)
895             rt->type = RT_NORMAL;
896         else if(rt->type != RT_NORMAL)
897             break;
898
899         if(stat->end_expr) {
900             hres = expr_eval(ctx, stat->end_expr, 0, &rt->ei, &val);
901             if(FAILED(hres))
902                 break;
903
904             VariantClear(&val);
905         }
906     }
907
908     if(FAILED(hres)) {
909         VariantClear(&retv);
910         return hres;
911     }
912
913     if(rt->type == RT_BREAK)
914         rt->type = RT_NORMAL;
915
916     *ret = retv;
917     return S_OK;
918 }
919
920 static HRESULT array_expression_eval(script_ctx_t*,expression_t*,jsexcept_t*,exprval_t*);
921 static HRESULT member_expression_eval(script_ctx_t*,expression_t*,jsexcept_t*,exprval_t*);
922 static HRESULT identifier_expression_eval(script_ctx_t*,expression_t*,jsexcept_t*,exprval_t*);
923
924 /* ECMA-262 3rd Edition    12.6.4 */
925 HRESULT forin_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
926 {
927     forin_statement_t *stat = (forin_statement_t*)_stat;
928     VARIANT val, name, retv, tmp;
929     DISPID id = DISPID_STARTENUM;
930     BSTR str, identifier = NULL;
931     IDispatchEx *in_obj;
932     exprval_t exprval;
933     HRESULT hres;
934
935     TRACE("\n");
936
937     if(stat->variable) {
938         hres = variable_list_eval(ctx, stat->variable, &rt->ei);
939         if(FAILED(hres))
940             return hres;
941     }
942
943     hres = expr_eval(ctx, stat->in_expr, 0, &rt->ei, &val);
944     if(FAILED(hres))
945         return hres;
946
947     if(V_VT(&val) != VT_DISPATCH) {
948         TRACE("in vt %d\n", V_VT(&val));
949         VariantClear(&val);
950         V_VT(ret) = VT_EMPTY;
951         return S_OK;
952     }
953
954     hres = IDispatch_QueryInterface(V_DISPATCH(&val), &IID_IDispatchEx, (void**)&in_obj);
955     IDispatch_Release(V_DISPATCH(&val));
956     if(FAILED(hres)) {
957         TRACE("Object doesn't support IDispatchEx\n");
958         V_VT(ret) = VT_EMPTY;
959         return S_OK;
960     }
961
962     V_VT(&retv) = VT_EMPTY;
963
964     if(stat->variable)
965         identifier = SysAllocString(stat->variable->identifier);
966
967     while(1) {
968         hres = IDispatchEx_GetNextDispID(in_obj, fdexEnumDefault, id, &id);
969         if(FAILED(hres) || hres == S_FALSE)
970             break;
971
972         hres = IDispatchEx_GetMemberName(in_obj, id, &str);
973         if(FAILED(hres))
974             break;
975
976         TRACE("iter %s\n", debugstr_w(str));
977
978         if(stat->variable) {
979             hres = identifier_eval(ctx, identifier, 0, NULL, &exprval);
980         }else {
981             switch(stat->expr->type) {
982             case EXPR_ARRAY:
983                 hres = array_expression_eval(ctx, stat->expr, &rt->ei, &exprval);
984                 break;
985             case EXPR_IDENT:
986                 hres = identifier_expression_eval(ctx, stat->expr, &rt->ei, &exprval);
987                 break;
988             case EXPR_MEMBER:
989                 hres = member_expression_eval(ctx, stat->expr, &rt->ei, &exprval);
990                 break;
991             default:
992                 hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &tmp);
993                 if(FAILED(hres))
994                     break;
995
996                 VariantClear(&tmp);
997                 hres = throw_reference_error(ctx, &rt->ei, JS_E_ILLEGAL_ASSIGN, NULL);
998                 break;
999             }
1000         }
1001         if(SUCCEEDED(hres)) {
1002             V_VT(&name) = VT_BSTR;
1003             V_BSTR(&name) = str;
1004             hres = put_value(ctx, &exprval, &name, &rt->ei);
1005             exprval_release(&exprval);
1006         }
1007         SysFreeString(str);
1008         if(FAILED(hres))
1009             break;
1010
1011         hres = stat_eval(ctx, stat->statement, rt, &tmp);
1012         if(FAILED(hres))
1013             break;
1014
1015         VariantClear(&retv);
1016         retv = tmp;
1017
1018         if(rt->type == RT_CONTINUE)
1019             rt->type = RT_NORMAL;
1020         else if(rt->type != RT_NORMAL)
1021             break;
1022     }
1023
1024     SysFreeString(identifier);
1025     IDispatchEx_Release(in_obj);
1026     if(FAILED(hres)) {
1027         VariantClear(&retv);
1028         return hres;
1029     }
1030
1031     if(rt->type == RT_BREAK)
1032         rt->type = RT_NORMAL;
1033
1034     *ret = retv;
1035     return S_OK;
1036 }
1037
1038 /* ECMA-262 3rd Edition    12.7 */
1039 HRESULT continue_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1040 {
1041     branch_statement_t *stat = (branch_statement_t*)_stat;
1042
1043     TRACE("\n");
1044
1045     if(stat->identifier) {
1046         FIXME("indentifier not implemented\n");
1047         return E_NOTIMPL;
1048     }
1049
1050     rt->type = RT_CONTINUE;
1051     V_VT(ret) = VT_EMPTY;
1052     return S_OK;
1053 }
1054
1055 /* ECMA-262 3rd Edition    12.8 */
1056 HRESULT break_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1057 {
1058     branch_statement_t *stat = (branch_statement_t*)_stat;
1059
1060     TRACE("\n");
1061
1062     if(stat->identifier) {
1063         FIXME("indentifier not implemented\n");
1064         return E_NOTIMPL;
1065     }
1066
1067     rt->type = RT_BREAK;
1068     V_VT(ret) = VT_EMPTY;
1069     return S_OK;
1070 }
1071
1072 /* ECMA-262 3rd Edition    12.9 */
1073 HRESULT return_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1074 {
1075     expression_statement_t *stat = (expression_statement_t*)_stat;
1076     HRESULT hres;
1077
1078     TRACE("\n");
1079
1080     if(stat->expr) {
1081         hres = expr_eval(ctx, stat->expr, 0, &rt->ei, ret);
1082         if(FAILED(hres))
1083             return hres;
1084     }else {
1085         V_VT(ret) = VT_EMPTY;
1086     }
1087
1088     TRACE("= %s\n", debugstr_variant(ret));
1089     rt->type = RT_RETURN;
1090     return S_OK;
1091 }
1092
1093 /* ECMA-262 3rd Edition    12.10 */
1094 HRESULT with_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1095 {
1096     with_statement_t *stat = (with_statement_t*)_stat;
1097     IDispatch *disp;
1098     jsdisp_t *obj;
1099     VARIANT val;
1100     HRESULT hres;
1101
1102     TRACE("\n");
1103
1104     hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &val);
1105     if(FAILED(hres))
1106         return hres;
1107
1108     hres = to_object(ctx, &val, &disp);
1109     VariantClear(&val);
1110     if(FAILED(hres))
1111         return hres;
1112
1113     obj = iface_to_jsdisp((IUnknown*)disp);
1114     IDispatch_Release(disp);
1115     if(!obj) {
1116         FIXME("disp id not jsdisp\n");
1117         return E_NOTIMPL;
1118     }
1119
1120     hres = scope_push(ctx->exec_ctx->scope_chain, obj, &ctx->exec_ctx->scope_chain);
1121     jsdisp_release(obj);
1122     if(FAILED(hres))
1123         return hres;
1124
1125     hres = stat_eval(ctx, stat->statement, rt, ret);
1126
1127     scope_pop(&ctx->exec_ctx->scope_chain);
1128     return hres;
1129 }
1130
1131 /* ECMA-262 3rd Edition    12.12 */
1132 HRESULT labelled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
1133 {
1134     FIXME("\n");
1135     return E_NOTIMPL;
1136 }
1137
1138 /* ECMA-262 3rd Edition    12.13 */
1139 HRESULT switch_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1140 {
1141     switch_statement_t *stat = (switch_statement_t*)_stat;
1142     case_clausule_t *iter, *default_clausule = NULL;
1143     statement_t *stat_iter;
1144     VARIANT val, cval;
1145     BOOL b;
1146     HRESULT hres;
1147
1148     TRACE("\n");
1149
1150     hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &val);
1151     if(FAILED(hres))
1152         return hres;
1153
1154     for(iter = stat->case_list; iter; iter = iter->next) {
1155         if(!iter->expr) {
1156             default_clausule = iter;
1157             continue;
1158         }
1159
1160         hres = expr_eval(ctx, iter->expr, 0, &rt->ei, &cval);
1161         if(FAILED(hres))
1162             break;
1163
1164         hres = equal2_values(&val, &cval, &b);
1165         VariantClear(&cval);
1166         if(FAILED(hres) || b)
1167             break;
1168     }
1169
1170     VariantClear(&val);
1171     if(FAILED(hres))
1172         return hres;
1173
1174     if(!iter)
1175         iter = default_clausule;
1176
1177     V_VT(&val) = VT_EMPTY;
1178     if(iter) {
1179         VARIANT tmp;
1180
1181         for(stat_iter = iter->stat; stat_iter; stat_iter = stat_iter->next) {
1182             hres = stat_eval(ctx, stat_iter, rt, &tmp);
1183             if(FAILED(hres))
1184                 break;
1185
1186             VariantClear(&val);
1187             val = tmp;
1188
1189             if(rt->type != RT_NORMAL)
1190                 break;
1191         }
1192     }
1193
1194     if(FAILED(hres)) {
1195         VariantClear(&val);
1196         return hres;
1197     }
1198
1199     if(rt->type == RT_BREAK)
1200         rt->type = RT_NORMAL;
1201
1202     *ret = val;
1203     return S_OK;
1204 }
1205
1206 /* ECMA-262 3rd Edition    12.13 */
1207 HRESULT throw_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1208 {
1209     expression_statement_t *stat = (expression_statement_t*)_stat;
1210     VARIANT val;
1211     HRESULT hres;
1212
1213     TRACE("\n");
1214
1215     hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &val);
1216     if(FAILED(hres))
1217         return hres;
1218
1219     rt->ei.var = val;
1220     return DISP_E_EXCEPTION;
1221 }
1222
1223 static HRESULT interp_throw(exec_ctx_t *ctx)
1224 {
1225     const HRESULT arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1226
1227     TRACE("%08x\n", arg);
1228
1229     return throw_reference_error(ctx->parser->script, &ctx->ei, arg, NULL);
1230 }
1231
1232 static HRESULT interp_throw_type(exec_ctx_t *ctx)
1233 {
1234     const HRESULT hres = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1235     const WCHAR *str = ctx->parser->code->instrs[ctx->ip].arg2.str;
1236
1237     TRACE("%08x %s\n", hres, debugstr_w(str));
1238
1239     return throw_type_error(ctx->parser->script, &ctx->ei, hres, str);
1240 }
1241
1242 /* ECMA-262 3rd Edition    12.14 */
1243 static HRESULT catch_eval(script_ctx_t *ctx, catch_block_t *block, return_type_t *rt, VARIANT *ret)
1244 {
1245     jsdisp_t *var_disp;
1246     VARIANT ex, val;
1247     HRESULT hres;
1248
1249     ex = rt->ei.var;
1250     memset(&rt->ei, 0, sizeof(jsexcept_t));
1251
1252     hres = create_dispex(ctx, NULL, NULL, &var_disp);
1253     if(SUCCEEDED(hres)) {
1254         hres = jsdisp_propput_name(var_disp, block->identifier, &ex, &rt->ei, NULL/*FIXME*/);
1255         if(SUCCEEDED(hres)) {
1256             hres = scope_push(ctx->exec_ctx->scope_chain, var_disp, &ctx->exec_ctx->scope_chain);
1257             if(SUCCEEDED(hres)) {
1258                 hres = stat_eval(ctx, block->statement, rt, &val);
1259                 scope_pop(&ctx->exec_ctx->scope_chain);
1260             }
1261         }
1262
1263         jsdisp_release(var_disp);
1264     }
1265
1266     VariantClear(&ex);
1267     if(FAILED(hres))
1268         return hres;
1269
1270     *ret = val;
1271     return S_OK;
1272 }
1273
1274 /* ECMA-262 3rd Edition    12.14 */
1275 HRESULT try_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
1276 {
1277     try_statement_t *stat = (try_statement_t*)_stat;
1278     VARIANT val;
1279     HRESULT hres;
1280
1281     TRACE("\n");
1282
1283     hres = stat_eval(ctx, stat->try_statement, rt, &val);
1284     if(FAILED(hres)) {
1285         TRACE("EXCEPTION\n");
1286         if(!stat->catch_block)
1287             return hres;
1288
1289         hres = catch_eval(ctx, stat->catch_block, rt, &val);
1290         if(FAILED(hres))
1291             return hres;
1292     }
1293
1294     if(stat->finally_statement) {
1295         VariantClear(&val);
1296         hres = stat_eval(ctx, stat->finally_statement, rt, &val);
1297         if(FAILED(hres))
1298             return hres;
1299     }
1300
1301     *ret = val;
1302     return S_OK;
1303 }
1304
1305 /* ECMA-262 3rd Edition    13 */
1306 static HRESULT interp_func(exec_ctx_t *ctx)
1307 {
1308     function_expression_t *expr = ctx->parser->code->instrs[ctx->ip].arg1.func;
1309     jsdisp_t *dispex;
1310     VARIANT v;
1311     HRESULT hres;
1312
1313     TRACE("\n");
1314
1315     hres = create_source_function(ctx->parser, expr->parameter_list, expr->source_elements, ctx->scope_chain,
1316             expr->src_str, expr->src_len, &dispex);
1317     if(FAILED(hres))
1318         return hres;
1319
1320     var_set_jsdisp(&v, dispex);
1321     return stack_push(ctx, &v);
1322 }
1323
1324 /* ECMA-262 3rd Edition    11.2.1 */
1325 static HRESULT array_expression_eval(script_ctx_t *ctx, expression_t *_expr, jsexcept_t *ei, exprval_t *ret)
1326 {
1327     binary_expression_t *expr = (binary_expression_t*)_expr;
1328     VARIANT member, val;
1329     DISPID id;
1330     BSTR str;
1331     IDispatch *obj = NULL;
1332     HRESULT hres;
1333
1334     TRACE("\n");
1335
1336     hres = expr_eval(ctx, expr->expression1, 0, ei, &member);
1337     if(FAILED(hres))
1338         return hres;
1339
1340     hres = expr_eval(ctx, expr->expression2, 0, ei, &val);
1341     if(SUCCEEDED(hres)) {
1342         hres = to_object(ctx, &member, &obj);
1343         if(FAILED(hres))
1344             VariantClear(&val);
1345     }
1346     VariantClear(&member);
1347     if(SUCCEEDED(hres)) {
1348         hres = to_string(ctx, &val, ei, &str);
1349         VariantClear(&val);
1350         if(SUCCEEDED(hres)) {
1351             hres = disp_get_id(ctx, obj, str, fdexNameEnsure, &id);
1352             SysFreeString(str);
1353         }
1354
1355         if(SUCCEEDED(hres))
1356             exprval_set_idref(ret, obj, id);
1357
1358         IDispatch_Release(obj);
1359     }
1360
1361     return hres;
1362 }
1363
1364 /* ECMA-262 3rd Edition    11.2.1 */
1365 static HRESULT interp_array(exec_ctx_t *ctx)
1366 {
1367     VARIANT v, *namev;
1368     IDispatch *obj;
1369     DISPID id;
1370     BSTR name;
1371     HRESULT hres;
1372
1373     TRACE("\n");
1374
1375     namev = stack_pop(ctx);
1376
1377     hres = stack_pop_object(ctx, &obj);
1378     if(FAILED(hres)) {
1379         VariantClear(namev);
1380         return hres;
1381     }
1382
1383     hres = to_string(ctx->parser->script, namev, &ctx->ei, &name);
1384     VariantClear(namev);
1385     if(FAILED(hres)) {
1386         IDispatch_Release(obj);
1387         return hres;
1388     }
1389
1390     hres = disp_get_id(ctx->parser->script, obj, name, 0, &id);
1391     SysFreeString(name);
1392     if(SUCCEEDED(hres)) {
1393         hres = disp_propget(ctx->parser->script, obj, id, &v, &ctx->ei, NULL/*FIXME*/);
1394     }else if(hres == DISP_E_UNKNOWNNAME) {
1395         V_VT(&v) = VT_EMPTY;
1396         hres = S_OK;
1397     }
1398     IDispatch_Release(obj);
1399     if(FAILED(hres))
1400         return hres;
1401
1402     return stack_push(ctx, &v);
1403 }
1404
1405 /* ECMA-262 3rd Edition    11.2.1 */
1406 static HRESULT member_expression_eval(script_ctx_t *ctx, expression_t *_expr, jsexcept_t *ei, exprval_t *ret)
1407 {
1408     member_expression_t *expr = (member_expression_t*)_expr;
1409     IDispatch *obj = NULL;
1410     VARIANT member;
1411     DISPID id;
1412     BSTR str;
1413     HRESULT hres;
1414
1415     TRACE("\n");
1416
1417     hres = expr_eval(ctx, expr->expression, 0, ei, &member);
1418     if(FAILED(hres))
1419         return hres;
1420
1421     hres = to_object(ctx, &member, &obj);
1422     VariantClear(&member);
1423     if(FAILED(hres))
1424         return hres;
1425
1426     str = SysAllocString(expr->identifier);
1427     if(!str) {
1428         IDispatch_Release(obj);
1429         return E_OUTOFMEMORY;
1430     }
1431
1432     hres = disp_get_id(ctx, obj, str, fdexNameEnsure, &id);
1433     SysFreeString(str);
1434     if(SUCCEEDED(hres))
1435         exprval_set_idref(ret, obj, id);
1436
1437     IDispatch_Release(obj);
1438     return hres;
1439 }
1440
1441 /* ECMA-262 3rd Edition    11.2.1 */
1442 static HRESULT interp_member(exec_ctx_t *ctx)
1443 {
1444     const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1445     IDispatch *obj;
1446     VARIANT v;
1447     DISPID id;
1448     HRESULT hres;
1449
1450     TRACE("\n");
1451
1452     hres = stack_pop_object(ctx, &obj);
1453     if(FAILED(hres))
1454         return hres;
1455
1456     hres = disp_get_id(ctx->parser->script, obj, arg, 0, &id);
1457     if(SUCCEEDED(hres)) {
1458         V_VT(&v) = VT_EMPTY;
1459         hres = disp_propget(ctx->parser->script, obj, id, &v, &ctx->ei, NULL/*FIXME*/);
1460     }else if(hres == DISP_E_UNKNOWNNAME) {
1461         V_VT(&v) = VT_EMPTY;
1462         hres = S_OK;
1463     }
1464     IDispatch_Release(obj);
1465     if(FAILED(hres))
1466         return hres;
1467
1468     return stack_push(ctx, &v);
1469 }
1470
1471 /* ECMA-262 3rd Edition    11.2.1 */
1472 static HRESULT interp_memberid(exec_ctx_t *ctx)
1473 {
1474     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1475     VARIANT *objv, *namev;
1476     IDispatch *obj;
1477     BSTR name;
1478     DISPID id;
1479     HRESULT hres;
1480
1481     TRACE("%x\n", arg);
1482
1483     namev = stack_pop(ctx);
1484     objv = stack_pop(ctx);
1485
1486     hres = to_object(ctx->parser->script, objv, &obj);
1487     VariantClear(objv);
1488     if(SUCCEEDED(hres)) {
1489         hres = to_string(ctx->parser->script, namev, &ctx->ei, &name);
1490         if(FAILED(hres))
1491             IDispatch_Release(obj);
1492     }
1493     VariantClear(namev);
1494     if(FAILED(hres))
1495         return hres;
1496
1497     hres = disp_get_id(ctx->parser->script, obj, name, arg, &id);
1498     SysFreeString(name);
1499     if(FAILED(hres)) {
1500         IDispatch_Release(obj);
1501         if(hres == DISP_E_UNKNOWNNAME && !(arg & fdexNameEnsure)) {
1502             obj = NULL;
1503             id = JS_E_INVALID_PROPERTY;
1504         }else {
1505             return hres;
1506         }
1507     }
1508
1509     return stack_push_objid(ctx, obj, id);
1510 }
1511
1512 /* ECMA-262 3rd Edition    11.2.1 */
1513 static HRESULT interp_refval(exec_ctx_t *ctx)
1514 {
1515     IDispatch *disp;
1516     VARIANT v;
1517     DISPID id;
1518     HRESULT hres;
1519
1520     TRACE("\n");
1521
1522     disp = stack_topn_objid(ctx, 0, &id);
1523     if(!disp)
1524         return throw_reference_error(ctx->parser->script, &ctx->ei, JS_E_ILLEGAL_ASSIGN, NULL);
1525
1526     hres = disp_propget(ctx->parser->script, disp, id, &v, &ctx->ei, NULL/*FIXME*/);
1527     if(FAILED(hres))
1528         return hres;
1529
1530     return stack_push(ctx, &v);
1531 }
1532
1533 static void jsstack_to_dp(exec_ctx_t *ctx, unsigned arg_cnt, DISPPARAMS *dp)
1534 {
1535     VARIANT tmp;
1536     unsigned i;
1537
1538     dp->cArgs = arg_cnt;
1539     dp->rgdispidNamedArgs = NULL;
1540     dp->cNamedArgs = 0;
1541
1542     assert(ctx->top >= arg_cnt);
1543
1544     for(i=1; i*2 <= arg_cnt; i++) {
1545         tmp = ctx->stack[ctx->top-i];
1546         ctx->stack[ctx->top-i] = ctx->stack[ctx->top-arg_cnt+i-1];
1547         ctx->stack[ctx->top-arg_cnt+i-1] = tmp;
1548     }
1549
1550     dp->rgvarg = ctx->stack + ctx->top-arg_cnt;
1551 }
1552
1553 /* ECMA-262 3rd Edition    11.2.2 */
1554 static HRESULT interp_new(exec_ctx_t *ctx)
1555 {
1556     const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1557     VARIANT *constr, v;
1558     DISPPARAMS dp;
1559     HRESULT hres;
1560
1561     TRACE("%d\n", arg);
1562
1563     constr = stack_topn(ctx, arg);
1564
1565     /* NOTE: Should use to_object here */
1566
1567     if(V_VT(constr) == VT_NULL)
1568         return throw_type_error(ctx->parser->script, &ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
1569     else if(V_VT(constr) != VT_DISPATCH)
1570         return throw_type_error(ctx->parser->script, &ctx->ei, JS_E_INVALID_ACTION, NULL);
1571     else if(!V_DISPATCH(constr))
1572         return throw_type_error(ctx->parser->script, &ctx->ei, JS_E_INVALID_PROPERTY, NULL);
1573
1574     jsstack_to_dp(ctx, arg, &dp);
1575     hres = disp_call(ctx->parser->script, V_DISPATCH(constr), DISPID_VALUE,
1576             DISPATCH_CONSTRUCT, &dp, &v, &ctx->ei, NULL/*FIXME*/);
1577     if(FAILED(hres))
1578         return hres;
1579
1580     stack_popn(ctx, arg+1);
1581     return stack_push(ctx, &v);
1582 }
1583
1584 /* ECMA-262 3rd Edition    11.2.3 */
1585 static HRESULT interp_call(exec_ctx_t *ctx)
1586 {
1587     const unsigned argn = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1588     const int do_ret = ctx->parser->code->instrs[ctx->ip].arg2.lng;
1589     VARIANT v, *objv;
1590     DISPPARAMS dp;
1591     HRESULT hres;
1592
1593     TRACE("%d %d\n", argn, do_ret);
1594
1595     objv = stack_topn(ctx, argn);
1596     if(V_VT(objv) != VT_DISPATCH)
1597         return throw_type_error(ctx->parser->script, &ctx->ei, JS_E_INVALID_PROPERTY, NULL);
1598
1599     jsstack_to_dp(ctx, argn, &dp);
1600     hres = disp_call(ctx->parser->script, V_DISPATCH(objv), DISPID_VALUE, DISPATCH_METHOD, &dp,
1601             do_ret ? &v : NULL, &ctx->ei, NULL/*FIXME*/);
1602     if(FAILED(hres))
1603         return hres;
1604
1605     stack_popn(ctx, argn+1);
1606     return do_ret ? stack_push(ctx, &v) : S_OK;
1607
1608 }
1609
1610 /* ECMA-262 3rd Edition    11.2.3 */
1611 static HRESULT interp_call_member(exec_ctx_t *ctx)
1612 {
1613     const unsigned argn = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1614     const int do_ret = ctx->parser->code->instrs[ctx->ip].arg2.lng;
1615     IDispatch *obj;
1616     DISPPARAMS dp;
1617     VARIANT v;
1618     DISPID id;
1619     HRESULT hres;
1620
1621     TRACE("%d %d\n", argn, do_ret);
1622
1623     obj = stack_topn_objid(ctx, argn, &id);
1624     if(!obj)
1625         return throw_type_error(ctx->parser->script, &ctx->ei, id, NULL);
1626
1627     jsstack_to_dp(ctx, argn, &dp);
1628     hres = disp_call(ctx->parser->script, obj, id, DISPATCH_METHOD, &dp, do_ret ? &v : NULL, &ctx->ei, NULL/*FIXME*/);
1629     if(FAILED(hres))
1630         return hres;
1631
1632     stack_popn(ctx, argn+2);
1633     return do_ret ? stack_push(ctx, &v) : S_OK;
1634
1635 }
1636
1637 /* ECMA-262 3rd Edition    11.1.1 */
1638 static HRESULT interp_this(exec_ctx_t *ctx)
1639 {
1640     VARIANT v;
1641
1642     TRACE("\n");
1643
1644     V_VT(&v) = VT_DISPATCH;
1645     V_DISPATCH(&v) = ctx->this_obj;
1646     IDispatch_AddRef(ctx->this_obj);
1647     return stack_push(ctx, &v);
1648 }
1649
1650 /* ECMA-262 3rd Edition    10.1.4 */
1651 static HRESULT identifier_expression_eval(script_ctx_t *ctx, expression_t *_expr, jsexcept_t *ei, exprval_t *ret)
1652 {
1653     identifier_expression_t *expr = (identifier_expression_t*)_expr;
1654     BSTR identifier;
1655     HRESULT hres;
1656
1657     TRACE("\n");
1658
1659     identifier = SysAllocString(expr->identifier);
1660     if(!identifier)
1661         return E_OUTOFMEMORY;
1662
1663     hres = identifier_eval(ctx, identifier, fdexNameEnsure, ei, ret);
1664
1665     SysFreeString(identifier);
1666     return hres;
1667 }
1668
1669 /* ECMA-262 3rd Edition    10.1.4 */
1670 static HRESULT interp_ident(exec_ctx_t *ctx)
1671 {
1672     const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1673     exprval_t exprval;
1674     VARIANT v;
1675     HRESULT hres;
1676
1677     TRACE("%s\n", debugstr_w(arg));
1678
1679     hres = identifier_eval(ctx->parser->script, arg, 0, &ctx->ei, &exprval);
1680     if(FAILED(hres))
1681         return hres;
1682
1683     hres = exprval_to_value(ctx->parser->script, &exprval, &ctx->ei, &v);
1684     exprval_release(&exprval);
1685     if(FAILED(hres))
1686         return hres;
1687
1688     return stack_push(ctx, &v);
1689 }
1690
1691 /* ECMA-262 3rd Edition    10.1.4 */
1692 static HRESULT interp_identid(exec_ctx_t *ctx)
1693 {
1694     const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1695     const unsigned flags = ctx->parser->code->instrs[ctx->ip].arg2.uint;
1696     exprval_t exprval;
1697     HRESULT hres;
1698
1699     TRACE("%s %x\n", debugstr_w(arg), flags);
1700
1701     hres = identifier_eval(ctx->parser->script, arg, flags, &ctx->ei, &exprval);
1702     if(FAILED(hres))
1703         return hres;
1704
1705     if(exprval.type != EXPRVAL_IDREF) {
1706         WARN("invalid ref\n");
1707         exprval_release(&exprval);
1708         return stack_push_objid(ctx, NULL, JS_E_OBJECT_EXPECTED);
1709     }
1710
1711     return stack_push_objid(ctx, exprval.u.idref.disp, exprval.u.idref.id);
1712 }
1713
1714 /* ECMA-262 3rd Edition    7.8.1 */
1715 static HRESULT interp_null(exec_ctx_t *ctx)
1716 {
1717     VARIANT v;
1718
1719     TRACE("\n");
1720
1721     V_VT(&v) = VT_NULL;
1722     return stack_push(ctx, &v);
1723 }
1724
1725 /* ECMA-262 3rd Edition    7.8.2 */
1726 static HRESULT interp_bool(exec_ctx_t *ctx)
1727 {
1728     const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1729
1730     TRACE("%s\n", arg ? "true" : "false");
1731
1732     return stack_push_bool(ctx, arg);
1733 }
1734
1735 /* ECMA-262 3rd Edition    7.8.3 */
1736 static HRESULT interp_int(exec_ctx_t *ctx)
1737 {
1738     const LONG arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
1739     VARIANT v;
1740
1741     TRACE("%d\n", arg);
1742
1743     V_VT(&v) = VT_I4;
1744     V_I4(&v) = arg;
1745     return stack_push(ctx, &v);
1746 }
1747
1748 /* ECMA-262 3rd Edition    7.8.3 */
1749 static HRESULT interp_double(exec_ctx_t *ctx)
1750 {
1751     const double arg = *ctx->parser->code->instrs[ctx->ip].arg1.dbl;
1752     VARIANT v;
1753
1754     TRACE("%lf\n", arg);
1755
1756     V_VT(&v) = VT_R8;
1757     V_R8(&v) = arg;
1758     return stack_push(ctx, &v);
1759 }
1760
1761 /* ECMA-262 3rd Edition    7.8.4 */
1762 static HRESULT interp_str(exec_ctx_t *ctx)
1763 {
1764     const WCHAR *str = ctx->parser->code->instrs[ctx->ip].arg1.str;
1765     VARIANT v;
1766
1767     TRACE("%s\n", debugstr_w(str));
1768
1769     V_VT(&v) = VT_BSTR;
1770     V_BSTR(&v) = SysAllocString(str);
1771     if(!V_BSTR(&v))
1772         return E_OUTOFMEMORY;
1773
1774     return stack_push(ctx, &v);
1775 }
1776
1777 /* ECMA-262 3rd Edition    7.8 */
1778 static HRESULT interp_regexp(exec_ctx_t *ctx)
1779 {
1780     const WCHAR *source = ctx->parser->code->instrs[ctx->ip].arg1.str;
1781     const LONG flags = ctx->parser->code->instrs[ctx->ip].arg2.lng;
1782     jsdisp_t *regexp;
1783     VARIANT v;
1784     HRESULT hres;
1785
1786     TRACE("%s %x\n", debugstr_w(source), flags);
1787
1788     hres = create_regexp(ctx->parser->script, source, strlenW(source), flags, &regexp);
1789     if(FAILED(hres))
1790         return hres;
1791
1792     var_set_jsdisp(&v, regexp);
1793     return stack_push(ctx, &v);
1794 }
1795
1796 /* ECMA-262 3rd Edition    11.1.4 */
1797 static HRESULT interp_carray(exec_ctx_t *ctx)
1798 {
1799     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1800     jsdisp_t *array;
1801     VARIANT *v, r;
1802     unsigned i;
1803     HRESULT hres;
1804
1805     TRACE("%u\n", arg);
1806
1807     hres = create_array(ctx->parser->script, arg, &array);
1808     if(FAILED(hres))
1809         return hres;
1810
1811     i = arg;
1812     while(i--) {
1813         v = stack_pop(ctx);
1814         hres = jsdisp_propput_idx(array, i, v, &ctx->ei, NULL/*FIXME*/);
1815         VariantClear(v);
1816         if(FAILED(hres)) {
1817             jsdisp_release(array);
1818             return hres;
1819         }
1820     }
1821
1822     var_set_jsdisp(&r, array);
1823     return stack_push(ctx, &r);
1824 }
1825
1826 /* ECMA-262 3rd Edition    11.1.5 */
1827 HRESULT interp_new_obj(exec_ctx_t *ctx)
1828 {
1829     jsdisp_t *obj;
1830     VARIANT v;
1831     HRESULT hres;
1832
1833     TRACE("\n");
1834
1835     hres = create_object(ctx->parser->script, NULL, &obj);
1836     if(FAILED(hres))
1837         return hres;
1838
1839     var_set_jsdisp(&v, obj);
1840     return stack_push(ctx, &v);
1841 }
1842
1843 /* ECMA-262 3rd Edition    11.1.5 */
1844 HRESULT interp_obj_prop(exec_ctx_t *ctx)
1845 {
1846     const BSTR name = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
1847     jsdisp_t *obj;
1848     VARIANT *v;
1849     HRESULT hres;
1850
1851     TRACE("%s\n", debugstr_w(name));
1852
1853     v = stack_pop(ctx);
1854
1855     assert(V_VT(stack_top(ctx)) == VT_DISPATCH);
1856     obj = as_jsdisp(V_DISPATCH(stack_top(ctx)));
1857
1858     hres = jsdisp_propput_name(obj, name, v, &ctx->ei, NULL/*FIXME*/);
1859     VariantClear(v);
1860     return hres;
1861 }
1862
1863 /* ECMA-262 3rd Edition    11.11 */
1864 static HRESULT interp_jmp_nz(exec_ctx_t *ctx)
1865 {
1866     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1867     VARIANT_BOOL b;
1868     HRESULT hres;
1869
1870     TRACE("\n");
1871
1872     hres = to_boolean(stack_top(ctx), &b);
1873     if(FAILED(hres))
1874         return hres;
1875
1876     if(b) {
1877         ctx->ip = arg;
1878     }else {
1879         stack_popn(ctx, 1);
1880         ctx->ip++;
1881     }
1882     return S_OK;
1883 }
1884
1885 /* ECMA-262 3rd Edition    11.11 */
1886 static HRESULT interp_jmp_z(exec_ctx_t *ctx)
1887 {
1888     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
1889     VARIANT_BOOL b;
1890     HRESULT hres;
1891
1892     TRACE("\n");
1893
1894     hres = to_boolean(stack_top(ctx), &b);
1895     if(FAILED(hres))
1896         return hres;
1897
1898     if(b) {
1899         stack_popn(ctx, 1);
1900         ctx->ip++;
1901     }else {
1902         ctx->ip = arg;
1903     }
1904     return S_OK;
1905 }
1906
1907 /* ECMA-262 3rd Edition    11.10 */
1908 static HRESULT interp_or(exec_ctx_t *ctx)
1909 {
1910     INT l, r;
1911     HRESULT hres;
1912
1913     TRACE("\n");
1914
1915     hres = stack_pop_int(ctx, &r);
1916     if(FAILED(hres))
1917         return hres;
1918
1919     hres = stack_pop_int(ctx, &l);
1920     if(FAILED(hres))
1921         return hres;
1922
1923     return stack_push_int(ctx, l|r);
1924 }
1925
1926 /* ECMA-262 3rd Edition    11.10 */
1927 static HRESULT interp_xor(exec_ctx_t *ctx)
1928 {
1929     INT l, r;
1930     HRESULT hres;
1931
1932     TRACE("\n");
1933
1934     hres = stack_pop_int(ctx, &r);
1935     if(FAILED(hres))
1936         return hres;
1937
1938     hres = stack_pop_int(ctx, &l);
1939     if(FAILED(hres))
1940         return hres;
1941
1942     return stack_push_int(ctx, l^r);
1943 }
1944
1945 /* ECMA-262 3rd Edition    11.10 */
1946 static HRESULT interp_and(exec_ctx_t *ctx)
1947 {
1948     INT l, r;
1949     HRESULT hres;
1950
1951     TRACE("\n");
1952
1953     hres = stack_pop_int(ctx, &r);
1954     if(FAILED(hres))
1955         return hres;
1956
1957     hres = stack_pop_int(ctx, &l);
1958     if(FAILED(hres))
1959         return hres;
1960
1961     return stack_push_int(ctx, l&r);
1962 }
1963
1964 /* ECMA-262 3rd Edition    11.8.6 */
1965 static HRESULT interp_instanceof(exec_ctx_t *ctx)
1966 {
1967     jsdisp_t *obj, *iter, *tmp = NULL;
1968     VARIANT prot, *v;
1969     BOOL ret = FALSE;
1970     HRESULT hres;
1971
1972     static const WCHAR prototypeW[] = {'p','r','o','t','o','t', 'y', 'p','e',0};
1973
1974     v = stack_pop(ctx);
1975     if(V_VT(v) != VT_DISPATCH || !V_DISPATCH(v)) {
1976         VariantClear(v);
1977         return throw_type_error(ctx->parser->script, &ctx->ei, JS_E_FUNCTION_EXPECTED, NULL);
1978     }
1979
1980     obj = iface_to_jsdisp((IUnknown*)V_DISPATCH(v));
1981     IDispatch_Release(V_DISPATCH(v));
1982     if(!obj) {
1983         FIXME("non-jsdisp objects not supported\n");
1984         return E_FAIL;
1985     }
1986
1987     if(is_class(obj, JSCLASS_FUNCTION)) {
1988         hres = jsdisp_propget_name(obj, prototypeW, &prot, &ctx->ei, NULL/*FIXME*/);
1989     }else {
1990         hres = throw_type_error(ctx->parser->script, &ctx->ei, JS_E_FUNCTION_EXPECTED, NULL);
1991     }
1992     jsdisp_release(obj);
1993     if(FAILED(hres))
1994         return hres;
1995
1996     v = stack_pop(ctx);
1997
1998     if(V_VT(&prot) == VT_DISPATCH) {
1999         if(V_VT(v) == VT_DISPATCH)
2000             tmp = iface_to_jsdisp((IUnknown*)V_DISPATCH(v));
2001         for(iter = tmp; !ret && iter; iter = iter->prototype) {
2002             hres = disp_cmp(V_DISPATCH(&prot), to_disp(iter), &ret);
2003             if(FAILED(hres))
2004                 break;
2005         }
2006
2007         if(tmp)
2008             jsdisp_release(tmp);
2009     }else {
2010         FIXME("prototype is not an object\n");
2011         hres = E_FAIL;
2012     }
2013
2014     VariantClear(&prot);
2015     VariantClear(v);
2016     if(FAILED(hres))
2017         return hres;
2018
2019     return stack_push_bool(ctx, ret);
2020 }
2021
2022 /* ECMA-262 3rd Edition    11.8.7 */
2023 static HRESULT interp_in(exec_ctx_t *ctx)
2024 {
2025     VARIANT *obj, *v;
2026     DISPID id = 0;
2027     BOOL ret;
2028     BSTR str;
2029     HRESULT hres;
2030
2031     TRACE("\n");
2032
2033     obj = stack_pop(ctx);
2034     v = stack_pop(ctx);
2035
2036     if(V_VT(obj) != VT_DISPATCH || !V_DISPATCH(obj)) {
2037         VariantClear(obj);
2038         VariantClear(v);
2039         return throw_type_error(ctx->parser->script, &ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
2040     }
2041
2042     hres = to_string(ctx->parser->script, v, &ctx->ei, &str);
2043     VariantClear(v);
2044     if(FAILED(hres)) {
2045         IDispatch_Release(V_DISPATCH(obj));
2046         return hres;
2047     }
2048
2049     hres = disp_get_id(ctx->parser->script, V_DISPATCH(obj), str, 0, &id);
2050     IDispatch_Release(V_DISPATCH(obj));
2051     SysFreeString(str);
2052     if(SUCCEEDED(hres))
2053         ret = TRUE;
2054     else if(hres == DISP_E_UNKNOWNNAME)
2055         ret = FALSE;
2056     else
2057         return hres;
2058
2059     return stack_push_bool(ctx, ret);
2060 }
2061
2062 /* ECMA-262 3rd Edition    11.6.1 */
2063 static HRESULT add_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
2064 {
2065     VARIANT r, l;
2066     HRESULT hres;
2067
2068     hres = to_primitive(ctx, lval, ei, &l, NO_HINT);
2069     if(FAILED(hres))
2070         return hres;
2071
2072     hres = to_primitive(ctx, rval, ei, &r, NO_HINT);
2073     if(FAILED(hres)) {
2074         VariantClear(&l);
2075         return hres;
2076     }
2077
2078     if(V_VT(&l) == VT_BSTR || V_VT(&r) == VT_BSTR) {
2079         BSTR lstr = NULL, rstr = NULL;
2080
2081         if(V_VT(&l) == VT_BSTR)
2082             lstr = V_BSTR(&l);
2083         else
2084             hres = to_string(ctx, &l, ei, &lstr);
2085
2086         if(SUCCEEDED(hres)) {
2087             if(V_VT(&r) == VT_BSTR)
2088                 rstr = V_BSTR(&r);
2089             else
2090                 hres = to_string(ctx, &r, ei, &rstr);
2091         }
2092
2093         if(SUCCEEDED(hres)) {
2094             int len1, len2;
2095
2096             len1 = SysStringLen(lstr);
2097             len2 = SysStringLen(rstr);
2098
2099             V_VT(retv) = VT_BSTR;
2100             V_BSTR(retv) = SysAllocStringLen(NULL, len1+len2);
2101             memcpy(V_BSTR(retv), lstr, len1*sizeof(WCHAR));
2102             memcpy(V_BSTR(retv)+len1, rstr, (len2+1)*sizeof(WCHAR));
2103         }
2104
2105         if(V_VT(&l) != VT_BSTR)
2106             SysFreeString(lstr);
2107         if(V_VT(&r) != VT_BSTR)
2108             SysFreeString(rstr);
2109     }else {
2110         VARIANT nl, nr;
2111
2112         hres = to_number(ctx, &l, ei, &nl);
2113         if(SUCCEEDED(hres)) {
2114             hres = to_number(ctx, &r, ei, &nr);
2115             if(SUCCEEDED(hres))
2116                 num_set_val(retv, num_val(&nl) + num_val(&nr));
2117         }
2118     }
2119
2120     VariantClear(&r);
2121     VariantClear(&l);
2122     return hres;
2123 }
2124
2125 /* ECMA-262 3rd Edition    11.6.1 */
2126 static HRESULT interp_add(exec_ctx_t *ctx)
2127 {
2128     VARIANT *l, *r, ret;
2129     HRESULT hres;
2130
2131     r = stack_pop(ctx);
2132     l = stack_pop(ctx);
2133
2134     TRACE("%s + %s\n", debugstr_variant(l), debugstr_variant(r));
2135
2136     hres = add_eval(ctx->parser->script, l, r, &ctx->ei, &ret);
2137     VariantClear(l);
2138     VariantClear(r);
2139     if(FAILED(hres))
2140         return hres;
2141
2142     return stack_push(ctx, &ret);
2143 }
2144
2145 /* ECMA-262 3rd Edition    11.6.2 */
2146 static HRESULT interp_sub(exec_ctx_t *ctx)
2147 {
2148     VARIANT l, r;
2149     HRESULT hres;
2150
2151     TRACE("\n");
2152
2153     hres = stack_pop_number(ctx, &r);
2154     if(FAILED(hres))
2155         return hres;
2156
2157     hres = stack_pop_number(ctx, &l);
2158     if(FAILED(hres))
2159         return hres;
2160
2161     return stack_push_number(ctx, num_val(&l)-num_val(&r));
2162 }
2163
2164 /* ECMA-262 3rd Edition    11.5.1 */
2165 static HRESULT interp_mul(exec_ctx_t *ctx)
2166 {
2167     VARIANT l, r;
2168     HRESULT hres;
2169
2170     TRACE("\n");
2171
2172     hres = stack_pop_number(ctx, &r);
2173     if(FAILED(hres))
2174         return hres;
2175
2176     hres = stack_pop_number(ctx, &l);
2177     if(FAILED(hres))
2178         return hres;
2179
2180     return stack_push_number(ctx, num_val(&l)*num_val(&r));
2181 }
2182
2183 /* ECMA-262 3rd Edition    11.5.2 */
2184 static HRESULT interp_div(exec_ctx_t *ctx)
2185 {
2186     VARIANT l, r;
2187     HRESULT hres;
2188
2189     TRACE("\n");
2190
2191     hres = stack_pop_number(ctx, &r);
2192     if(FAILED(hres))
2193         return hres;
2194
2195     hres = stack_pop_number(ctx, &l);
2196     if(FAILED(hres))
2197         return hres;
2198
2199     return stack_push_number(ctx, num_val(&l)/num_val(&r));
2200 }
2201
2202 /* ECMA-262 3rd Edition    11.5.3 */
2203 static HRESULT interp_mod(exec_ctx_t *ctx)
2204 {
2205     VARIANT l, r;
2206     HRESULT hres;
2207
2208     TRACE("\n");
2209
2210     hres = stack_pop_number(ctx, &r);
2211     if(FAILED(hres))
2212         return hres;
2213
2214     hres = stack_pop_number(ctx, &l);
2215     if(FAILED(hres))
2216         return hres;
2217
2218     return stack_push_number(ctx, fmod(num_val(&l), num_val(&r)));
2219 }
2220
2221 /* ECMA-262 3rd Edition    11.4.2 */
2222 static HRESULT interp_delete(exec_ctx_t *ctx)
2223 {
2224     VARIANT *obj_var, *name_var;
2225     IDispatchEx *dispex;
2226     IDispatch *obj;
2227     BSTR name;
2228     BOOL ret;
2229     HRESULT hres;
2230
2231     TRACE("\n");
2232
2233     name_var = stack_pop(ctx);
2234     obj_var = stack_pop(ctx);
2235
2236     hres = to_object(ctx->parser->script, obj_var, &obj);
2237     VariantClear(obj_var);
2238     if(FAILED(hres)) {
2239         VariantClear(name_var);
2240         return hres;
2241     }
2242
2243     hres = to_string(ctx->parser->script, name_var, &ctx->ei, &name);
2244     VariantClear(name_var);
2245     if(FAILED(hres)) {
2246         IDispatch_Release(obj);
2247         return hres;
2248     }
2249
2250     hres = IDispatch_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex);
2251     if(SUCCEEDED(hres)) {
2252         hres = IDispatchEx_DeleteMemberByName(dispex, name, make_grfdex(ctx->parser->script, fdexNameCaseSensitive));
2253         ret = TRUE;
2254         IDispatchEx_Release(dispex);
2255     }else {
2256         hres = S_OK;
2257         ret = FALSE;
2258     }
2259
2260     IDispatch_Release(obj);
2261     SysFreeString(name);
2262     if(FAILED(hres))
2263         return hres;
2264
2265     return stack_push_bool(ctx, ret);
2266 }
2267
2268 /* ECMA-262 3rd Edition    11.4.2 */
2269 static HRESULT interp_delete_ident(exec_ctx_t *ctx)
2270 {
2271     const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
2272     IDispatchEx *dispex;
2273     exprval_t exprval;
2274     BOOL ret = FALSE;
2275     HRESULT hres;
2276
2277     TRACE("%s\n", debugstr_w(arg));
2278
2279     hres = identifier_eval(ctx->parser->script, arg, 0, &ctx->ei, &exprval);
2280     if(FAILED(hres))
2281         return hres;
2282
2283     if(exprval.type != EXPRVAL_IDREF) {
2284         FIXME("Unsupported exprval\n");
2285         exprval_release(&exprval);
2286         return E_NOTIMPL;
2287     }
2288
2289     hres = IDispatch_QueryInterface(exprval.u.idref.disp, &IID_IDispatchEx, (void**)&dispex);
2290     IDispatch_Release(exprval.u.idref.disp);
2291     if(SUCCEEDED(hres)) {
2292         hres = IDispatchEx_DeleteMemberByDispID(dispex, exprval.u.idref.id);
2293         IDispatchEx_Release(dispex);
2294         if(FAILED(hres))
2295             return hres;
2296
2297         ret = TRUE;
2298     }
2299
2300     return stack_push_bool(ctx, ret);
2301 }
2302
2303 /* ECMA-262 3rd Edition    11.4.2 */
2304 static HRESULT interp_void(exec_ctx_t *ctx)
2305 {
2306     VARIANT v;
2307
2308     TRACE("\n");
2309
2310     stack_popn(ctx, 1);
2311
2312     V_VT(&v) = VT_EMPTY;
2313     return stack_push(ctx, &v);
2314 }
2315
2316 /* ECMA-262 3rd Edition    11.4.3 */
2317 static HRESULT typeof_string(VARIANT *v, const WCHAR **ret)
2318 {
2319     switch(V_VT(v)) {
2320     case VT_EMPTY:
2321         *ret = undefinedW;
2322         break;
2323     case VT_NULL:
2324         *ret = objectW;
2325         break;
2326     case VT_BOOL:
2327         *ret = booleanW;
2328         break;
2329     case VT_I4:
2330     case VT_R8:
2331         *ret = numberW;
2332         break;
2333     case VT_BSTR:
2334         *ret = stringW;
2335         break;
2336     case VT_DISPATCH: {
2337         jsdisp_t *dispex;
2338
2339         if(V_DISPATCH(v) && (dispex = iface_to_jsdisp((IUnknown*)V_DISPATCH(v)))) {
2340             *ret = is_class(dispex, JSCLASS_FUNCTION) ? functionW : objectW;
2341             jsdisp_release(dispex);
2342         }else {
2343             *ret = objectW;
2344         }
2345         break;
2346     }
2347     default:
2348         FIXME("unhandled vt %d\n", V_VT(v));
2349         return E_NOTIMPL;
2350     }
2351
2352     return S_OK;
2353 }
2354
2355 /* ECMA-262 3rd Edition    11.4.3 */
2356 static HRESULT interp_typeofid(exec_ctx_t *ctx)
2357 {
2358     const WCHAR *ret;
2359     IDispatch *obj;
2360     VARIANT v;
2361     DISPID id;
2362     HRESULT hres;
2363
2364     static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
2365
2366     TRACE("\n");
2367
2368     obj = stack_pop_objid(ctx, &id);
2369     if(!obj)
2370         return stack_push_string(ctx, undefinedW);
2371
2372     V_VT(&v) = VT_EMPTY;
2373     hres = disp_propget(ctx->parser->script, obj, id, &v, &ctx->ei, NULL/*FIXME*/);
2374     IDispatch_Release(obj);
2375     if(FAILED(hres))
2376         return stack_push_string(ctx, unknownW);
2377
2378     hres = typeof_string(&v, &ret);
2379     VariantClear(&v);
2380     if(FAILED(hres))
2381         return hres;
2382
2383     return stack_push_string(ctx, ret);
2384 }
2385
2386 /* ECMA-262 3rd Edition    11.4.3 */
2387 static HRESULT interp_typeofident(exec_ctx_t *ctx)
2388 {
2389     const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
2390     exprval_t exprval;
2391     const WCHAR *ret;
2392     VARIANT v;
2393     HRESULT hres;
2394
2395     TRACE("%s\n", debugstr_w(arg));
2396
2397     hres = identifier_eval(ctx->parser->script, arg, 0, &ctx->ei, &exprval);
2398     if(FAILED(hres))
2399         return hres;
2400
2401     if(exprval.type == EXPRVAL_INVALID) {
2402         hres = stack_push_string(ctx, undefinedW);
2403         exprval_release(&exprval);
2404         return hres;
2405     }
2406
2407     hres = exprval_to_value(ctx->parser->script, &exprval, &ctx->ei, &v);
2408     exprval_release(&exprval);
2409     if(FAILED(hres))
2410         return hres;
2411
2412     hres = typeof_string(&v, &ret);
2413     VariantClear(&v);
2414     if(FAILED(hres))
2415         return hres;
2416
2417     return stack_push_string(ctx, ret);
2418 }
2419
2420 /* ECMA-262 3rd Edition    11.4.3 */
2421 static HRESULT interp_typeof(exec_ctx_t *ctx)
2422 {
2423     const WCHAR *ret;
2424     VARIANT *v;
2425     HRESULT hres;
2426
2427     TRACE("\n");
2428
2429     v = stack_pop(ctx);
2430     hres = typeof_string(v, &ret);
2431     VariantClear(v);
2432     if(FAILED(hres))
2433         return hres;
2434
2435     return stack_push_string(ctx, ret);
2436 }
2437
2438 /* ECMA-262 3rd Edition    11.4.7 */
2439 static HRESULT interp_minus(exec_ctx_t *ctx)
2440 {
2441     VARIANT n;
2442     HRESULT hres;
2443
2444     TRACE("\n");
2445
2446     hres = stack_pop_number(ctx, &n);
2447     if(FAILED(hres))
2448         return hres;
2449
2450     return stack_push_number(ctx, -num_val(&n));
2451 }
2452
2453 /* ECMA-262 3rd Edition    11.4.6 */
2454 static HRESULT interp_tonum(exec_ctx_t *ctx)
2455 {
2456     VARIANT *v, num;
2457     HRESULT hres;
2458
2459     TRACE("\n");
2460
2461     v = stack_pop(ctx);
2462     hres = to_number(ctx->parser->script, v, &ctx->ei, &num);
2463     VariantClear(v);
2464     if(FAILED(hres))
2465         return hres;
2466
2467     return stack_push(ctx, &num);
2468 }
2469
2470 /* ECMA-262 3rd Edition    11.3.1 */
2471 static HRESULT interp_postinc(exec_ctx_t *ctx)
2472 {
2473     const int arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
2474     IDispatch *obj;
2475     DISPID id;
2476     VARIANT v;
2477     HRESULT hres;
2478
2479     TRACE("%d\n", arg);
2480
2481     obj = stack_pop_objid(ctx, &id);
2482     if(!obj)
2483         return throw_type_error(ctx->parser->script, &ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
2484
2485     hres = disp_propget(ctx->parser->script, obj, id, &v, &ctx->ei, NULL/*FIXME*/);
2486     if(SUCCEEDED(hres)) {
2487         VARIANT n, inc;
2488
2489         hres = to_number(ctx->parser->script, &v, &ctx->ei, &n);
2490         if(SUCCEEDED(hres)) {
2491             num_set_val(&inc, num_val(&n)+(double)arg);
2492             hres = disp_propput(ctx->parser->script, obj, id, &inc, &ctx->ei, NULL/*FIXME*/);
2493         }
2494         if(FAILED(hres))
2495             VariantClear(&v);
2496     }
2497     IDispatch_Release(obj);
2498     if(FAILED(hres))
2499         return hres;
2500
2501     return stack_push(ctx, &v);
2502 }
2503
2504 /* ECMA-262 3rd Edition    11.4.4, 11.4.5 */
2505 static HRESULT interp_preinc(exec_ctx_t *ctx)
2506 {
2507     const int arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
2508     IDispatch *obj;
2509     DISPID id;
2510     VARIANT v;
2511     HRESULT hres;
2512
2513     TRACE("%d\n", arg);
2514
2515     obj = stack_pop_objid(ctx, &id);
2516     if(!obj)
2517         return throw_type_error(ctx->parser->script, &ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
2518
2519     hres = disp_propget(ctx->parser->script, obj, id, &v, &ctx->ei, NULL/*FIXME*/);
2520     if(SUCCEEDED(hres)) {
2521         VARIANT n;
2522
2523         hres = to_number(ctx->parser->script, &v, &ctx->ei, &n);
2524         VariantClear(&v);
2525         if(SUCCEEDED(hres)) {
2526             num_set_val(&v, num_val(&n)+(double)arg);
2527             hres = disp_propput(ctx->parser->script, obj, id, &v, &ctx->ei, NULL/*FIXME*/);
2528         }
2529     }
2530     IDispatch_Release(obj);
2531     if(FAILED(hres))
2532         return hres;
2533
2534     return stack_push(ctx, &v);
2535 }
2536
2537 /* ECMA-262 3rd Edition    11.9.3 */
2538 static HRESULT equal_values(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, BOOL *ret)
2539 {
2540     if(V_VT(lval) == V_VT(rval) || (is_num_vt(V_VT(lval)) && is_num_vt(V_VT(rval))))
2541        return equal2_values(lval, rval, ret);
2542
2543     /* FIXME: NULL disps should be handled in more general way */
2544     if(V_VT(lval) == VT_DISPATCH && !V_DISPATCH(lval)) {
2545         VARIANT v;
2546         V_VT(&v) = VT_NULL;
2547         return equal_values(ctx, &v, rval, ei, ret);
2548     }
2549
2550     if(V_VT(rval) == VT_DISPATCH && !V_DISPATCH(rval)) {
2551         VARIANT v;
2552         V_VT(&v) = VT_NULL;
2553         return equal_values(ctx, lval, &v, ei, ret);
2554     }
2555
2556     if((V_VT(lval) == VT_NULL && V_VT(rval) == VT_EMPTY) ||
2557        (V_VT(lval) == VT_EMPTY && V_VT(rval) == VT_NULL)) {
2558         *ret = TRUE;
2559         return S_OK;
2560     }
2561
2562     if(V_VT(lval) == VT_BSTR && is_num_vt(V_VT(rval))) {
2563         VARIANT v;
2564         HRESULT hres;
2565
2566         hres = to_number(ctx, lval, ei, &v);
2567         if(FAILED(hres))
2568             return hres;
2569
2570         return equal_values(ctx, &v, rval, ei, ret);
2571     }
2572
2573     if(V_VT(rval) == VT_BSTR && is_num_vt(V_VT(lval))) {
2574         VARIANT v;
2575         HRESULT hres;
2576
2577         hres = to_number(ctx, rval, ei, &v);
2578         if(FAILED(hres))
2579             return hres;
2580
2581         return equal_values(ctx, lval, &v, ei, ret);
2582     }
2583
2584     if(V_VT(rval) == VT_BOOL) {
2585         VARIANT v;
2586
2587         V_VT(&v) = VT_I4;
2588         V_I4(&v) = V_BOOL(rval) ? 1 : 0;
2589         return equal_values(ctx, lval, &v, ei, ret);
2590     }
2591
2592     if(V_VT(lval) == VT_BOOL) {
2593         VARIANT v;
2594
2595         V_VT(&v) = VT_I4;
2596         V_I4(&v) = V_BOOL(lval) ? 1 : 0;
2597         return equal_values(ctx, &v, rval, ei, ret);
2598     }
2599
2600
2601     if(V_VT(rval) == VT_DISPATCH && (V_VT(lval) == VT_BSTR || is_num_vt(V_VT(lval)))) {
2602         VARIANT v;
2603         HRESULT hres;
2604
2605         hres = to_primitive(ctx, rval, ei, &v, NO_HINT);
2606         if(FAILED(hres))
2607             return hres;
2608
2609         hres = equal_values(ctx, lval, &v, ei, ret);
2610
2611         VariantClear(&v);
2612         return hres;
2613     }
2614
2615
2616     if(V_VT(lval) == VT_DISPATCH && (V_VT(rval) == VT_BSTR || is_num_vt(V_VT(rval)))) {
2617         VARIANT v;
2618         HRESULT hres;
2619
2620         hres = to_primitive(ctx, lval, ei, &v, NO_HINT);
2621         if(FAILED(hres))
2622             return hres;
2623
2624         hres = equal_values(ctx, &v, rval, ei, ret);
2625
2626         VariantClear(&v);
2627         return hres;
2628     }
2629
2630
2631     *ret = FALSE;
2632     return S_OK;
2633 }
2634
2635 /* ECMA-262 3rd Edition    11.9.1 */
2636 static HRESULT interp_eq(exec_ctx_t *ctx)
2637 {
2638     VARIANT *l, *r;
2639     BOOL b;
2640     HRESULT hres;
2641
2642     r = stack_pop(ctx);
2643     l = stack_pop(ctx);
2644
2645     TRACE("%s == %s\n", debugstr_variant(l), debugstr_variant(r));
2646
2647     hres = equal_values(ctx->parser->script, l, r, &ctx->ei, &b);
2648     VariantClear(l);
2649     VariantClear(r);
2650     if(FAILED(hres))
2651         return hres;
2652
2653     return stack_push_bool(ctx, b);
2654 }
2655
2656 /* ECMA-262 3rd Edition    11.9.2 */
2657 static HRESULT interp_neq(exec_ctx_t *ctx)
2658 {
2659     VARIANT *l, *r;
2660     BOOL b;
2661     HRESULT hres;
2662
2663     r = stack_pop(ctx);
2664     l = stack_pop(ctx);
2665
2666     TRACE("%s != %s\n", debugstr_variant(l), debugstr_variant(r));
2667
2668     hres = equal_values(ctx->parser->script, l, r, &ctx->ei, &b);
2669     VariantClear(l);
2670     VariantClear(r);
2671     if(FAILED(hres))
2672         return hres;
2673
2674     return stack_push_bool(ctx, !b);
2675 }
2676
2677 /* ECMA-262 3rd Edition    11.9.4 */
2678 static HRESULT interp_eq2(exec_ctx_t *ctx)
2679 {
2680     VARIANT *l, *r;
2681     BOOL b;
2682     HRESULT hres;
2683
2684     TRACE("\n");
2685
2686     r = stack_pop(ctx);
2687     l = stack_pop(ctx);
2688
2689     hres = equal2_values(r, l, &b);
2690     VariantClear(l);
2691     VariantClear(r);
2692     if(FAILED(hres))
2693         return hres;
2694
2695     return stack_push_bool(ctx, b);
2696 }
2697
2698 /* ECMA-262 3rd Edition    11.9.5 */
2699 static HRESULT interp_neq2(exec_ctx_t *ctx)
2700 {
2701     VARIANT *l, *r;
2702     BOOL b;
2703     HRESULT hres;
2704
2705     TRACE("\n");
2706
2707     r = stack_pop(ctx);
2708     l = stack_pop(ctx);
2709
2710     hres = equal2_values(r, l, &b);
2711     VariantClear(l);
2712     VariantClear(r);
2713     if(FAILED(hres))
2714         return hres;
2715
2716     return stack_push_bool(ctx, !b);
2717 }
2718
2719 /* ECMA-262 3rd Edition    11.8.5 */
2720 static HRESULT less_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, BOOL greater, jsexcept_t *ei, BOOL *ret)
2721 {
2722     VARIANT l, r, ln, rn;
2723     HRESULT hres;
2724
2725     hres = to_primitive(ctx, lval, ei, &l, NO_HINT);
2726     if(FAILED(hres))
2727         return hres;
2728
2729     hres = to_primitive(ctx, rval, ei, &r, NO_HINT);
2730     if(FAILED(hres)) {
2731         VariantClear(&l);
2732         return hres;
2733     }
2734
2735     if(V_VT(&l) == VT_BSTR && V_VT(&r) == VT_BSTR) {
2736         *ret = (strcmpW(V_BSTR(&l), V_BSTR(&r)) < 0) ^ greater;
2737         SysFreeString(V_BSTR(&l));
2738         SysFreeString(V_BSTR(&r));
2739         return S_OK;
2740     }
2741
2742     hres = to_number(ctx, &l, ei, &ln);
2743     VariantClear(&l);
2744     if(SUCCEEDED(hres))
2745         hres = to_number(ctx, &r, ei, &rn);
2746     VariantClear(&r);
2747     if(FAILED(hres))
2748         return hres;
2749
2750     if(V_VT(&ln) == VT_I4 && V_VT(&rn) == VT_I4) {
2751         *ret = (V_I4(&ln) < V_I4(&rn)) ^ greater;
2752     }else  {
2753         DOUBLE ld = num_val(&ln);
2754         DOUBLE rd = num_val(&rn);
2755
2756         *ret = !isnan(ld) && !isnan(rd) && ((ld < rd) ^ greater);
2757     }
2758
2759     return S_OK;
2760 }
2761
2762 /* ECMA-262 3rd Edition    11.8.1 */
2763 static HRESULT interp_lt(exec_ctx_t *ctx)
2764 {
2765     VARIANT *l, *r;
2766     BOOL b;
2767     HRESULT hres;
2768
2769     r = stack_pop(ctx);
2770     l = stack_pop(ctx);
2771
2772     TRACE("%s < %s\n", debugstr_variant(l), debugstr_variant(r));
2773
2774     hres = less_eval(ctx->parser->script, l, r, FALSE, &ctx->ei, &b);
2775     VariantClear(l);
2776     VariantClear(r);
2777     if(FAILED(hres))
2778         return hres;
2779
2780     return stack_push_bool(ctx, b);
2781 }
2782
2783 /* ECMA-262 3rd Edition    11.8.1 */
2784 static HRESULT interp_lteq(exec_ctx_t *ctx)
2785 {
2786     VARIANT *l, *r;
2787     BOOL b;
2788     HRESULT hres;
2789
2790     r = stack_pop(ctx);
2791     l = stack_pop(ctx);
2792
2793     TRACE("%s <= %s\n", debugstr_variant(l), debugstr_variant(r));
2794
2795     hres = less_eval(ctx->parser->script, r, l, TRUE, &ctx->ei, &b);
2796     VariantClear(l);
2797     VariantClear(r);
2798     if(FAILED(hres))
2799         return hres;
2800
2801     return stack_push_bool(ctx, b);
2802 }
2803
2804 /* ECMA-262 3rd Edition    11.8.2 */
2805 static HRESULT interp_gt(exec_ctx_t *ctx)
2806 {
2807     VARIANT *l, *r;
2808     BOOL b;
2809     HRESULT hres;
2810
2811     r = stack_pop(ctx);
2812     l = stack_pop(ctx);
2813
2814     TRACE("%s > %s\n", debugstr_variant(l), debugstr_variant(r));
2815
2816     hres = less_eval(ctx->parser->script, r, l, FALSE, &ctx->ei, &b);
2817     VariantClear(l);
2818     VariantClear(r);
2819     if(FAILED(hres))
2820         return hres;
2821
2822     return stack_push_bool(ctx, b);
2823 }
2824
2825 /* ECMA-262 3rd Edition    11.8.4 */
2826 static HRESULT interp_gteq(exec_ctx_t *ctx)
2827 {
2828     VARIANT *l, *r;
2829     BOOL b;
2830     HRESULT hres;
2831
2832     r = stack_pop(ctx);
2833     l = stack_pop(ctx);
2834
2835     TRACE("%s >= %s\n", debugstr_variant(l), debugstr_variant(r));
2836
2837     hres = less_eval(ctx->parser->script, l, r, TRUE, &ctx->ei, &b);
2838     VariantClear(l);
2839     VariantClear(r);
2840     if(FAILED(hres))
2841         return hres;
2842
2843     return stack_push_bool(ctx, b);
2844 }
2845
2846 /* ECMA-262 3rd Edition    11.4.8 */
2847 static HRESULT interp_bneg(exec_ctx_t *ctx)
2848 {
2849     VARIANT *v, r;
2850     INT i;
2851     HRESULT hres;
2852
2853     TRACE("\n");
2854
2855     v = stack_pop(ctx);
2856     hres = to_int32(ctx->parser->script, v, &ctx->ei, &i);
2857     VariantClear(v);
2858     if(FAILED(hres))
2859         return hres;
2860
2861     V_VT(&r) = VT_I4;
2862     V_I4(&r) = ~i;
2863     return stack_push(ctx, &r);
2864 }
2865
2866 /* ECMA-262 3rd Edition    11.4.9 */
2867 static HRESULT interp_neg(exec_ctx_t *ctx)
2868 {
2869     VARIANT *v;
2870     VARIANT_BOOL b;
2871     HRESULT hres;
2872
2873     TRACE("\n");
2874
2875     v = stack_pop(ctx);
2876     hres = to_boolean(v, &b);
2877     VariantClear(v);
2878     if(FAILED(hres))
2879         return hres;
2880
2881     return stack_push_bool(ctx, !b);
2882 }
2883
2884 /* ECMA-262 3rd Edition    11.7.1 */
2885 static HRESULT interp_lshift(exec_ctx_t *ctx)
2886 {
2887     DWORD r;
2888     INT l;
2889     HRESULT hres;
2890
2891     hres = stack_pop_uint(ctx, &r);
2892     if(FAILED(hres))
2893         return hres;
2894
2895     hres = stack_pop_int(ctx, &l);
2896     if(FAILED(hres))
2897         return hres;
2898
2899     return stack_push_int(ctx, l << (r&0x1f));
2900 }
2901
2902 /* ECMA-262 3rd Edition    11.7.2 */
2903 static HRESULT interp_rshift(exec_ctx_t *ctx)
2904 {
2905     DWORD r;
2906     INT l;
2907     HRESULT hres;
2908
2909     hres = stack_pop_uint(ctx, &r);
2910     if(FAILED(hres))
2911         return hres;
2912
2913     hres = stack_pop_int(ctx, &l);
2914     if(FAILED(hres))
2915         return hres;
2916
2917     return stack_push_int(ctx, l >> (r&0x1f));
2918 }
2919
2920 /* ECMA-262 3rd Edition    11.7.3 */
2921 static HRESULT interp_rshift2(exec_ctx_t *ctx)
2922 {
2923     DWORD r, l;
2924     HRESULT hres;
2925
2926     hres = stack_pop_uint(ctx, &r);
2927     if(FAILED(hres))
2928         return hres;
2929
2930     hres = stack_pop_uint(ctx, &l);
2931     if(FAILED(hres))
2932         return hres;
2933
2934     return stack_push_int(ctx, l >> (r&0x1f));
2935 }
2936
2937 /* ECMA-262 3rd Edition    11.13.1 */
2938 static HRESULT interp_assign(exec_ctx_t *ctx)
2939 {
2940     IDispatch *disp;
2941     DISPID id;
2942     VARIANT *v;
2943     HRESULT hres;
2944
2945     TRACE("\n");
2946
2947     v = stack_pop(ctx);
2948     disp = stack_pop_objid(ctx, &id);
2949
2950     if(!disp)
2951         return throw_reference_error(ctx->parser->script, &ctx->ei, JS_E_ILLEGAL_ASSIGN, NULL);
2952
2953     hres = disp_propput(ctx->parser->script, disp, id, v, &ctx->ei, NULL/*FIXME*/);
2954     IDispatch_Release(disp);
2955     if(FAILED(hres)) {
2956         VariantClear(v);
2957         return hres;
2958     }
2959
2960     return stack_push(ctx, v);
2961 }
2962
2963 static HRESULT interp_undefined(exec_ctx_t *ctx)
2964 {
2965     VARIANT v;
2966
2967     TRACE("\n");
2968
2969     V_VT(&v) = VT_EMPTY;
2970     return stack_push(ctx, &v);
2971 }
2972
2973 static HRESULT interp_jmp(exec_ctx_t *ctx)
2974 {
2975     const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
2976
2977     TRACE("\n");
2978
2979     ctx->ip = arg;
2980     return S_OK;
2981 }
2982
2983 static HRESULT interp_pop(exec_ctx_t *ctx)
2984 {
2985     TRACE("\n");
2986
2987     stack_popn(ctx, 1);
2988     return S_OK;
2989 }
2990
2991 static HRESULT interp_ret(exec_ctx_t *ctx)
2992 {
2993     TRACE("\n");
2994
2995     ctx->ip = -1;
2996     return S_OK;
2997 }
2998
2999 static HRESULT interp_tree(exec_ctx_t *ctx)
3000 {
3001     instr_t *instr = ctx->parser->code->instrs+ctx->ip;
3002     VARIANT v;
3003     HRESULT hres;
3004
3005     TRACE("\n");
3006
3007     hres = expr_eval(ctx->parser->script, instr->arg1.expr, 0, &ctx->ei, &v);
3008     if(FAILED(hres))
3009         return hres;
3010
3011     return stack_push(ctx, &v);
3012 }
3013
3014 typedef HRESULT (*op_func_t)(exec_ctx_t*);
3015
3016 static const op_func_t op_funcs[] = {
3017 #define X(x,a,b,c) interp_##x,
3018 OP_LIST
3019 #undef X
3020 };
3021
3022 static const unsigned op_move[] = {
3023 #define X(a,x,b,c) x,
3024 OP_LIST
3025 #undef X
3026 };
3027
3028 static HRESULT expr_eval(script_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, VARIANT *ret)
3029 {
3030     exec_ctx_t *exec_ctx = ctx->exec_ctx;
3031     unsigned prev_ip, prev_top;
3032     jsop_t op;
3033     HRESULT hres = S_OK;
3034
3035     TRACE("\n");
3036
3037     if(expr->instr_off == -1) {
3038         hres = compile_subscript(ctx->exec_ctx->parser, expr, !(flags & EXPR_NOVAL), &expr->instr_off);
3039         if(FAILED(hres))
3040             return hres;
3041     }
3042
3043     prev_top = exec_ctx->top;
3044     prev_ip = exec_ctx->ip;
3045     exec_ctx->ip = expr->instr_off;
3046
3047     while(exec_ctx->ip != -1) {
3048         op = exec_ctx->parser->code->instrs[exec_ctx->ip].op;
3049         hres = op_funcs[op](exec_ctx);
3050         if(FAILED(hres))
3051             break;
3052         exec_ctx->ip += op_move[op];
3053     }
3054
3055     exec_ctx->ip = prev_ip;
3056
3057     if(FAILED(hres)) {
3058         stack_popn(exec_ctx, exec_ctx->top-prev_top);
3059         *ei = exec_ctx->ei;
3060         memset(&exec_ctx->ei, 0, sizeof(exec_ctx->ei));
3061         return hres;
3062     }
3063
3064     assert(exec_ctx->top == prev_top+1 || ((flags&EXPR_NOVAL) && exec_ctx->top == prev_top));
3065
3066     if(exec_ctx->top == prev_top)
3067         V_VT(ret) = VT_EMPTY;
3068     else
3069         *ret = *stack_pop(exec_ctx);
3070     return S_OK;
3071 }