protected override void WalkNonNull(IAbstractSyntax syntax, BindingScope bindingScope) { switch (syntax) { case IConcreteInvocableDeclaration syn: foreach (var parameter in syn.Parameters.OfType <INamedParameter>()) { bindingScope = new VariableBindingScope(bindingScope, parameter); } break; case IFieldDeclaration syn: WalkChildren(syn, bindingScope); break; case IBodyOrBlock syn: foreach (var statement in syn.Statements) { WalkNonNull(statement, bindingScope); // Each variable declaration establishes a new binding scope if (statement is IVariableDeclarationStatement variableDeclaration) { bindingScope = new VariableBindingScope(bindingScope, variableDeclaration); } } return; case IVariableDeclarationStatement syn: { WalkChildren(syn, bindingScope); if (!bindingScope.Lookup(syn.Symbol.Name, out var binding)) { return; } if (binding.MutableBinding) { diagnostics.Add(SemanticError.CantRebindMutableBinding(file, syn.NameSpan)); } else if (syn.Symbol.IsMutableBinding) { diagnostics.Add(SemanticError.CantRebindAsMutableBinding(file, syn.NameSpan)); } return; } case INameExpression syn: { // This checks for cases where a variable was shadowed, but then used later if (!bindingScope.Lookup(syn.ReferencedSymbol.Name, out var binding)) { return; } if (binding.WasShadowedBy.Any()) { diagnostics.Add(SemanticError.CantShadow(file, binding.WasShadowedBy[^ 1].NameSpan, syn.Span));
public override void VisitIdentifierName(IdentifierNameSyntax identifierName, BindingScope bindingScope) { if (!bindingScope.Lookup(identifierName.Name, out var binding)) { return; } var shadowedBy = binding.WasShadowedBy.LastOrDefault(); if (shadowedBy == null) { return; } diagnostics.Add(SemanticError.CantShadow(function.File, shadowedBy.NameSpan, identifierName.Span)); function.Poison(); }