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