Represents a scope in the lexical scope chain.
Represents a scope in the lexical scope chain. Base type for all AstNode implementations that can introduce a new scope.
Inheritance: Jump
示例#1
0
文件: Name.cs 项目: hazzik/Rhino.Net
		/// <summary>
		/// Set the
		/// <see cref="Scope">Scope</see>
		/// associated with this node.  This method does not
		/// set the scope's ast-node field to this node.  The field exists only
		/// for temporary storage by the code generator.  Not every name has an
		/// associated scope - typically only function and variable names (but not
		/// property names) are registered in a scope.
		/// </summary>
		/// <param name="s">
		/// the scope.  Can be null.  Doesn't set any fields in the
		/// scope.
		/// </param>
		public override void SetScope(Scope s)
		{
			scope = s;
		}
示例#2
0
		/// <summary>Sets this symbol's Scope</summary>
		public virtual void SetContainingTable(Scope containingTable)
		{
			this.containingTable = containingTable;
		}
示例#3
0
文件: Scope.cs 项目: hazzik/Rhino.Net
		/// <summary>Used only for code generation.</summary>
		/// <remarks>Used only for code generation.</remarks>
		public virtual void ClearParentScope()
		{
			this.parentScope = null;
		}
示例#4
0
文件: Scope.cs 项目: hazzik/Rhino.Net
		/// <summary>Sets parent scope</summary>
		public virtual void SetParentScope(Rhino.Ast.Scope parentScope)
		{
			this.parentScope = parentScope;
			this.top = parentScope == null ? (ScriptNode)this : parentScope.top;
		}
示例#5
0
文件: Scope.cs 项目: hazzik/Rhino.Net
		/// <summary>
		/// Creates a new scope node, moving symbol table information
		/// from "scope" to the new node, and making "scope" a nested
		/// scope contained by the new node.
		/// </summary>
		/// <remarks>
		/// Creates a new scope node, moving symbol table information
		/// from "scope" to the new node, and making "scope" a nested
		/// scope contained by the new node.
		/// Useful for injecting a new scope in a scope chain.
		/// </remarks>
		public static Rhino.Ast.Scope SplitScope(Rhino.Ast.Scope scope)
		{
			Rhino.Ast.Scope result = new Rhino.Ast.Scope(scope.GetType());
			result.symbolTable = scope.symbolTable;
			scope.symbolTable = null;
			result.parent = scope.parent;
			result.SetParentScope(scope.GetParentScope());
			result.SetParentScope(result);
			scope.parent = result;
			result.top = scope.top;
			return result;
		}
示例#6
0
		private Node CreateFor(Scope loop, Node init, Node test, Node incr, Node body)
		{
			if (init.GetType() == Token.LET)
			{
				// rewrite "for (let i=s; i < N; i++)..." as
				// "let (i=s) { for (; i < N; i++)..." so that "s" is evaluated
				// outside the scope of the for.
				Scope let = Scope.SplitScope(loop);
				let.SetType(Token.LET);
				let.AddChildrenToBack(init);
				let.AddChildToBack(CreateLoop(loop, LOOP_FOR, body, test, new Node(Token.EMPTY), incr));
				return let;
			}
			return CreateLoop(loop, LOOP_FOR, body, test, init, incr);
		}
