diff --git a/Avalonia.sln b/Avalonia.sln
index 410a7171c7..124f1e535d 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -223,8 +223,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.ReactiveUI.Events"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sandbox", "samples\Sandbox\Sandbox.csproj", "{11BE52AF-E2DD-4CF0-B19A-05285ACAF571}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MicroComGenerator", "src\tools\MicroComGenerator\MicroComGenerator.csproj", "{AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.MicroCom", "src\Avalonia.MicroCom\Avalonia.MicroCom.csproj", "{FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MiniMvvm", "samples\MiniMvvm\MiniMvvm.csproj", "{BC594FD5-4AF2-409E-A1E6-04123F54D7C5}"
@@ -2029,30 +2027,6 @@ Global
{11BE52AF-E2DD-4CF0-B19A-05285ACAF571}.Release|iPhone.Build.0 = Release|Any CPU
{11BE52AF-E2DD-4CF0-B19A-05285ACAF571}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{11BE52AF-E2DD-4CF0-B19A-05285ACAF571}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.AppStore|Any CPU.Build.0 = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.AppStore|iPhone.Build.0 = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Debug|iPhone.ActiveCfg = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Debug|iPhone.Build.0 = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Release|Any CPU.Build.0 = Release|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Release|iPhone.ActiveCfg = Release|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Release|iPhone.Build.0 = Release|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
@@ -2255,7 +2229,6 @@ Global
{3C84E04B-36CF-4D0D-B965-C26DD649D1F3} = {A0CC0258-D18C-4AB3-854F-7101680FC3F9}
{909A8CBD-7D0E-42FD-B841-022AD8925820} = {8B6A8209-894F-4BA1-B880-965FD453982C}
{11BE52AF-E2DD-4CF0-B19A-05285ACAF571} = {9B9E3891-2366-4253-A952-D08BCEB71098}
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
{BC594FD5-4AF2-409E-A1E6-04123F54D7C5} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{25831348-EB2A-483E-9576-E8F6528674A5} = {86A3F706-DC3C-43C6-BE1B-B98F5BAAA268}
{C08E9894-AA92-426E-BF56-033E262CAD3E} = {9B9E3891-2366-4253-A952-D08BCEB71098}
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 903146cdd7..497402fe4b 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -58,8 +58,10 @@ jobs:
displayName: 'Generate avalonia-native'
inputs:
script: |
- export PATH="`pwd`/sdk:$PATH"
- cd src/tools/MicroComGenerator; dotnet run -f net6.0 -i ../../Avalonia.Native/avn.idl --cpp ../../../native/Avalonia.Native/inc/avalonia-native.h
+ export COREHOST_TRACE=0
+ export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
+ export DOTNET_CLI_TELEMETRY_OPTOUT=1
+ ./build.sh --target GenerateCppHeaders --configuration Release
- task: Xcode@5
inputs:
diff --git a/build/MicroCom.targets b/build/MicroCom.targets
deleted file mode 100644
index 1ed388f689..0000000000
--- a/build/MicroCom.targets
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
- false
- all
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- <_AvaloniaPatchComInterop>true
-
-
-
diff --git a/nukebuild/MicroComGen.cs b/nukebuild/MicroComGen.cs
index 06c8acbf23..b1e546cb97 100644
--- a/nukebuild/MicroComGen.cs
+++ b/nukebuild/MicroComGen.cs
@@ -1,14 +1,14 @@
using System.IO;
-using MicroComGenerator;
+using MicroCom.CodeGenerator;
using Nuke.Common;
partial class Build : NukeBuild
{
Target GenerateCppHeaders => _ => _.Executes(() =>
{
- var text = File.ReadAllText(RootDirectory / "src" / "Avalonia.Native" / "avn.idl");
- var ast = AstParser.Parse(text);
+ var file = MicroComCodeGenerator.Parse(
+ File.ReadAllText(RootDirectory / "src" / "Avalonia.Native" / "avn.idl"));
File.WriteAllText(RootDirectory / "native" / "Avalonia.Native" / "inc" / "avalonia-native.h",
- CppGen.GenerateCpp(ast));
+ file.GenerateCppHeader());
});
}
\ No newline at end of file
diff --git a/nukebuild/_build.csproj b/nukebuild/_build.csproj
index a6cb86a9bd..af087e3180 100644
--- a/nukebuild/_build.csproj
+++ b/nukebuild/_build.csproj
@@ -15,7 +15,7 @@
-
+
@@ -38,10 +38,6 @@
-
- MicroComGenerator\%(Filename)%(Extension)
-
-
diff --git a/src/Avalonia.MicroCom/MicroComRuntime.cs b/src/Avalonia.MicroCom/MicroComRuntime.cs
index 85507674d2..e0f524146a 100644
--- a/src/Avalonia.MicroCom/MicroComRuntime.cs
+++ b/src/Avalonia.MicroCom/MicroComRuntime.cs
@@ -36,7 +36,13 @@ namespace Avalonia.MicroCom
public static T CreateProxyFor(void* pObject, bool ownsHandle) => (T)CreateProxyFor(typeof(T), new IntPtr(pObject), ownsHandle);
public static T CreateProxyFor(IntPtr pObject, bool ownsHandle) => (T)CreateProxyFor(typeof(T), pObject, ownsHandle);
+
+ public static T CreateProxyOrNullFor(void* pObject, bool ownsHandle) where T : class =>
+ pObject == null ? null : (T)CreateProxyFor(typeof(T), new IntPtr(pObject), ownsHandle);
+ public static T CreateProxyOrNullFor(IntPtr pObject, bool ownsHandle) where T : class =>
+ pObject == IntPtr.Zero ? null : (T)CreateProxyFor(typeof(T), pObject, ownsHandle);
+
public static object CreateProxyFor(Type type, IntPtr pObject, bool ownsHandle) => _factories[type](pObject, ownsHandle);
public static IntPtr GetNativeIntPtr(this T obj, bool owned = false) where T : IUnknown
diff --git a/src/Avalonia.MicroCom/MicroComVtblBase.cs b/src/Avalonia.MicroCom/MicroComVtblBase.cs
index 2f0607c0a8..7092f8131a 100644
--- a/src/Avalonia.MicroCom/MicroComVtblBase.cs
+++ b/src/Avalonia.MicroCom/MicroComVtblBase.cs
@@ -21,6 +21,11 @@ namespace Avalonia.MicroCom
AddMethod((AddRefDelegate)Release);
}
+ protected void AddMethod(void* f)
+ {
+ _methods.Add(new IntPtr(f));
+ }
+
protected void AddMethod(Delegate d)
{
GCHandle.Alloc(d);
diff --git a/src/Avalonia.Native/Avalonia.Native.csproj b/src/Avalonia.Native/Avalonia.Native.csproj
index 3913484431..393467a8b1 100644
--- a/src/Avalonia.Native/Avalonia.Native.csproj
+++ b/src/Avalonia.Native/Avalonia.Native.csproj
@@ -6,6 +6,7 @@
true
netstandard2.0
true
+ Avalonia.MicroCom
@@ -20,7 +21,7 @@
-
+
+
-
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index a3f0c01a51..869602e452 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -2,4 +2,10 @@
+
+
+ Shared\_ModuleInitializer.cs
+ false
+
+
diff --git a/src/Shared/ModuleInitializer.cs b/src/Shared/ModuleInitializer.cs
new file mode 100644
index 0000000000..c14b150c1a
--- /dev/null
+++ b/src/Shared/ModuleInitializer.cs
@@ -0,0 +1,10 @@
+namespace System.Runtime.CompilerServices
+{
+#if !NET5_0_OR_GREATER
+ internal class ModuleInitializerAttribute : Attribute
+ {
+
+ }
+#endif
+}
+
diff --git a/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj b/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj
index 2a2aff322a..e970fc87ea 100644
--- a/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj
+++ b/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj
@@ -3,14 +3,15 @@
netstandard2.0
true
Avalonia.Win32
+ Avalonia.MicroCom
-
-
+
+
+
-
diff --git a/src/tools/MicroComGenerator/Ast.cs b/src/tools/MicroComGenerator/Ast.cs
deleted file mode 100644
index e9a55308be..0000000000
--- a/src/tools/MicroComGenerator/Ast.cs
+++ /dev/null
@@ -1,241 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace MicroComGenerator.Ast
-{
- public class AstAttributeNode
- {
- public string Name { get; set; }
- public string Value { get; set; }
-
- public AstAttributeNode(string name, string value)
- {
- Name = name;
- Value = value;
- }
-
- public override string ToString() => $"{Name} = {Value}";
- public AstAttributeNode Clone() => new AstAttributeNode(Name, Value);
- }
-
- public class AstAttributes : List
- {
- public bool HasAttribute(string a) => this.Any(x => x.Name == a);
-
- public AstAttributes Clone()
- {
- var rv= new AstAttributes();
- rv.AddRange(this.Select(x => x.Clone()));
- return rv;
- }
- }
-
- public interface IAstNodeWithAttributes
- {
- public AstAttributes Attributes { get; set; }
- }
-
- public class AstEnumNode : List, IAstNodeWithAttributes
- {
- public AstAttributes Attributes { get; set; } = new AstAttributes();
- public string Name { get; set; }
- public override string ToString() => "Enum " + Name;
-
- public AstEnumNode Clone()
- {
- var rv = new AstEnumNode { Name = Name, Attributes = Attributes.Clone() };
- rv.AddRange(this.Select(x => x.Clone()));
- return rv;
- }
- }
-
- public class AstEnumMemberNode
- {
- public string Name { get; set; }
- public string Value { get; set; }
-
- public AstEnumMemberNode(string name, string value)
- {
- Name = name;
- Value = value;
- }
-
- public override string ToString() => $"Enum member {Name} = {Value}";
- public AstEnumMemberNode Clone() => new AstEnumMemberNode(Name, Value);
- }
-
- public class AstStructNode : List, IAstNodeWithAttributes
- {
- public AstAttributes Attributes { get; set; } = new AstAttributes();
- public string Name { get; set; }
- public override string ToString() => "Struct " + Name;
-
- public AstStructNode Clone()
- {
- var rv = new AstStructNode { Name = Name, Attributes = Attributes.Clone() };
- rv.AddRange(this.Select(x => x.Clone()));
- return rv;
- }
- }
-
- public class AstTypeNode
- {
- public string Name { get; set; }
- public int PointerLevel { get; set; }
- public bool IsLink { get; set; }
-
- public string Format() => Name + new string('*', PointerLevel)
- + (IsLink ? "&" : "");
- public override string ToString() => Format();
- public AstTypeNode Clone() => new AstTypeNode() {
- Name = Name,
- PointerLevel = PointerLevel,
- IsLink = IsLink
- };
- }
-
- public class AstStructMemberNode : IAstNodeWithAttributes
- {
- public string Name { get; set; }
- public AstTypeNode Type { get; set; }
-
- public override string ToString() => $"Struct member {Type.Format()} {Name}";
- public AstStructMemberNode Clone() => new AstStructMemberNode() { Name = Name, Type = Type.Clone() };
- public AstAttributes Attributes { get; set; } = new AstAttributes();
- }
-
- public class AstInterfaceNode : List, IAstNodeWithAttributes
- {
- public AstAttributes Attributes { get; set; } = new AstAttributes();
- public string Name { get; set; }
- public string Inherits { get; set; }
-
- public override string ToString()
- {
- if (Inherits == null)
- return Name;
- return $"Interface {Name} : {Inherits}";
- }
- public AstInterfaceNode Clone()
- {
- var rv = new AstInterfaceNode { Name = Name, Inherits = Inherits, Attributes = Attributes.Clone() };
- rv.AddRange(this.Select(x => x.Clone()));
- return rv;
- }
- }
-
- public class AstInterfaceMemberNode : List, IAstNodeWithAttributes
- {
- public string Name { get; set; }
- public AstTypeNode ReturnType { get; set; }
- public AstAttributes Attributes { get; set; } = new AstAttributes();
-
- public AstInterfaceMemberNode Clone()
- {
- var rv = new AstInterfaceMemberNode()
- {
- Name = Name, Attributes = Attributes.Clone(), ReturnType = ReturnType
- };
- rv.AddRange(this.Select(x => x.Clone()));
- return rv;
- }
-
- public override string ToString() =>
- $"Interface member {ReturnType.Format()} {Name} ({string.Join(", ", this.Select(x => x.Format()))})";
- }
-
- public class AstInterfaceMemberArgumentNode : IAstNodeWithAttributes
- {
- public string Name { get; set; }
- public AstTypeNode Type { get; set; }
- public AstAttributes Attributes { get; set; } = new AstAttributes();
-
-
- public string Format() => $"{Type.Format()} {Name}";
- public override string ToString() => "Argument " + Format();
-
- public AstInterfaceMemberArgumentNode Clone() => new AstInterfaceMemberArgumentNode
- {
- Name = Name, Type = Type.Clone(), Attributes = Attributes.Clone()
- };
- }
-
- public static class AstExtensions
- {
- public static bool HasAttribute(this IAstNodeWithAttributes node, string s) => node.Attributes.HasAttribute(s);
-
- public static string GetAttribute(this IAstNodeWithAttributes node, string s)
- {
- var value = node.Attributes.FirstOrDefault(a => a.Name == s)?.Value;
- if (value == null)
- throw new CodeGenException("Expected attribute " + s + " for node " + node);
- return value;
- }
-
- public static string GetAttributeOrDefault(this IAstNodeWithAttributes node, string s)
- => node.Attributes.FirstOrDefault(a => a.Name == s)?.Value;
- }
-
- class AstVisitor
- {
- protected virtual void VisitType(AstTypeNode type)
- {
- }
-
- protected virtual void VisitArgument(AstInterfaceMemberArgumentNode argument)
- {
- VisitType(argument.Type);
- }
-
- protected virtual void VisitInterfaceMember(AstInterfaceMemberNode member)
- {
- foreach(var a in member)
- VisitArgument(a);
- VisitType(member.ReturnType);
- }
-
- protected virtual void VisitInterface(AstInterfaceNode iface)
- {
- foreach(var m in iface)
- VisitInterfaceMember(m);
- }
-
- protected virtual void VisitStructMember(AstStructMemberNode member)
- {
- VisitType(member.Type);
- }
-
- protected virtual void VisitStruct(AstStructNode node)
- {
- foreach(var m in node)
- VisitStructMember(m);
- }
-
- public virtual void VisitAst(AstIdlNode ast)
- {
- foreach(var iface in ast.Interfaces)
- VisitInterface(iface);
- foreach (var s in ast.Structs)
- VisitStruct(s);
- }
-
-
- }
-
- public class AstIdlNode : IAstNodeWithAttributes
- {
- public AstAttributes Attributes { get; set; } = new AstAttributes();
- public List Enums { get; set; } = new List();
- public List Structs { get; set; } = new List();
- public List Interfaces { get; set; } = new List();
-
- public AstIdlNode Clone() => new AstIdlNode()
- {
- Attributes = Attributes.Clone(),
- Enums = Enums.Select(x => x.Clone()).ToList(),
- Structs = Structs.Select(x => x.Clone()).ToList(),
- Interfaces = Interfaces.Select(x => x.Clone()).ToList()
- };
- }
-}
diff --git a/src/tools/MicroComGenerator/AstParser.cs b/src/tools/MicroComGenerator/AstParser.cs
deleted file mode 100644
index 388a8eb018..0000000000
--- a/src/tools/MicroComGenerator/AstParser.cs
+++ /dev/null
@@ -1,232 +0,0 @@
-using System.Collections.Generic;
-using MicroComGenerator.Ast;
-
-namespace MicroComGenerator
-{
- public class AstParser
- {
- public static AstIdlNode Parse(string source)
- {
- var parser = new TokenParser(source);
- var idl = new AstIdlNode { Attributes = ParseGlobalAttributes(ref parser) };
-
- while (!parser.Eof)
- {
- var attrs = ParseLocalAttributes(ref parser);
- if (parser.TryConsume(";"))
- continue;
- if (parser.TryParseKeyword("enum"))
- idl.Enums.Add(ParseEnum(attrs, ref parser));
- else if (parser.TryParseKeyword("struct"))
- idl.Structs.Add(ParseStruct(attrs, ref parser));
- else if (parser.TryParseKeyword("interface"))
- idl.Interfaces.Add(ParseInterface(attrs, ref parser));
- else
- throw new ParseException("Unexpected character", ref parser);
- }
-
- return idl;
- }
-
- static AstAttributes ParseGlobalAttributes(ref TokenParser parser)
- {
- var rv = new AstAttributes();
- while (!parser.Eof)
- {
- parser.SkipWhitespace();
- if (parser.TryConsume('@'))
- {
- var ident = parser.ParseIdentifier("-");
- var value = parser.ReadToEol().Trim();
- if (value == "@@")
- {
- parser.Advance(1);
- value = "";
- while (true)
- {
- var l = parser.ReadToEol();
- if (l == "@@")
- break;
- else
- value = value.Length == 0 ? l : (value + "\n" + l);
- parser.Advance(1);
- }
-
- }
- rv.Add(new AstAttributeNode(ident, value));
- }
- else
- return rv;
- }
-
- return rv;
- }
-
- static AstAttributes ParseLocalAttributes(ref TokenParser parser)
- {
- var rv = new AstAttributes();
- while (parser.TryConsume("["))
- {
- while (!parser.TryConsume("]") && !parser.Eof)
- {
- if (parser.TryConsume(','))
- continue;
-
- // Get identifier
- var ident = parser.ParseIdentifier("-");
-
- // No value, end of attribute list
- if (parser.TryConsume(']'))
- {
- rv.Add(new AstAttributeNode(ident, null));
- break;
- }
- // No value, next attribute
- else if (parser.TryConsume(','))
- rv.Add(new AstAttributeNode(ident, null));
- // Has value
- else if (parser.TryConsume('('))
- {
- var value = parser.ReadTo(')');
- parser.Consume(')');
- rv.Add(new AstAttributeNode(ident, value));
- }
- else
- throw new ParseException("Unexpected character", ref parser);
- }
-
- if (parser.Eof)
- throw new ParseException("Unexpected EOF", ref parser);
- }
-
- return rv;
- }
-
- static void EnsureOpenBracket(ref TokenParser parser)
- {
- if (!parser.TryConsume('{'))
- throw new ParseException("{ expected", ref parser);
- }
-
- static AstEnumNode ParseEnum(AstAttributes attrs, ref TokenParser parser)
- {
- var name = parser.ParseIdentifier();
- EnsureOpenBracket(ref parser);
- var rv = new AstEnumNode { Name = name, Attributes = attrs };
- while (!parser.TryConsume('}') && !parser.Eof)
- {
- if (parser.TryConsume(','))
- continue;
-
- var ident = parser.ParseIdentifier();
-
- // Automatic value
- if (parser.TryConsume(',') || parser.Peek == '}')
- {
- rv.Add(new AstEnumMemberNode(ident, null));
- continue;
- }
-
- if (!parser.TryConsume('='))
- throw new ParseException("Unexpected character", ref parser);
-
- var value = parser.ReadToAny(",}").Trim();
- rv.Add(new AstEnumMemberNode(ident, value));
-
- if (parser.Eof)
- throw new ParseException("Unexpected EOF", ref parser);
- }
-
-
- return rv;
- }
-
- static AstTypeNode ParseType(ref TokenParser parser)
- {
- var ident = parser.ParseIdentifier();
- var t = new AstTypeNode { Name = ident };
- while (parser.TryConsume('*'))
- t.PointerLevel++;
- if (parser.TryConsume("&"))
- t.IsLink = true;
- return t;
- }
-
- static AstStructNode ParseStruct(AstAttributes attrs, ref TokenParser parser)
- {
- var name = parser.ParseIdentifier();
- EnsureOpenBracket(ref parser);
- var rv = new AstStructNode { Name = name, Attributes = attrs };
- while (!parser.TryConsume('}') && !parser.Eof)
- {
- var memberAttrs = ParseLocalAttributes(ref parser);
- var t = ParseType(ref parser);
- bool parsedAtLeastOneMember = false;
- while (!parser.TryConsume(';'))
- {
- // Skip any ,
- while (parser.TryConsume(',')) { }
-
- var ident = parser.ParseIdentifier();
- parsedAtLeastOneMember = true;
- rv.Add(new AstStructMemberNode { Name = ident, Type = t, Attributes = memberAttrs});
- }
-
- if (!parsedAtLeastOneMember)
- throw new ParseException("Expected at least one enum member with declared type " + t, ref parser);
- }
-
- return rv;
- }
-
- static AstInterfaceNode ParseInterface(AstAttributes interfaceAttrs, ref TokenParser parser)
- {
- var interfaceName = parser.ParseIdentifier();
- string inheritsFrom = null;
- if (parser.TryConsume(":"))
- inheritsFrom = parser.ParseIdentifier();
-
- EnsureOpenBracket(ref parser);
- var rv = new AstInterfaceNode
- {
- Name = interfaceName, Attributes = interfaceAttrs, Inherits = inheritsFrom
- };
- while (!parser.TryConsume('}') && !parser.Eof)
- {
- var memberAttrs = ParseLocalAttributes(ref parser);
- var returnType = ParseType(ref parser);
- var name = parser.ParseIdentifier();
- var member = new AstInterfaceMemberNode
- {
- Name = name, ReturnType = returnType, Attributes = memberAttrs
- };
- rv.Add(member);
-
- parser.Consume('(');
- while (true)
- {
- if (parser.TryConsume(')'))
- break;
-
- var argumentAttrs = ParseLocalAttributes(ref parser);
- var type = ParseType(ref parser);
- var argName = parser.ParseIdentifier();
- member.Add(new AstInterfaceMemberArgumentNode
- {
- Name = argName, Type = type, Attributes = argumentAttrs
- });
-
- if (parser.TryConsume(')'))
- break;
- if (parser.TryConsume(','))
- continue;
- throw new ParseException("Unexpected character", ref parser);
- }
-
- parser.Consume(';');
- }
-
- return rv;
- }
- }
-}
diff --git a/src/tools/MicroComGenerator/CSharpGen.InterfaceGen.cs b/src/tools/MicroComGenerator/CSharpGen.InterfaceGen.cs
deleted file mode 100644
index adb8faf938..0000000000
--- a/src/tools/MicroComGenerator/CSharpGen.InterfaceGen.cs
+++ /dev/null
@@ -1,484 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using MicroComGenerator.Ast;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
-
-// ReSharper disable CoVariantArrayConversion
-
-// HERE BE DRAGONS
-
-namespace MicroComGenerator
-{
- public partial class CSharpGen
- {
- abstract class Arg
- {
- public string Name;
- public string NativeType;
- public AstAttributes Attributes { get; set; }
- public virtual StatementSyntax CreateFixed(StatementSyntax inner) => inner;
-
- public virtual void PreMarshal(List body)
- {
- }
-
- public virtual void PreMarshalForReturn(List body) =>
- throw new InvalidOperationException("Don't know how to use " + NativeType + " as HRESULT-return");
-
- public virtual ExpressionSyntax Value(bool isHresultReturn) => ParseExpression(Name);
- public abstract string ManagedType { get; }
- public virtual string ReturnManagedType => ManagedType;
-
- public virtual StatementSyntax[] ReturnMarshalResult() => new[] { ParseStatement("return " + Name + ";") };
-
-
- public virtual void BackPreMarshal(List body)
- {
- }
-
- public virtual ExpressionSyntax BackMarshalValue() => ParseExpression(Name);
- public virtual ExpressionSyntax BackMarshalReturn(string resultVar) => ParseExpression(resultVar);
-
- }
-
- class InterfaceReturnArg : Arg
- {
- public string InterfaceType;
- public override ExpressionSyntax Value(bool isHresultReturn) => ParseExpression("&" + PName);
- public override string ManagedType => InterfaceType;
-
- private string PName => "__marshal_" + Name;
-
- public override void PreMarshalForReturn(List body)
- {
- body.Add(ParseStatement("void* " + PName + " = null;"));
- }
-
- public override StatementSyntax[] ReturnMarshalResult() => new[]
- {
- ParseStatement("return Avalonia.MicroCom.MicroComRuntime.CreateProxyFor<" + InterfaceType + ">(" +
- PName + ", true);")
- };
-
- public override ExpressionSyntax BackMarshalValue()
- {
- return ParseExpression("INVALID");
- }
-
- public override ExpressionSyntax BackMarshalReturn(string resultVar)
- {
- return ParseExpression($"Avalonia.MicroCom.MicroComRuntime.GetNativePointer({resultVar}, true)");
- }
- }
-
- class InterfaceArg : Arg
- {
- public string InterfaceType;
-
- public override ExpressionSyntax Value(bool isHresultReturn) =>
- ParseExpression("Avalonia.MicroCom.MicroComRuntime.GetNativePointer(" + Name + ")");
-
- public override string ManagedType => InterfaceType;
-
- public override StatementSyntax[] ReturnMarshalResult() => new[]
- {
- ParseStatement("return Avalonia.MicroCom.MicroComRuntime.CreateProxyFor<" + InterfaceType + ">(" +
- Name + ", true);")
- };
-
- public override ExpressionSyntax BackMarshalValue()
- {
- return ParseExpression("Avalonia.MicroCom.MicroComRuntime.CreateProxyFor<" + InterfaceType + ">(" +
- Name + ", false)");
- }
-
- public override ExpressionSyntax BackMarshalReturn(string resultVar)
- {
- return ParseExpression($"Avalonia.MicroCom.MicroComRuntime.GetNativePointer({resultVar}, true)");
- }
- }
-
- class BypassArg : Arg
- {
- public string Type { get; set; }
- public int PointerLevel;
- public override string ManagedType => Type + new string('*', PointerLevel);
- public override string ReturnManagedType => Type + new string('*', PointerLevel - 1);
-
- public override ExpressionSyntax Value(bool isHresultReturn)
- {
- if (isHresultReturn)
- return ParseExpression("&" + Name);
- return base.Value(false);
- }
-
- public override void PreMarshalForReturn(List body)
- {
- if (PointerLevel == 0)
- base.PreMarshalForReturn(body);
- else
- body.Add(ParseStatement(Type + new string('*', PointerLevel - 1) + " " + Name + "=default;"));
- }
- }
-
- class StringArg : Arg
- {
- private string BName => "__bytemarshal_" + Name;
- private string FName => "__fixedmarshal_" + Name;
-
- public override void PreMarshal(List body)
- {
- body.Add(ParseStatement($"var {BName} = new byte[System.Text.Encoding.UTF8.GetByteCount({Name})+1];"));
- body.Add(ParseStatement($"System.Text.Encoding.UTF8.GetBytes({Name}, 0, {Name}.Length, {BName}, 0);"));
- }
-
- public override StatementSyntax CreateFixed(StatementSyntax inner)
- {
- return FixedStatement(DeclareVar("byte*", FName, ParseExpression(BName)), inner);
- }
-
- public override ExpressionSyntax Value(bool isHresultReturn) => ParseExpression(FName);
- public override string ManagedType => "string";
- public override ExpressionSyntax BackMarshalValue()
- {
- return ParseExpression(
- $"({Name} == null ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(new IntPtr(" + Name + ")))");
- }
- }
-
- string ConvertNativeType(string type)
- {
- if (type == "size_t")
- return "System.IntPtr";
- if (type == "HRESULT")
- return "int";
- return type;
- }
-
- Arg ConvertArg(AstInterfaceMemberArgumentNode node)
- {
- var arg = ConvertArg(node.Name, node.Type);
- arg.Attributes = node.Attributes.Clone();
- return arg;
- }
-
- Arg ConvertArg(string name, AstTypeNode type)
- {
- type = new AstTypeNode { Name = ConvertNativeType(type.Name), PointerLevel = type.PointerLevel };
-
- if (type.PointerLevel == 2)
- {
- if (IsInterface(type))
- return new InterfaceReturnArg { Name = name, InterfaceType = type.Name, NativeType = "void**" };
- }
- else if (type.PointerLevel == 1)
- {
- if (IsInterface(type))
- return new InterfaceArg { Name = name, InterfaceType = type.Name, NativeType = "void*" };
- if (type.Name == "char")
- return new StringArg { Name = name, NativeType = "byte*" };
- }
-
- return new BypassArg
- {
- Name = name, Type = type.Name, PointerLevel = type.PointerLevel, NativeType = type.ToString()
- };
- }
-
-
- void GenerateInterfaceMember(AstInterfaceMemberNode member, ref InterfaceDeclarationSyntax iface,
- ref ClassDeclarationSyntax proxy, ref ClassDeclarationSyntax vtbl,
- List vtblCtor, int num)
- {
- // Prepare method information
- if (member.Name == "GetRenderingDevice")
- Console.WriteLine();
- var args = member.Select(ConvertArg).ToList();
- var returnArg = ConvertArg("__result", member.ReturnType);
- bool isHresult = member.ReturnType.Name == "HRESULT";
- bool isHresultLastArgumentReturn = isHresult
- && args.Count > 0
- && (args.Last().Name == "ppv"
- || args.Last().Name == "retOut"
- || args.Last().Name == "ret"
- || args.Last().Attributes.HasAttribute("out")
- || args.Last().Attributes.HasAttribute("retval")
- )
- && ((member.Last().Type.PointerLevel > 0
- && !IsInterface(member.Last().Type))
- || member.Last().Type.PointerLevel == 2);
-
- bool isVoidReturn = member.ReturnType.Name == "void" && member.ReturnType.PointerLevel == 0;
-
-
- // Generate method signature
- MethodDeclarationSyntax GenerateManagedSig(string returnType, string name,
- IEnumerable<(string n, string t)> args)
- => MethodDeclaration(ParseTypeName(returnType), name).WithParameterList(
- ParameterList(
- SeparatedList(args.Select(x => Parameter(Identifier(x.n)).WithType(ParseTypeName(x.t))))));
-
- var managedSig =
- isHresult ?
- GenerateManagedSig(isHresultLastArgumentReturn ? args.Last().ReturnManagedType : "void",
- member.Name,
- (isHresultLastArgumentReturn ? args.SkipLast(1) : args).Select(a => (a.Name, a.ManagedType))) :
- GenerateManagedSig(returnArg.ManagedType, member.Name, args.Select(a => (a.Name, a.ManagedType)));
-
- iface = iface.AddMembers(managedSig.WithSemicolonToken(Semicolon()));
-
- // Prepare args for marshaling
- var preMarshal = new List();
- if (!isVoidReturn)
- preMarshal.Add(ParseStatement(returnArg.NativeType + " __result;"));
-
- for (var idx = 0; idx < args.Count; idx++)
- {
- if (isHresultLastArgumentReturn && idx == args.Count - 1)
- args[idx].PreMarshalForReturn(preMarshal);
- else
- args[idx].PreMarshal(preMarshal);
- }
-
- // Generate call expression
- ExpressionSyntax callExpr = InvocationExpression(_localInterop.GetCaller(returnArg.NativeType,
- args.Select(x => x.NativeType).ToList()))
- .AddArgumentListArguments(Argument(ParseExpression("PPV")))
- .AddArgumentListArguments(args
- .Select((a, i) => Argument(a.Value(isHresultLastArgumentReturn && i == args.Count - 1))).ToArray())
- .AddArgumentListArguments(Argument(ParseExpression("(*PPV)[base.VTableSize + " + num + "]")));
-
- if (!isVoidReturn)
- callExpr = CastExpression(ParseTypeName(returnArg.NativeType), callExpr);
-
- // Save call result if needed
- if (!isVoidReturn)
- callExpr = AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, ParseExpression("__result"),
- callExpr);
-
-
- // Wrap call into fixed() blocks
- StatementSyntax callStatement = ExpressionStatement(callExpr);
- foreach (var arg in args)
- callStatement = arg.CreateFixed(callStatement);
-
- // Build proxy body
- var proxyBody = Block()
- .AddStatements(preMarshal.ToArray())
- .AddStatements(callStatement);
-
- // Process return value
- if (!isVoidReturn)
- {
- if (isHresult)
- {
- proxyBody = proxyBody.AddStatements(
- ParseStatement(
- $"if(__result != 0) throw new System.Runtime.InteropServices.COMException(\"{member.Name} failed\", __result);"));
-
- if (isHresultLastArgumentReturn)
- proxyBody = proxyBody.AddStatements(args.Last().ReturnMarshalResult());
- }
- else
- proxyBody = proxyBody.AddStatements(returnArg.ReturnMarshalResult());
- }
-
- // Add the proxy method
- proxy = proxy.AddMembers(managedSig.AddModifiers(SyntaxKind.PublicKeyword)
- .WithBody(proxyBody));
-
-
- // Generate VTable method
- var shadowDelegate = DelegateDeclaration(ParseTypeName(returnArg.NativeType), member.Name + "Delegate")
- .AddParameterListParameters(Parameter(Identifier("@this")).WithType(ParseTypeName("IntPtr")))
- .AddParameterListParameters(args.Select(x =>
- Parameter(Identifier(x.Name)).WithType(ParseTypeName(x.NativeType))).ToArray())
- .AddAttribute("System.Runtime.InteropServices.UnmanagedFunctionPointer",
- "System.Runtime.InteropServices.CallingConvention.StdCall");
-
- var shadowMethod = MethodDeclaration(shadowDelegate.ReturnType, member.Name)
- .WithParameterList(shadowDelegate.ParameterList)
- .AddModifiers(Token(SyntaxKind.StaticKeyword));
-
- var backPreMarshal = new List();
- foreach (var arg in args)
- arg.BackPreMarshal(backPreMarshal);
-
- backPreMarshal.Add(
- ParseStatement($"__target = ({iface.Identifier.Text})Avalonia.MicroCom.MicroComRuntime.GetObjectFromCcw(@this);"));
-
- var isBackVoidReturn = isVoidReturn || (isHresult && !isHresultLastArgumentReturn);
-
- StatementSyntax backCallStatement;
-
- var backCallExpr =
- IsPropertyRewriteCandidate(managedSig) ?
- ParseExpression("__target." + member.Name.Substring(3)) :
- InvocationExpression(ParseExpression("__target." + member.Name))
- .WithArgumentList(ArgumentList(SeparatedList(
- (isHresultLastArgumentReturn ? args.SkipLast(1) : args)
- .Select(a =>
- Argument(a.BackMarshalValue())))));
-
- if (isBackVoidReturn)
- backCallStatement = ExpressionStatement(backCallExpr);
- else
- {
- backCallStatement = LocalDeclarationStatement(DeclareVar("var", "__result", backCallExpr));
- if (isHresultLastArgumentReturn)
- {
- backCallStatement = Block(backCallStatement,
- ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
- ParseExpression("*" + args.Last().Name),
- args.Last().BackMarshalReturn("__result")
- )));
-
- }
- else
- backCallStatement = Block(backCallStatement,
- ReturnStatement(returnArg.BackMarshalReturn("__result")));
- }
-
- BlockSyntax backBodyBlock = Block().AddStatements(backPreMarshal.ToArray()).AddStatements(backCallStatement);
-
-
- var exceptions = new List()
- {
- CatchClause(
- CatchDeclaration(ParseTypeName("System.Exception"), Identifier("__exception__")), null,
- Block(
- ParseStatement(
- "Avalonia.MicroCom.MicroComRuntime.UnhandledException(__target, __exception__);"),
- isHresult ? ParseStatement("return unchecked((int)0x80004005u);")
- : isVoidReturn ? EmptyStatement() : ParseStatement("return default;")
- ))
- };
-
- if (isHresult)
- exceptions.Insert(0, CatchClause(
- CatchDeclaration(ParseTypeName("System.Runtime.InteropServices.COMException"),
- Identifier("__com_exception__")),
- null, Block(ParseStatement("return __com_exception__.ErrorCode;"))));
-
- backBodyBlock = Block(
- TryStatement(
- List(exceptions))
- .WithBlock(Block(backBodyBlock))
- );
- if (isHresult)
- backBodyBlock = backBodyBlock.AddStatements(ParseStatement("return 0;"));
-
-
- backBodyBlock = Block()
- .AddStatements(ParseStatement($"{iface.Identifier.Text} __target = null;"))
- .AddStatements(backBodyBlock.Statements.ToArray());
-
- shadowMethod = shadowMethod.WithBody(backBodyBlock);
-
- vtbl = vtbl.AddMembers(shadowDelegate).AddMembers(shadowMethod);
- vtblCtor.Add(ParseStatement("base.AddMethod((" + shadowDelegate.Identifier.Text + ")" +
- shadowMethod.Identifier.Text + ");"));
-
-
-
-
- }
-
- class LocalInteropHelper
- {
- public ClassDeclarationSyntax Class { get; private set; } = ClassDeclaration("LocalInterop");
- private HashSet _existing = new HashSet();
-
- public ExpressionSyntax GetCaller(string returnType, List args)
- {
- string ConvertType(string t) => t.EndsWith("*") ? "void*" : t;
- returnType = ConvertType(returnType);
- args = args.Select(ConvertType).ToList();
-
- var name = "CalliStdCall" + returnType.Replace("*", "_ptr");
- var signature = returnType + "::" + name + "::" + string.Join("::", args);
- if (_existing.Add(signature))
- {
- Class = Class.AddMembers(MethodDeclaration(ParseTypeName(returnType), name)
- .AddModifiers(SyntaxKind.StaticKeyword, SyntaxKind.UnsafeKeyword, SyntaxKind.PublicKeyword)
- .AddParameterListParameters(Parameter(Identifier("thisObj")).WithType(ParseTypeName("void*")))
- .AddParameterListParameters(args.Select((x, i) =>
- Parameter(Identifier("arg" + i)).WithType(ParseTypeName(x))).ToArray())
- .AddParameterListParameters(Parameter(Identifier("methodPtr")).WithType(ParseTypeName("void*")))
- .WithBody(Block(ExpressionStatement(ThrowExpression(ParseExpression("null"))))));
- }
-
- return ParseExpression("LocalInterop." + name);
- }
- }
-
-
- void GenerateInterface(ref NamespaceDeclarationSyntax ns, ref NamespaceDeclarationSyntax implNs,
- AstInterfaceNode iface)
- {
- var guidString = iface.GetAttribute("uuid");
- var inheritsUnknown = iface.Inherits == null || iface.Inherits == "IUnknown";
-
- var ifaceDec = InterfaceDeclaration(iface.Name)
- .WithBaseType(inheritsUnknown ? "Avalonia.MicroCom.IUnknown" : iface.Inherits)
- .AddModifiers(Token(_visibility), Token(SyntaxKind.UnsafeKeyword), Token(SyntaxKind.PartialKeyword));
-
- var proxyClassName = "__MicroCom" + iface.Name + "Proxy";
- var proxy = ClassDeclaration(proxyClassName)
- .AddModifiers(Token(SyntaxKind.UnsafeKeyword), Token(_visibility), Token(SyntaxKind.PartialKeyword))
- .WithBaseType(inheritsUnknown ?
- "Avalonia.MicroCom.MicroComProxyBase" :
- ("__MicroCom" + iface.Inherits + "Proxy"))
- .AddBaseListTypes(SimpleBaseType(ParseTypeName(iface.Name)));
-
-
- // Generate vtable
- var vtbl = ClassDeclaration("__MicroCom" + iface.Name + "VTable")
- .AddModifiers(Token(SyntaxKind.UnsafeKeyword));
-
- vtbl = vtbl.WithBaseType(inheritsUnknown ?
- "Avalonia.MicroCom.MicroComVtblBase" :
- "__MicroCom" + iface.Inherits + "VTable");
-
- var vtblCtor = new List();
- for (var idx = 0; idx < iface.Count; idx++)
- GenerateInterfaceMember(iface[idx], ref ifaceDec, ref proxy, ref vtbl, vtblCtor, idx);
-
- vtbl = vtbl.AddMembers(
- ConstructorDeclaration(vtbl.Identifier.Text)
- .AddModifiers(Token(SyntaxKind.PublicKeyword))
- .WithBody(Block(vtblCtor))
- )
- .AddMembers(MethodDeclaration(ParseTypeName("void"), "__MicroComModuleInit")
- .AddModifiers(Token(SyntaxKind.StaticKeyword), Token(SyntaxKind.InternalKeyword))
- .WithExpressionBody(ArrowExpressionClause(
- ParseExpression("Avalonia.MicroCom.MicroComRuntime.RegisterVTable(typeof(" +
- iface.Name + "), new " + vtbl.Identifier.Text + "().CreateVTable())")))
- .WithSemicolonToken(Semicolon()));
-
-
- // Finalize proxy code
- proxy = proxy.AddMembers(
- MethodDeclaration(ParseTypeName("void"), "__MicroComModuleInit")
- .AddModifiers(Token(SyntaxKind.StaticKeyword), Token(SyntaxKind.InternalKeyword))
- .WithBody(Block(
- ParseStatement("Avalonia.MicroCom.MicroComRuntime.Register(typeof(" +
- iface.Name + "), new Guid(\"" + guidString + "\"), (p, owns) => new " +
- proxyClassName + "(p, owns));")
- )))
- .AddMembers(ParseMemberDeclaration("public " + proxyClassName +
- "(IntPtr nativePointer, bool ownsHandle) : base(nativePointer, ownsHandle) {}"))
- .AddMembers(ParseMemberDeclaration("protected override int VTableSize => base.VTableSize + " +
- iface.Count + ";"));
-
- ns = ns.AddMembers(RewriteMethodsToProperties(ifaceDec));
- implNs = implNs.AddMembers(RewriteMethodsToProperties(proxy), RewriteMethodsToProperties(vtbl));
- }
- }
-}
diff --git a/src/tools/MicroComGenerator/CSharpGen.Utils.cs b/src/tools/MicroComGenerator/CSharpGen.Utils.cs
deleted file mode 100644
index 28baaa65f8..0000000000
--- a/src/tools/MicroComGenerator/CSharpGen.Utils.cs
+++ /dev/null
@@ -1,111 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using MicroComGenerator.Ast;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Formatting;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-
-using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
-namespace MicroComGenerator
-{
- public partial class CSharpGen
- {
-
- CompilationUnitSyntax Unit()
- => CompilationUnit().WithUsings(List(new[]
- {
- "System", "System.Text", "System.Collections", "System.Collections.Generic", "Avalonia.MicroCom"
- }
- .Concat(_extraUsings).Select(u => UsingDirective(IdentifierName(u)))));
-
- string Format(CompilationUnitSyntax unit)
- {
- var cw = new AdhocWorkspace();
- return
- "#pragma warning disable 108\n" +
- Microsoft.CodeAnalysis.Formatting.Formatter.Format(unit.NormalizeWhitespace(), cw, cw.Options
- .WithChangedOption(CSharpFormattingOptions.NewLineForMembersInObjectInit, true)
- .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInObjectCollectionArrayInitializers,
- true)
- .WithChangedOption(CSharpFormattingOptions.NewLineForMembersInAnonymousTypes, true)
- .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInMethods, true)
-
- ).ToFullString();
- }
-
-
- SyntaxToken Semicolon() => Token(SyntaxKind.SemicolonToken);
-
- static VariableDeclarationSyntax DeclareVar(string type, string name,
- ExpressionSyntax initializer = null)
- => VariableDeclaration(ParseTypeName(type),
- SingletonSeparatedList(VariableDeclarator(name)
- .WithInitializer(initializer == null ? null : EqualsValueClause(initializer))));
-
- FieldDeclarationSyntax DeclareConstant(string type, string name, LiteralExpressionSyntax value)
- => FieldDeclaration(
- VariableDeclaration(ParseTypeName(type),
- SingletonSeparatedList(
- VariableDeclarator(name).WithInitializer(EqualsValueClause(value))
- ))
- ).WithSemicolonToken(Semicolon())
- .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.ConstKeyword)));
-
- FieldDeclarationSyntax DeclareField(string type, string name, params SyntaxKind[] modifiers) =>
- DeclareField(type, name, null, modifiers);
-
- FieldDeclarationSyntax DeclareField(string type, string name, EqualsValueClauseSyntax initializer,
- params SyntaxKind[] modifiers) =>
- FieldDeclaration(
- VariableDeclaration(ParseTypeName(type),
- SingletonSeparatedList(
- VariableDeclarator(name).WithInitializer(initializer))))
- .WithSemicolonToken(Semicolon())
- .WithModifiers(TokenList(modifiers.Select(x => Token(x))));
-
- bool IsPropertyRewriteCandidate(MethodDeclarationSyntax method)
- {
-
- return
- method.ReturnType.ToFullString() != "void"
- && method.Identifier.Text.StartsWith("Get")
- && method.ParameterList.Parameters.Count == 0;
- }
-
- TypeDeclarationSyntax RewriteMethodsToProperties(T decl) where T : TypeDeclarationSyntax
- {
- var replace = new Dictionary();
- foreach (var method in decl.Members.OfType().ToList())
- {
- if (IsPropertyRewriteCandidate(method))
- {
- var getter = AccessorDeclaration(SyntaxKind.GetAccessorDeclaration);
- if (method.Body != null)
- getter = getter.WithBody(method.Body);
- else
- getter = getter.WithSemicolonToken(Semicolon());
-
- replace[method] = PropertyDeclaration(method.ReturnType,
- method.Identifier.Text.Substring(3))
- .WithModifiers(method.Modifiers).AddAccessorListAccessors(getter);
-
- }
- }
-
- return decl.ReplaceNodes(replace.Keys, (m, m2) => replace[m]);
- }
-
- bool IsInterface(string name)
- {
- if (name == "IUnknown")
- return true;
- return _idl.Interfaces.Any(i => i.Name == name);
- }
-
- private bool IsInterface(AstTypeNode type) => IsInterface(type.Name);
-
- }
-}
diff --git a/src/tools/MicroComGenerator/CSharpGen.cs b/src/tools/MicroComGenerator/CSharpGen.cs
deleted file mode 100644
index ff4c351fd9..0000000000
--- a/src/tools/MicroComGenerator/CSharpGen.cs
+++ /dev/null
@@ -1,155 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Runtime.CompilerServices;
-using MicroComGenerator.Ast;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
-// ReSharper disable CoVariantArrayConversion
-
-namespace MicroComGenerator
-{
- public partial class CSharpGen
- {
- private readonly AstIdlNode _idl;
- private List _extraUsings;
- private string _namespace;
- private SyntaxKind _visibility;
- private LocalInteropHelper _localInterop = new LocalInteropHelper();
-
- public CSharpGen(AstIdlNode idl)
- {
- _idl = idl.Clone();
- new AstRewriter(_idl.Attributes.Where(a => a.Name == "clr-map")
- .Select(x => x.Value.Trim().Split(' '))
- .ToDictionary(x => x[0], x => x[1])
- ).VisitAst(_idl);
-
- _extraUsings = _idl.Attributes.Where(u => u.Name == "clr-using").Select(u => u.Value).ToList();
- _namespace = _idl.GetAttribute("clr-namespace");
- var visibilityString = _idl.GetAttribute("clr-access");
-
- if (visibilityString == "internal")
- _visibility = SyntaxKind.InternalKeyword;
- else if (visibilityString == "public")
- _visibility = SyntaxKind.PublicKeyword;
- else
- throw new CodeGenException("Invalid clr-access attribute");
- }
-
- class AstRewriter : AstVisitor
- {
- private readonly Dictionary _typeMap = new Dictionary();
-
- public AstRewriter(Dictionary typeMap)
- {
- _typeMap = typeMap;
- }
-
- void ConvertIntPtr(AstTypeNode type)
- {
- if (type.Name == "void" && type.PointerLevel > 0)
- {
- type.Name = "IntPtr";
- type.PointerLevel--;
- }
- }
-
- protected override void VisitStructMember(AstStructMemberNode member)
- {
- if (member.HasAttribute("intptr"))
- ConvertIntPtr(member.Type);
- base.VisitStructMember(member);
- }
-
- protected override void VisitType(AstTypeNode type)
- {
- if (type.IsLink)
- {
- type.PointerLevel++;
- type.IsLink = false;
- }
-
- if (_typeMap.TryGetValue(type.Name, out var mapped))
- type.Name = mapped;
-
- base.VisitType(type);
- }
-
- protected override void VisitArgument(AstInterfaceMemberArgumentNode argument)
- {
- if (argument.HasAttribute("intptr"))
- {
- if(argument.Name == "retOut")
- Console.WriteLine();
- ConvertIntPtr(argument.Type);
- }
-
- base.VisitArgument(argument);
- }
-
- protected override void VisitInterfaceMember(AstInterfaceMemberNode member)
- {
- if (member.HasAttribute("intptr"))
- ConvertIntPtr(member.ReturnType);
- if (member.HasAttribute("propget") && !member.Name.StartsWith("Get"))
- member.Name = "Get" + member.Name;
- if (member.HasAttribute("propput") && !member.Name.StartsWith("Set"))
- member.Name = "Set" + member.Name;
- base.VisitInterfaceMember(member);
- }
- }
-
-
- public string Generate()
- {
- var ns = NamespaceDeclaration(ParseName(_namespace));
- var implNs = NamespaceDeclaration(ParseName(_namespace + ".Impl"));
- ns = GenerateEnums(ns);
- ns = GenerateStructs(ns);
- foreach (var i in _idl.Interfaces)
- GenerateInterface(ref ns, ref implNs, i);
-
- implNs = implNs.AddMembers(_localInterop.Class);
- var unit = Unit().AddMembers(ns, implNs);
-
- return Format(unit);
- }
-
- NamespaceDeclarationSyntax GenerateEnums(NamespaceDeclarationSyntax ns)
- {
- return ns.AddMembers(_idl.Enums.Select(e =>
- {
- var dec = EnumDeclaration(e.Name)
- .WithModifiers(TokenList(Token(_visibility)))
- .WithMembers(SeparatedList(e.Select(m =>
- {
- var member = EnumMemberDeclaration(m.Name);
- if (m.Value != null)
- return member.WithEqualsValue(EqualsValueClause(ParseExpression(m.Value)));
- return member;
- })));
- if (e.HasAttribute("flags"))
- dec = dec.AddAttribute("System.Flags");
- return dec;
- }).ToArray());
- }
-
- NamespaceDeclarationSyntax GenerateStructs(NamespaceDeclarationSyntax ns)
- {
- return ns.AddMembers(_idl.Structs.Select(e =>
- StructDeclaration(e.Name)
- .WithModifiers(TokenList(Token(_visibility)))
- .AddAttribute("System.Runtime.InteropServices.StructLayout", "System.Runtime.InteropServices.LayoutKind.Sequential")
- .AddModifiers(Token(SyntaxKind.UnsafeKeyword))
- .WithMembers(new SyntaxList(SeparatedList(e.Select(m =>
- DeclareField(m.Type.ToString(), m.Name, SyntaxKind.PublicKeyword)))))
- ).ToArray());
- }
-
-
-
- }
-}
diff --git a/src/tools/MicroComGenerator/CppGen.cs b/src/tools/MicroComGenerator/CppGen.cs
deleted file mode 100644
index b053088ca9..0000000000
--- a/src/tools/MicroComGenerator/CppGen.cs
+++ /dev/null
@@ -1,119 +0,0 @@
-using System;
-using System.Linq;
-using System.Text;
-using MicroComGenerator.Ast;
-
-namespace MicroComGenerator
-{
- public class CppGen
- {
- static string ConvertType(AstTypeNode type)
- {
- var name = type.Name;
- if (name == "byte")
- name = "unsigned char";
- else if(name == "uint")
- name = "unsigned int";
-
- type = type.Clone();
- type.Name = name;
- return type.Format();
- }
-
- public static string GenerateCpp(AstIdlNode idl)
- {
- var sb = new StringBuilder();
- var preamble = idl.GetAttributeOrDefault("cpp-preamble");
- if (preamble != null)
- sb.AppendLine(preamble);
-
- foreach (var s in idl.Structs)
- sb.AppendLine("struct " + s.Name + ";");
-
- foreach (var s in idl.Interfaces)
- sb.AppendLine("struct " + s.Name + ";");
-
- foreach (var en in idl.Enums)
- {
- sb.Append("enum ");
- if (en.Attributes.Any(a => a.Name == "class-enum"))
- sb.Append("class ");
- sb.AppendLine(en.Name).AppendLine("{");
-
- foreach (var m in en)
- {
- sb.Append(" ").Append(m.Name);
- if (m.Value != null)
- sb.Append(" = ").Append(m.Value);
- sb.AppendLine(",");
- }
-
- sb.AppendLine("};");
- }
-
- foreach (var s in idl.Structs)
- {
- sb.Append("struct ").AppendLine(s.Name).AppendLine("{");
- foreach (var m in s)
- sb.Append(" ").Append(ConvertType(m.Type)).Append(" ").Append(m.Name).AppendLine(";");
-
- sb.AppendLine("};");
- }
-
- foreach (var i in idl.Interfaces)
- {
- var guidString = i.GetAttribute("uuid");
- var guid = Guid.Parse(guidString).ToString().Replace("-", "");
-
-
- sb.Append("COMINTERFACE(").Append(i.Name).Append(", ")
- .Append(guid.Substring(0, 8)).Append(", ")
- .Append(guid.Substring(8, 4)).Append(", ")
- .Append(guid.Substring(12, 4));
- for (var c = 0; c < 8; c++)
- {
- sb.Append(", ").Append(guid.Substring(16 + c * 2, 2));
- }
-
- sb.Append(") : ");
- if (i.HasAttribute("cpp-virtual-inherits"))
- sb.Append("virtual ");
- sb.AppendLine(i.Inherits ?? "IUnknown")
- .AppendLine("{");
-
- foreach (var m in i)
- {
- sb.Append(" ")
- .Append("virtual ")
- .Append(ConvertType(m.ReturnType))
- .Append(" ").Append(m.Name).Append(" (");
- if (m.Count == 0)
- sb.AppendLine(") = 0;");
- else
- {
- sb.AppendLine();
- for (var c = 0; c < m.Count; c++)
- {
- var arg = m[c];
- sb.Append(" ");
- if (arg.Attributes.Any(a => a.Name == "const"))
- sb.Append("const ");
- sb.Append(ConvertType(arg.Type))
- .Append(" ")
- .Append(arg.Name);
- if (c != m.Count - 1)
- sb.Append(", ");
- sb.AppendLine();
- }
-
- sb.AppendLine(" ) = 0;");
- }
- }
-
- sb.AppendLine("};");
- }
-
- return sb.ToString();
- }
- }
-}
diff --git a/src/tools/MicroComGenerator/Extensions.cs b/src/tools/MicroComGenerator/Extensions.cs
deleted file mode 100644
index c8a4c8f45c..0000000000
--- a/src/tools/MicroComGenerator/Extensions.cs
+++ /dev/null
@@ -1,97 +0,0 @@
-
-using System;
-using System.Linq;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
-namespace MicroComGenerator
-{
- public static class Extensions
- {
- public static ClassDeclarationSyntax AddModifiers(this ClassDeclarationSyntax cl, params SyntaxKind[] modifiers)
- {
- if (modifiers == null)
- return cl;
- return cl.AddModifiers(modifiers.Select(x => SyntaxFactory.Token(x)).ToArray());
- }
-
- public static MethodDeclarationSyntax AddModifiers(this MethodDeclarationSyntax cl, params SyntaxKind[] modifiers)
- {
- if (modifiers == null)
- return cl;
- return cl.AddModifiers(modifiers.Select(x => SyntaxFactory.Token(x)).ToArray());
- }
-
- public static PropertyDeclarationSyntax AddModifiers(this PropertyDeclarationSyntax cl, params SyntaxKind[] modifiers)
- {
- if (modifiers == null)
- return cl;
- return cl.AddModifiers(modifiers.Select(x => SyntaxFactory.Token(x)).ToArray());
- }
-
- public static ConstructorDeclarationSyntax AddModifiers(this ConstructorDeclarationSyntax cl, params SyntaxKind[] modifiers)
- {
- if (modifiers == null)
- return cl;
- return cl.AddModifiers(modifiers.Select(x => SyntaxFactory.Token(x)).ToArray());
- }
-
- public static AccessorDeclarationSyntax AddModifiers(this AccessorDeclarationSyntax cl, params SyntaxKind[] modifiers)
- {
- if (modifiers == null)
- return cl;
- return cl.AddModifiers(modifiers.Select(x => SyntaxFactory.Token(x)).ToArray());
- }
-
- public static string WithLowerFirst(this string s)
- {
- if (string.IsNullOrEmpty(s))
- return s;
- return char.ToLowerInvariant(s[0]) + s.Substring(1);
- }
-
- public static ExpressionSyntax MemberAccess(params string[] identifiers)
- {
- if (identifiers == null || identifiers.Length == 0)
- throw new ArgumentException();
- var expr = (ExpressionSyntax)IdentifierName(identifiers[0]);
- for (var c = 1; c < identifiers.Length; c++)
- expr = MemberAccess(expr, identifiers[c]);
- return expr;
- }
-
- public static ExpressionSyntax MemberAccess(ExpressionSyntax expr, params string[] identifiers)
- {
- foreach (var i in identifiers)
- expr = MemberAccess(expr, i);
- return expr;
- }
-
- public static MemberAccessExpressionSyntax MemberAccess(ExpressionSyntax expr, string identifier) =>
- MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, expr, IdentifierName(identifier));
-
- public static ClassDeclarationSyntax WithBaseType(this ClassDeclarationSyntax cl, string bt)
- {
- return cl.AddBaseListTypes(SimpleBaseType(SyntaxFactory.ParseTypeName(bt)));
- }
-
- public static InterfaceDeclarationSyntax WithBaseType(this InterfaceDeclarationSyntax cl, string bt)
- {
- return cl.AddBaseListTypes(SimpleBaseType(SyntaxFactory.ParseTypeName(bt)));
- }
-
- public static T AddAttribute(this T member, string attribute, params string[] args) where T : MemberDeclarationSyntax
- {
- return (T)member.AddAttributeLists(AttributeList(SingletonSeparatedList(
- Attribute(ParseName(attribute), AttributeArgumentList(
- SeparatedList(args.Select(a => AttributeArgument(ParseExpression(a)))))))));
- }
-
- public static string StripPrefix(this string s, string prefix) => string.IsNullOrEmpty(s)
- ? s
- : s.StartsWith(prefix)
- ? s.Substring(prefix.Length)
- : s;
- }
-}
diff --git a/src/tools/MicroComGenerator/MicroComGenerator.csproj b/src/tools/MicroComGenerator/MicroComGenerator.csproj
deleted file mode 100644
index 68895b96ca..0000000000
--- a/src/tools/MicroComGenerator/MicroComGenerator.csproj
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
- Exe
- net6.0
-
-
-
-
-
-
diff --git a/src/tools/MicroComGenerator/ParseException.cs b/src/tools/MicroComGenerator/ParseException.cs
deleted file mode 100644
index cb54918100..0000000000
--- a/src/tools/MicroComGenerator/ParseException.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using System;
-
-namespace MicroComGenerator
-{
- class ParseException : Exception
- {
- public int Line { get; }
- public int Position { get; }
-
- public ParseException(string message, int line, int position) : base($"({line}, {position}) {message}")
- {
- Line = line;
- Position = position;
- }
-
- public ParseException(string message, ref TokenParser parser) : this(message, parser.Line, parser.Position)
- {
- }
- }
-
- class CodeGenException : Exception
- {
- public CodeGenException(string message) : base(message)
- {
- }
- }
-}
diff --git a/src/tools/MicroComGenerator/Program.cs b/src/tools/MicroComGenerator/Program.cs
deleted file mode 100644
index 2468b1b5a4..0000000000
--- a/src/tools/MicroComGenerator/Program.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-using System;
-using System.IO;
-using System.Linq;
-using CommandLine;
-
-namespace MicroComGenerator
-{
- class Program
- {
- public class Options
- {
- [Option('i', "input", Required = true, HelpText = "Input IDL file")]
- public string Input { get; set; }
-
- [Option("cpp", Required = false, HelpText = "C++ output file")]
- public string CppOutput { get; set; }
-
- [Option("cs", Required = false, HelpText = "C# output file")]
- public string CSharpOutput { get; set; }
-
- }
-
- static int Main(string[] args)
- {
- var p = Parser.Default.ParseArguments(args);
- if (p is NotParsed)
- {
- return 1;
- }
-
- var opts = ((Parsed)p).Value;
-
- var text = File.ReadAllText(opts.Input);
- var ast = AstParser.Parse(text);
-
- if (opts.CppOutput != null)
- File.WriteAllText(opts.CppOutput, CppGen.GenerateCpp(ast));
-
- if (opts.CSharpOutput != null)
- {
- File.WriteAllText(opts.CSharpOutput, new CSharpGen(ast).Generate());
-
- // HACK: Can't work out how to get the VS project system's fast up-to-date checks
- // to ignore the generated code, so as a workaround set the write time to that of
- // the input.
- File.SetLastWriteTime(opts.CSharpOutput, File.GetLastWriteTime(opts.Input));
- }
-
- return 0;
- }
- }
-}
diff --git a/src/tools/MicroComGenerator/TokenParser.cs b/src/tools/MicroComGenerator/TokenParser.cs
deleted file mode 100644
index ea8850b8e4..0000000000
--- a/src/tools/MicroComGenerator/TokenParser.cs
+++ /dev/null
@@ -1,417 +0,0 @@
-using System;
-using System.Globalization;
-using System.IO;
-
-namespace MicroComGenerator
-{
- internal ref struct TokenParser
- {
- private ReadOnlySpan _s;
- public int Position { get; private set; }
- public int Line { get; private set; }
- public TokenParser(ReadOnlySpan s)
- {
- _s = s;
- Position = 0;
- Line = 0;
- }
-
- public void SkipWhitespace()
- {
- while (true)
- {
- if(_s.Length == 0)
- return;
- if (char.IsWhiteSpace(_s[0]))
- Advance(1);
- else if (_s[0] == '/' && _s.Length>1)
- {
- if (_s[1] == '/')
- SkipOneLineComment();
- else if (_s[1] == '*')
- SkipMultiLineComment();
- else
- return;
- }
- else
- return;
- }
- }
-
- void SkipOneLineComment()
- {
- while (true)
- {
- if (_s.Length > 0 && _s[0] != '\n' && _s[0] != '\r')
- Advance(1);
- else
- return;
- }
- }
-
- void SkipMultiLineComment()
- {
- var l = Line;
- var p = Position;
- while (true)
- {
- if (_s.Length == 0)
- throw new ParseException("No matched */ found for /*", l, p);
-
- if (_s[0] == '*' && _s.Length > 1 && _s[1] == '/')
- {
- Advance(2);
- return;
- }
-
- Advance(1);
- }
- }
-
- static bool IsAlphaNumeric(char ch) => (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') ||
- (ch >= 'A' && ch <= 'Z');
-
- public void Consume(char c)
- {
- if (!TryConsume(c))
- throw new ParseException("Expected " + c, Line, Position);
- }
- public bool TryConsume(char c)
- {
- SkipWhitespace();
- if (_s.Length == 0 || _s[0] != c)
- return false;
-
- Advance(1);
- return true;
- }
-
- public bool TryConsume(string s)
- {
- SkipWhitespace();
- if (_s.Length < s.Length)
- return false;
- for (var c = 0; c < s.Length; c++)
- {
- if (_s[c] != s[c])
- return false;
- }
-
- Advance(s.Length);
- return true;
- }
-
- public bool TryConsumeAny(ReadOnlySpan chars, out char token)
- {
- SkipWhitespace();
- token = default;
- if (_s.Length == 0)
- return false;
-
- foreach (var c in chars)
- {
- if (c == _s[0])
- {
- token = c;
- Advance(1);
- return true;
- }
- }
-
- return false;
- }
-
-
- public bool TryParseKeyword(string keyword)
- {
- SkipWhitespace();
- if (keyword.Length > _s.Length)
- return false;
- for(var c=0; c keyword.Length && IsAlphaNumeric(_s[keyword.Length]))
- return false;
-
- Advance(keyword.Length);
- return true;
- }
-
- public bool TryParseKeywordLowerCase(string keywordInLowerCase)
- {
- SkipWhitespace();
- if (keywordInLowerCase.Length > _s.Length)
- return false;
- for(var c=0; c keywordInLowerCase.Length && IsAlphaNumeric(_s[keywordInLowerCase.Length]))
- return false;
-
- Advance(keywordInLowerCase.Length);
- return true;
- }
-
- public void Advance(int c)
- {
- while (c > 0)
- {
- if (_s[0] == '\n')
- {
- Line++;
- Position = 0;
- }
- else
- Position++;
-
- _s = _s.Slice(1);
- c--;
- }
- }
-
- public int Length => _s.Length;
- public bool Eof
- {
- get
- {
- SkipWhitespace();
- return Length == 0;
- }
- }
-
- public char Peek
- {
- get
- {
- if (_s.Length == 0)
- throw new ParseException("Unexpected EOF", Line, Position);
- return _s[0];
- }
- }
-
- public string ParseIdentifier(ReadOnlySpan extraValidChars)
- {
- if (!TryParseIdentifier(extraValidChars, out var ident))
- throw new ParseException("Identifier expected", Line, Position);
- return ident.ToString();
- }
-
- public string ParseIdentifier()
- {
- if (!TryParseIdentifier(out var ident))
- throw new ParseException("Identifier expected", Line, Position);
- return ident.ToString();
- }
-
- public bool TryParseIdentifier(ReadOnlySpan extraValidChars, out ReadOnlySpan res)
- {
- res = ReadOnlySpan.Empty;
- SkipWhitespace();
- if (_s.Length == 0)
- return false;
- var first = _s[0];
- if (!((first >= 'a' && first <= 'z') || (first >= 'A' && first <= 'Z') || first == '_'))
- return false;
- int len = 1;
- for (var c = 1; c < _s.Length; c++)
- {
- var ch = _s[c];
- if (IsAlphaNumeric(ch) || ch == '_')
- len++;
- else
- {
- var found = false;
- foreach(var vc in extraValidChars)
- if (vc == ch)
- {
- found = true;
- break;
- }
-
- if (found)
- len++;
- else
- break;
- }
- }
-
- res = _s.Slice(0, len);
- Advance(len);
- return true;
- }
-
- public bool TryParseIdentifier(out ReadOnlySpan res)
- {
- res = ReadOnlySpan.Empty;
- SkipWhitespace();
- if (_s.Length == 0)
- return false;
- var first = _s[0];
- if (!((first >= 'a' && first <= 'z') || (first >= 'A' && first <= 'Z') || first == '_'))
- return false;
- int len = 1;
- for (var c = 1; c < _s.Length; c++)
- {
- var ch = _s[c];
- if (IsAlphaNumeric(ch) || ch == '_')
- len++;
- else
- break;
- }
-
- res = _s.Slice(0, len);
- Advance(len);
- return true;
- }
-
- public string ReadToEol()
- {
- var initial = _s;
- var len = 0;
- while (true)
- {
- if (_s.Length > 0 && _s[0] != '\n' && _s[0] != '\r')
- {
- len++;
- Advance(1);
- }
- else
- return initial.Slice(0, len).ToString();
- }
- }
-
- public string ReadTo(char c)
- {
- var initial = _s;
- var len = 0;
- var l = Line;
- var p = Position;
- while (true)
- {
- if (_s.Length == 0)
- throw new ParseException("Expected " + c + " before EOF", l, p);
-
- if (_s[0] != c)
- {
- len++;
- Advance(1);
- }
- else
- return initial.Slice(0, len).ToString();
- }
- }
-
- public string ReadToAny(ReadOnlySpan chars)
- {
- var initial = _s;
- var len = 0;
- var l = Line;
- var p = Position;
- while (true)
- {
- if (_s.Length == 0)
- throw new ParseException("Expected any of '" + chars.ToString() + "' before EOF", l, p);
-
- var foundTerminator = false;
- foreach (var term in chars)
- {
- if (_s[0] == term)
- {
- foundTerminator = true;
- break;
- }
- }
-
- if (!foundTerminator)
- {
- len++;
- Advance(1);
- }
- else
- return initial.Slice(0, len).ToString();
- }
- }
-
- public bool TryParseCall(out ReadOnlySpan res)
- {
- res = ReadOnlySpan.Empty;
- SkipWhitespace();
- if (_s.Length == 0)
- return false;
- var first = _s[0];
- if (!((first >= 'a' && first <= 'z') || (first >= 'A' && first <= 'Z')))
- return false;
- int len = 1;
- for (var c = 1; c < _s.Length; c++)
- {
- var ch = _s[c];
- if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch<= 'Z') || ch == '.')
- len++;
- else
- break;
- }
-
- res = _s.Slice(0, len);
-
- // Find '('
- for (var c = len; c < _s.Length; c++)
- {
- if(char.IsWhiteSpace(_s[c]))
- continue;
- if(_s[c]=='(')
- {
- Advance(c + 1);
- return true;
- }
-
- return false;
-
- }
-
- return false;
-
- }
-
-
- public bool TryParseFloat(out float res)
- {
- res = 0;
- SkipWhitespace();
- if (_s.Length == 0)
- return false;
-
- var len = 0;
- var dotCount = 0;
- for (var c = 0; c < _s.Length; c++)
- {
- var ch = _s[c];
- if (ch >= '0' && ch <= '9')
- len = c + 1;
- else if (ch == '.' && dotCount == 0)
- {
- len = c + 1;
- dotCount++;
- }
- else
- break;
- }
-
- var span = _s.Slice(0, len);
-
-#if NETSTANDARD2_0
- if (!float.TryParse(span.ToString(), NumberStyles.Number, CultureInfo.InvariantCulture, out res))
- return false;
-#else
- if (!float.TryParse(span, NumberStyles.Number, CultureInfo.InvariantCulture, out res))
- return false;
-#endif
- Advance(len);
- return true;
- }
-
- public override string ToString() => _s.ToString();
-
- }
-}