AST node for a JavaScript 1.7 Array comprehension.
AST node for a JavaScript 1.7 Array comprehension. Node type is Rhino.Token.ARRAYCOMP .

Inheritance: Scope
Example #1
0
		private Node ArrayCompTransformHelper(ArrayComprehension node, string arrayName)
		{
			decompiler.AddToken(Token.LB);
			int lineno = node.GetLineno();
			Node expr = Transform(node.GetResult());
			IList<ArrayComprehensionLoop> loops = node.GetLoops();
			int numLoops = loops.Count;
			// Walk through loops, collecting and defining their iterator symbols.
			Node[] iterators = new Node[numLoops];
			Node[] iteratedObjs = new Node[numLoops];
			for (int i = 0; i < numLoops; i++)
			{
				ArrayComprehensionLoop acl = loops[i];
				decompiler.AddName(" ");
				decompiler.AddToken(Token.FOR);
				if (acl.IsForEach())
				{
					decompiler.AddName("each ");
				}
				decompiler.AddToken(Token.LP);
				AstNode iter = acl.GetIterator();
				string name = null;
				if (iter.GetType() == Token.NAME)
				{
					name = iter.GetString();
					decompiler.AddName(name);
				}
				else
				{
					// destructuring assignment
					Decompile(iter);
					name = currentScriptOrFn.GetNextTempName();
					DefineSymbol(Token.LP, name, false);
					expr = CreateBinary(Token.COMMA, CreateAssignment(Token.ASSIGN, iter, CreateName(name)), expr);
				}
				Node init = CreateName(name);
				// Define as a let since we want the scope of the variable to
				// be restricted to the array comprehension
				DefineSymbol(Token.LET, name, false);
				iterators[i] = init;
				decompiler.AddToken(Token.IN);
				iteratedObjs[i] = Transform(acl.GetIteratedObject());
				decompiler.AddToken(Token.RP);
			}
			// generate code for tmpArray.push(body)
			Node call = CreateCallOrNew(Token.CALL, CreatePropertyGet(CreateName(arrayName), null, "push", 0));
			Node body = new Node(Token.EXPR_VOID, call, lineno);
			if (node.GetFilter() != null)
			{
				decompiler.AddName(" ");
				decompiler.AddToken(Token.IF);
				decompiler.AddToken(Token.LP);
				body = CreateIf(Transform(node.GetFilter()), body, null, lineno);
				decompiler.AddToken(Token.RP);
			}
			// Now walk loops in reverse to build up the body statement.
			int pushed = 0;
			try
			{
				for (int i_1 = numLoops - 1; i_1 >= 0; i_1--)
				{
					ArrayComprehensionLoop acl = loops[i_1];
					Scope loop = CreateLoopNode(null, acl.GetLineno());
					// no label
					PushScope(loop);
					pushed++;
					body = CreateForIn(Token.LET, loop, iterators[i_1], iteratedObjs[i_1], body, acl.IsForEach());
				}
			}
			finally
			{
				for (int i_1 = 0; i_1 < pushed; i_1++)
				{
					PopScope();
				}
			}
			decompiler.AddToken(Token.RB);
			// Now that we've accumulated any destructuring forms,
			// add expr to the call node; it's pushed on each iteration.
			call.AddChildToBack(expr);
			return body;
		}
Example #2
0
		private Node TransformArrayComp(ArrayComprehension node)
		{
			// An array comprehension expression such as
			//
			//   [expr for (x in foo) for each ([y, z] in bar) if (cond)]
			//
			// is rewritten approximately as
			//
			// new Scope(ARRAYCOMP) {
			//   new Node(BLOCK) {
			//     let tmp1 = new Array;
			//     for (let x in foo) {
			//       for each (let tmp2 in bar) {
			//         if (cond) {
			//           tmp1.push([y, z] = tmp2, expr);
			//         }
			//       }
			//     }
			//   }
			//   createName(tmp1)
			// }
			int lineno = node.GetLineno();
			Scope scopeNode = CreateScopeNode(Token.ARRAYCOMP, lineno);
			string arrayName = currentScriptOrFn.GetNextTempName();
			PushScope(scopeNode);
			try
			{
				DefineSymbol(Token.LET, arrayName, false);
				Node block = new Node(Token.BLOCK, lineno);
				Node newArray = CreateCallOrNew(Token.NEW, CreateName("Array"));
				Node init = new Node(Token.EXPR_VOID, CreateAssignment(Token.ASSIGN, CreateName(arrayName), newArray), lineno);
				block.AddChildToBack(init);
				block.AddChildToBack(ArrayCompTransformHelper(node, arrayName));
				scopeNode.AddChildToBack(block);
				scopeNode.AddChildToBack(CreateName(arrayName));
				return scopeNode;
			}
			finally
			{
				PopScope();
			}
		}