public CatchScope(ResolvedIdentifier identifier, Scope scope, CatchScope parent) { Identifier = identifier; Scope = scope; Parent = parent; }
public void EnterWith() { var identifier = new ResolvedIdentifier( WithPrefix + (_nextWithScopeIndex++).ToString(CultureInfo.InvariantCulture), null, IdentifierType.Local, true ); _resolvedIdentifiers.Add(identifier); _withScope = new BuilderWithScope( FindWithScope(false), identifier, this ); }
private ReadOnlyArray<IIdentifier> CommitIdentifiers() { var identifiers = new Dictionary<string, ResolvedIdentifier>(); // Create the parameters. if (_parameters != null) { for (int i = _parameters.Count - 1; i >= 0; i--) { if (!identifiers.ContainsKey(_parameters[i])) { identifiers.Add( _parameters[i], new ResolvedIdentifier( _parameters[i], i, IdentifierType.Parameter, true ) ); } } } // Add the declared identifiers. foreach (string identifier in _declaredIdentifiers) { if (!identifiers.ContainsKey(identifier)) { identifiers.Add( identifier, new ResolvedIdentifier( identifier, null, _bodyType == BodyType.Program ? IdentifierType.Global : IdentifierType.Local, true ) ); } } // Resolve all identifiers. foreach (var identifier in _identifiers) { ResolvedIdentifier resolved = null; // First check whether we have a catch variable in scope. if (identifier.CatchScope != null && identifier.CatchScope.Scope == this) { var catchScope = identifier.CatchScope; while (catchScope != null && catchScope.Scope == this) { if (catchScope.Identifier.Name == identifier.Name) { resolved = catchScope.Identifier; break; } catchScope = catchScope.Parent; } if (resolved != null) { identifier.Identifier.ResolvedIdentifier = resolved; if (identifier.Scope != this) _closedOverIdentifiers.Add(resolved); continue; } // We need to change the catch scope of the unresolved // identifier to strip the catch scopes that belong to // us. This way resolving in the parent scope resolves // to a declared variable or to the catch variable of // that scope. identifier.CatchScope = catchScope; } if (identifiers.TryGetValue(identifier.Name, out resolved)) { // We have this identifier. identifier.Identifier.ResolvedIdentifier = resolved; // If the identifier does not belong to this scope, // it's being closed over. if (identifier.Scope != this && resolved.Type != IdentifierType.Global) _closedOverIdentifiers.Add(resolved); } else if (Parent == null) { // It's an undeclared global identifier. resolved = new ResolvedIdentifier( identifier.Name, null, IdentifierType.Global, false ); identifiers.Add(identifier.Name, resolved); identifier.Identifier.ResolvedIdentifier = resolved; } else { // Else, push it to the parent and let that figure it out. Parent._identifiers.Add(identifier); } } var builder = new ReadOnlyArray<IIdentifier>.Builder(); builder.AddRange(identifiers.Select(p => p.Value)); builder.AddRange(_resolvedIdentifiers); return builder.ToReadOnly(); }
public void EnterCatch(string name) { var identifier = new ResolvedIdentifier( name, null, IdentifierType.Local, true ); _resolvedIdentifiers.Add(identifier); _catchScope = new CatchScope(identifier, this, FindCatchScope()); }