示例#7
0
		private void TransformCompilationUnit_r(ScriptNode tree, Node parent, Scope scope, bool createScopeObjects, bool inStrictMode)
		{
			Node node = null;
			for (; ; )
			{
				Node previous = null;
				if (node == null)
				{
					node = parent.GetFirstChild();
				}
				else
				{
					previous = node;
					node = node.GetNext();
				}
				if (node == null)
				{
					break;
				}
				int type = node.GetType();
				if (createScopeObjects && (type == Token.BLOCK || type == Token.LOOP || type == Token.ARRAYCOMP) && (node is Scope))
				{
					Scope newScope = (Scope)node;
					if (newScope.GetSymbolTable() != null)
					{
						// transform to let statement so we get a with statement
						// created to contain scoped let variables
						Node let = new Node(type == Token.ARRAYCOMP ? Token.LETEXPR : Token.LET);
						Node innerLet = new Node(Token.LET);
						let.AddChildToBack(innerLet);
						foreach (string name in newScope.GetSymbolTable().Keys)
						{
							innerLet.AddChildToBack(Node.NewString(Token.NAME, name));
						}
						newScope.SetSymbolTable(null);
						// so we don't transform again
						Node oldNode = node;
						node = ReplaceCurrent(parent, previous, node, let);
						type = node.GetType();
						let.AddChildToBack(oldNode);
					}
				}
				switch (type)
				{
					case Token.LABEL:
					case Token.SWITCH:
					case Token.LOOP:
					{
						loops.Push(node);
						loopEnds.Push(((Jump)node).target);
						break;
					}

					case Token.WITH:
					{
						loops.Push(node);
						Node leave = node.GetNext();
						if (leave.GetType() != Token.LEAVEWITH)
						{
							Kit.CodeBug();
						}
						loopEnds.Push(leave);
						break;
					}

					case Token.TRY:
					{
						Jump jump = (Jump)node;
						Node finallytarget = jump.GetFinally();
						if (finallytarget != null)
						{
							hasFinally = true;
							loops.Push(node);
							loopEnds.Push(finallytarget);
						}
						break;
					}

					case Token.TARGET:
					case Token.LEAVEWITH:
					{
						if (!loopEnds.IsEmpty() && loopEnds.Peek() == node)
						{
							loopEnds.Pop();
							loops.Pop();
						}
						break;
					}

					case Token.YIELD:
					{
						((FunctionNode)tree).AddResumptionPoint(node);
						break;
					}

					case Token.RETURN:
					{
						bool isGenerator = tree.GetType() == Token.FUNCTION && ((FunctionNode)tree).IsGenerator();
						if (isGenerator)
						{
							node.PutIntProp(Node.GENERATOR_END_PROP, 1);
						}
						if (!hasFinally)
						{
							break;
						}
						// skip the whole mess.
						Node unwindBlock = null;
						for (int i = loops.Size() - 1; i >= 0; i--)
						{
							Node n = (Node)loops.Get(i);
							int elemtype = n.GetType();
							if (elemtype == Token.TRY || elemtype == Token.WITH)
							{
								Node unwind;
								if (elemtype == Token.TRY)
								{
									Jump jsrnode = new Jump(Token.JSR);
									Node jsrtarget = ((Jump)n).GetFinally();
									jsrnode.target = jsrtarget;
									unwind = jsrnode;
								}
								else
								{
									unwind = new Node(Token.LEAVEWITH);
								}
								if (unwindBlock == null)
								{
									unwindBlock = new Node(Token.BLOCK, node.GetLineno());
								}
								unwindBlock.AddChildToBack(unwind);
							}
						}
						if (unwindBlock != null)
						{
							Node returnNode = node;
							Node returnExpr = returnNode.GetFirstChild();
							node = ReplaceCurrent(parent, previous, node, unwindBlock);
							if (returnExpr == null || isGenerator)
							{
								unwindBlock.AddChildToBack(returnNode);
							}
							else
							{
								Node store = new Node(Token.EXPR_RESULT, returnExpr);
								unwindBlock.AddChildToFront(store);
								returnNode = new Node(Token.RETURN_RESULT);
								unwindBlock.AddChildToBack(returnNode);
								// transform return expression
								TransformCompilationUnit_r(tree, store, scope, createScopeObjects, inStrictMode);
							}
							// skip transformCompilationUnit_r to avoid infinite loop
							goto siblingLoop_continue;
						}
						break;
					}

					case Token.BREAK:
					case Token.CONTINUE:
					{
						Jump jump = (Jump)node;
						Jump jumpStatement = jump.GetJumpStatement();
						if (jumpStatement == null)
						{
							Kit.CodeBug();
						}
						for (int i = loops.Size(); ; )
						{
							if (i == 0)
							{
								// Parser/IRFactory ensure that break/continue
								// always has a jump statement associated with it
								// which should be found
								throw Kit.CodeBug();
							}
							--i;
							Node n = (Node)loops.Get(i);
							if (n == jumpStatement)
							{
								break;
							}
							int elemtype = n.GetType();
							if (elemtype == Token.WITH)
							{
								Node leave = new Node(Token.LEAVEWITH);
								previous = AddBeforeCurrent(parent, previous, node, leave);
							}
							else
							{
								if (elemtype == Token.TRY)
								{
									Jump tryNode = (Jump)n;
									Jump jsrFinally = new Jump(Token.JSR);
									jsrFinally.target = tryNode.GetFinally();
									previous = AddBeforeCurrent(parent, previous, node, jsrFinally);
								}
							}
						}
						if (type == Token.BREAK)
						{
							jump.target = jumpStatement.target;
						}
						else
						{
							jump.target = jumpStatement.GetContinue();
						}
						jump.SetType(Token.GOTO);
						break;
					}

					case Token.CALL:
					{
						VisitCall(node, tree);
						break;
					}

					case Token.NEW:
					{
						VisitNew(node, tree);
						break;
					}

					case Token.LETEXPR:
					case Token.LET:
					{
						Node child = node.GetFirstChild();
						if (child.GetType() == Token.LET)
						{
							// We have a let statement or expression rather than a
							// let declaration
							bool createWith = tree.GetType() != Token.FUNCTION || ((FunctionNode)tree).RequiresActivation();
							node = VisitLet(createWith, parent, previous, node);
							break;
						}
						goto case Token.CONST;
					}

					case Token.CONST:
					case Token.VAR:
					{
						// fall through to process let declaration...
						Node result = new Node(Token.BLOCK);
						for (Node cursor = node.GetFirstChild(); cursor != null; )
						{
							// Move cursor to next before createAssignment gets chance
							// to change n.next
							Node n = cursor;
							cursor = cursor.GetNext();
							if (n.GetType() == Token.NAME)
							{
								if (!n.HasChildren())
								{
									continue;
								}
								Node init = n.GetFirstChild();
								n.RemoveChild(init);
								n.SetType(Token.BINDNAME);
								n = new Node(type == Token.CONST ? Token.SETCONST : Token.SETNAME, n, init);
							}
							else
							{
								// May be a destructuring assignment already transformed
								// to a LETEXPR
								if (n.GetType() != Token.LETEXPR)
								{
									throw Kit.CodeBug();
								}
							}
							Node pop = new Node(Token.EXPR_VOID, n, node.GetLineno());
							result.AddChildToBack(pop);
						}
						node = ReplaceCurrent(parent, previous, node, result);
						break;
					}

					case Token.TYPEOFNAME:
					{
						Scope defining = scope.GetDefiningScope(node.GetString());
						if (defining != null)
						{
							node.SetScope(defining);
						}
						break;
					}

					case Token.TYPEOF:
					case Token.IFNE:
					{
						Node child = node.GetFirstChild();
						if (type == Token.IFNE)
						{
							while (child.GetType() == Token.NOT)
							{
								child = child.GetFirstChild();
							}
							if (child.GetType() == Token.EQ || child.GetType() == Token.NE)
							{
								Node first = child.GetFirstChild();
								Node last = child.GetLastChild();
								if (first.GetType() == Token.NAME && first.GetString().Equals("undefined"))
								{
									child = last;
								}
								else
								{
									if (last.GetType() == Token.NAME && last.GetString().Equals("undefined"))
									{
										child = first;
									}
								}
							}
						}
						if (child.GetType() == Token.GETPROP)
						{
							child.SetType(Token.GETPROPNOWARN);
						}
						break;
					}

					case Token.SETNAME:
					{
						if (inStrictMode)
						{
							node.SetType(Token.STRICT_SETNAME);
						}
						goto case Token.NAME;
					}

					case Token.NAME:
					case Token.SETCONST:
					case Token.DELPROP:
					{
						// Turn name to var for faster access if possible
						if (createScopeObjects)
						{
							break;
						}
						Node nameSource;
						if (type == Token.NAME)
						{
							nameSource = node;
						}
						else
						{
							nameSource = node.GetFirstChild();
							if (nameSource.GetType() != Token.BINDNAME)
							{
								if (type == Token.DELPROP)
								{
									break;
								}
								throw Kit.CodeBug();
							}
						}
						if (nameSource.GetScope() != null)
						{
							break;
						}
						// already have a scope set
						string name = nameSource.GetString();
						Scope defining = scope.GetDefiningScope(name);
						if (defining != null)
						{
							nameSource.SetScope(defining);
							if (type == Token.NAME)
							{
								node.SetType(Token.GETVAR);
							}
							else
							{
								if (type == Token.SETNAME || type == Token.STRICT_SETNAME)
								{
									node.SetType(Token.SETVAR);
									nameSource.SetType(Token.STRING);
								}
								else
								{
									if (type == Token.SETCONST)
									{
										node.SetType(Token.SETCONSTVAR);
										nameSource.SetType(Token.STRING);
									}
									else
									{
										if (type == Token.DELPROP)
										{
											// Local variables are by definition permanent
											Node n = new Node(Token.FALSE);
											node = ReplaceCurrent(parent, previous, node, n);
										}
										else
										{
											throw Kit.CodeBug();
										}
									}
								}
							}
						}
						break;
					}
				}
				TransformCompilationUnit_r(tree, node, node is Scope ? (Scope)node : scope, createScopeObjects, inStrictMode);
siblingLoop_continue: ;
			}
siblingLoop_break: ;
		}