jscript: Added assign 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 HRESULT create_exec_ctx(exec_ctx_t **ret)
100 {
101     exec_ctx_t *ctx;
102
103     ctx = heap_alloc_zero(sizeof(exec_ctx_t));
104     if(!ctx)
105         return E_OUTOFMEMORY;
106
107     *ret = ctx;
108     return S_OK;
109 }
110
111 void exec_release(exec_ctx_t *ctx)
112 {
113     if(--ctx->ref)
114         return;
115
116     heap_free(ctx);
117 }
118
119 static HRESULT dispex_get_id(IDispatchEx *dispex, BSTR name, DWORD flags, DISPID *id)
120 {
121     *id = 0;
122
123     return IDispatchEx_GetDispID(dispex, name, flags|fdexNameCaseSensitive, id);
124 }
125
126 static HRESULT disp_get_id(IDispatch *disp, BSTR name, DWORD flags, DISPID *id)
127 {
128     IDispatchEx *dispex;
129     HRESULT hres;
130
131     hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
132     if(FAILED(hres)) {
133         TRACE("unsing IDispatch\n");
134
135         *id = 0;
136         return IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, id);
137     }
138
139     hres = dispex_get_id(dispex, name, flags, id);
140     IDispatchEx_Release(dispex);
141     return hres;
142 }
143
144 /* ECMA-262 3rd Edition    8.7.2 */
145 static HRESULT put_value(script_ctx_t *ctx, exprval_t *ref, VARIANT *v, jsexcept_t *ei)
146 {
147     if(ref->type != EXPRVAL_IDREF) {
148         FIXME("throw ReferemceError\n");
149         return E_FAIL;
150     }
151
152     return disp_propput(ref->u.idref.disp, ref->u.idref.id, ctx->lcid, v, ei, NULL/*FIXME*/);
153 }
154
155 HRESULT exec_source(exec_ctx_t *ctx, parser_ctx_t *parser, source_elements_t *source, jsexcept_t *ei, VARIANT *retv)
156 {
157     script_ctx_t *script = parser->script;
158     parser_ctx_t *prev_parser;
159     VARIANT val, tmp;
160     statement_t *stat;
161     exec_ctx_t *prev_ctx;
162     return_type_t rt;
163     HRESULT hres = S_OK;
164
165     prev_ctx = script->exec_ctx;
166     script->exec_ctx = ctx;
167
168     prev_parser = ctx->parser;
169     ctx->parser = parser;
170
171     V_VT(&val) = VT_EMPTY;
172     memset(&rt, 0, sizeof(rt));
173     rt.type = RT_NORMAL;
174
175     for(stat = source->statement; stat; stat = stat->next) {
176         hres = stat_eval(ctx, stat, &rt, &tmp);
177         if(FAILED(hres))
178             break;
179
180         VariantClear(&val);
181         val = tmp;
182         if(rt.type != RT_NORMAL)
183             break;
184     }
185
186     script->exec_ctx = prev_ctx;
187     ctx->parser = prev_parser;
188
189     if(rt.type != RT_NORMAL && rt.type != RT_RETURN) {
190         FIXME("wrong rt %d\n", rt.type);
191         hres = E_FAIL;
192     }
193
194     *ei = rt.ei;
195     if(FAILED(hres)) {
196         VariantClear(&val);
197         return hres;
198     }
199
200     if(retv)
201         *retv = val;
202     else
203         VariantClear(&val);
204     return S_OK;
205 }
206
207 /* ECMA-262 3rd Edition    10.1.4 */
208 static HRESULT identifier_eval(exec_ctx_t *ctx, BSTR identifier, DWORD flags, exprval_t *ret)
209 {
210     named_item_t *item;
211     DISPID id = 0;
212     HRESULT hres;
213
214     TRACE("%s\n", debugstr_w(identifier));
215
216     /* FIXME: scope chain */
217
218     hres = dispex_get_id(_IDispatchEx_(ctx->parser->script->global), identifier, 0, &id);
219     if(SUCCEEDED(hres)) {
220         exprval_set_idref(ret, (IDispatch*)_IDispatchEx_(ctx->parser->script->global), id);
221         return S_OK;
222     }
223
224     for(item = ctx->parser->script->named_items; item; item = item->next) {
225         hres = disp_get_id(item->disp, identifier, 0, &id);
226         if(SUCCEEDED(hres))
227             break;
228     }
229
230     if(item) {
231         exprval_set_idref(ret, (IDispatch*)item->disp, id);
232         return S_OK;
233     }
234
235     hres = dispex_get_id(_IDispatchEx_(ctx->parser->script->script_disp), identifier, 0, &id);
236     if(SUCCEEDED(hres)) {
237         exprval_set_idref(ret, (IDispatch*)_IDispatchEx_(ctx->parser->script->script_disp), id);
238         return S_OK;
239     }
240
241     if(flags & EXPR_NEWREF) {
242         FIXME("create ref\n");
243         return E_NOTIMPL;
244     }
245
246     WARN("Could not find identifier %s\n", debugstr_w(identifier));
247     return E_FAIL;
248 }
249
250 HRESULT block_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
251 {
252     FIXME("\n");
253     return E_NOTIMPL;
254 }
255
256 HRESULT var_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
257 {
258     FIXME("\n");
259     return E_NOTIMPL;
260 }
261
262 /* ECMA-262 3rd Edition    12.3 */
263 HRESULT empty_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
264 {
265     TRACE("\n");
266
267     V_VT(ret) = VT_EMPTY;
268     return S_OK;
269 }
270
271 /* ECMA-262 3rd Edition    12.4 */
272 HRESULT expression_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
273 {
274     expression_statement_t *stat = (expression_statement_t*)_stat;
275     exprval_t exprval;
276     VARIANT val;
277     HRESULT hres;
278
279     TRACE("\n");
280
281     hres = expr_eval(ctx, stat->expr, EXPR_NOVAL, &rt->ei, &exprval);
282     if(FAILED(hres))
283         return hres;
284
285     hres = exprval_to_value(ctx->parser->script, &exprval, &rt->ei, &val);
286     exprval_release(&exprval);
287     if(FAILED(hres))
288         return hres;
289
290     *ret = val;
291     TRACE("= %s\n", debugstr_variant(ret));
292     return S_OK;
293 }
294
295 HRESULT if_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
296 {
297     FIXME("\n");
298     return E_NOTIMPL;
299 }
300
301 HRESULT dowhile_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
302 {
303     FIXME("\n");
304     return E_NOTIMPL;
305 }
306
307 HRESULT while_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
308 {
309     FIXME("\n");
310     return E_NOTIMPL;
311 }
312
313 HRESULT for_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
314 {
315     FIXME("\n");
316     return E_NOTIMPL;
317 }
318
319 HRESULT forin_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
320 {
321     FIXME("\n");
322     return E_NOTIMPL;
323 }
324
325 HRESULT continue_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
326 {
327     FIXME("\n");
328     return E_NOTIMPL;
329 }
330
331 HRESULT break_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
332 {
333     FIXME("\n");
334     return E_NOTIMPL;
335 }
336
337 HRESULT return_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
338 {
339     FIXME("\n");
340     return E_NOTIMPL;
341 }
342
343 HRESULT with_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
344 {
345     FIXME("\n");
346     return E_NOTIMPL;
347 }
348
349 HRESULT labelled_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
350 {
351     FIXME("\n");
352     return E_NOTIMPL;
353 }
354
355 HRESULT switch_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
356 {
357     FIXME("\n");
358     return E_NOTIMPL;
359 }
360
361 HRESULT throw_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
362 {
363     FIXME("\n");
364     return E_NOTIMPL;
365 }
366
367 HRESULT try_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
368 {
369     FIXME("\n");
370     return E_NOTIMPL;
371 }
372
373 HRESULT function_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
374 {
375     FIXME("\n");
376     return E_NOTIMPL;
377 }
378
379 HRESULT conditional_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
380 {
381     FIXME("\n");
382     return E_NOTIMPL;
383 }
384
385 HRESULT array_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
386 {
387     FIXME("\n");
388     return E_NOTIMPL;
389 }
390
391 HRESULT member_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
392 {
393     FIXME("\n");
394     return E_NOTIMPL;
395 }
396
397 HRESULT member_new_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
398 {
399     FIXME("\n");
400     return E_NOTIMPL;
401 }
402
403 HRESULT call_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
404 {
405     FIXME("\n");
406     return E_NOTIMPL;
407 }
408
409 HRESULT this_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
410 {
411     FIXME("\n");
412     return E_NOTIMPL;
413 }
414
415 /* ECMA-262 3rd Edition    10.1.4 */
416 HRESULT identifier_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
417 {
418     identifier_expression_t *expr = (identifier_expression_t*)_expr;
419     BSTR identifier;
420     HRESULT hres;
421
422     TRACE("\n");
423
424     identifier = SysAllocString(expr->identifier);
425     if(!identifier)
426         return E_OUTOFMEMORY;
427
428     hres = identifier_eval(ctx, identifier, flags, ret);
429
430     SysFreeString(identifier);
431     return hres;
432 }
433
434 HRESULT literal_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
435 {
436     FIXME("\n");
437     return E_NOTIMPL;
438 }
439
440 HRESULT array_literal_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
441 {
442     FIXME("\n");
443     return E_NOTIMPL;
444 }
445
446 HRESULT property_value_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
447 {
448     FIXME("\n");
449     return E_NOTIMPL;
450 }
451
452 HRESULT comma_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
453 {
454     FIXME("\n");
455     return E_NOTIMPL;
456 }
457
458 HRESULT logical_or_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
459 {
460     FIXME("\n");
461     return E_NOTIMPL;
462 }
463
464 HRESULT logical_and_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
465 {
466     FIXME("\n");
467     return E_NOTIMPL;
468 }
469
470 HRESULT binary_or_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
471 {
472     FIXME("\n");
473     return E_NOTIMPL;
474 }
475
476 HRESULT binary_xor_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
477 {
478     FIXME("\n");
479     return E_NOTIMPL;
480 }
481
482 HRESULT binary_and_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
483 {
484     FIXME("\n");
485     return E_NOTIMPL;
486 }
487
488 HRESULT instanceof_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
489 {
490     FIXME("\n");
491     return E_NOTIMPL;
492 }
493
494 HRESULT in_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
495 {
496     FIXME("\n");
497     return E_NOTIMPL;
498 }
499
500 HRESULT add_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
501 {
502     FIXME("\n");
503     return E_NOTIMPL;
504 }
505
506 HRESULT sub_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
507 {
508     FIXME("\n");
509     return E_NOTIMPL;
510 }
511
512 HRESULT mul_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
513 {
514     FIXME("\n");
515     return E_NOTIMPL;
516 }
517
518 HRESULT div_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
519 {
520     FIXME("\n");
521     return E_NOTIMPL;
522 }
523
524 HRESULT mod_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
525 {
526     FIXME("\n");
527     return E_NOTIMPL;
528 }
529
530 HRESULT delete_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
531 {
532     FIXME("\n");
533     return E_NOTIMPL;
534 }
535
536 HRESULT void_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
537 {
538     FIXME("\n");
539     return E_NOTIMPL;
540 }
541
542 HRESULT typeof_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
543 {
544     FIXME("\n");
545     return E_NOTIMPL;
546 }
547
548 HRESULT minus_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
549 {
550     FIXME("\n");
551     return E_NOTIMPL;
552 }
553
554 HRESULT plus_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
555 {
556     FIXME("\n");
557     return E_NOTIMPL;
558 }
559
560 HRESULT post_increment_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
561 {
562     FIXME("\n");
563     return E_NOTIMPL;
564 }
565
566 HRESULT post_decrement_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
567 {
568     FIXME("\n");
569     return E_NOTIMPL;
570 }
571
572 HRESULT pre_increment_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
573 {
574     FIXME("\n");
575     return E_NOTIMPL;
576 }
577
578 HRESULT pre_decrement_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
579 {
580     FIXME("\n");
581     return E_NOTIMPL;
582 }
583
584 HRESULT new_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
585 {
586     FIXME("\n");
587     return E_NOTIMPL;
588 }
589
590 HRESULT equal_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
591 {
592     FIXME("\n");
593     return E_NOTIMPL;
594 }
595
596 HRESULT equal2_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
597 {
598     FIXME("\n");
599     return E_NOTIMPL;
600 }
601
602 HRESULT not_equal_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
603 {
604
605     FIXME("\n");
606     return E_NOTIMPL;
607 }
608
609 HRESULT not_equal2_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
610 {
611     FIXME("\n");
612     return E_NOTIMPL;
613 }
614
615 HRESULT less_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
616 {
617     FIXME("\n");
618     return E_NOTIMPL;
619 }
620
621 HRESULT lesseq_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
622 {
623     FIXME("\n");
624     return E_NOTIMPL;
625 }
626
627 HRESULT greater_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
628 {
629     FIXME("\n");
630     return E_NOTIMPL;
631 }
632
633 HRESULT greatereq_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
634 {
635     FIXME("\n");
636     return E_NOTIMPL;
637 }
638
639 HRESULT binary_negation_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
640 {
641     FIXME("\n");
642     return E_NOTIMPL;
643 }
644
645 HRESULT logical_negation_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
646 {
647     FIXME("\n");
648     return E_NOTIMPL;
649 }
650
651 HRESULT left_shift_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
652 {
653     FIXME("\n");
654     return E_NOTIMPL;
655 }
656
657 HRESULT right_shift_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
658 {
659     FIXME("\n");
660     return E_NOTIMPL;
661 }
662
663 HRESULT right2_shift_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
664 {
665     FIXME("\n");
666     return E_NOTIMPL;
667 }
668
669 /* ECMA-262 3rd Edition    11.13.1 */
670 HRESULT assign_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
671 {
672     binary_expression_t *expr = (binary_expression_t*)_expr;
673     exprval_t exprval, exprvalr;
674     VARIANT rval;
675     HRESULT hres;
676
677     TRACE("\n");
678
679     hres = expr_eval(ctx, expr->expression1, EXPR_NEWREF, ei, &exprval);
680     if(FAILED(hres))
681         return hres;
682
683     hres = expr_eval(ctx, expr->expression2, 0, ei, &exprvalr);
684     if(SUCCEEDED(hres)) {
685         hres = exprval_to_value(ctx->parser->script, &exprvalr, ei, &rval);
686         exprval_release(&exprvalr);
687     }
688
689     if(SUCCEEDED(hres))
690         hres = put_value(ctx->parser->script, &exprval, &rval, ei);
691
692     exprval_release(&exprval);
693     if(FAILED(hres)) {
694         VariantClear(&rval);
695         return hres;
696     }
697
698     ret->type = EXPRVAL_VARIANT;
699     ret->u.var = rval;
700     return S_OK;
701 }
702
703 HRESULT assign_lshift_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
704 {
705     FIXME("\n");
706     return E_NOTIMPL;
707 }
708
709 HRESULT assign_rshift_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
710 {
711     FIXME("\n");
712     return E_NOTIMPL;
713 }
714
715 HRESULT assign_rrshift_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
716 {
717     FIXME("\n");
718     return E_NOTIMPL;
719 }
720
721 HRESULT assign_add_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
722 {
723     FIXME("\n");
724     return E_NOTIMPL;
725 }
726
727 HRESULT assign_sub_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
728 {
729     FIXME("\n");
730     return E_NOTIMPL;
731 }
732
733 HRESULT assign_mul_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
734 {
735     FIXME("\n");
736     return E_NOTIMPL;
737 }
738
739 HRESULT assign_div_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
740 {
741     FIXME("\n");
742     return E_NOTIMPL;
743 }
744
745 HRESULT assign_mod_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
746 {
747     FIXME("\n");
748     return E_NOTIMPL;
749 }
750
751 HRESULT assign_and_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
752 {
753     FIXME("\n");
754     return E_NOTIMPL;
755 }
756
757 HRESULT assign_or_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
758 {
759     FIXME("\n");
760     return E_NOTIMPL;
761 }
762
763 HRESULT assign_xor_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
764 {
765     FIXME("\n");
766     return E_NOTIMPL;
767 }