jscript: Added call 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 "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 void exprval_set_idref(exprval_t *val, IDispatch *disp, DISPID id)
90 {
91     val->type = EXPRVAL_IDREF;
92     val->u.idref.disp = disp;
93     val->u.idref.id = id;
94
95     if(disp)
96         IDispatch_AddRef(disp);
97 }
98
99 void scope_release(scope_chain_t *scope)
100 {
101     if(--scope->ref)
102         return;
103
104     if(scope->next)
105         scope_release(scope->next);
106
107     IDispatchEx_Release(_IDispatchEx_(scope->obj));
108     heap_free(scope);
109 }
110
111 HRESULT create_exec_ctx(DispatchEx *var_disp, scope_chain_t *scope, exec_ctx_t **ret)
112 {
113     exec_ctx_t *ctx;
114
115     ctx = heap_alloc_zero(sizeof(exec_ctx_t));
116     if(!ctx)
117         return E_OUTOFMEMORY;
118
119     IDispatchEx_AddRef(_IDispatchEx_(var_disp));
120     ctx->var_disp = var_disp;
121
122     if(scope) {
123         scope_addref(scope);
124         ctx->scope_chain = scope;
125     }
126
127     *ret = ctx;
128     return S_OK;
129 }
130
131 void exec_release(exec_ctx_t *ctx)
132 {
133     if(--ctx->ref)
134         return;
135
136     if(ctx->scope_chain)
137         scope_release(ctx->scope_chain);
138     if(ctx->var_disp)
139         IDispatchEx_Release(_IDispatchEx_(ctx->var_disp));
140     heap_free(ctx);
141 }
142
143 static HRESULT dispex_get_id(IDispatchEx *dispex, BSTR name, DWORD flags, DISPID *id)
144 {
145     *id = 0;
146
147     return IDispatchEx_GetDispID(dispex, name, flags|fdexNameCaseSensitive, id);
148 }
149
150 static HRESULT disp_get_id(IDispatch *disp, BSTR name, DWORD flags, DISPID *id)
151 {
152     IDispatchEx *dispex;
153     HRESULT hres;
154
155     hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
156     if(FAILED(hres)) {
157         TRACE("unsing IDispatch\n");
158
159         *id = 0;
160         return IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, id);
161     }
162
163     hres = dispex_get_id(dispex, name, flags, id);
164     IDispatchEx_Release(dispex);
165     return hres;
166 }
167
168 /* ECMA-262 3rd Edition    8.7.2 */
169 static HRESULT put_value(script_ctx_t *ctx, exprval_t *ref, VARIANT *v, jsexcept_t *ei)
170 {
171     if(ref->type != EXPRVAL_IDREF) {
172         FIXME("throw ReferemceError\n");
173         return E_FAIL;
174     }
175
176     return disp_propput(ref->u.idref.disp, ref->u.idref.id, ctx->lcid, v, ei, NULL/*FIXME*/);
177 }
178
179 static HRESULT literal_to_var(literal_t *literal, VARIANT *v)
180 {
181     V_VT(v) = literal->vt;
182
183     switch(V_VT(v)) {
184     case VT_EMPTY:
185     case VT_NULL:
186         break;
187     case VT_I4:
188         V_I4(v) = literal->u.lval;
189         break;
190     case VT_R8:
191         V_R8(v) = literal->u.dval;
192         break;
193     case VT_BSTR:
194         V_BSTR(v) = SysAllocString(literal->u.wstr);
195         break;
196     case VT_BOOL:
197         V_BOOL(v) = literal->u.bval;
198         break;
199     case VT_DISPATCH:
200         IDispatch_AddRef(literal->u.disp);
201         V_DISPATCH(v) = literal->u.disp;
202         break;
203     default:
204         ERR("wrong type %d\n", V_VT(v));
205         return E_NOTIMPL;
206     }
207
208     return S_OK;
209 }
210
211 HRESULT exec_source(exec_ctx_t *ctx, parser_ctx_t *parser, source_elements_t *source, jsexcept_t *ei, VARIANT *retv)
212 {
213     script_ctx_t *script = parser->script;
214     parser_ctx_t *prev_parser;
215     VARIANT val, tmp;
216     statement_t *stat;
217     exec_ctx_t *prev_ctx;
218     return_type_t rt;
219     HRESULT hres = S_OK;
220
221     prev_ctx = script->exec_ctx;
222     script->exec_ctx = ctx;
223
224     prev_parser = ctx->parser;
225     ctx->parser = parser;
226
227     V_VT(&val) = VT_EMPTY;
228     memset(&rt, 0, sizeof(rt));
229     rt.type = RT_NORMAL;
230
231     for(stat = source->statement; stat; stat = stat->next) {
232         hres = stat_eval(ctx, stat, &rt, &tmp);
233         if(FAILED(hres))
234             break;
235
236         VariantClear(&val);
237         val = tmp;
238         if(rt.type != RT_NORMAL)
239             break;
240     }
241
242     script->exec_ctx = prev_ctx;
243     ctx->parser = prev_parser;
244
245     if(rt.type != RT_NORMAL && rt.type != RT_RETURN) {
246         FIXME("wrong rt %d\n", rt.type);
247         hres = E_FAIL;
248     }
249
250     *ei = rt.ei;
251     if(FAILED(hres)) {
252         VariantClear(&val);
253         return hres;
254     }
255
256     if(retv)
257         *retv = val;
258     else
259         VariantClear(&val);
260     return S_OK;
261 }
262
263 /* ECMA-262 3rd Edition    10.1.4 */
264 static HRESULT identifier_eval(exec_ctx_t *ctx, BSTR identifier, DWORD flags, exprval_t *ret)
265 {
266     scope_chain_t *scope;
267     named_item_t *item;
268     DISPID id = 0;
269     HRESULT hres;
270
271     TRACE("%s\n", debugstr_w(identifier));
272
273     for(scope = ctx->scope_chain; scope; scope = scope->next) {
274         hres = dispex_get_id(_IDispatchEx_(scope->obj), identifier, 0, &id);
275         if(SUCCEEDED(hres))
276             break;
277     }
278
279     if(scope) {
280         exprval_set_idref(ret, (IDispatch*)_IDispatchEx_(scope->obj), id);
281         return S_OK;
282     }
283
284     hres = dispex_get_id(_IDispatchEx_(ctx->parser->script->global), identifier, 0, &id);
285     if(SUCCEEDED(hres)) {
286         exprval_set_idref(ret, (IDispatch*)_IDispatchEx_(ctx->parser->script->global), id);
287         return S_OK;
288     }
289
290     for(item = ctx->parser->script->named_items; item; item = item->next) {
291         hres = disp_get_id(item->disp, identifier, 0, &id);
292         if(SUCCEEDED(hres))
293             break;
294     }
295
296     if(item) {
297         exprval_set_idref(ret, (IDispatch*)item->disp, id);
298         return S_OK;
299     }
300
301     hres = dispex_get_id(_IDispatchEx_(ctx->parser->script->script_disp), identifier, 0, &id);
302     if(SUCCEEDED(hres)) {
303         exprval_set_idref(ret, (IDispatch*)_IDispatchEx_(ctx->parser->script->script_disp), id);
304         return S_OK;
305     }
306
307     if(flags & EXPR_NEWREF) {
308         hres = dispex_get_id(_IDispatchEx_(ctx->var_disp), identifier, fdexNameEnsure, &id);
309         if(FAILED(hres))
310             return hres;
311
312         exprval_set_idref(ret, (IDispatch*)_IDispatchEx_(ctx->var_disp), id);
313         return S_OK;
314     }
315
316     WARN("Could not find identifier %s\n", debugstr_w(identifier));
317     return E_FAIL;
318 }
319
320 HRESULT block_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
321 {
322     FIXME("\n");
323     return E_NOTIMPL;
324 }
325
326 HRESULT var_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
327 {
328     FIXME("\n");
329     return E_NOTIMPL;
330 }
331
332 /* ECMA-262 3rd Edition    12.3 */
333 HRESULT empty_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
334 {
335     TRACE("\n");
336
337     V_VT(ret) = VT_EMPTY;
338     return S_OK;
339 }
340
341 /* ECMA-262 3rd Edition    12.4 */
342 HRESULT expression_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
343 {
344     expression_statement_t *stat = (expression_statement_t*)_stat;
345     exprval_t exprval;
346     VARIANT val;
347     HRESULT hres;
348
349     TRACE("\n");
350
351     hres = expr_eval(ctx, stat->expr, EXPR_NOVAL, &rt->ei, &exprval);
352     if(FAILED(hres))
353         return hres;
354
355     hres = exprval_to_value(ctx->parser->script, &exprval, &rt->ei, &val);
356     exprval_release(&exprval);
357     if(FAILED(hres))
358         return hres;
359
360     *ret = val;
361     TRACE("= %s\n", debugstr_variant(ret));
362     return S_OK;
363 }
364
365 HRESULT if_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
366 {
367     FIXME("\n");
368     return E_NOTIMPL;
369 }
370
371 HRESULT dowhile_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
372 {
373     FIXME("\n");
374     return E_NOTIMPL;
375 }
376
377 HRESULT while_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
378 {
379     FIXME("\n");
380     return E_NOTIMPL;
381 }
382
383 HRESULT for_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
384 {
385     FIXME("\n");
386     return E_NOTIMPL;
387 }
388
389 HRESULT forin_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
390 {
391     FIXME("\n");
392     return E_NOTIMPL;
393 }
394
395 HRESULT continue_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
396 {
397     FIXME("\n");
398     return E_NOTIMPL;
399 }
400
401 HRESULT break_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
402 {
403     FIXME("\n");
404     return E_NOTIMPL;
405 }
406
407 HRESULT return_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
408 {
409     FIXME("\n");
410     return E_NOTIMPL;
411 }
412
413 HRESULT with_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
414 {
415     FIXME("\n");
416     return E_NOTIMPL;
417 }
418
419 HRESULT labelled_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
420 {
421     FIXME("\n");
422     return E_NOTIMPL;
423 }
424
425 HRESULT switch_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
426 {
427     FIXME("\n");
428     return E_NOTIMPL;
429 }
430
431 HRESULT throw_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
432 {
433     FIXME("\n");
434     return E_NOTIMPL;
435 }
436
437 HRESULT try_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
438 {
439     FIXME("\n");
440     return E_NOTIMPL;
441 }
442
443 HRESULT function_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
444 {
445     FIXME("\n");
446     return E_NOTIMPL;
447 }
448
449 HRESULT conditional_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
450 {
451     FIXME("\n");
452     return E_NOTIMPL;
453 }
454
455 HRESULT array_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
456 {
457     FIXME("\n");
458     return E_NOTIMPL;
459 }
460
461 HRESULT member_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
462 {
463     FIXME("\n");
464     return E_NOTIMPL;
465 }
466
467 static void free_dp(DISPPARAMS *dp)
468 {
469     DWORD i;
470
471     for(i=0; i < dp->cArgs; i++)
472         VariantClear(dp->rgvarg+i);
473     heap_free(dp->rgvarg);
474 }
475
476 static HRESULT args_to_param(exec_ctx_t *ctx, argument_t *args, jsexcept_t *ei, DISPPARAMS *dp)
477 {
478     VARIANTARG *vargs;
479     exprval_t exprval;
480     argument_t *iter;
481     DWORD cnt = 0, i;
482     HRESULT hres = S_OK;
483
484     memset(dp, 0, sizeof(*dp));
485
486     for(iter = args; iter; iter = iter->next)
487         cnt++;
488     if(!cnt)
489         return S_OK;
490
491     vargs = heap_alloc_zero(cnt * sizeof(*vargs));
492     if(!vargs)
493         return E_OUTOFMEMORY;
494
495     for(i = cnt, iter = args; iter; iter = iter->next) {
496         hres = expr_eval(ctx, iter->expr, 0, ei, &exprval);
497         if(FAILED(hres))
498             break;
499
500         hres = exprval_to_value(ctx->parser->script, &exprval, ei, vargs + (--i));
501         exprval_release(&exprval);
502         if(FAILED(hres))
503             break;
504     }
505
506     if(FAILED(hres)) {
507         free_dp(dp);
508         return hres;
509     }
510
511     dp->rgvarg = vargs;
512     dp->cArgs = cnt;
513     return S_OK;
514 }
515
516 HRESULT member_new_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
517 {
518     FIXME("\n");
519     return E_NOTIMPL;
520 }
521
522 HRESULT call_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
523 {
524     call_expression_t *expr = (call_expression_t*)_expr;
525     VARIANT func, var;
526     exprval_t exprval;
527     DISPPARAMS dp;
528     HRESULT hres;
529
530     TRACE("\n");
531
532     hres = expr_eval(ctx, expr->expression, 0, ei, &exprval);
533     if(FAILED(hres))
534         return hres;
535
536     hres = args_to_param(ctx, expr->argument_list, ei, &dp);
537     if(SUCCEEDED(hres)) {
538         switch(exprval.type) {
539         case EXPRVAL_IDREF:
540             hres = disp_call(exprval.u.idref.disp, exprval.u.idref.id, ctx->parser->script->lcid, DISPATCH_METHOD,
541                     &dp, flags & EXPR_NOVAL ? NULL : &var, ei, NULL/*FIXME*/);
542             if(flags & EXPR_NOVAL)
543                 V_VT(&var) = VT_EMPTY;
544             break;
545         default:
546             FIXME("unimplemented type %d\n", V_VT(&func));
547             hres = E_NOTIMPL;
548         }
549
550         free_dp(&dp);
551     }
552
553     exprval_release(&exprval);
554     if(FAILED(hres))
555         return hres;
556
557     TRACE("= %s\n", debugstr_variant(&var));
558     ret->type = EXPRVAL_VARIANT;
559     ret->u.var = var;
560     return S_OK;
561 }
562
563 HRESULT this_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
564 {
565     FIXME("\n");
566     return E_NOTIMPL;
567 }
568
569 /* ECMA-262 3rd Edition    10.1.4 */
570 HRESULT identifier_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
571 {
572     identifier_expression_t *expr = (identifier_expression_t*)_expr;
573     BSTR identifier;
574     HRESULT hres;
575
576     TRACE("\n");
577
578     identifier = SysAllocString(expr->identifier);
579     if(!identifier)
580         return E_OUTOFMEMORY;
581
582     hres = identifier_eval(ctx, identifier, flags, ret);
583
584     SysFreeString(identifier);
585     return hres;
586 }
587
588 /* ECMA-262 3rd Edition    7.8 */
589 HRESULT literal_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
590 {
591     literal_expression_t *expr = (literal_expression_t*)_expr;
592     VARIANT var;
593     HRESULT hres;
594
595     TRACE("\n");
596
597     hres = literal_to_var(expr->literal, &var);
598     if(FAILED(hres))
599         return hres;
600
601     ret->type = EXPRVAL_VARIANT;
602     ret->u.var = var;
603     return S_OK;
604 }
605
606 HRESULT array_literal_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
607 {
608     FIXME("\n");
609     return E_NOTIMPL;
610 }
611
612 HRESULT property_value_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
613 {
614     FIXME("\n");
615     return E_NOTIMPL;
616 }
617
618 HRESULT comma_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
619 {
620     FIXME("\n");
621     return E_NOTIMPL;
622 }
623
624 HRESULT logical_or_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
625 {
626     FIXME("\n");
627     return E_NOTIMPL;
628 }
629
630 HRESULT logical_and_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
631 {
632     FIXME("\n");
633     return E_NOTIMPL;
634 }
635
636 HRESULT binary_or_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
637 {
638     FIXME("\n");
639     return E_NOTIMPL;
640 }
641
642 HRESULT binary_xor_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
643 {
644     FIXME("\n");
645     return E_NOTIMPL;
646 }
647
648 HRESULT binary_and_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
649 {
650     FIXME("\n");
651     return E_NOTIMPL;
652 }
653
654 HRESULT instanceof_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
655 {
656     FIXME("\n");
657     return E_NOTIMPL;
658 }
659
660 HRESULT in_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
661 {
662     FIXME("\n");
663     return E_NOTIMPL;
664 }
665
666 HRESULT add_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
667 {
668     FIXME("\n");
669     return E_NOTIMPL;
670 }
671
672 HRESULT sub_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
673 {
674     FIXME("\n");
675     return E_NOTIMPL;
676 }
677
678 HRESULT mul_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
679 {
680     FIXME("\n");
681     return E_NOTIMPL;
682 }
683
684 HRESULT div_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
685 {
686     FIXME("\n");
687     return E_NOTIMPL;
688 }
689
690 HRESULT mod_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
691 {
692     FIXME("\n");
693     return E_NOTIMPL;
694 }
695
696 HRESULT delete_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
697 {
698     FIXME("\n");
699     return E_NOTIMPL;
700 }
701
702 HRESULT void_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
703 {
704     FIXME("\n");
705     return E_NOTIMPL;
706 }
707
708 HRESULT typeof_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
709 {
710     FIXME("\n");
711     return E_NOTIMPL;
712 }
713
714 HRESULT minus_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
715 {
716     FIXME("\n");
717     return E_NOTIMPL;
718 }
719
720 HRESULT plus_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
721 {
722     FIXME("\n");
723     return E_NOTIMPL;
724 }
725
726 HRESULT post_increment_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
727 {
728     FIXME("\n");
729     return E_NOTIMPL;
730 }
731
732 HRESULT post_decrement_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
733 {
734     FIXME("\n");
735     return E_NOTIMPL;
736 }
737
738 HRESULT pre_increment_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
739 {
740     FIXME("\n");
741     return E_NOTIMPL;
742 }
743
744 HRESULT pre_decrement_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
745 {
746     FIXME("\n");
747     return E_NOTIMPL;
748 }
749
750 HRESULT new_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
751 {
752     FIXME("\n");
753     return E_NOTIMPL;
754 }
755
756 HRESULT equal_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
757 {
758     FIXME("\n");
759     return E_NOTIMPL;
760 }
761
762 HRESULT equal2_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
763 {
764     FIXME("\n");
765     return E_NOTIMPL;
766 }
767
768 HRESULT not_equal_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
769 {
770
771     FIXME("\n");
772     return E_NOTIMPL;
773 }
774
775 HRESULT not_equal2_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
776 {
777     FIXME("\n");
778     return E_NOTIMPL;
779 }
780
781 HRESULT less_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
782 {
783     FIXME("\n");
784     return E_NOTIMPL;
785 }
786
787 HRESULT lesseq_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
788 {
789     FIXME("\n");
790     return E_NOTIMPL;
791 }
792
793 HRESULT greater_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
794 {
795     FIXME("\n");
796     return E_NOTIMPL;
797 }
798
799 HRESULT greatereq_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
800 {
801     FIXME("\n");
802     return E_NOTIMPL;
803 }
804
805 HRESULT binary_negation_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
806 {
807     FIXME("\n");
808     return E_NOTIMPL;
809 }
810
811 HRESULT logical_negation_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
812 {
813     FIXME("\n");
814     return E_NOTIMPL;
815 }
816
817 HRESULT left_shift_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
818 {
819     FIXME("\n");
820     return E_NOTIMPL;
821 }
822
823 HRESULT right_shift_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
824 {
825     FIXME("\n");
826     return E_NOTIMPL;
827 }
828
829 HRESULT right2_shift_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
830 {
831     FIXME("\n");
832     return E_NOTIMPL;
833 }
834
835 /* ECMA-262 3rd Edition    11.13.1 */
836 HRESULT assign_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
837 {
838     binary_expression_t *expr = (binary_expression_t*)_expr;
839     exprval_t exprval, exprvalr;
840     VARIANT rval;
841     HRESULT hres;
842
843     TRACE("\n");
844
845     hres = expr_eval(ctx, expr->expression1, EXPR_NEWREF, ei, &exprval);
846     if(FAILED(hres))
847         return hres;
848
849     hres = expr_eval(ctx, expr->expression2, 0, ei, &exprvalr);
850     if(SUCCEEDED(hres)) {
851         hres = exprval_to_value(ctx->parser->script, &exprvalr, ei, &rval);
852         exprval_release(&exprvalr);
853     }
854
855     if(SUCCEEDED(hres))
856         hres = put_value(ctx->parser->script, &exprval, &rval, ei);
857
858     exprval_release(&exprval);
859     if(FAILED(hres)) {
860         VariantClear(&rval);
861         return hres;
862     }
863
864     ret->type = EXPRVAL_VARIANT;
865     ret->u.var = rval;
866     return S_OK;
867 }
868
869 HRESULT assign_lshift_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
870 {
871     FIXME("\n");
872     return E_NOTIMPL;
873 }
874
875 HRESULT assign_rshift_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
876 {
877     FIXME("\n");
878     return E_NOTIMPL;
879 }
880
881 HRESULT assign_rrshift_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
882 {
883     FIXME("\n");
884     return E_NOTIMPL;
885 }
886
887 HRESULT assign_add_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
888 {
889     FIXME("\n");
890     return E_NOTIMPL;
891 }
892
893 HRESULT assign_sub_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
894 {
895     FIXME("\n");
896     return E_NOTIMPL;
897 }
898
899 HRESULT assign_mul_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
900 {
901     FIXME("\n");
902     return E_NOTIMPL;
903 }
904
905 HRESULT assign_div_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
906 {
907     FIXME("\n");
908     return E_NOTIMPL;
909 }
910
911 HRESULT assign_mod_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
912 {
913     FIXME("\n");
914     return E_NOTIMPL;
915 }
916
917 HRESULT assign_and_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
918 {
919     FIXME("\n");
920     return E_NOTIMPL;
921 }
922
923 HRESULT assign_or_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
924 {
925     FIXME("\n");
926     return E_NOTIMPL;
927 }
928
929 HRESULT assign_xor_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
930 {
931     FIXME("\n");
932     return E_NOTIMPL;
933 }