From dc88a56324831a0a991667efbb82ed38e6f2cab9 Mon Sep 17 00:00:00 2001 From: Luca Bolognese Date: Thu, 31 Dec 2020 15:39:12 +0100 Subject: [PATCH 1/4] First check-in Math Generator. --- .../GeneratedDemo/GeneratedDemo.csproj | 2 + .../GeneratedDemo/Geometry.math | 6 + .../SourceGenerators/GeneratedDemo/Program.cs | 3 + .../GeneratedDemo/UseMathsGenerator.cs | 14 + .../SourceGeneratorSamples/MathsGenerator.cs | 412 ++++++++++++++++++ 5 files changed, 437 insertions(+) create mode 100644 samples/CSharp/SourceGenerators/GeneratedDemo/Geometry.math create mode 100644 samples/CSharp/SourceGenerators/GeneratedDemo/UseMathsGenerator.cs create mode 100644 samples/CSharp/SourceGenerators/SourceGeneratorSamples/MathsGenerator.cs diff --git a/samples/CSharp/SourceGenerators/GeneratedDemo/GeneratedDemo.csproj b/samples/CSharp/SourceGenerators/GeneratedDemo/GeneratedDemo.csproj index 7f24ec8a4..43b04da37 100644 --- a/samples/CSharp/SourceGenerators/GeneratedDemo/GeneratedDemo.csproj +++ b/samples/CSharp/SourceGenerators/GeneratedDemo/GeneratedDemo.csproj @@ -6,9 +6,11 @@ preview + + diff --git a/samples/CSharp/SourceGenerators/GeneratedDemo/Geometry.math b/samples/CSharp/SourceGenerators/GeneratedDemo/Geometry.math new file mode 100644 index 000000000..c9c54c019 --- /dev/null +++ b/samples/CSharp/SourceGenerators/GeneratedDemo/Geometry.math @@ -0,0 +1,6 @@ +AreaRectangle(w, h) = w * h +AreaSquare(l) = AreaRectangle(l,l) +AreaCircle(r) = pi * r * r +Quadratic(a, b, c) = {-b + sqrt(pow(b,2) - 4 * a * c)} / (2 * a) + +PointDist(x', x'', y', y'') = sqrt(pow([x'-x''],2) + pow([y'-y''], 2)) diff --git a/samples/CSharp/SourceGenerators/GeneratedDemo/Program.cs b/samples/CSharp/SourceGenerators/GeneratedDemo/Program.cs index e735b0737..297582c51 100644 --- a/samples/CSharp/SourceGenerators/GeneratedDemo/Program.cs +++ b/samples/CSharp/SourceGenerators/GeneratedDemo/Program.cs @@ -21,6 +21,9 @@ static void Main(string[] args) Console.WriteLine("\n\nRunning MustacheGenerator:\n"); UseMustacheGenerator.Run(); + + Console.WriteLine("\n\nRunning MathsGenerator:\n"); + UseMathsGenerator.Run(); } } } diff --git a/samples/CSharp/SourceGenerators/GeneratedDemo/UseMathsGenerator.cs b/samples/CSharp/SourceGenerators/GeneratedDemo/UseMathsGenerator.cs new file mode 100644 index 000000000..199e37e65 --- /dev/null +++ b/samples/CSharp/SourceGenerators/GeneratedDemo/UseMathsGenerator.cs @@ -0,0 +1,14 @@ +using static System.Console; +using Maths; + +namespace GeneratedDemo +{ + public static class UseMathsGenerator + { + public static void Run() + { + WriteLine($"The area of a (10, 5) rectangle is: {Formulas.AreaRectangle(10, 5)}"); + WriteLine($"The area of a (10) square is: {Formulas.AreaSquare(10)}"); + } + } +} diff --git a/samples/CSharp/SourceGenerators/SourceGeneratorSamples/MathsGenerator.cs b/samples/CSharp/SourceGenerators/SourceGeneratorSamples/MathsGenerator.cs new file mode 100644 index 000000000..6d8724905 --- /dev/null +++ b/samples/CSharp/SourceGenerators/SourceGeneratorSamples/MathsGenerator.cs @@ -0,0 +1,412 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.RegularExpressions; +using static System.Console; +using Tokens = System.Collections.Generic.IEnumerable; +using SymTable = System.Collections.Generic.HashSet; +using System.Linq; +using Microsoft.CodeAnalysis; +using System.IO; +using Microsoft.CodeAnalysis.Text; +using System.Diagnostics; + +#pragma warning disable IDE0008 // Use explicit type + +namespace MathsGenerator { + public enum TokenType { + Number, + Identifier, + Operation, + OpenParens, + CloseParens, + Equal, + EOL, + EOF, + Spaces, + Comma, + None + } + + public struct Token { + public TokenType Type; + public string Value; + public int Line; + public int Column; + } + + public static class Lexer { + + public static void PrintTokens(IEnumerable tokens) { + foreach (var token in tokens) { + WriteLine($"{token.Line}, {token.Column}, {token.Type}, {token.Value}"); + } + } + + static (TokenType, string)[] tokenStrings = { + (TokenType.EOL, @"(\r\n|\r|\n)"), + (TokenType.Spaces, @"\s+"), + (TokenType.Number, @"[+-]?((\d+\.?\d*)|(\.\d+))"), + (TokenType.Identifier, @"[_a-zA-Z][`'""_a-zA-Z0-9]*"), + (TokenType.Operation, @"[\+\-/\*]"), + (TokenType.OpenParens, @"[([{]"), + (TokenType.CloseParens, @"[)\]}]"), + (TokenType.Equal, @"="), + (TokenType.Comma, @",") + }; + + static IEnumerable<(TokenType, Regex)> tokenExpressions = + tokenStrings.Select( + t => (t.Item1, new Regex($"^{t.Item2}", RegexOptions.Compiled | RegexOptions.Singleline))); + + // Can be optimized with spans to avoid so many allocations ... + static public Tokens Tokenize(string source) { + var currentLine = 1; + var currentColumn = 1; + + while (source.Length > 0) { + + var matchLength = 0; + var tokenType = TokenType.None; + var value = ""; + + foreach (var (type, rule) in tokenExpressions) { + var match = rule.Match(source); + if(match.Success) { + matchLength = match.Length; + tokenType = type; + value = match.Value; + break; + } + } + + if (matchLength == 0) { + + throw new Exception($"Unrecognized symbol '{source[currentLine - 1]}' at index {currentLine - 1} (line {currentLine}, column {currentColumn})."); + + } else { + + if(tokenType != TokenType.Spaces) + yield return new Token { + Type = tokenType, + Value = value, + Line = currentLine, + Column = currentColumn + }; + + currentColumn += matchLength; + if(tokenType == TokenType.EOL) { + currentLine += 1; + currentColumn = 0; + } + + source = source.Substring(matchLength); + } + } + + yield return new Token { + Type = TokenType.EOF, + Line = currentLine, + Column = currentColumn + }; + } + } + + /* EBNF for the language + lines = {line} EOF + line = {EOL} identifier [lround args rround] equal expr EOL {EOL} + args = identifier {comma identifier} + expr = [plus|minus] term { (plus|minus) term } + term = factor { (times|divide) factor }; + factor = number | var | func | matrix | lround expr rround; + var = identifier; + func = identifier lround expr {comma expr} rround; + */ + public static class Parser { + + + public static string Parse(Tokens tokens) { + var globalSymbolTable = new SymTable(); + var symbolTable = new SymTable(); + var buffer = new StringBuilder(); + + var en = tokens.GetEnumerator(); + en.MoveNext(); + + buffer = Lines(new Context { + tokens = en, + globalSymbolTable = globalSymbolTable, + symbolTable = symbolTable, + buffer = buffer + }); + return buffer.ToString(); + + } + + private readonly static string Preamble = @" +using static System.Math; + +namespace Maths { + + public static partial class Formulas { +"; + private readonly static string Ending = @" + } +}"; + + private struct Context { + public IEnumerator tokens; + public SymTable globalSymbolTable; + public SymTable symbolTable; + public StringBuilder buffer; + } + + private static StringBuilder Error(Token token, TokenType type, string value = "") => + throw new Exception($"Expected {type} {(value == "" ? "" : $" with {token.Value}")} at {token.Line},{token.Column} Instead found {token.Type} with value {token.Value}"); + + static HashSet validFunctions = + new HashSet(typeof(System.Math).GetMethods().Select(m => m.Name.ToLower())); + + static Dictionary replacementStrings = new Dictionary { + {"'''", "Third" }, {"''", "Second" }, {"'", "Prime"} + }; + + private static StringBuilder EmitIdentifier(Context ctx, Token token) { + var val = token.Value; + + if(val == "pi") { + ctx.buffer.Append("PI"); // Doesn't follow pattern + return ctx.buffer; + } + + if(validFunctions.Contains(val)) { + ctx.buffer.Append(char.ToUpper(val[0]) + val.Substring(1)); + return ctx.buffer; + } + + string id = token.Value; + if(ctx.globalSymbolTable.Contains(token.Value) || + ctx.symbolTable.Contains(token.Value)) { + foreach (var r in replacementStrings) { + id = id.Replace(r.Key, r.Value); + } + return ctx.buffer.Append(id); + } else { + throw new Exception($"{token.Value} not a known function."); + } + } + + private static StringBuilder Emit(Context ctx, Token token) => token.Type switch + { + TokenType.EOL => ctx.buffer.Append("\n"), + TokenType.CloseParens => ctx.buffer.Append(')'), // All parens become rounded + TokenType.OpenParens => ctx.buffer.Append('('), + TokenType.Equal => ctx.buffer.Append("=>"), + TokenType.Comma => ctx.buffer.Append(token.Value), + + // Identifiers are normalized and checked for injection attacks + TokenType.Identifier => EmitIdentifier(ctx, token), + TokenType.Number => ctx.buffer.Append(token.Value), + TokenType.Operation => ctx.buffer.Append(token.Value), + _ => Error(token, TokenType.None) + }; + + private static bool Peek(Context ctx, TokenType type, string value = "") { + var token = ctx.tokens.Current; + + return (token.Type == type && value == "") || + (token.Type == type && value == token.Value); + } + private static void Consume(Context ctx, TokenType type, string value = "") { + + var token = ctx.tokens.Current; + + var moreTokens = ctx.tokens.MoveNext(); + + if((token.Type == type && value == "") || + (token.Type == type && value == token.Value)) { + + ctx.buffer.Append(" "); + Emit(ctx, token); + } else { + Error(token, type, value); + } + } + + private static StringBuilder Lines(Context ctx) { + // lines = {line} EOF + + ctx.buffer.Append(Preamble); + + while(!Peek(ctx, TokenType.EOF)) + Line(ctx); + + ctx.buffer.Append(Ending); + + return ctx.buffer; + } + + private static void AddGlobalSymbol(Context ctx) { + var token = ctx.tokens.Current; + if(Peek(ctx, TokenType.Identifier)) { + ctx.globalSymbolTable.Add(token.Value); + } else { + Error(token, TokenType.Identifier); + } + } + private static void AddSymbol(Context ctx) { + var token = ctx.tokens.Current; + if(Peek(ctx, TokenType.Identifier)) { + ctx.symbolTable.Add(token.Value); + } else { + Error(token, TokenType.Identifier); + } + } + private static void Line(Context ctx) { + // line = {EOL} identifier [lround args rround] equal expr EOL {EOL} + + ctx.symbolTable.Clear(); + + while(Peek(ctx, TokenType.EOL)) + Consume(ctx, TokenType.EOL); + + ctx.buffer.Append("\tpublic static double "); + + AddGlobalSymbol(ctx); + Consume(ctx, TokenType.Identifier); + + if(Peek(ctx, TokenType.OpenParens, "(")) { + Consume(ctx, TokenType.OpenParens, "("); // Just round parens + Args(ctx); + Consume(ctx, TokenType.CloseParens, ")"); + } + + Consume(ctx, TokenType.Equal); + Expr(ctx); + ctx.buffer.Append(" ;"); + + Consume(ctx, TokenType.EOL); + + while(Peek(ctx, TokenType.EOL)) + Consume(ctx, TokenType.EOL); + } + private static void Args(Context ctx) { + // args = identifier {comma identifier} + // It doesn't make sense for a math function to have zero args (I think) + + ctx.buffer.Append("double "); + AddSymbol(ctx); + Consume(ctx, TokenType.Identifier); + + while(Peek(ctx, TokenType.Comma)) { + Consume(ctx, TokenType.Comma); + ctx.buffer.Append("double "); + AddSymbol(ctx); + Consume(ctx, TokenType.Identifier); + } + } + private static Func IsOp = (ctx, op) + => Peek(ctx, TokenType.Operation, op); + private static Action ConsOp = (ctx, op) + => Consume(ctx, TokenType.Operation, op); + + private static void Expr(Context ctx) { + // expr = [plus|minus] term { (plus|minus) term } + + if(IsOp(ctx, "+")) ConsOp(ctx, "+"); + if(IsOp(ctx, "-")) ConsOp(ctx, "-"); + + Term(ctx); + + while(IsOp(ctx, "+") || IsOp(ctx, "-")) { + + if(IsOp(ctx, "+")) ConsOp(ctx, "+"); + if(IsOp(ctx, "-")) ConsOp(ctx, "-"); + + Term(ctx); + } + } + private static void Term(Context ctx) { + // term = factor { (times|divide) factor }; + Factor(ctx); + + while(IsOp(ctx, "*") || IsOp(ctx, "/")) { + if(IsOp(ctx, "*")) ConsOp(ctx, "*"); + if(IsOp(ctx, "/")) ConsOp(ctx, "/"); + + Term(ctx); + } + } + private static void Factor(Context ctx) { + // factor = number | var | func | lround expr rround; + if(Peek(ctx, TokenType.Number)) { + Consume(ctx, TokenType.Number); + return; + } + + if(Peek(ctx, TokenType.Identifier)) { + Consume(ctx, TokenType.Identifier); // Is either var or func + if(Peek(ctx, TokenType.OpenParens, "(")) { // Is Func, but we already consumed its name + Funct(ctx); + } + return; + } + // Must be a parenthesized expression + Consume(ctx, TokenType.OpenParens); + Expr(ctx); + Consume(ctx, TokenType.CloseParens); + } + private static void Funct(Context ctx) { + // func = identifier lround expr {comma expr} rround; + Consume(ctx, TokenType.OpenParens, "("); + Expr(ctx); + while(Peek(ctx, TokenType.Comma)) { + Consume(ctx, TokenType.Comma); + Expr(ctx); + } + Consume(ctx, TokenType.CloseParens, ")"); + } + } + + [Generator] + public class MathsGenerator : ISourceGenerator + { + public void Execute(SourceGeneratorContext context) + { + + foreach (AdditionalText file in context.AdditionalFiles) + { + if (Path.GetExtension(file.Path).Equals(".math", StringComparison.OrdinalIgnoreCase)) + { + // Load formulas from .math files + var mathText = file.GetText(); + var mathString = ""; + + if(mathText != null) + { + mathString = mathText.ToString(); + } else + { + throw new Exception($"Cannot load file {file.Path}"); + } + + // Get name of generated namespace from file name + string fileName = Path.GetFileNameWithoutExtension(file.Path); + + // Parse and gen the formulas functions + var tokens = Lexer.Tokenize(mathString); + var code = Parser.Parse(tokens); + + var codeFileName = $@"{fileName}.cs"; + + context.AddSource(codeFileName, SourceText.From(code, Encoding.UTF8)); + } + } + } + + public void Initialize(InitializationContext context) + { + } + } +} + From 3207c328d7c430cab6e0e53b2c98d2d2d388cbf7 Mon Sep 17 00:00:00 2001 From: Luca Bolognese Date: Fri, 8 Jan 2021 16:12:18 +0100 Subject: [PATCH 2/4] Introduce summation --- .../GeneratedDemo/Geometry.math | 9 ++- .../GeneratedDemo/UseMathsGenerator.cs | 1 + .../SourceGeneratorSamples/MathsGenerator.cs | 78 +++++++++++++++++-- 3 files changed, 77 insertions(+), 11 deletions(-) diff --git a/samples/CSharp/SourceGenerators/GeneratedDemo/Geometry.math b/samples/CSharp/SourceGenerators/GeneratedDemo/Geometry.math index c9c54c019..9ccca204c 100644 --- a/samples/CSharp/SourceGenerators/GeneratedDemo/Geometry.math +++ b/samples/CSharp/SourceGenerators/GeneratedDemo/Geometry.math @@ -1,6 +1,9 @@ -AreaRectangle(w, h) = w * h -AreaSquare(l) = AreaRectangle(l,l) +AreaSquare(l) = pow(l, 2) +AreaRectangle(w, h) = w * h AreaCircle(r) = pi * r * r Quadratic(a, b, c) = {-b + sqrt(pow(b,2) - 4 * a * c)} / (2 * a) -PointDist(x', x'', y', y'') = sqrt(pow([x'-x''],2) + pow([y'-y''], 2)) +GoldenRatio = 1.61803 +GoldHarm(n) = GoldenRatio + 1 * ∑(i, 1, n, 1 / i) + +D(x', x'', y', y'') = sqrt(pow([x'-x''],2) + pow([y'-y''], 2)) diff --git a/samples/CSharp/SourceGenerators/GeneratedDemo/UseMathsGenerator.cs b/samples/CSharp/SourceGenerators/GeneratedDemo/UseMathsGenerator.cs index 199e37e65..2c8b7ecf0 100644 --- a/samples/CSharp/SourceGenerators/GeneratedDemo/UseMathsGenerator.cs +++ b/samples/CSharp/SourceGenerators/GeneratedDemo/UseMathsGenerator.cs @@ -9,6 +9,7 @@ public static void Run() { WriteLine($"The area of a (10, 5) rectangle is: {Formulas.AreaRectangle(10, 5)}"); WriteLine($"The area of a (10) square is: {Formulas.AreaSquare(10)}"); + WriteLine($"The GoldHarmon of 3 is: {Formulas.GoldHarm(3)}"); } } } diff --git a/samples/CSharp/SourceGenerators/SourceGeneratorSamples/MathsGenerator.cs b/samples/CSharp/SourceGenerators/SourceGeneratorSamples/MathsGenerator.cs index 6d8724905..d410d2447 100644 --- a/samples/CSharp/SourceGenerators/SourceGeneratorSamples/MathsGenerator.cs +++ b/samples/CSharp/SourceGenerators/SourceGeneratorSamples/MathsGenerator.cs @@ -25,6 +25,7 @@ public enum TokenType { EOF, Spaces, Comma, + Sum, None } @@ -52,7 +53,8 @@ public static void PrintTokens(IEnumerable tokens) { (TokenType.OpenParens, @"[([{]"), (TokenType.CloseParens, @"[)\]}]"), (TokenType.Equal, @"="), - (TokenType.Comma, @",") + (TokenType.Comma, @","), + (TokenType.Sum, @"∑") }; static IEnumerable<(TokenType, Regex)> tokenExpressions = @@ -118,9 +120,10 @@ static public Tokens Tokenize(string source) { args = identifier {comma identifier} expr = [plus|minus] term { (plus|minus) term } term = factor { (times|divide) factor }; - factor = number | var | func | matrix | lround expr rround; + factor = number | var | func | sum | matrix | lround expr rround; var = identifier; func = identifier lround expr {comma expr} rround; + sum = ∑ lround identifier comma expr comma expr comma expr rround; */ public static class Parser { @@ -145,6 +148,7 @@ public static string Parse(Tokens tokens) { private readonly static string Preamble = @" using static System.Math; +using static ___MathLibrary___.Formulas; namespace Maths { @@ -192,7 +196,7 @@ private static StringBuilder EmitIdentifier(Context ctx, Token token) { } return ctx.buffer.Append(id); } else { - throw new Exception($"{token.Value} not a known function."); + throw new Exception($"{token.Value} not a known identifier or function."); } } @@ -208,6 +212,7 @@ private static StringBuilder EmitIdentifier(Context ctx, Token token) { TokenType.Identifier => EmitIdentifier(ctx, token), TokenType.Number => ctx.buffer.Append(token.Value), TokenType.Operation => ctx.buffer.Append(token.Value), + TokenType.Sum => ctx.buffer.Append("___MySum___"), _ => Error(token, TokenType.None) }; @@ -217,11 +222,15 @@ private static bool Peek(Context ctx, TokenType type, string value = "") { return (token.Type == type && value == "") || (token.Type == type && value == token.Value); } - private static void Consume(Context ctx, TokenType type, string value = "") { + private static Token NextToken(Context ctx) { var token = ctx.tokens.Current; + ctx.tokens.MoveNext(); + return token; + } + private static void Consume(Context ctx, TokenType type, string value = "") { - var moreTokens = ctx.tokens.MoveNext(); + var token = NextToken(ctx); if((token.Type == type && value == "") || (token.Type == type && value == token.Value)) { @@ -351,11 +360,39 @@ private static void Factor(Context ctx) { } return; } + if(Peek(ctx, TokenType.Sum)) { + Sum(ctx); + return; + } // Must be a parenthesized expression Consume(ctx, TokenType.OpenParens); Expr(ctx); Consume(ctx, TokenType.CloseParens); } + private static void Sum(Context ctx) { + // sum = ∑ lround identifier comma expr1 comma expr2 comma expr3 rround; + // TODO: differentiate in the language between integer and double, but complicated for a sample. + Consume(ctx, TokenType.Sum); + Consume(ctx, TokenType.OpenParens, "("); + + AddSymbol(ctx); + var varName = NextToken(ctx).Value; + NextToken(ctx); // consume the first comma without emitting it + + ctx.buffer.Append("(int)"); + Expr(ctx); // Start index + Consume(ctx, TokenType.Comma); + + ctx.buffer.Append("(int)"); + Expr(ctx); // End index + Consume(ctx, TokenType.Comma); + + ctx.buffer.Append($"{varName} => "); // It needs to be a lambda + + Expr(ctx); // expr to evaluate at each iteration + + Consume(ctx, TokenType.CloseParens, ")"); + } private static void Funct(Context ctx) { // func = identifier lround expr {comma expr} rround; Consume(ctx, TokenType.OpenParens, "("); @@ -371,6 +408,28 @@ private static void Funct(Context ctx) { [Generator] public class MathsGenerator : ISourceGenerator { + private bool libraryIsAdded = false; + + private const string libraryCode = @" +using System.Linq; +using System; +using System.Collections.Generic; + +namespace ___MathLibrary___ { + public static partial class Formulas { + + public static IEnumerable ConvertToDouble(IEnumerable col) + { + foreach (var s in col) + yield return (double)Convert.ChangeType(s, typeof(double)); + } + + public static double ___MySum___(int start, int end, Func f) => + Enumerable.Sum(ConvertToDouble(Enumerable.Range(start, end - start)), f); + } +} +"; + public void Execute(SourceGeneratorContext context) { @@ -378,6 +437,11 @@ public void Execute(SourceGeneratorContext context) { if (Path.GetExtension(file.Path).Equals(".math", StringComparison.OrdinalIgnoreCase)) { + if(!libraryIsAdded) + { + context.AddSource("___MathLibrary___.cs", SourceText.From(libraryCode, Encoding.UTF8)); + libraryIsAdded = true; + } // Load formulas from .math files var mathText = file.GetText(); var mathString = ""; @@ -404,9 +468,7 @@ public void Execute(SourceGeneratorContext context) } } - public void Initialize(InitializationContext context) - { - } + public void Initialize(InitializationContext context) { } } } From 8fbc804e9af50d2f6bd4b8f5b24962f236386853 Mon Sep 17 00:00:00 2001 From: Luca Bolognese Date: Tue, 12 Jan 2021 10:29:48 +0100 Subject: [PATCH 3/4] Fix awkward ConvertToDouble function. --- .../SourceGenerators/SourceGeneratorSamples/MathsGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/CSharp/SourceGenerators/SourceGeneratorSamples/MathsGenerator.cs b/samples/CSharp/SourceGenerators/SourceGeneratorSamples/MathsGenerator.cs index d410d2447..5a1c43571 100644 --- a/samples/CSharp/SourceGenerators/SourceGeneratorSamples/MathsGenerator.cs +++ b/samples/CSharp/SourceGenerators/SourceGeneratorSamples/MathsGenerator.cs @@ -421,7 +421,7 @@ public static partial class Formulas { public static IEnumerable ConvertToDouble(IEnumerable col) { foreach (var s in col) - yield return (double)Convert.ChangeType(s, typeof(double)); + yield return (double) s; } public static double ___MySum___(int start, int end, Func f) => From 425941d959a4c69588f79e7407841ab1e97fba0a Mon Sep 17 00:00:00 2001 From: Luca Bolognese Date: Tue, 12 Jan 2021 10:39:41 +0100 Subject: [PATCH 4/4] Generate helper class in the Maths namespace instead of its own crazily named one. --- .../SourceGeneratorSamples/MathsGenerator.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/samples/CSharp/SourceGenerators/SourceGeneratorSamples/MathsGenerator.cs b/samples/CSharp/SourceGenerators/SourceGeneratorSamples/MathsGenerator.cs index 5a1c43571..163afd588 100644 --- a/samples/CSharp/SourceGenerators/SourceGeneratorSamples/MathsGenerator.cs +++ b/samples/CSharp/SourceGenerators/SourceGeneratorSamples/MathsGenerator.cs @@ -148,7 +148,7 @@ public static string Parse(Tokens tokens) { private readonly static string Preamble = @" using static System.Math; -using static ___MathLibrary___.Formulas; +using static Maths.FormulaHelpers; namespace Maths { @@ -212,7 +212,7 @@ private static StringBuilder EmitIdentifier(Context ctx, Token token) { TokenType.Identifier => EmitIdentifier(ctx, token), TokenType.Number => ctx.buffer.Append(token.Value), TokenType.Operation => ctx.buffer.Append(token.Value), - TokenType.Sum => ctx.buffer.Append("___MySum___"), + TokenType.Sum => ctx.buffer.Append("MySum"), _ => Error(token, TokenType.None) }; @@ -415,8 +415,8 @@ public class MathsGenerator : ISourceGenerator using System; using System.Collections.Generic; -namespace ___MathLibrary___ { - public static partial class Formulas { +namespace Maths { + public static class FormulaHelpers { public static IEnumerable ConvertToDouble(IEnumerable col) { @@ -424,7 +424,7 @@ public static IEnumerable ConvertToDouble(IEnumerable col) yield return (double) s; } - public static double ___MySum___(int start, int end, Func f) => + public static double MySum(int start, int end, Func f) => Enumerable.Sum(ConvertToDouble(Enumerable.Range(start, end - start)), f); } }