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