/// <summary> /// Generates a function signature from the specified parameters. /// </summary> /// <param name="receiver">Optional signature for a receiver.</param> /// <param name="name">The name of the function.</param> /// <param name="parameters">Optional list of parameters. Pass null if there are no parameters.</param> /// <param name="returns">Optional list of return values. Pass null if there are no return values.</param> /// <returns>The root node in the function signature AST.</returns> public static Node Generate(FuncParamSig receiver, string name, IReadOnlyList <FuncParamSig> parameters, IReadOnlyList <FuncReturnSig> returns) { if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentException(nameof(name)); } var func = new Func(); if (receiver != null) { var recvOpenParen = new OpenDelimiter(BinaryDelimiterType.Paren); recvOpenParen.AddChild(receiver); recvOpenParen.AddClosingDelimiter(); func.AddChild(recvOpenParen); } func.AddChild(new Identifier(name)); // build parameters var paramsStart = new OpenDelimiter(BinaryDelimiterType.Paren); if (parameters != null) { paramsStart.AddChild(DelimitedSequence.Generate(UnaryDelimiterType.Comma, parameters)); } paramsStart.AddClosingDelimiter(); func.AddChild(paramsStart); if (returns != null) { // multiple return values or a single return value // that has a name must be enclosed in parentheses if (returns.Count == 1) { var ret = returns[0]; if (ret.IsNamed) { var returnOpenParen = new OpenDelimiter(BinaryDelimiterType.Paren); returnOpenParen.AddChild(ret); returnOpenParen.AddClosingDelimiter(); func.AddChild(returnOpenParen); } else { func.AddChild(ret); } } else { var returnOpenParen = new OpenDelimiter(BinaryDelimiterType.Paren); returnOpenParen.AddChild(DelimitedSequence.Generate(UnaryDelimiterType.Comma, returns)); returnOpenParen.AddClosingDelimiter(); func.AddChild(returnOpenParen); } } return(func); }