jscript: Added return statement implementation.
[wine] / dlls / jscript / engine.c
1 /*
2  * Copyright 2008 Jacek Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include "jscript.h"
20 #include "engine.h"
21
22 #include "wine/debug.h"
23
24 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
25
26 #define EXPR_NOVAL   0x0001
27 #define EXPR_NEWREF  0x0002
28 #define EXPR_STRREF  0x0004
29
30 static inline HRESULT stat_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
31 {
32     return stat->eval(ctx, stat, rt, ret);
33 }
34
35 static inline HRESULT expr_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
36 {
37     return _expr->eval(ctx, _expr, flags, ei, ret);
38 }
39
40 static void exprval_release(exprval_t *val)
41 {
42     switch(val->type) {
43     case EXPRVAL_VARIANT:
44         VariantClear(&val->u.var);
45         return;
46     case EXPRVAL_IDREF:
47         if(val->u.idref.disp)
48             IDispatch_Release(val->u.idref.disp);
49         return;
50     case EXPRVAL_NAMEREF:
51         if(val->u.nameref.disp)
52             IDispatch_Release(val->u.nameref.disp);
53         SysFreeString(val->u.nameref.name);
54     }
55 }
56
57 /* ECMA-262 3rd Edition    8.7.1 */
58 static HRESULT exprval_value(script_ctx_t *ctx, exprval_t *val, jsexcept_t *ei, VARIANT *ret)
59 {
60     V_VT(ret) = VT_EMPTY;
61
62     switch(val->type) {
63     case EXPRVAL_VARIANT:
64         return VariantCopy(ret, &val->u.var);
65     case EXPRVAL_IDREF:
66         if(!val->u.idref.disp) {
67             FIXME("throw ReferenceError\n");
68             return E_FAIL;
69         }
70
71         return disp_propget(val->u.idref.disp, val->u.idref.id, ctx->lcid, ret, ei, NULL/*FIXME*/);
72     default:
73         ERR("type %d\n", val->type);
74         return E_FAIL;
75     }
76 }
77
78 static HRESULT exprval_to_value(script_ctx_t *ctx, exprval_t *val, jsexcept_t *ei, VARIANT *ret)
79 {
80     if(val->type == EXPRVAL_VARIANT) {
81         *ret = val->u.var;
82         V_VT(&val->u.var) = VT_EMPTY;
83         return S_OK;
84     }
85
86     return exprval_value(ctx, val, ei, ret);
87 }
88
89 static HRESULT exprval_to_boolean(script_ctx_t *ctx, exprval_t *exprval, jsexcept_t *ei, VARIANT_BOOL *b)
90 {
91     if(exprval->type != EXPRVAL_VARIANT) {
92         VARIANT val;
93         HRESULT hres;
94
95         hres = exprval_to_value(ctx, exprval, ei, &val);
96         if(FAILED(hres))
97             return hres;
98
99         hres = to_boolean(&val, b);
100         VariantClear(&val);
101         return hres;
102     }
103
104     return to_boolean(&exprval->u.var, b);
105 }
106
107 static void exprval_init(exprval_t *val)
108 {
109     val->type = EXPRVAL_VARIANT;
110     V_VT(&val->u.var) = VT_EMPTY;
111 }
112
113 static void exprval_set_idref(exprval_t *val, IDispatch *disp, DISPID id)
114 {
115     val->type = EXPRVAL_IDREF;
116     val->u.idref.disp = disp;
117     val->u.idref.id = id;
118
119     if(disp)
120         IDispatch_AddRef(disp);
121 }
122
123 void scope_release(scope_chain_t *scope)
124 {
125     if(--scope->ref)
126         return;
127
128     if(scope->next)
129         scope_release(scope->next);
130
131     IDispatchEx_Release(_IDispatchEx_(scope->obj));
132     heap_free(scope);
133 }
134
135 HRESULT create_exec_ctx(IDispatch *this_obj, DispatchEx *var_disp, scope_chain_t *scope, exec_ctx_t **ret)
136 {
137     exec_ctx_t *ctx;
138
139     ctx = heap_alloc_zero(sizeof(exec_ctx_t));
140     if(!ctx)
141         return E_OUTOFMEMORY;
142
143     IDispatch_AddRef(this_obj);
144     ctx->this_obj = this_obj;
145
146     IDispatchEx_AddRef(_IDispatchEx_(var_disp));
147     ctx->var_disp = var_disp;
148
149     if(scope) {
150         scope_addref(scope);
151         ctx->scope_chain = scope;
152     }
153
154     *ret = ctx;
155     return S_OK;
156 }
157
158 void exec_release(exec_ctx_t *ctx)
159 {
160     if(--ctx->ref)
161         return;
162
163     if(ctx->scope_chain)
164         scope_release(ctx->scope_chain);
165     if(ctx->var_disp)
166         IDispatchEx_Release(_IDispatchEx_(ctx->var_disp));
167     if(ctx->this_obj)
168         IDispatch_Release(ctx->this_obj);
169     heap_free(ctx);
170 }
171
172 static HRESULT dispex_get_id(IDispatchEx *dispex, BSTR name, DWORD flags, DISPID *id)
173 {
174     *id = 0;
175
176     return IDispatchEx_GetDispID(dispex, name, flags|fdexNameCaseSensitive, id);
177 }
178
179 static HRESULT disp_get_id(IDispatch *disp, BSTR name, DWORD flags, DISPID *id)
180 {
181     IDispatchEx *dispex;
182     HRESULT hres;
183
184     hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
185     if(FAILED(hres)) {
186         TRACE("unsing IDispatch\n");
187
188         *id = 0;
189         return IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, id);
190     }
191
192     hres = dispex_get_id(dispex, name, flags, id);
193     IDispatchEx_Release(dispex);
194     return hres;
195 }
196
197 /* ECMA-262 3rd Edition    8.7.2 */
198 static HRESULT put_value(script_ctx_t *ctx, exprval_t *ref, VARIANT *v, jsexcept_t *ei)
199 {
200     if(ref->type != EXPRVAL_IDREF) {
201         FIXME("throw ReferemceError\n");
202         return E_FAIL;
203     }
204
205     return disp_propput(ref->u.idref.disp, ref->u.idref.id, ctx->lcid, v, ei, NULL/*FIXME*/);
206 }
207
208 static HRESULT disp_cmp(IDispatch *disp1, IDispatch *disp2, BOOL *ret)
209 {
210     IObjectIdentity *identity;
211     IUnknown *unk1, *unk2;
212     HRESULT hres;
213
214     if(disp1 == disp2) {
215         *ret = TRUE;
216         return S_OK;
217     }
218
219     hres = IDispatch_QueryInterface(disp1, &IID_IUnknown, (void**)&unk1);
220     if(FAILED(hres))
221         return hres;
222
223     hres = IDispatch_QueryInterface(disp2, &IID_IUnknown, (void**)&unk2);
224     if(FAILED(hres)) {
225         IUnknown_Release(unk1);
226         return hres;
227     }
228
229     if(unk1 == unk2) {
230         *ret = TRUE;
231     }else {
232         hres = IUnknown_QueryInterface(unk1, &IID_IObjectIdentity, (void**)&identity);
233         if(SUCCEEDED(hres)) {
234             hres = IObjectIdentity_IsEqualObject(identity, unk2);
235             IObjectIdentity_Release(identity);
236             *ret = hres == S_OK;
237         }else {
238             *ret = FALSE;
239         }
240     }
241
242     IUnknown_Release(unk1);
243     IUnknown_Release(unk2);
244     return S_OK;
245 }
246
247 static inline BOOL is_num_vt(enum VARENUM vt)
248 {
249     return vt == VT_I4 || vt == VT_R8;
250 }
251
252 static inline DOUBLE num_val(const VARIANT *v)
253 {
254     return V_VT(v) == VT_I4 ? V_I4(v) : V_R8(v);
255 }
256
257 /* ECMA-262 3rd Edition    11.9.6 */
258 HRESULT equal2_values(VARIANT *lval, VARIANT *rval, BOOL *ret)
259 {
260     TRACE("\n");
261
262     if(V_VT(lval) != V_VT(rval)) {
263         if(is_num_vt(V_VT(lval)) && is_num_vt(V_VT(rval))) {
264             *ret = num_val(lval) == num_val(rval);
265             return S_OK;
266         }
267
268         *ret = FALSE;
269         return S_OK;
270     }
271
272     switch(V_VT(lval)) {
273     case VT_EMPTY:
274     case VT_NULL:
275         *ret = VARIANT_TRUE;
276         break;
277     case VT_I4:
278         *ret = V_I4(lval) == V_I4(rval);
279         break;
280     case VT_R8:
281         *ret = V_R8(lval) == V_R8(rval);
282         break;
283     case VT_BSTR:
284         *ret = !strcmpW(V_BSTR(lval), V_BSTR(rval));
285         break;
286     case VT_DISPATCH:
287         return disp_cmp(V_DISPATCH(lval), V_DISPATCH(rval), ret);
288     case VT_BOOL:
289         *ret = !V_BOOL(lval) == !V_BOOL(rval);
290         break;
291     default:
292         FIXME("unimplemented vt %d\n", V_VT(lval));
293         return E_NOTIMPL;
294     }
295
296     return S_OK;
297 }
298
299 static HRESULT literal_to_var(literal_t *literal, VARIANT *v)
300 {
301     V_VT(v) = literal->vt;
302
303     switch(V_VT(v)) {
304     case VT_EMPTY:
305     case VT_NULL:
306         break;
307     case VT_I4:
308         V_I4(v) = literal->u.lval;
309         break;
310     case VT_R8:
311         V_R8(v) = literal->u.dval;
312         break;
313     case VT_BSTR:
314         V_BSTR(v) = SysAllocString(literal->u.wstr);
315         break;
316     case VT_BOOL:
317         V_BOOL(v) = literal->u.bval;
318         break;
319     case VT_DISPATCH:
320         IDispatch_AddRef(literal->u.disp);
321         V_DISPATCH(v) = literal->u.disp;
322         break;
323     default:
324         ERR("wrong type %d\n", V_VT(v));
325         return E_NOTIMPL;
326     }
327
328     return S_OK;
329 }
330
331 HRESULT exec_source(exec_ctx_t *ctx, parser_ctx_t *parser, source_elements_t *source, jsexcept_t *ei, VARIANT *retv)
332 {
333     script_ctx_t *script = parser->script;
334     function_declaration_t *func;
335     parser_ctx_t *prev_parser;
336     VARIANT val, tmp;
337     statement_t *stat;
338     exec_ctx_t *prev_ctx;
339     return_type_t rt;
340     HRESULT hres = S_OK;
341
342     for(func = source->functions; func; func = func->next) {
343         DispatchEx *func_obj;
344         VARIANT var;
345
346         hres = create_source_function(parser, func->parameter_list, func->source_elements, ctx->scope_chain, &func_obj);
347         if(FAILED(hres))
348             return hres;
349
350         V_VT(&var) = VT_DISPATCH;
351         V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(func_obj);
352         hres = jsdisp_propput_name(ctx->var_disp, func->identifier, script->lcid, &var, ei, NULL);
353         IDispatchEx_Release(_IDispatchEx_(func_obj));
354         if(FAILED(hres))
355             return hres;
356     }
357
358     prev_ctx = script->exec_ctx;
359     script->exec_ctx = ctx;
360
361     prev_parser = ctx->parser;
362     ctx->parser = parser;
363
364     V_VT(&val) = VT_EMPTY;
365     memset(&rt, 0, sizeof(rt));
366     rt.type = RT_NORMAL;
367
368     for(stat = source->statement; stat; stat = stat->next) {
369         hres = stat_eval(ctx, stat, &rt, &tmp);
370         if(FAILED(hres))
371             break;
372
373         VariantClear(&val);
374         val = tmp;
375         if(rt.type != RT_NORMAL)
376             break;
377     }
378
379     script->exec_ctx = prev_ctx;
380     ctx->parser = prev_parser;
381
382     if(rt.type != RT_NORMAL && rt.type != RT_RETURN) {
383         FIXME("wrong rt %d\n", rt.type);
384         hres = E_FAIL;
385     }
386
387     *ei = rt.ei;
388     if(FAILED(hres)) {
389         VariantClear(&val);
390         return hres;
391     }
392
393     if(retv)
394         *retv = val;
395     else
396         VariantClear(&val);
397     return S_OK;
398 }
399
400 /* ECMA-262 3rd Edition    10.1.4 */
401 static HRESULT identifier_eval(exec_ctx_t *ctx, BSTR identifier, DWORD flags, exprval_t *ret)
402 {
403     scope_chain_t *scope;
404     named_item_t *item;
405     DISPID id = 0;
406     HRESULT hres;
407
408     TRACE("%s\n", debugstr_w(identifier));
409
410     for(scope = ctx->scope_chain; scope; scope = scope->next) {
411         hres = dispex_get_id(_IDispatchEx_(scope->obj), identifier, 0, &id);
412         if(SUCCEEDED(hres))
413             break;
414     }
415
416     if(scope) {
417         exprval_set_idref(ret, (IDispatch*)_IDispatchEx_(scope->obj), id);
418         return S_OK;
419     }
420
421     hres = dispex_get_id(_IDispatchEx_(ctx->parser->script->global), identifier, 0, &id);
422     if(SUCCEEDED(hres)) {
423         exprval_set_idref(ret, (IDispatch*)_IDispatchEx_(ctx->parser->script->global), id);
424         return S_OK;
425     }
426
427     for(item = ctx->parser->script->named_items; item; item = item->next) {
428         hres = disp_get_id(item->disp, identifier, 0, &id);
429         if(SUCCEEDED(hres))
430             break;
431     }
432
433     if(item) {
434         exprval_set_idref(ret, (IDispatch*)item->disp, id);
435         return S_OK;
436     }
437
438     hres = dispex_get_id(_IDispatchEx_(ctx->parser->script->script_disp), identifier, 0, &id);
439     if(SUCCEEDED(hres)) {
440         exprval_set_idref(ret, (IDispatch*)_IDispatchEx_(ctx->parser->script->script_disp), id);
441         return S_OK;
442     }
443
444     if(flags & EXPR_NEWREF) {
445         hres = dispex_get_id(_IDispatchEx_(ctx->var_disp), identifier, fdexNameEnsure, &id);
446         if(FAILED(hres))
447             return hres;
448
449         exprval_set_idref(ret, (IDispatch*)_IDispatchEx_(ctx->var_disp), id);
450         return S_OK;
451     }
452
453     WARN("Could not find identifier %s\n", debugstr_w(identifier));
454     return E_FAIL;
455 }
456
457 HRESULT block_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
458 {
459     FIXME("\n");
460     return E_NOTIMPL;
461 }
462
463 /* ECMA-262 3rd Edition    12.2 */
464 static HRESULT variable_list_eval(exec_ctx_t *ctx, variable_declaration_t *var_list, jsexcept_t *ei)
465 {
466     variable_declaration_t *iter;
467     HRESULT hres;
468
469     for(iter = var_list; iter; iter = iter->next) {
470         VARIANT val;
471
472         if(iter->expr) {
473             exprval_t exprval;
474
475             hres = expr_eval(ctx, iter->expr, 0, ei, &exprval);
476             if(FAILED(hres))
477                 break;
478
479             hres = exprval_to_value(ctx->parser->script, &exprval, ei, &val);
480             exprval_release(&exprval);
481             if(FAILED(hres))
482                 break;
483         }else {
484             V_VT(&val) = VT_EMPTY;
485         }
486
487         hres = jsdisp_propput_name(ctx->var_disp, iter->identifier, ctx->parser->script->lcid, &val, ei, NULL/*FIXME*/);
488         VariantClear(&val);
489         if(FAILED(hres))
490             break;
491     }
492
493     return hres;
494 }
495
496 /* ECMA-262 3rd Edition    12.2 */
497 HRESULT var_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
498 {
499     var_statement_t *stat = (var_statement_t*)_stat;
500     HRESULT hres;
501
502     TRACE("\n");
503
504     hres = variable_list_eval(ctx, stat->variable_list, &rt->ei);
505     if(FAILED(hres))
506         return hres;
507
508     V_VT(ret) = VT_EMPTY;
509     return S_OK;
510 }
511
512 /* ECMA-262 3rd Edition    12.3 */
513 HRESULT empty_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
514 {
515     TRACE("\n");
516
517     V_VT(ret) = VT_EMPTY;
518     return S_OK;
519 }
520
521 /* ECMA-262 3rd Edition    12.4 */
522 HRESULT expression_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
523 {
524     expression_statement_t *stat = (expression_statement_t*)_stat;
525     exprval_t exprval;
526     VARIANT val;
527     HRESULT hres;
528
529     TRACE("\n");
530
531     hres = expr_eval(ctx, stat->expr, EXPR_NOVAL, &rt->ei, &exprval);
532     if(FAILED(hres))
533         return hres;
534
535     hres = exprval_to_value(ctx->parser->script, &exprval, &rt->ei, &val);
536     exprval_release(&exprval);
537     if(FAILED(hres))
538         return hres;
539
540     *ret = val;
541     TRACE("= %s\n", debugstr_variant(ret));
542     return S_OK;
543 }
544
545 HRESULT if_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
546 {
547     FIXME("\n");
548     return E_NOTIMPL;
549 }
550
551 HRESULT dowhile_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
552 {
553     FIXME("\n");
554     return E_NOTIMPL;
555 }
556
557 HRESULT while_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
558 {
559     FIXME("\n");
560     return E_NOTIMPL;
561 }
562
563 HRESULT for_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
564 {
565     FIXME("\n");
566     return E_NOTIMPL;
567 }
568
569 HRESULT forin_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
570 {
571     FIXME("\n");
572     return E_NOTIMPL;
573 }
574
575 HRESULT continue_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
576 {
577     FIXME("\n");
578     return E_NOTIMPL;
579 }
580
581 HRESULT break_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
582 {
583     FIXME("\n");
584     return E_NOTIMPL;
585 }
586
587 /* ECMA-262 3rd Edition    12.9 */
588 HRESULT return_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
589 {
590     expression_statement_t *stat = (expression_statement_t*)_stat;
591     HRESULT hres;
592
593     TRACE("\n");
594
595     if(stat->expr) {
596         exprval_t exprval;
597
598         hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
599         if(FAILED(hres))
600             return hres;
601
602         hres = exprval_to_value(ctx->parser->script, &exprval, &rt->ei, ret);
603         exprval_release(&exprval);
604         if(FAILED(hres))
605             return hres;
606     }else {
607         V_VT(ret) = VT_EMPTY;
608     }
609
610     TRACE("= %s\n", debugstr_variant(ret));
611     rt->type = RT_RETURN;
612     return S_OK;
613 }
614
615 HRESULT with_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
616 {
617     FIXME("\n");
618     return E_NOTIMPL;
619 }
620
621 HRESULT labelled_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
622 {
623     FIXME("\n");
624     return E_NOTIMPL;
625 }
626
627 HRESULT switch_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
628 {
629     FIXME("\n");
630     return E_NOTIMPL;
631 }
632
633 HRESULT throw_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
634 {
635     FIXME("\n");
636     return E_NOTIMPL;
637 }
638
639 HRESULT try_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
640 {
641     FIXME("\n");
642     return E_NOTIMPL;
643 }
644
645 static HRESULT return_bool(exprval_t *ret, DWORD b)
646 {
647     ret->type = EXPRVAL_VARIANT;
648     V_VT(&ret->u.var) = VT_BOOL;
649     V_BOOL(&ret->u.var) = b ? VARIANT_TRUE : VARIANT_FALSE;
650
651     return S_OK;
652 }
653
654 static HRESULT get_binary_expr_values(exec_ctx_t *ctx, binary_expression_t *expr, jsexcept_t *ei, VARIANT *lval, VARIANT *rval)
655 {
656     exprval_t exprval;
657     HRESULT hres;
658
659     hres = expr_eval(ctx, expr->expression1, 0, ei, &exprval);
660     if(FAILED(hres))
661         return hres;
662
663     hres = exprval_to_value(ctx->parser->script, &exprval, ei, lval);
664     exprval_release(&exprval);
665     if(FAILED(hres))
666         return hres;
667
668     hres = expr_eval(ctx, expr->expression2, 0, ei, &exprval);
669     if(SUCCEEDED(hres)) {
670         hres = exprval_to_value(ctx->parser->script, &exprval, ei, rval);
671         exprval_release(&exprval);
672     }
673
674     if(FAILED(hres)) {
675         VariantClear(lval);
676         return hres;
677     }
678
679     return S_OK;
680 }
681
682 HRESULT function_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
683 {
684     FIXME("\n");
685     return E_NOTIMPL;
686 }
687
688 HRESULT conditional_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
689 {
690     FIXME("\n");
691     return E_NOTIMPL;
692 }
693
694 HRESULT array_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
695 {
696     FIXME("\n");
697     return E_NOTIMPL;
698 }
699
700 /* ECMA-262 3rd Edition    11.2.1 */
701 HRESULT member_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
702 {
703     member_expression_t *expr = (member_expression_t*)_expr;
704     IDispatch *obj = NULL;
705     exprval_t exprval;
706     VARIANT member;
707     DISPID id;
708     BSTR str;
709     HRESULT hres;
710
711     TRACE("\n");
712
713     hres = expr_eval(ctx, expr->expression, 0, ei, &exprval);
714     if(FAILED(hres))
715         return hres;
716
717     hres = exprval_to_value(ctx->parser->script, &exprval, ei, &member);
718     exprval_release(&exprval);
719     if(FAILED(hres))
720         return hres;
721
722     hres = to_object(ctx, &member, &obj);
723     VariantClear(&member);
724     if(FAILED(hres))
725         return hres;
726
727     str = SysAllocString(expr->identifier);
728     if(flags & EXPR_STRREF) {
729         ret->type = EXPRVAL_NAMEREF;
730         ret->u.nameref.disp = obj;
731         ret->u.nameref.name = str;
732         return S_OK;
733     }
734
735     hres = disp_get_id(obj, str, flags & EXPR_NEW ? fdexNameEnsure : 0, &id);
736     SysFreeString(str);
737     if(SUCCEEDED(hres)) {
738         exprval_set_idref(ret, obj, id);
739     }else if(!(flags & EXPR_NEWREF) && hres == DISP_E_UNKNOWNNAME) {
740         exprval_init(ret);
741         hres = S_OK;
742     }
743
744     IDispatch_Release(obj);
745     return hres;
746 }
747
748 static void free_dp(DISPPARAMS *dp)
749 {
750     DWORD i;
751
752     for(i=0; i < dp->cArgs; i++)
753         VariantClear(dp->rgvarg+i);
754     heap_free(dp->rgvarg);
755 }
756
757 static HRESULT args_to_param(exec_ctx_t *ctx, argument_t *args, jsexcept_t *ei, DISPPARAMS *dp)
758 {
759     VARIANTARG *vargs;
760     exprval_t exprval;
761     argument_t *iter;
762     DWORD cnt = 0, i;
763     HRESULT hres = S_OK;
764
765     memset(dp, 0, sizeof(*dp));
766
767     for(iter = args; iter; iter = iter->next)
768         cnt++;
769     if(!cnt)
770         return S_OK;
771
772     vargs = heap_alloc_zero(cnt * sizeof(*vargs));
773     if(!vargs)
774         return E_OUTOFMEMORY;
775
776     for(i = cnt, iter = args; iter; iter = iter->next) {
777         hres = expr_eval(ctx, iter->expr, 0, ei, &exprval);
778         if(FAILED(hres))
779             break;
780
781         hres = exprval_to_value(ctx->parser->script, &exprval, ei, vargs + (--i));
782         exprval_release(&exprval);
783         if(FAILED(hres))
784             break;
785     }
786
787     if(FAILED(hres)) {
788         free_dp(dp);
789         return hres;
790     }
791
792     dp->rgvarg = vargs;
793     dp->cArgs = cnt;
794     return S_OK;
795 }
796
797 HRESULT member_new_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
798 {
799     FIXME("\n");
800     return E_NOTIMPL;
801 }
802
803 HRESULT call_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
804 {
805     call_expression_t *expr = (call_expression_t*)_expr;
806     VARIANT func, var;
807     exprval_t exprval;
808     DISPPARAMS dp;
809     HRESULT hres;
810
811     TRACE("\n");
812
813     hres = expr_eval(ctx, expr->expression, 0, ei, &exprval);
814     if(FAILED(hres))
815         return hres;
816
817     hres = args_to_param(ctx, expr->argument_list, ei, &dp);
818     if(SUCCEEDED(hres)) {
819         switch(exprval.type) {
820         case EXPRVAL_IDREF:
821             hres = disp_call(exprval.u.idref.disp, exprval.u.idref.id, ctx->parser->script->lcid, DISPATCH_METHOD,
822                     &dp, flags & EXPR_NOVAL ? NULL : &var, ei, NULL/*FIXME*/);
823             if(flags & EXPR_NOVAL)
824                 V_VT(&var) = VT_EMPTY;
825             break;
826         default:
827             FIXME("unimplemented type %d\n", V_VT(&func));
828             hres = E_NOTIMPL;
829         }
830
831         free_dp(&dp);
832     }
833
834     exprval_release(&exprval);
835     if(FAILED(hres))
836         return hres;
837
838     TRACE("= %s\n", debugstr_variant(&var));
839     ret->type = EXPRVAL_VARIANT;
840     ret->u.var = var;
841     return S_OK;
842 }
843
844 HRESULT this_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
845 {
846     TRACE("\n");
847
848     ret->type = EXPRVAL_VARIANT;
849     V_VT(&ret->u.var) = VT_DISPATCH;
850     V_DISPATCH(&ret->u.var) = ctx->this_obj;
851     IDispatch_AddRef(ctx->this_obj);
852     return S_OK;
853 }
854
855 /* ECMA-262 3rd Edition    10.1.4 */
856 HRESULT identifier_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
857 {
858     identifier_expression_t *expr = (identifier_expression_t*)_expr;
859     BSTR identifier;
860     HRESULT hres;
861
862     TRACE("\n");
863
864     identifier = SysAllocString(expr->identifier);
865     if(!identifier)
866         return E_OUTOFMEMORY;
867
868     hres = identifier_eval(ctx, identifier, flags, ret);
869
870     SysFreeString(identifier);
871     return hres;
872 }
873
874 /* ECMA-262 3rd Edition    7.8 */
875 HRESULT literal_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
876 {
877     literal_expression_t *expr = (literal_expression_t*)_expr;
878     VARIANT var;
879     HRESULT hres;
880
881     TRACE("\n");
882
883     hres = literal_to_var(expr->literal, &var);
884     if(FAILED(hres))
885         return hres;
886
887     ret->type = EXPRVAL_VARIANT;
888     ret->u.var = var;
889     return S_OK;
890 }
891
892 HRESULT array_literal_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
893 {
894     FIXME("\n");
895     return E_NOTIMPL;
896 }
897
898 HRESULT property_value_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
899 {
900     FIXME("\n");
901     return E_NOTIMPL;
902 }
903
904 HRESULT comma_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
905 {
906     FIXME("\n");
907     return E_NOTIMPL;
908 }
909
910 HRESULT logical_or_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
911 {
912     FIXME("\n");
913     return E_NOTIMPL;
914 }
915
916 HRESULT logical_and_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
917 {
918     FIXME("\n");
919     return E_NOTIMPL;
920 }
921
922 HRESULT binary_or_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
923 {
924     FIXME("\n");
925     return E_NOTIMPL;
926 }
927
928 HRESULT binary_xor_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
929 {
930     FIXME("\n");
931     return E_NOTIMPL;
932 }
933
934 HRESULT binary_and_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
935 {
936     FIXME("\n");
937     return E_NOTIMPL;
938 }
939
940 HRESULT instanceof_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
941 {
942     FIXME("\n");
943     return E_NOTIMPL;
944 }
945
946 HRESULT in_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
947 {
948     FIXME("\n");
949     return E_NOTIMPL;
950 }
951
952 HRESULT add_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
953 {
954     FIXME("\n");
955     return E_NOTIMPL;
956 }
957
958 HRESULT sub_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
959 {
960     FIXME("\n");
961     return E_NOTIMPL;
962 }
963
964 HRESULT mul_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
965 {
966     FIXME("\n");
967     return E_NOTIMPL;
968 }
969
970 HRESULT div_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
971 {
972     FIXME("\n");
973     return E_NOTIMPL;
974 }
975
976 HRESULT mod_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
977 {
978     FIXME("\n");
979     return E_NOTIMPL;
980 }
981
982 HRESULT delete_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
983 {
984     FIXME("\n");
985     return E_NOTIMPL;
986 }
987
988 HRESULT void_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
989 {
990     FIXME("\n");
991     return E_NOTIMPL;
992 }
993
994 HRESULT typeof_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
995 {
996     unary_expression_t *expr = (unary_expression_t*)_expr;
997     const WCHAR *str;
998     exprval_t exprval;
999     VARIANT val;
1000     HRESULT hres;
1001
1002     static const WCHAR booleanW[] = {'b','o','o','l','e','a','n',0};
1003     static const WCHAR functionW[] = {'f','u','n','c','t','i','o','n',0};
1004     static const WCHAR numberW[] = {'n','u','m','b','e','r',0};
1005     static const WCHAR objectW[] = {'o','b','j','e','c','t',0};
1006     static const WCHAR stringW[] = {'s','t','r','i','n','g',0};
1007     static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
1008
1009     TRACE("\n");
1010
1011     hres = expr_eval(ctx, expr->expression, 0, ei, &exprval);
1012     if(FAILED(hres))
1013         return hres;
1014
1015     hres = exprval_to_value(ctx->parser->script, &exprval, ei, &val);
1016     exprval_release(&exprval);
1017     if(FAILED(hres))
1018         return hres;
1019
1020     switch(V_VT(&val)) {
1021     case VT_EMPTY:
1022         str = undefinedW;
1023         break;
1024     case VT_NULL:
1025         str = objectW;
1026         break;
1027     case VT_BOOL:
1028         str = booleanW;
1029         break;
1030     case VT_I4:
1031     case VT_R8:
1032         str = numberW;
1033         break;
1034     case VT_BSTR:
1035         str = stringW;
1036         break;
1037     case VT_DISPATCH: {
1038         DispatchEx *dispex;
1039
1040         dispex = iface_to_jsdisp((IUnknown*)V_DISPATCH(&val));
1041         if(dispex) {
1042             str = dispex->builtin_info->class == JSCLASS_FUNCTION ? functionW : objectW;
1043             IDispatchEx_Release(_IDispatchEx_(dispex));
1044         }else {
1045             str = objectW;
1046         }
1047         break;
1048     }
1049     default:
1050         FIXME("unhandled vt %d\n", V_VT(&val));
1051         hres = E_NOTIMPL;
1052     }
1053
1054     VariantClear(&val);
1055     if(FAILED(hres))
1056         return hres;
1057
1058     ret->type = EXPRVAL_VARIANT;
1059     V_VT(&ret->u.var) = VT_BSTR;
1060     V_BSTR(&ret->u.var) = SysAllocString(str);
1061     return S_OK;
1062 }
1063
1064 HRESULT minus_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1065 {
1066     FIXME("\n");
1067     return E_NOTIMPL;
1068 }
1069
1070 HRESULT plus_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1071 {
1072     FIXME("\n");
1073     return E_NOTIMPL;
1074 }
1075
1076 HRESULT post_increment_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1077 {
1078     FIXME("\n");
1079     return E_NOTIMPL;
1080 }
1081
1082 HRESULT post_decrement_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1083 {
1084     FIXME("\n");
1085     return E_NOTIMPL;
1086 }
1087
1088 HRESULT pre_increment_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1089 {
1090     FIXME("\n");
1091     return E_NOTIMPL;
1092 }
1093
1094 HRESULT pre_decrement_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1095 {
1096     FIXME("\n");
1097     return E_NOTIMPL;
1098 }
1099
1100 HRESULT new_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1101 {
1102     FIXME("\n");
1103     return E_NOTIMPL;
1104 }
1105
1106 HRESULT equal_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1107 {
1108     FIXME("\n");
1109     return E_NOTIMPL;
1110 }
1111
1112 /* ECMA-262 3rd Edition    11.9.4 */
1113 HRESULT equal2_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1114 {
1115     binary_expression_t *expr = (binary_expression_t*)_expr;
1116     VARIANT rval, lval;
1117     BOOL b;
1118     HRESULT hres;
1119
1120     TRACE("\n");
1121
1122     hres = get_binary_expr_values(ctx, expr, ei, &rval, &lval);
1123     if(FAILED(hres))
1124         return hres;
1125
1126     hres = equal2_values(&rval, &lval, &b);
1127     if(FAILED(hres))
1128         return hres;
1129
1130     return return_bool(ret, b);
1131 }
1132
1133 HRESULT not_equal_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1134 {
1135
1136     FIXME("\n");
1137     return E_NOTIMPL;
1138 }
1139
1140 /* ECMA-262 3rd Edition    11.9.5 */
1141 HRESULT not_equal2_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1142 {
1143     binary_expression_t *expr = (binary_expression_t*)_expr;
1144     VARIANT rval, lval;
1145     BOOL b;
1146     HRESULT hres;
1147
1148     TRACE("\n");
1149
1150     hres = get_binary_expr_values(ctx, expr, ei, &rval, &lval);
1151     if(FAILED(hres))
1152         return hres;
1153
1154     hres = equal2_values(&rval, &lval, &b);
1155     if(FAILED(hres))
1156         return hres;
1157
1158     return return_bool(ret, !b);
1159 }
1160
1161 HRESULT less_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1162 {
1163     FIXME("\n");
1164     return E_NOTIMPL;
1165 }
1166
1167 HRESULT lesseq_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1168 {
1169     FIXME("\n");
1170     return E_NOTIMPL;
1171 }
1172
1173 HRESULT greater_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1174 {
1175     FIXME("\n");
1176     return E_NOTIMPL;
1177 }
1178
1179 HRESULT greatereq_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1180 {
1181     FIXME("\n");
1182     return E_NOTIMPL;
1183 }
1184
1185 HRESULT binary_negation_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1186 {
1187     FIXME("\n");
1188     return E_NOTIMPL;
1189 }
1190
1191 /* ECMA-262 3rd Edition    11.4.9 */
1192 HRESULT logical_negation_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1193 {
1194     unary_expression_t *expr = (unary_expression_t*)_expr;
1195     exprval_t exprval;
1196     VARIANT_BOOL b;
1197     HRESULT hres;
1198
1199     TRACE("\n");
1200
1201     hres = expr_eval(ctx, expr->expression, EXPR_NEWREF, ei, &exprval);
1202     if(FAILED(hres))
1203         return hres;
1204
1205     hres = exprval_to_boolean(ctx->parser->script, &exprval, ei, &b);
1206     exprval_release(&exprval);
1207     if(FAILED(hres))
1208         return hres;
1209
1210     return return_bool(ret, !b);
1211 }
1212
1213 HRESULT left_shift_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1214 {
1215     FIXME("\n");
1216     return E_NOTIMPL;
1217 }
1218
1219 HRESULT right_shift_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1220 {
1221     FIXME("\n");
1222     return E_NOTIMPL;
1223 }
1224
1225 HRESULT right2_shift_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1226 {
1227     FIXME("\n");
1228     return E_NOTIMPL;
1229 }
1230
1231 /* ECMA-262 3rd Edition    11.13.1 */
1232 HRESULT assign_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1233 {
1234     binary_expression_t *expr = (binary_expression_t*)_expr;
1235     exprval_t exprval, exprvalr;
1236     VARIANT rval;
1237     HRESULT hres;
1238
1239     TRACE("\n");
1240
1241     hres = expr_eval(ctx, expr->expression1, EXPR_NEWREF, ei, &exprval);
1242     if(FAILED(hres))
1243         return hres;
1244
1245     hres = expr_eval(ctx, expr->expression2, 0, ei, &exprvalr);
1246     if(SUCCEEDED(hres)) {
1247         hres = exprval_to_value(ctx->parser->script, &exprvalr, ei, &rval);
1248         exprval_release(&exprvalr);
1249     }
1250
1251     if(SUCCEEDED(hres))
1252         hres = put_value(ctx->parser->script, &exprval, &rval, ei);
1253
1254     exprval_release(&exprval);
1255     if(FAILED(hres)) {
1256         VariantClear(&rval);
1257         return hres;
1258     }
1259
1260     ret->type = EXPRVAL_VARIANT;
1261     ret->u.var = rval;
1262     return S_OK;
1263 }
1264
1265 HRESULT assign_lshift_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1266 {
1267     FIXME("\n");
1268     return E_NOTIMPL;
1269 }
1270
1271 HRESULT assign_rshift_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1272 {
1273     FIXME("\n");
1274     return E_NOTIMPL;
1275 }
1276
1277 HRESULT assign_rrshift_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1278 {
1279     FIXME("\n");
1280     return E_NOTIMPL;
1281 }
1282
1283 HRESULT assign_add_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1284 {
1285     FIXME("\n");
1286     return E_NOTIMPL;
1287 }
1288
1289 HRESULT assign_sub_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1290 {
1291     FIXME("\n");
1292     return E_NOTIMPL;
1293 }
1294
1295 HRESULT assign_mul_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1296 {
1297     FIXME("\n");
1298     return E_NOTIMPL;
1299 }
1300
1301 HRESULT assign_div_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1302 {
1303     FIXME("\n");
1304     return E_NOTIMPL;
1305 }
1306
1307 HRESULT assign_mod_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1308 {
1309     FIXME("\n");
1310     return E_NOTIMPL;
1311 }
1312
1313 HRESULT assign_and_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1314 {
1315     FIXME("\n");
1316     return E_NOTIMPL;
1317 }
1318
1319 HRESULT assign_or_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1320 {
1321     FIXME("\n");
1322     return E_NOTIMPL;
1323 }
1324
1325 HRESULT assign_xor_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
1326 {
1327     FIXME("\n");
1328     return E_NOTIMPL;
1329 }