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