public bool MustCaptureVariable(IKnownVariable variable) { if (CurrentAnonymousMethod == null) { return(false); } return(variable.Scope.TopLevel != CurrentScope.TopLevel); }
internal void AddKnownVariable(string name, IKnownVariable variable) { if (_knownVariables == null) { _knownVariables = new Dictionary <string, IKnownVariable>(); } if (!_knownVariables.ContainsKey(name)) { _knownVariables[name] = variable; } if (Parent != null) { Parent.Explicit.AddKnownVariable(name, variable); } }
// <summary> // Marks a variable with name @name as being used in this or a child block. // If a variable name has been used in a child block, it's illegal to // declare a variable with the same name in the current block. // </summary> internal void AddKnownVariable (string name, IKnownVariable info) { if (known_variables == null) known_variables = new Dictionary<string, IKnownVariable> (); known_variables [name] = info; if (Parent != null) Parent.Explicit.AddKnownVariable (name, info); }
public bool CheckInvariantMeaningInBlock(string name, Expression e, SourceSpan span) { var b = this; IKnownVariable kvi = b.Explicit.GetKnownVariable(name); while (kvi == null) { b = b.Explicit.Parent; if (b == null) { return(true); } kvi = b.Explicit.GetKnownVariable(name); } if (kvi.Scope == b) { return(true); } // Is kvi.Block nested inside 'b' if (b.Explicit != kvi.Scope.Explicit) //if (kvi.Scope.Explicit.IsDescendantOf(b.Explicit)) { // // If a variable by the same name it defined in a nested block of this // block, we violate the invariant meaning in a block. // if (b == this) { _compilerContext.Errors.Add( _compilerContext.SourceUnit, string.Format("'{0}' conflicts with a declaration in a child block.", name), span, 135, Severity.Error); return(false); } // // It's ok if the definition is in a nested subblock of b, but not // nested inside this block -- a definition in a sibling block // should not affect us. // return(true); } // // Block 'b' and kvi.Block are the same textual block. // However, different variables are extant. // // Check if the variable is in scope in both blocks. We use // an indirect check that depends on AddVariable doing its // part in maintaining the invariant-meaning-in-block property. // if (e is ParameterReference) { return(true); } if (this is TopLevelScope) { _compilerContext.Errors.Add( _compilerContext.SourceUnit, string.Format("A local variable '{0}' cannot be used before it is declared.", name), span, 841, Severity.Error); return(false); } // // Even though we detected the error when the name is used, we // treat it as if the variable declaration was in error. // OnAlreadyDeclaredError(kvi.Span, name, "parent or current"); return(false); }