public override void Visit(ExternalDeclarationNode node) { foreach (var param in node.ParameterList.Parameters.Nodes) { var name = param.NameToken; if (name.IsMissing) { continue; } var duplicate = false; foreach (var param2 in node.ParameterList.Parameters.Nodes) { if (param2 != param && param2.NameToken.Text == name.Text) { duplicate = true; break; } } if (!duplicate) { continue; } Error(param, SyntaxDiagnosticKind.DuplicateParameter, name.Location, $"Function parameter '{name}' (of '{node.NameToken}') declared multiple times"); } base.Visit(node); }
public override IEnumerable <(SyntaxNode, SyntaxDiagnostic)> Run(NamedDeclarationNode node) { if (node.VisibilityKeywordToken?.Kind != SyntaxTokenKind.PubKeyword) { yield break; } var type = node switch { ConstantDeclarationNode _ => "constant", FunctionDeclarationNode _ => "function", ExternalDeclarationNode _ => "function", _ => throw DebugAssert.Unreachable(), }; var ident = node.NameToken; if (ident.IsMissing) { yield break; } var diag = CheckDocAttribute(node.Attributes, ident.Location, $"Public {type} {ident} is undocumented"); if (diag != null) { yield return(node, diag); } }
internal External(Module module, ExternalDeclarationNode node) : base(module, node) { var parms = ImmutableArray <Parameter> .Empty; var i = 0; foreach (var param in node.ParameterList.Parameters.Nodes) { parms = parms.Add(new Parameter(this, param.Attributes, param.NameToken.Text, i, param.DotDotToken != null)); i++; } Parameters = parms; }
internal Module(ModuleLoader loader, ModulePath path, ProgramNode node) : base(node.Attributes) { Loader = loader; Path = path; var decls = ImmutableArray <Declaration> .Empty; foreach (var decl in node.Declarations) { if (decl is UseDeclarationNode) { continue; } decls = decls.Add(decl switch { ConstantDeclarationNode c => (Declaration) new Constant(this, c), FunctionDeclarationNode f => new Function(this, f), ExternalDeclarationNode e => new External(this, e), TestDeclarationNode t => new Test(this, t), _ => throw DebugAssert.Unreachable(), });
public override void Visit(ProgramNode node) { _path = CreatePath(node.Path); foreach (var decl in node.Declarations) { if (!(decl is UseDeclarationNode use)) { continue; } var path = CreateCorrectPath(use.Path); if (path == null) { continue; } if (use.Alias is UseDeclarationAliasNode alias && !alias.NameToken.IsMissing) { var name = alias.NameToken; var duplicate = false; foreach (var decl2 in node.Declarations) { if (decl2 is UseDeclarationNode use2 && use2.Alias is UseDeclarationAliasNode alias2 && alias2 != alias && alias2.NameToken.Text == name.Text) { duplicate = true; break; } } if (!duplicate) { _aliases.Add(name.Text, path); } else { Error(alias, SyntaxDiagnosticKind.DuplicateUseDeclarationAlias, name.Location, $"Module alias '{name}' declared multiple times"); } } if (!(LoadModule(use, use.Path.ComponentTokens.Tokens[0].Location, path) is Module mod)) { continue; } // Don't import symbols if the module is aliased. if (use.Alias != null) { continue; } foreach (var mdecl in mod.Declarations) { if (!mdecl.IsPublic) { continue; } var sym = mdecl switch { Constant _ => SyntaxSymbolKind.Constant, Function _ => SyntaxSymbolKind.Function, External _ => SyntaxSymbolKind.External, _ => (SyntaxSymbolKind?)null, }; if (sym is SyntaxSymbolKind kind) { _scope.Define(kind, path, null, mdecl.Name); } } } foreach (var decl in node.Declarations) { if (!(decl is NamedDeclarationNode named) || decl is MissingNamedDeclarationNode) { continue; } var name = named.NameToken; if (name.IsMissing) { continue; } if (name.Text.StartsWith('_')) { Error(named, SyntaxDiagnosticKind.InvalidDeclarationName, name.Location, $"Declaration '{name}' is invalid; declaration names cannot start with '_'"); continue; } var duplicate = false; foreach (var decl2 in node.Declarations) { if (decl2 == decl || !(decl2 is NamedDeclarationNode named2) || decl2 is MissingNamedDeclarationNode) { continue; } var name2 = named2.NameToken; if (name2.Text != name.Text) { continue; } duplicate = true; } if (duplicate) { Error(named, SyntaxDiagnosticKind.DuplicateDeclaration, name.Location, $"Declaration name '{name}' declared multiple times"); continue; } var sym = decl switch { ConstantDeclarationNode _ => SyntaxSymbolKind.Constant, FunctionDeclarationNode _ => SyntaxSymbolKind.Function, ExternalDeclarationNode _ => SyntaxSymbolKind.External, _ => (SyntaxSymbolKind?)null, }; if (sym is SyntaxSymbolKind kind) { _scope.Define(kind, _path, decl, name.Text); } } foreach (var decl in node.Declarations) { if (!(decl is TestDeclarationNode test)) { continue; } var name = test.NameToken; if (name.Text.StartsWith('_')) { Error(test, SyntaxDiagnosticKind.InvalidDeclarationName, name.Location, $"Test name '{name}' is invalid; test names cannot start with '_'"); continue; } var duplicate = false; foreach (var decl2 in node.Declarations) { if (decl2 != decl && decl2 is TestDeclarationNode test2 && test2.NameToken.Text == name.Text) { duplicate = true; break; } } if (duplicate) { Error(test, SyntaxDiagnosticKind.DuplicateDeclaration, name.Location, $"Test '{name}' declared multiple times"); continue; } } base.Visit(node); }