Merge remote-tracking branch 'redux/master' into sh4-pool
[tamarin-stm.git] / eval / eval-parse-stmt.cpp
blobeda42d2572de595b25e234281ff0f75c1c615b45
1 /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
2 /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
16 * The Original Code is [Open Source Virtual Machine.].
18 * The Initial Developer of the Original Code is
19 * Adobe System Incorporated.
20 * Portions created by the Initial Developer are Copyright (C) 2008
21 * the Initial Developer. All Rights Reserved.
23 * Contributor(s):
24 * Adobe AS3 Team
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #include "avmplus.h"
42 #ifdef VMCFG_EVAL
44 #include "eval.h"
46 namespace avmplus
48 namespace RTC
50 Stmt* Parser::statement(bool config)
52 AvmAssert(config == true || hd() == T_LeftBrace);
53 switch (hd()) {
54 case T_Semicolon: {
55 Stmt* stmt = ALLOC(EmptyStmt, ());
56 next();
57 return stmt;
60 case T_LeftBrace:
61 return ALLOC(BlockStmt, (statementBlock(config)));
63 case T_Break: {
64 Stmt* stmt = breakStatement();
65 semicolon();
66 return stmt;
69 case T_Continue: {
70 Stmt* stmt = continueStatement();
71 semicolon();
72 return stmt;
75 case T_Default: {
76 next();
77 if (hd() == T_Identifier && identValue() == compiler->SYM_xml) {
78 Stmt* stmt = defaultXmlNamespaceStatement();
79 semicolon();
80 return stmt;
82 else {
83 compiler->syntaxError(position(), SYNTAXERR_DEFAULT_NOT_EXPECTED);
84 /*NOTREACHED*/
85 return NULL;
89 case T_Do: {
90 Stmt* stmt = doStatement();
91 semicolon();
92 return stmt;
95 case T_For:
96 return forStatement();
98 case T_If:
99 return ifStatement();
101 case T_Import:
102 return importStatement();
104 case T_Return: {
105 Stmt* stmt = returnStatement();
106 semicolon();
107 return stmt;
110 case T_Switch:
111 return switchStatement();
113 case T_Throw: {
114 Stmt* stmt = throwStatement();
115 semicolon();
116 return stmt;
119 case T_Try:
120 return tryStatement();
122 case T_Use: {
123 Stmt* stmt = useStatement();
124 semicolon();
125 return stmt;
128 case T_Var:
129 case T_Const: {
130 Stmt* stmt = varStatement(hd() == T_Const);
131 semicolon();
132 return stmt;
135 case T_While:
136 return whileStatement();
138 case T_With:
139 return withStatement ();
141 case T_Function:
142 if (compiler->local_functions) {
143 // FIXME: should block-internal function definition be initialized on block entry?
144 uint32_t pos = position();
145 Qualifier qual;
146 FunctionDefn* fn = functionGuts(&qual, true, false, true);
147 Str* name = fn->name;
148 fn->name = NULL;
149 addVarBinding(name, NULL);
150 return ALLOC(ExprStmt, (pos,
151 ALLOC(AssignExpr,
152 (OPR_assign,
153 ALLOC(QualifiedName, (NULL, ALLOC(SimpleName, (name)), false, pos)),
154 ALLOC(LiteralFunction, (fn))))));
156 else {
157 compiler->syntaxError(position(), SYNTAXERR_NO_FUNCTIONS_IN_BLOCKS);
158 /*NOTREACHED*/
159 return NULL;
162 case T_Super:
163 return superStatement();
165 default: {
166 if (hd() == T_Identifier && hd2() == T_Colon)
167 return labeledStatement();
168 uint32_t pos = position();
169 Stmt* stmt = ALLOC(ExprStmt, (pos, commaExpression(0)));
170 semicolon();
171 return stmt;
176 void Parser::semicolon()
178 switch (hd ()) {
179 case T_Semicolon:
180 next();
181 return;
182 case T_EOS:
183 case T_RightBrace:
184 // Inserting it
185 return;
186 default:
187 if (!newline ())
188 compiler->syntaxError(position(), SYNTAXERR_SEMICOLON_OR_NEWLINE);
189 // Inserting it
190 return;
194 bool Parser::noNewline()
196 switch (hd ()) {
197 case T_EOS:
198 case T_Semicolon:
199 case T_RightBrace:
200 return false;
201 default:
202 if (newline())
203 return false;
204 return true;
208 Seq<Stmt*>* Parser::statementBlock(bool config)
210 SeqBuilder<Stmt*> stmts(allocator);
211 eat (T_LeftBrace);
212 while (hd() != T_RightBrace)
213 stmts.addAtEnd(statement(config));
214 eat (T_RightBrace);
215 return stmts.get();
218 // updates bindings by side effect, returns a single expression
219 // statement for the initialization.
221 Stmt* Parser::varStatement(bool is_const)
223 uint32_t pos = 0;
224 Expr* inits = varBindings(&pos, is_const);
225 return ALLOC(ExprStmt, (pos, inits));
228 // updates bindings by side effect, returns a single expression for
229 // the initialization, a LiteralUndefined node if there was no useful
230 // initialization.
232 Expr* Parser::varBindings(uint32_t* pos, bool is_const, int flags, uint32_t* numbindings, Expr** firstName)
234 AvmAssert( !is_const || firstName == NULL );
236 Expr* inits = NULL;
237 eat(is_const ? T_Const : T_Var);
238 *pos = position();
239 if (numbindings)
240 *numbindings = 0;
241 if (firstName)
242 *firstName = NULL;
243 for (;;) {
244 Str* name = identifier();
245 QualifiedName* type_name = NULL;
246 if (match(T_Colon))
247 type_name = typeExpression();
248 if (numbindings)
249 *numbindings += 1;
250 if (!is_const)
251 addVarBinding(name, type_name);
253 if (is_const && hd() != T_Assign)
254 compiler->syntaxError(*pos, SYNTAXERR_CONST_INIT_REQD);
256 if (match(T_Assign)) {
257 Expr* init = assignmentExpression(flags);
258 Expr* lhs = ALLOC(QualifiedName, (NULL, ALLOC(SimpleName, (name)), false, *pos));
259 if (is_const)
260 addConstBinding(name, type_name);
261 Expr* assign = ALLOC(AssignExpr, (is_const ? OPR_init : OPR_assign, lhs, init));
262 if (firstName && *firstName == NULL)
263 *firstName = lhs;
264 if (inits == NULL)
265 inits = assign;
266 else
267 inits = ALLOC(BinaryExpr, (OPR_comma, inits, assign));
269 else if (firstName && *firstName == NULL) {
270 *firstName = ALLOC(QualifiedName, (NULL, ALLOC(SimpleName, (name)), false, *pos));
273 if (!match(T_Comma))
274 break;
276 return inits ? inits : ALLOC(LiteralUndefined, (*pos));
279 Stmt* Parser::useStatement()
281 uint32_t pos = position();
282 eat(T_Use);
283 if (!match(T_Namespace))
284 compiler->syntaxError(pos, SYNTAXERR_ILLEGAL_USE);
285 Str* ns = identifier();
286 addOpenNamespace(ALLOC(NamespaceRef, (ns)));
287 return ALLOC(EmptyStmt, ());
290 // <import> ::= "import" <ident> { "." <ident> }* { "." "*" }
291 Stmt* Parser::importStatement()
293 SeqBuilder<Str*> name(allocator);
294 StringBuilder id(compiler);
296 eat(T_Import);
297 if (hd() == T_Identifier) {
298 name.addAtEnd(identValue());
299 id.append(identValue());
301 eat(T_Identifier);
302 bool qualified = true;
303 while (match(T_Dot)) {
304 if (hd() == T_Multiply) {
305 match(T_Multiply);
306 qualified = false;
307 break;
309 id.append(".");
310 if (hd() == T_Identifier) {
311 name.addAtEnd(identValue());
312 id.append(identValue());
314 eat(T_Identifier);
316 Seq<Str*>* n = name.get();
317 if (qualified)
318 addQualifiedImport(n);
319 else {
320 addOpenNamespace(ALLOC(CommonNamespace, (id.str())));
321 addUnqualifiedImport(n);
323 return ALLOC(EmptyStmt, ());
326 Stmt* Parser::labeledStatement()
328 Str* label = identifier();
329 eat(T_Colon);
331 Stmt* stmt = statement();
333 Stmt* s = stmt;
334 while (s->isLabeledStmt())
335 s = ((LabeledStmt*)s)->stmt;
336 if (s->isLabelSetStmt()) {
337 LabelSetStmt* ls = (LabelSetStmt*)s;
338 ls->labels = ALLOC(Seq<Str*>, (label, ls->labels));
341 return ALLOC(LabeledStmt, (label, stmt));
344 Stmt* Parser::returnStatement()
346 eat (T_Return);
347 uint32_t pos = position();
348 if (topRib->tag != RIB_Function)
349 compiler->syntaxError(pos, SYNTAXERR_RETURN_OUTSIDE_FN);
350 Expr* expr = NULL;
351 if (noNewline()) {
352 if (topRib->is_void)
353 compiler->syntaxError(pos, SYNTAXERR_VOIDFN_RETURNS_VALUE);
354 expr = commaExpression(0);
356 return ALLOC(ReturnStmt, (pos, expr));
359 Stmt* Parser::breakStatement()
361 uint32_t pos = position();
362 return ALLOC(BreakStmt, (pos, breakOrContinueLabel(T_Break)));
365 Stmt* Parser::continueStatement()
367 uint32_t pos = position();
368 return ALLOC(ContinueStmt, (pos, breakOrContinueLabel(T_Continue)));
371 Str* Parser::breakOrContinueLabel(Token tok)
373 eat(tok);
374 return noNewline() ? identifier() : NULL;
377 // 'default' has been consumed, hd() is the identifier 'xml'
378 Stmt* Parser::defaultXmlNamespaceStatement()
380 uint32_t pos = position();
381 if(hd() != T_Identifier || identValue() != compiler->SYM_xml)
382 goto failure;
383 eat(T_Identifier);
384 if(hd() != T_Namespace)
385 goto failure;
386 eat(T_Namespace);
387 eat(T_Assign);
388 setUsesDefaultXmlNamespace();
389 return ALLOC(DefaultXmlNamespaceStmt, (pos, commaExpression(0)));
390 failure:
391 compiler->syntaxError(pos, SYNTAXERR_EXPECT_DXNS);
392 /*NOTREACHED*/
393 return NULL;
396 Stmt* Parser::ifStatement()
398 eat(T_If);
399 uint32_t pos = position();
400 Expr* test = parenExpression();
401 Stmt* consequent = statement();
402 Stmt* alternate = NULL;
403 if (match(T_Else))
404 alternate = statement();
406 return ALLOC(IfStmt, (pos, test, consequent, alternate));
409 Stmt* Parser::whileStatement()
411 eat(T_While);
412 uint32_t pos = position();
413 Expr* expr = parenExpression();
414 Stmt* body = statement();
416 return ALLOC(WhileStmt, (pos, expr, body));
419 Stmt* Parser::doStatement()
421 eat(T_Do);
422 Stmt* body = statement();
423 eat(T_While);
424 uint32_t pos = position();
425 Expr* expr = parenExpression ();
427 return ALLOC(DoWhileStmt, (pos, expr, body));
430 Stmt* Parser::forStatement()
432 Expr* init=NULL;
433 Expr* lhs=NULL;
434 uint32_t numbindings = 0;
435 bool is_each = false;
437 eat (T_For);
438 if (hd() == T_Identifier && identValue() == compiler->SYM_each) {
439 is_each = true;
440 eat(T_Identifier);
442 uint32_t pos = position();
443 eat (T_LeftParen);
445 if (hd() == T_Var)
447 uint32_t dummy = 0;
448 init = varBindings(&dummy, false, EFLAG_NoIn, &numbindings, &lhs);
450 else if (hd() == T_Semicolon)
452 else
453 lhs = init = commaExpression(EFLAG_NoIn);
455 if (match(T_In)) {
456 if (numbindings > 1)
457 compiler->syntaxError(pos, SYNTAXERR_FOR_IN_ONEBINDING);
459 Expr* objexpr = commaExpression(0);
460 eat (T_RightParen);
461 Stmt* body = statement();
463 AvmAssert( lhs != NULL );
464 return ALLOC(ForInStmt, (pos, lhs, init, objexpr, body, is_each));
466 else {
467 if (is_each)
468 compiler->syntaxError(pos, SYNTAXERR_FOR_EACH_REQS_IN);
470 eat(T_Semicolon);
471 Expr* test = hd() == T_Semicolon ? NULL : commaExpression(0);
472 eat(T_Semicolon);
473 Expr* update = hd() == T_RightParen ? NULL : commaExpression(0);
474 eat(T_RightParen);
475 Stmt* body = statement ();
477 return ALLOC(ForStmt, (pos, init, test, update, body));
481 Stmt* Parser::switchStatement()
483 eat (T_Switch);
484 uint32_t pos = position();
485 Expr* expr = parenExpression ();
487 eat (T_LeftBrace);
488 Seq<CaseClause*>* cases = NULL;
489 if (hd() == T_Case || hd() == T_Default)
490 cases = caseElements();
491 eat(T_RightBrace);
493 return ALLOC(SwitchStmt, (pos, expr, cases));
496 Seq<CaseClause*>* Parser::caseElements()
498 SeqBuilder<CaseClause*> cases(allocator);
499 bool hasDefault = false;
500 CaseClause* last = NULL;
502 for (;;) {
503 switch (hd ()) {
504 case T_RightBrace:
505 return cases.get();
507 case T_Default: {
508 if (hd2() != T_Colon)
509 goto just_a_statement; // default xml namespace
510 eat(T_Default);
511 eat(T_Colon);
512 if (hasDefault)
513 compiler->syntaxError(position(), SYNTAXERR_DUPLICATE_DEFAULT);
514 hasDefault = true;
515 cases.addAtEnd(last = ALLOC(CaseClause, (0, NULL)));
516 break;
519 case T_Case: {
520 eat(T_Case);
521 uint32_t pos = position();
522 Expr* expr = commaExpression(0);
523 eat(T_Colon);
524 cases.addAtEnd(last = ALLOC(CaseClause, (pos, expr)));
526 /*FALLTHROUGH*/
527 just_a_statement:
528 default: {
529 if (last == NULL)
530 compiler->syntaxError(position(), SYNTAXERR_EXPECT_CASE_OR_DEFAULT);
531 AvmAssert(last->stmts == NULL);
532 SeqBuilder<Stmt*> stmts(allocator);
533 while (hd() != T_RightBrace && hd() != T_Case && hd() != T_Default)
534 stmts.addAtEnd(statement());
535 last->stmts = stmts.get();
536 break;
542 Stmt* Parser::throwStatement()
544 eat (T_Throw);
545 uint32_t pos = position();
546 return ALLOC(ThrowStmt, (pos, commaExpression(0)));
549 Stmt* Parser::tryStatement()
551 eat (T_Try);
553 Seq<Stmt*>* tryblock = statementBlock();
554 Seq<CatchClause*>* catchblocks = catches();
555 Seq<Stmt*>* finallyblock = NULL;
557 if (match(T_Finally)) {
558 setUsesFinally();
559 finallyblock = statementBlock();
562 return ALLOC(TryStmt, (tryblock, catchblocks,finallyblock));
565 Seq<CatchClause*>* Parser::catches()
567 SeqBuilder<CatchClause*> catches(allocator);
569 // Sort of silly that this allows multiple catches yet catchClause() does not
570 // allow the clauses to discriminate by type.
572 while (match(T_Catch)) {
573 setUsesCatch();
574 catches.addAtEnd(catchClause());
577 return catches.get();
580 CatchClause* Parser::catchClause()
582 eat (T_LeftParen);
583 Str* catchvar_name = identifier();
584 QualifiedName* catchvar_type_name = NULL;
585 if (match(T_Colon))
586 catchvar_type_name = typeExpression();
587 eat (T_RightParen);
588 Seq<Stmt*>* catchblock = statementBlock();
589 return ALLOC(CatchClause, (catchvar_name, catchvar_type_name, catchblock));
592 Stmt* Parser::withStatement()
594 eat (T_With);
595 uint32_t pos = position();
596 Expr* expr = parenExpression();
597 Stmt* body = statement();
598 return ALLOC(WithStmt, (pos, expr, body));
601 // This also parses super expressions when they appear in the statement position.
602 Stmt* Parser::superStatement()
604 eat (T_Super);
605 uint32_t pos = position();
606 Seq<Expr*>* arguments = NULL;
607 bool argsPresent = false;
608 if (hd() == T_LeftParen) {
609 argsPresent = true;
610 arguments = argumentList();
612 if (argsPresent && hd() != T_Dot && hd() != T_LeftBracket)
613 return ALLOC(SuperStmt, (pos, arguments));
614 if (argsPresent && (arguments == NULL || arguments->tl != NULL))
615 compiler->syntaxError(pos, SYNTAXERR_ONE_ARGUMENT_REQUIRED);
616 Expr* obj = argsPresent ? arguments->hd : ALLOC(ThisExpr, ());
617 return ALLOC(ExprStmt, (pos, propertyOperator(ALLOC(SuperExpr, (obj)))));
622 #endif // VMCFG_EVAL