/// <summary> /// Leave this context scope. The context /// will then be the next last one on the stack. /// </summary> public void Leave() { if (!_hasLeft) { // Remove it from stack if (ScopeStack == null || ScopeStack.Count == 0) { throw new InvalidOperationException("Error when trying to leave an unknown context scope."); } Scope <T> delScope = ScopeStack.Pop(); if (!delScope.Equals(this)) { // This context scope is not at the top of the stack. ScopeStack.Push(delScope); throw new InvalidOperationException("This context scope is not at the top of the stack."); } if (_isDisposable) { Release(); } // Clean up the stack object if it is empty if (ScopeStack.Count == 0) { ScopeStack = null; } } _hasLeft = true; }
public virtual void Dispose() { try { if (!this.keepOpen) { try { this.connection.Close(); } catch { /* nada a fazer */ } try { this.connection.Dispose(); } catch { /* nada a fazer */ } } this.connection = null; var primaryScope = ScopeBag[ScopeName]; if (primaryScope == this) { ScopeBag[ScopeName] = null; } } finally { ScopeStack.Pop(); } }
public void ReadEnd() { if (_scopeStack.Count == 0) { throw new Exception("Scope stack empty"); } Scope scope = _scopeStack.Pop(); if (scope.ScopeType == ScopeType.Array) { if (_c != ']') { throw new Exception("Expected ']'."); } } else if (scope.ScopeType == ScopeType.Object) { if (_c != '}') { throw new Exception("Expected '}'."); } } if (_scopeStack.Count > 0) { _c = (char)_reader.Read(); ParseWhiteSpace(); ParseComma(); } }
public void Dispose() { if (ScopeStack.Peek() != this) { throw new InvalidOperationException("Parent logging scope is being disposed before child scope."); } ScopeStack = ScopeStack.Pop(); RebuildCurrent(); }
private bool ParseStatement(TemplateStream stream, TokenList tokens, ContextStack context, ScopeStack scope) { if (scope.Current == Scope.Statement) { scope.Pop(); } else if (scope.Current == Scope.Block) { var previous = stream.Peek(-1); if (previous == '$' || char.IsLetterOrDigit(previous)) { return(false); } } else { return(false); } var name = stream.PeekWord(); var identifier = context.Current.GetIdentifier(name); if (identifier != null) { tokens.Add(new Token(stream.Position, name.Length, stream.Line, TokenType.Identifier, context.Current, identifier.QuickInfo)); stream.Advance(name.Length); if (identifier.Type == IdentifierType.Indexed) { if (stream.Current == '(') { scope.Push(Scope.Filter); } if (stream.Current == '[') { scope.Push(Scope.Template); context.Push(name, stream.Position); } } else if (identifier.Type == IdentifierType.Boolean) { if (stream.Current == '[') { scope.Push(Scope.True); } } return(true); } return(false); }
internal string Result() { if (ScopeStack.Count == 0) { throw new IcuParserException("Syntax error"); } var scope = ScopeStack.Pop(); if (ScopeStack.Count > 0) { throw new IcuParserException($"Scope stack mismatch: expected zero scopes left, but was {ScopeStack.Count}"); } return(scope.Result()); }
private static void ConfigScopeToPrevious() { // If there is no scope in stack, then clear _Current scope only if (ScopeStack.Count == 0) { _Current = null; return; } // Pop from stack and make then the Current scope _Current = ScopeStack.Pop(); // Continue pop scope's from stack until find one not yet disposed while ((ScopeStack.Count > 0) && (_Current._IsDisposed)) { _Current = ScopeStack.Pop(); } }
/// <summary> /// Closes an open object or array. /// </summary> public JsonWriter WriteEnd() { if (_scopeStack.Count == 0) { throw new Exception(); } Scope scope = _scopeStack.Pop(); if (scope.ScopeType == ScopeType.Object) { _writer.Write('}'); } else { _writer.Write(']'); } return(this); }
internal override void AnalyzeNode() { // get the name of this function, calculate something if it's anonymous m_name = (m_identifier == null ? GuessAtName() : m_identifier.Name); // don't analyze the identifier or we'll add an extra reference to it. // and we don't need to analyze the parameters because they were fielded-up // back when the function object was created, too // push the stack and analyze the body ScopeStack.Push(m_functionScope); try { // recurse base.AnalyzeNode(); } finally { ScopeStack.Pop(); } }
internal override void AnalyzeNode() { // javascript doesn't have block scope, so there really is no point // in nesting blocks. Unnest any now, before we start combining var statements UnnestBlocks(); // if we want to remove debug statements... if (Parser.Settings.StripDebugStatements && Parser.Settings.IsModificationAllowed(TreeModifications.StripDebugStatements)) { // do it now before we try doing other things StripDebugStatements(); } // these variables are used to check for combining a particular type of // for-statement with preceding var-statements. ForNode targetForNode = null; string targetName = null; // check to see if we want to combine adjacent var statements bool combineVarStatements = Parser.Settings.IsModificationAllowed(TreeModifications.CombineVarStatements); // check to see if we want to combine a preceding var with a for-statement bool moveVarIntoFor = Parser.Settings.IsModificationAllowed(TreeModifications.MoveVarIntoFor); // look at the statements in the block. // if there are multiple var statements adjacent to each other, combine them. // walk BACKWARDS down the list because we'll be removing items when we encounter // multiple vars. // we also don't need to check the first one, since there is nothing before it. for (int ndx = m_list.Count - 1; ndx > 0; --ndx) { // if the previous node is not a Var, then we don't need to try and combine // it withthe current node Var previousVar = m_list[ndx - 1] as Var; if (previousVar != null) { // see if THIS item is also a Var... if (m_list[ndx] is Var && combineVarStatements) { // add the items in this VAR to the end of the previous previousVar.Append(m_list[ndx]); // delete this item from the block m_list.RemoveAt(ndx); // if we have a target for-node waiting for another comparison.... if (targetForNode != null) { // check to see if the variable we are looking for is in the new list if (previousVar.Contains(targetName)) { // IT DOES! we can combine the var statement with the initializer in the for-statement // we already know it's a binaryop, or it wouldn't be a target for-statement BinaryOperator binaryOp = targetForNode.Initializer as BinaryOperator; // create a vardecl that matches our assignment initializer // ignore duplicates because this scope will already have the variable defined. VariableDeclaration varDecl = new VariableDeclaration( binaryOp.Context.Clone(), Parser, targetName, binaryOp.Operand1.Context.Clone(), binaryOp.Operand2, 0, true ); // append it to the preceding var-statement previousVar.Append(varDecl); // move the previous vardecl to our initializer targetForNode.ReplaceChild(targetForNode.Initializer, previousVar); // and remove the previous var from the list. m_list.RemoveAt(ndx - 1); // this will bump the for node up one position in the list, so the next iteration // will be right back on this node, but the initializer will not be null // but now we no longer need the target mechanism -- the for-statement is // not the current node again targetForNode = null; } } } else if (moveVarIntoFor) { // see if this item is a ForNode ForNode forNode = m_list[ndx] as ForNode; if (forNode != null) { // and see if the forNode's initializer is empty if (forNode.Initializer != null) { // not empty -- see if it is a Var node Var varInitializer = forNode.Initializer as Var; if (varInitializer != null) { // we want to PREPEND the initializers in the previous var statement // to our for-statement's initializer list varInitializer.InsertAt(0, previousVar); // then remove the previous var statement m_list.RemoveAt(ndx - 1); // this will bump the for node up one position in the list, so the next iteration // will be right back on this node in case there are other var statements we need // to combine } else { // see if the initializer is a simple assignment BinaryOperator binaryOp = forNode.Initializer as BinaryOperator; if (binaryOp != null && binaryOp.OperatorToken == JSToken.Assign) { // it is. See if it's a simple lookup Lookup lookup = binaryOp.Operand1 as Lookup; if (lookup != null) { // it is. see if that variable is in the previous var statement if (previousVar.Contains(lookup.Name)) { // create a vardecl that matches our assignment initializer // ignore duplicates because this scope will already have the variable defined. VariableDeclaration varDecl = new VariableDeclaration( binaryOp.Context.Clone(), Parser, lookup.Name, lookup.Context.Clone(), binaryOp.Operand2, 0, true ); // append it to the var statement before us previousVar.Append(varDecl); // move the previous vardecl to our initializer forNode.ReplaceChild(forNode.Initializer, previousVar); // and remove the previous var from the list. m_list.RemoveAt(ndx - 1); // this will bump the for node up one position in the list, so the next iteration // will be right back on this node, but the initializer will not be null } else { // it's not in the immediately preceding var-statement, but that doesn't mean it won't be in // a var-statement immediately preceding that one -- in which case they'll get combined and // then it WILL be in the immediately preceding var-statement. So hold on to this // for statement and we'll check after we do a combine. targetForNode = forNode; targetName = lookup.Name; } } } } } else { // if it's empty, then we're free to add the previous var statement // to this for statement's initializer. remove it from it's current // position and add it as the initializer m_list.RemoveAt(ndx - 1); forNode.ReplaceChild(forNode.Initializer, previousVar); // this will bump the for node up one position in the list, so the next iteration // will be right back on this node, but the initializer will not be null } } } } else { // not a var statement. make sure the target for-node is cleared. targetForNode = null; ConditionalCompilationComment previousComment = m_list[ndx - 1] as ConditionalCompilationComment; if (previousComment != null) { ConditionalCompilationComment thisComment = m_list[ndx] as ConditionalCompilationComment; if (thisComment != null) { // two adjacent conditional comments -- combine them into the first. // this will actually make the second block a nested block within the first block, // but they'll be flattened when the comment's block gets recursed. previousComment.Statements.Append(thisComment.Statements); // and remove the second one (which is now a duplicate) m_list.RemoveAt(ndx); } } } } if (m_blockScope != null) { ScopeStack.Push(m_blockScope); } try { // call the base class to recurse base.AnalyzeNode(); } finally { if (m_blockScope != null) { ScopeStack.Pop(); } } // NOW that we've recursively analyzed all the child nodes in this block, let's see // if we can further reduce the statements by checking for a couple good opportunities if (Parser.Settings.RemoveUnneededCode) { // Transform: {var foo=expression;return foo;} to: {return expression;} if (m_list.Count == 2 && Parser.Settings.IsModificationAllowed(TreeModifications.VarInitializeReturnToReturnInitializer)) { Var varStatement = m_list[0] as Var; ReturnNode returnStatement = m_list[1] as ReturnNode; // see if we have two statements in our block: a var with a single declaration, and a return if (returnStatement != null && varStatement != null && varStatement.Count == 1 && varStatement[0].Initializer != null) { // now see if the return is returning a lookup for the same var we are declaring in the // previous statement Lookup lookup = returnStatement.Operand as Lookup; if (lookup != null && string.Compare(lookup.Name, varStatement[0].Identifier, StringComparison.Ordinal) == 0) { // it's a match! // create a combined context starting with the var and adding in the return Context context = varStatement.Context.Clone(); context.UpdateWith(returnStatement.Context); // create a new return statement ReturnNode newReturn = new ReturnNode(context, Parser, varStatement[0].Initializer); // clear out the existing statements m_list.Clear(); // and add our new one Append(newReturn); } } } // we do things differently if these statements are the last in a function // because we can assume the implicit return bool isFunctionLevel = (Parent is FunctionObject); // see if we want to change if-statement that forces a return to a return conditional if (Parser.Settings.IsModificationAllowed(TreeModifications.IfElseReturnToReturnConditional)) { // transform: {...; if(cond1)return;} to {...;cond;} // transform: {...; if(cond1)return exp1;else return exp2;} to {...;return cond1?exp1:exp2;} if (m_list.Count >= 1) { // see if the last statement is an if-statement with a true-block containing only one statement IfNode ifStatement = m_list[m_list.Count - 1] as IfNode; if (ifStatement != null && ifStatement.TrueBlock != null) { // see if this if-statement is structured such that we can convert it to a // Conditional node that is the operand of a return statement Conditional returnOperand = ifStatement.CanBeReturnOperand(null, isFunctionLevel); if (returnOperand != null) { // it can! change it. ReturnNode returnNode = new ReturnNode( (Context == null ? null : Context.Clone()), Parser, returnOperand); // replace the if-statement with the return statement ReplaceChild(ifStatement, returnNode); } } // else last statement is not an if-statement, or true block is not a single statement } // transform: {...; if(cond1)return exp1;return exp2;} to {...; return cond1?exp1:exp2;} // my cascade! changing the two statements to a return may cause us to run this again if the // third statement up becomes the penultimate and is an if-statement while (m_list.Count > 1) { int lastIndex = m_list.Count - 1; // end in a return statement? ReturnNode finalReturn = m_list[lastIndex] as ReturnNode; if (finalReturn != null) { // it does -- see if the penultimate statement is an if-block IfNode ifNode = m_list[lastIndex - 1] as IfNode; if (ifNode != null) { // if followed by return. See if the if statement can be changed to a // return of a conditional, using the operand of the following return // as the ultimate expression Conditional returnConditional = ifNode.CanBeReturnOperand(finalReturn.Operand, isFunctionLevel); if (returnConditional != null) { // it can! so create the new return statement. // the context of this new return statement should start with a clone of // the if-statement and updated with the return statement Context context = ifNode.Context.Clone(); context.UpdateWith(finalReturn.Context); // create the new return node ReturnNode newReturn = new ReturnNode( context, Parser, returnConditional); // remove the last node (the old return) m_list.RemoveAt(lastIndex--); // and replace the if-statement with the new return m_list[lastIndex] = newReturn; newReturn.Parent = this; // we collapsed the last two statements, and we KNOW the last one is a // return -- go back up to the top of the loop to see if we can keep going. continue; } } } // if we get here, then something went wrong, we didn't collapse the last // two statements, so break out of the loop break; } // now we may have converted the last functional statement // from if(cond)return expr to return cond?expr:void 0, which is four // extra bytes. So let's check to see if the last statement in the function // now fits this pattern, and if so, change it back. // We didn't just NOT change it in the first place because changing it could've // enabled even more changes that would save a lot more space. But apparently // those subsequent changes didn't pan out. if (m_list.Count >= 1) { int lastIndex = m_list.Count - 1; ReturnNode returnNode = m_list[lastIndex] as ReturnNode; if (returnNode != null) { Conditional conditional = returnNode.Operand as Conditional; if (conditional != null) { VoidNode falseVoid = conditional.FalseExpression as VoidNode; if (falseVoid != null && falseVoid.Operand is ConstantWrapper) { // we have the required pattern: "return cond?expr:void 0" // (well, the object of the void is a constant, at least). // undo it back to "if(cond)return expr" because that takes fewer bytes. // by default, the operand of the return operator will be the // true branch of the conditional AstNode returnOperand = conditional.TrueExpression; VoidNode trueVoid = conditional.TrueExpression as VoidNode; if (trueVoid != null && trueVoid.Operand is ConstantWrapper) { // the true branch of the conditional is a void operator acting // on a constant! So really, there is no operand to the return statement returnOperand = null; if (Parser.Settings.IsModificationAllowed(TreeModifications.IfConditionReturnToCondition)) { // actually, we have return cond?void 0:void 0, // which would get changed back to function{...;if(cond)return} // BUT we can just shorten it to function{...;cond} m_list[lastIndex] = conditional.Condition; conditional.Condition.Parent = this; return; } } IfNode ifNode = new IfNode( returnNode.Context.Clone(), Parser, conditional.Condition, new ReturnNode(returnNode.Context.Clone(), Parser, returnOperand), null); m_list[lastIndex] = ifNode; ifNode.Parent = this; } } } } } } }
/// <summary> /// Get instance of the parent entry scope /// </summary> /// <returns> /// The parent entry scope /// Or null if there is no parent entry scope /// </returns> protected EntryScope GetParentEntryScope() { ScopeStack scopeStack = new ScopeStack(); Scope parentEntryScope = null; if (this.scopes.Count > 0) { // pop current scope and push into scope stack scopeStack.Push(this.scopes.Pop()); } while (this.scopes.Count > 0) { Scope scope = this.scopes.Pop(); scopeStack.Push(scope); if (scope is EntryScope) { parentEntryScope = scope; break; } } while (scopeStack.Count > 0) { Scope scope = scopeStack.Pop(); this.scopes.Push(scope); } return parentEntryScope as EntryScope; }
/// <summary> /// Get instance of the parent delta feed scope /// </summary> /// <returns> /// The parent delta feed scope /// Or null if there is no parent delta feed scope /// </returns> private DeltaFeedScope GetParentDeltaFeedScope() { ScopeStack scopeStack = new ScopeStack(); Scope parentFeedScope = null; if (this.scopes.Count > 0) { // pop current scope and push into scope stack scopeStack.Push(this.scopes.Pop()); } while (this.scopes.Count > 0) { Scope scope = this.scopes.Pop(); scopeStack.Push(scope); if (scope is DeltaFeedScope) { parentFeedScope = scope; break; } } while (scopeStack.Count > 0) { Scope scope = scopeStack.Pop(); this.scopes.Push(scope); } return parentFeedScope as DeltaFeedScope; }
private bool ParseOther(TemplateStream stream, TokenList tokens, ContextStack context, ScopeStack scope, BraceStack brace) { switch (stream.Current) { case '[': brace.Push(tokens.Add(new Token(stream.Position, 1, stream.Line, TokenType.OpenBrace, context.Current)), scope.Changed); stream.Advance(); return true; case ']': var openBrace = brace.Pop(TokenType.OpenBrace); var token = tokens.Add(new Token(stream.Position, 1, stream.Line, TokenType.CloseBrace, context.Current, null, openBrace.Token)); if (openBrace.Token != null) { openBrace.Token.MatchingToken = token; } stream.Advance(); if (openBrace.ScopeChanged) { var current = scope.Pop(); if (current == Scope.Template) { context.Pop(stream.Position); if (stream.Current == '[') scope.Push(Scope.Separator); } else if (current == Scope.True) { context.Pop(stream.Position); if (stream.Current == '[') scope.Push(Scope.False); } } return true; case '{': //tokens.Add(new Token(stream.Position - 1, 2, TokenType.OpenBlock, context.Current)); brace.Push(tokens.Add(new Token(stream.Position, 1, stream.Line, TokenType.OpenCurlyBrace, context.Current)), scope.Changed); stream.Advance(); return true; case '}': var openCurlyBrace = brace.Pop(TokenType.OpenCurlyBrace); token = tokens.Add(new Token(stream.Position, 1, stream.Line, TokenType.CloseCurlyBrace, context.Current, null, openCurlyBrace.Token)); if (openCurlyBrace.Token != null) { openCurlyBrace.Token.MatchingToken = token; } //tokens.Add(new Token(stream.Position, 1, TokenType.CloseBlock, context.Current)); stream.Advance(); if (openCurlyBrace.ScopeChanged) { scope.Pop(); } return true; case '(': brace.Push(tokens.Add(new Token(stream.Position, 1, stream.Line, TokenType.OpenFunctionBrace, context.Current)), scope.Changed); stream.Advance(); return true; case ')': var openFunctionBrace = brace.Pop(TokenType.OpenFunctionBrace); token = tokens.Add(new Token(stream.Position, 1, stream.Line, TokenType.CloseFunctionBrace, context.Current, null, openFunctionBrace.Token)); if (openFunctionBrace.Token != null) { openFunctionBrace.Token.MatchingToken = token; } stream.Advance(); if (openFunctionBrace.ScopeChanged) { scope.Pop(); } return true; } if (scope.Current == Scope.Block) return false; var name = stream.PeekWord(); if (name == null) return false; if (keywords.Contains(name)) { tokens.Add(new Token(stream.Position, name.Length, stream.Line, TokenType.Keyword, context.Current)); } stream.Advance(name.Length); return true; }
private bool ParseStatement(TemplateStream stream, TokenList tokens, ContextStack context, ScopeStack scope) { if (scope.Current == Scope.Statement) { scope.Pop(); } else if (scope.Current == Scope.Block) { var previous = stream.Peek(-1); if (previous == '$' || char.IsLetterOrDigit(previous)) return false; } else { return false; } var name = stream.PeekWord(); var identifier = context.Current.GetIdentifier(name); if (identifier != null) { tokens.Add(new Token(stream.Position, name.Length, stream.Line, TokenType.Identifier, context.Current, identifier.QuickInfo)); stream.Advance(name.Length); if (identifier.Type == IdentifierType.Indexed) { if (stream.Current == '(') scope.Push(Scope.Filter); if (stream.Current == '[') { scope.Push(Scope.Template); context.Push(name, stream.Position); } } else if (identifier.Type == IdentifierType.Boolean) { if (stream.Current == '[') scope.Push(Scope.True); } return true; } return false; }
private void EndScope() { _scopes.Pop(); }
private bool ParseOther(TemplateStream stream, TokenList tokens, ContextStack context, ScopeStack scope, BraceStack brace) { switch (stream.Current) { case '[': brace.Push(tokens.Add(new Token(stream.Position, 1, stream.Line, TokenType.OpenBrace, context.Current)), scope.Changed); stream.Advance(); return(true); case ']': var openBrace = brace.Pop(TokenType.OpenBrace); var token = tokens.Add(new Token(stream.Position, 1, stream.Line, TokenType.CloseBrace, context.Current, null, openBrace.Token)); if (openBrace.Token != null) { openBrace.Token.MatchingToken = token; } stream.Advance(); if (openBrace.ScopeChanged) { var current = scope.Pop(); if (current == Scope.Template) { context.Pop(stream.Position); if (stream.Current == '[') { scope.Push(Scope.Separator); } } else if (current == Scope.True) { context.Pop(stream.Position); if (stream.Current == '[') { scope.Push(Scope.False); } } } return(true); case '{': //tokens.Add(new Token(stream.Position - 1, 2, TokenType.OpenBlock, context.Current)); brace.Push(tokens.Add(new Token(stream.Position, 1, stream.Line, TokenType.OpenCurlyBrace, context.Current)), scope.Changed); stream.Advance(); return(true); case '}': var openCurlyBrace = brace.Pop(TokenType.OpenCurlyBrace); token = tokens.Add(new Token(stream.Position, 1, stream.Line, TokenType.CloseCurlyBrace, context.Current, null, openCurlyBrace.Token)); if (openCurlyBrace.Token != null) { openCurlyBrace.Token.MatchingToken = token; } //tokens.Add(new Token(stream.Position, 1, TokenType.CloseBlock, context.Current)); stream.Advance(); if (openCurlyBrace.ScopeChanged) { scope.Pop(); } return(true); case '(': brace.Push(tokens.Add(new Token(stream.Position, 1, stream.Line, TokenType.OpenFunctionBrace, context.Current)), scope.Changed); stream.Advance(); return(true); case ')': var openFunctionBrace = brace.Pop(TokenType.OpenFunctionBrace); token = tokens.Add(new Token(stream.Position, 1, stream.Line, TokenType.CloseFunctionBrace, context.Current, null, openFunctionBrace.Token)); if (openFunctionBrace.Token != null) { openFunctionBrace.Token.MatchingToken = token; } stream.Advance(); if (openFunctionBrace.ScopeChanged) { scope.Pop(); } return(true); } if (scope.Current == Scope.Block) { return(false); } var name = stream.PeekWord(); if (name == null) { return(false); } if (keywords.Contains(name)) { tokens.Add(new Token(stream.Position, name.Length, stream.Line, TokenType.Keyword, context.Current)); } stream.Advance(name.Length); return(true); }
/// <summary> /// Stops the stopwatch, logs the result, pops nested scope stack. /// </summary> public void Dispose() { Stop(); ScopeStack = ScopeStack.Pop(); }