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 VisitVariableDeclarationStatement(VariableDeclarationStatementSyntax variableDeclaration, BindingScope bindingScope) { base.VisitVariableDeclarationStatement(variableDeclaration, bindingScope); if (bindingScope.Lookup(variableDeclaration.Name, out var binding)) { if (binding.MutableBinding) { diagnostics.Add(SemanticError.CantRebindMutableBinding(function.File, variableDeclaration.NameSpan)); function.Poison(); } else if (variableDeclaration.MutableBinding) { diagnostics.Add(SemanticError.CantRebindAsMutableBinding(function.File, variableDeclaration.NameSpan)); function.Poison(); } } }