├── .github └── workflows │ └── dotnet_build.yml ├── .gitignore ├── HEADER ├── License.md ├── Readme.md ├── ReleaseNotes.txt └── src ├── .editorconfig ├── GameDevWare.Dynamic.Expressions.Playmaker └── Assets │ └── Plugins │ ├── GameDevWare.Dynamic.Expressions.meta │ └── GameDevWare.Dynamic.Expressions │ ├── GameDevWare.Dynamic.Expressions.xml │ └── link.xml ├── GameDevWare.Dynamic.Expressions.Tests ├── BinderTests.cs ├── ExecutorTests.cs ├── ExpressionUtils.cs ├── FormattingTests.cs ├── GameDevWare.Dynamic.Expressions.Tests.csproj ├── PackerTests.cs ├── ParserTests.cs ├── PatternStringTests.cs ├── TestStruct.cs ├── TokenizerTests.cs ├── TypeNameUtilsTests.cs ├── TypeResolverTests.cs └── sn.snk ├── GameDevWare.Dynamic.Expressions.Unity.2017 └── Assets │ ├── Plugins.meta │ ├── Plugins │ ├── GameDevWare.Dynamic.Expressions.meta │ └── GameDevWare.Dynamic.Expressions │ │ ├── GameDevWare.Dynamic.Expressions.dll │ │ ├── GameDevWare.Dynamic.Expressions.dll.meta │ │ ├── GameDevWare.Dynamic.Expressions.xml │ │ ├── GameDevWare.Dynamic.Expressions.xml.meta │ │ ├── link.xml │ │ ├── link.xml.meta │ │ ├── readme.md │ │ ├── readme.md.meta │ │ ├── readme.pdf │ │ └── readme.pdf.meta │ ├── Scripts.meta │ └── Scripts │ ├── Benchmark.meta │ ├── Benchmark │ ├── Benchmark.cs │ ├── Benchmark.cs.meta │ ├── Benchmark.unity │ └── Benchmark.unity.meta │ ├── Example.meta │ └── Example │ ├── PatternString.cs │ └── PatternString.cs.meta ├── GameDevWare.Dynamic.Expressions.Unity.2021 └── Assets │ ├── Plugins │ └── GameDevWare.Dynamic.Expressions │ │ ├── GameDevWare.Dynamic.Expressions.dll │ │ ├── GameDevWare.Dynamic.Expressions.xml │ │ ├── link.xml │ │ ├── readme.md │ │ └── readme.pdf │ └── Scripts │ ├── Benchmark │ ├── Benchmark.cs │ └── Benchmark.unity │ └── Example │ └── PatternString.cs ├── GameDevWare.Dynamic.Expressions.Unity.3.4 └── Assets │ ├── Plugins │ └── GameDevWare.Dynamic.Expressions │ │ ├── GameDevWare.Dynamic.Expressions.dll │ │ ├── GameDevWare.Dynamic.Expressions.xml │ │ ├── link.xml │ │ ├── readme.md │ │ └── readme.pdf │ └── Scripts │ ├── Benchmark │ ├── Benchmark.cs │ └── Benchmark.unity │ └── Example │ └── PatternString.cs ├── GameDevWare.Dynamic.Expressions.Unity.5.4 └── Assets │ ├── Plugins.meta │ ├── Plugins │ ├── GameDevWare.Dynamic.Expressions.meta │ └── GameDevWare.Dynamic.Expressions │ │ ├── GameDevWare.Dynamic.Expressions.dll │ │ ├── GameDevWare.Dynamic.Expressions.dll.meta │ │ ├── GameDevWare.Dynamic.Expressions.xml │ │ ├── GameDevWare.Dynamic.Expressions.xml.meta │ │ ├── link.xml │ │ ├── link.xml.meta │ │ ├── readme.md │ │ ├── readme.md.meta │ │ ├── readme.pdf │ │ └── readme.pdf.meta │ ├── Scripts.meta │ └── Scripts │ ├── Benchmark.meta │ ├── Benchmark │ ├── Benchmark.cs │ ├── Benchmark.cs.meta │ ├── Benchmark.unity │ └── Benchmark.unity.meta │ ├── Example.meta │ └── Example │ ├── PatternString.cs │ └── PatternString.cs.meta ├── GameDevWare.Dynamic.Expressions.sln └── GameDevWare.Dynamic.Expressions ├── .gitignore ├── Aot.cs ├── Aot.tt ├── AotCompilation.cs ├── ArgumentsTree.cs ├── ArrayUtils.cs ├── AssemblyTypeResolver.cs ├── Binder.cs ├── Binding ├── AnyBinder.cs ├── BinaryBinder.cs ├── BindingContext.cs ├── CallBinder.cs ├── ConditionBinder.cs ├── ConstantBinder.cs ├── DefaultBinder.cs ├── GroupBinder.cs ├── IndexBinder.cs ├── InvokeBinder.cs ├── LambdaBinder.cs ├── ListInitBinder.cs ├── MemberBinder.cs ├── MemberDescription.cs ├── MemberInitBinder.cs ├── NewArrayBoundsBinder.cs ├── NewArrayInitBinder.cs ├── NewBinder.cs ├── NumberUtils.cs ├── ParameterBinder.cs ├── QuoteBinder.cs ├── TypeBinaryBinder.cs ├── TypeCache.cs ├── TypeConversion.cs ├── TypeDescription.cs ├── TypeOfBinder.cs ├── TypeTuple.cs ├── TypeTuple2.cs └── UnaryBinder.cs ├── CSharp ├── CSharpExpression.cs ├── CSharpExpressionFormatter.cs ├── CSharpSyntaxTreeFormatter.cs ├── CSharpTypeNameAlias.cs ├── ListExtensions.cs ├── ParseTreeNode.cs ├── Parser.cs ├── StringUtils.cs ├── SyntaxTreeBuilder.cs ├── Token.cs ├── TokenAttribute.cs ├── TokenType.cs └── Tokenizer.cs ├── Constants.cs ├── DelegateUtils.cs ├── Execution ├── AotCompiler.cs ├── ArrayIndexNode.cs ├── ArrayLengthNode.cs ├── BinaryNode.cs ├── CallNode.cs ├── Closure.cs ├── CoalesceNode.cs ├── ConditionalNode.cs ├── ConstantNode.cs ├── ConstantsCollector.cs ├── ConvertNode.cs ├── ExecutionNode.cs ├── FastCall.cs ├── Intrinsic.cs ├── InvocationNode.cs ├── LambdaNode.cs ├── ListInitNode.cs ├── LocalNode.cs ├── MemberAccessNode.cs ├── MemberAssignmentsNode.cs ├── MemberInitNode.cs ├── MemberListBindingsNode.cs ├── MemberMemberBindingsNode.cs ├── NewArrayBoundsNode.cs ├── NewArrayInitNode.cs ├── NewNode.cs ├── NullNode.cs ├── ParameterNode.cs ├── QuoteNode.cs ├── TypeAsNode.cs ├── TypeIsNode.cs └── UnaryNode.cs ├── ExpressionExtentions.cs ├── ExpressionKnownTypeAttribute.cs ├── ExpressionLookupVisitor.cs ├── ExpressionPacker.cs ├── ExpressionParserException.cs ├── ExpressionPosition.cs ├── ExpressionSubstitutor.cs ├── ExpressionUtils.cs ├── ExpressionVisitor.cs ├── GameDevWare.Dynamic.Expressions.csproj ├── GameDevWare.Dynamic.Expressions.csproj.DotSettings ├── ILineInfo.cs ├── ITypeResolver.cs ├── JitSupportDetector.cs ├── KnownTypeResolver.cs ├── MethodCallSignature.cs ├── Packing ├── AnyPacker.cs ├── ArrayIndexPacker.cs ├── ArrayLengthPacker.cs ├── BinaryPacker.cs ├── CallPacker.cs ├── ConditionPacker.cs ├── ConstantPacker.cs ├── ConvertPacker.cs ├── InvokePacker.cs ├── LambdaPacker.cs ├── ListInitPacker.cs ├── MemberAccessPacker.cs ├── MemberInitPacker.cs ├── NewArrayPacker.cs ├── NewPacker.cs ├── ParameterPacker.cs ├── QuotePacker.cs ├── TypeAsPacker.cs ├── TypeIsPacker.cs └── UnaryPacker.cs ├── Properties ├── AssemblyInfo.cs └── Resources.resx ├── ReflectionUtils.cs ├── SyntaxTreeNode.cs ├── TypeDiscoveryOptions.cs ├── TypeNameFormatOptions.cs ├── TypeNameUtils.cs ├── TypeReference.cs ├── TypeScriptResources.ts ├── TypeScriptResources.tt ├── UnboundExpression.cs ├── UnityResources.cs ├── UnityResources.tt └── sn.snk /.github/workflows/dotnet_build.yml: -------------------------------------------------------------------------------- 1 | name: dotnet_build 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: windows-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v1 12 | 13 | - name: Setup .NET Core 14 | uses: actions/setup-dotnet@v1 15 | 16 | - name: Setup .NET Framework 3.5 17 | uses: crazy-max/ghaction-chocolatey@v1 18 | with: 19 | args: install dotnet3.5 20 | 21 | - name: dotnet restore 22 | working-directory: ./src/ 23 | run: dotnet restore 24 | 25 | - name: Setup MSBuild.exe 26 | uses: microsoft/setup-msbuild@v1.0.2 27 | 28 | - name: Build with MSBuild 29 | working-directory: ./src/ 30 | run: msbuild -t:Pack 31 | 32 | - name: Run rests 33 | working-directory: ./src/GameDevWare.Dynamic.Expressions.Tests/ 34 | run: dotnet test -f netcoreapp2.1 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.exp 2 | *.ipch 3 | *.metagen 4 | *.ncb 5 | *.nupkg 6 | *.obj 7 | *.opensdf 8 | *.pdb 9 | *.ReSharper 10 | *.sdf 11 | *.suo 12 | *.swp 13 | *.meta 14 | *.user 15 | *.log 16 | _ReSharper* 17 | *.userprefs 18 | *.exe 19 | *.dll 20 | 21 | .vs 22 | media/ 23 | bin/ 24 | obj/ 25 | packages/ 26 | deploy/ 27 | Assembly-* 28 | Library/ 29 | Temp/ 30 | Assets/StreamingAssets/ 31 | Assets/Bundles/ 32 | ProjectSettings/ 33 | AssetStoreTools/ 34 | src/GameDevWare.Dynamic.Expressions.Playmaker/Assets/PlayMaker/ 35 | src/GameDevWare.Dynamic.Expressions.Playmaker/Assets/Gizmos/ 36 | src/GameDevWare.Dynamic.Expressions.Playmaker/Assets/Plugins/PlayMaker/ 37 | src/GameDevWare.Dynamic.Expressions.Playmaker/Assets/iTween/ 38 | src/GameDevWare.Dynamic.Expressions.Playmaker/Assets/AssetStoreTools/ -------------------------------------------------------------------------------- /HEADER: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ -------------------------------------------------------------------------------- /License.md: -------------------------------------------------------------------------------- 1 | [Asset Store Terms of Service and EULA](https://unity3d.com/ru/legal/as_terms) 2 | 3 | TLDR; Buy asset once and use it in any number of projects in your company. Use it 'as-is' no warranties. 4 | -------------------------------------------------------------------------------- /ReleaseNotes.txt: -------------------------------------------------------------------------------- 1 | # 2.3.0 2 | fix: fixed netcore related error with enumerable.empty 3 | feature: added optional `global` parameter to all CSharpExpression methods to allow specify global object for expression. 4 | test: removed flaky test with double.tostring() comparison 5 | fix: fixed typo in `arg4Name` in `CSharpExpression.ParseFunc{4}` and `CSharpExpression.ParseAction{4}` 6 | 7 | # 2.2.9 8 | fix: fixed error with instantiated generic method on types (which is impossible in normal conditions, but fine for Unity AOT runtime). 9 | 10 | # 2.2.8 11 | - made AotCompilation.IsAotRuntime is mutable, this will allow to signal for AOT runtime and suppress further checks. 12 | 13 | # 2.2.7 14 | - added public CSharpExpression.Format method for SyntaxTreeNode 15 | 16 | # 2.2.6 17 | - changed order or SyntaxTreeNode fields and added "original C# expression" field to parsed AST. 18 | - refactored C# expression rendering to support null-propagation expressions, type aliases (int, byte, object ...), 19 | - renamed "Render" methods to "FormatAsCSharp". Now it is "formatting" 20 | - moved c# "formatting" methods to CSharpExpression class 21 | - mark old "Parse" functions as errors 22 | - mark old "Render" methods as obsolete 23 | - renamed CSharpExpressionFormatter to CSharpExpressionFormatter 24 | - fixed indexer experssion rendering 25 | - refactored NameUtils to properly render C# type names 26 | 27 | # 2.2.5 28 | renamed ParseTreeNode.Lexeme to .Token 29 | renamed few member of TokenType for better clarity 30 | added documentation file in Unity project assets 31 | changed 'propertyOrFieldName' attribute to 'name' in SyntaxTreeNode 32 | renamed PropertyOfFieldBinder to MemberBinder 33 | changed 'PropertyOrField' expression type to 'MemberResolve' in SyntaxTreeNode 34 | added backward compatibility checks in all related classes 35 | 36 | # 2.2.4 37 | added protection against wrong expressions like 'a b' which later bound as 'b' 38 | fixed some tokenization errors: 39 | - 'issa'scanned as 'is'[Operator] and 'sa'[Identifier], now as 'issa' 40 | - '.09' scanned as '.'[Operator] and '09'[Number], now as '0.09' 41 | - '0.1x' scanned as '0.1'[Number] and 'x'[Identifier], now cause error 42 | added method call support for numbers (example 1.ToString()) 43 | added short number notation (examples '.9' for '0.9') 44 | added '@' prefix for identifiers (example '@is') https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/verbatim 45 | done small Tokenizer optimization (reduced string allocation during scanning) 46 | 47 | # 2.2.3 48 | added ExpressionPacker type. This type allows packing/unpacking expressions into primitive structures (Dictionaries, Arrays...). These structures could be serialized and wired by network or stored for future use. 49 | added better error message for some binding cases 50 | denying call to 'Type.InvokeMember' if 'Type' is not within 'known types'. 51 | 52 | # 2.2.2 53 | * fixed conditional operator (a ? b : c) parsing with method call in place of 'b' 54 | 55 | # 2.2.1 56 | * fixed IL2CPP compilation error due _Attribute interface complilation failure 57 | * added few interfaces to AOT.cs file for better AOT coverage 58 | 59 | # 2.2.0 60 | Features 61 | * added support for void expressions (Action<> delegates) 62 | * added support of '.NET Standart 1.3' and '.NET Core 2.0' platforms 63 | -------------------------------------------------------------------------------- /src/.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | end_of_line = crlf 8 | indent_style = tab 9 | indent_size = 4 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Playmaker/Assets/Plugins/GameDevWare.Dynamic.Expressions.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2697c3f16f6f91d4ea1835304278ce02 3 | folderAsset: yes 4 | timeCreated: 1527015081 5 | licenseType: Free 6 | DefaultImporter: 7 | externalObjects: {} 8 | userData: 9 | assetBundleName: 10 | assetBundleVariant: 11 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Playmaker/Assets/Plugins/GameDevWare.Dynamic.Expressions/link.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Tests/ExpressionUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Linq.Expressions; 4 | using System.Reflection; 5 | using GameDevWare.Dynamic.Expressions.CSharp; 6 | 7 | namespace GameDevWare.Dynamic.Expressions.Tests 8 | { 9 | public class ExpressionUtils 10 | { 11 | public static object Evaluate(string expression, Type[] types, bool forceAot, ITypeResolver typeResolver = null, params object[] arguments) 12 | { 13 | var expressionObj = ParseFunc(expression, types, typeResolver); 14 | 15 | var compileMethod = typeof(ExpressionExtensions) 16 | .GetTypeInfo() 17 | .GetDeclaredMethods() 18 | .Where(m => m.IsPublic && m.IsStatic) 19 | .Single(m => m.Name == "CompileAot" && m.ReturnType.Name.StartsWith("Func") && m.IsGenericMethod && m.GetGenericArguments().Length == types.Length) 20 | .MakeGenericMethod(types); 21 | 22 | var @delegate = (Delegate)compileMethod.Invoke(null, new object[] { expressionObj, forceAot }); 23 | return @delegate.DynamicInvoke(arguments); 24 | } 25 | 26 | public static void Execute(string expression, Type[] types, bool forceAot, ITypeResolver typeResolver = null, params object[] arguments) 27 | { 28 | var expressionObj = ParseAction(expression, types, typeResolver); 29 | 30 | var compileMethod = typeof(ExpressionExtensions) 31 | .GetTypeInfo() 32 | .GetDeclaredMethods() 33 | .Where(m => m.IsPublic && m.IsStatic) 34 | .Single(m => m.Name == "CompileAot" && m.ReturnType.Name.StartsWith("Action") && (types.Length > 0 ? (m.IsGenericMethod && m.GetGenericArguments().Length == types.Length) : m.IsGenericMethod == false)); 35 | 36 | if (compileMethod.IsGenericMethodDefinition) 37 | compileMethod = compileMethod.MakeGenericMethod(types); 38 | 39 | var @delegate = (Delegate)compileMethod.Invoke(null, new object[] { expressionObj, forceAot }); 40 | @delegate.DynamicInvoke(arguments); 41 | } 42 | 43 | public static LambdaExpression ParseFunc(string expression, Type[] types, ITypeResolver typeResolver = null) 44 | { 45 | var parseMethod = typeof(CSharpExpression) 46 | .GetTypeInfo() 47 | .GetDeclaredMethods() 48 | .Where(m => m.IsPublic && m.IsStatic) 49 | .Single(m => m.Name == "ParseFunc" && m.IsGenericMethod && m.GetGenericArguments().Length == types.Length) 50 | .MakeGenericMethod(types); 51 | 52 | var parseArguments = new object[parseMethod.GetParameters().Length]; 53 | foreach (var parameter in parseMethod.GetParameters()) 54 | { 55 | if (parameter.ParameterType == typeof(ITypeResolver)) 56 | parseArguments[parameter.Position] = typeResolver; 57 | else 58 | parseArguments[parameter.Position] = parameter.DefaultValue; 59 | } 60 | parseArguments[0] = expression; 61 | 62 | var expressionObj = parseMethod.Invoke(null, parseArguments); 63 | return (LambdaExpression)expressionObj; 64 | } 65 | public static LambdaExpression ParseAction(string expression, Type[] types, ITypeResolver typeResolver = null) 66 | { 67 | var parseMethod = typeof(CSharpExpression) 68 | .GetTypeInfo() 69 | .GetDeclaredMethods() 70 | .Where(m => m.IsPublic && m.IsStatic) 71 | .Single(m => m.Name == "ParseAction" && (types.Length > 0 ? (m.IsGenericMethod && m.GetGenericArguments().Length == types.Length) : m.IsGenericMethod == false)); 72 | 73 | if(parseMethod.IsGenericMethodDefinition) 74 | parseMethod = parseMethod.MakeGenericMethod(types); 75 | 76 | var parseArguments = new object[parseMethod.GetParameters().Length]; 77 | foreach (var parameter in parseMethod.GetParameters()) 78 | { 79 | if (parameter.ParameterType == typeof(ITypeResolver)) 80 | parseArguments[parameter.Position] = typeResolver; 81 | else 82 | parseArguments[parameter.Position] = parameter.DefaultValue; 83 | } 84 | parseArguments[0] = expression; 85 | 86 | var expressionObj = parseMethod.Invoke(null, parseArguments); 87 | return (LambdaExpression)expressionObj; 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Tests/GameDevWare.Dynamic.Expressions.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Library 5 | 6 | 7 | net461;net5.0 8 | Denis Zykov 9 | 0.0.0 10 | GameDevWare.Dynamic.Expressions.Tests 11 | GameDevWare.Dynamic.Expressions.Tests 12 | GameDevWare.Dynamic.Expressions.Tests 13 | 14 | True 15 | 16 | library 17 | 18 | 0.0.0.0 19 | 0.0.0.0 20 | true 21 | true 22 | sn.snk 23 | false 24 | false 25 | 26 | 27 | False 28 | RELEASE 29 | 30 | 31 | DEBUG;TRACE 32 | 33 | 34 | $(DefineConstants);NETSTANDARD; 35 | 36 | 37 | $(DefineConstants);NET45 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Tests/PackerTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Linq.Expressions; 6 | using GameDevWare.Dynamic.Expressions.CSharp; 7 | using Newtonsoft.Json; 8 | using Xunit; 9 | using Xunit.Abstractions; 10 | 11 | namespace GameDevWare.Dynamic.Expressions.Tests 12 | { 13 | public class PackerTests 14 | { 15 | private class MyTestClass : IEnumerable 16 | { 17 | public MyTestClass(int param1) 18 | { 19 | 20 | } 21 | 22 | public int PublicField; 23 | public int PublicProperty { get; set; } 24 | public MyTestClass SubClassField; 25 | 26 | public int Add(int addParam1, string addParam2) 27 | { 28 | return 0; 29 | } 30 | public int Add(int addParam1) 31 | { 32 | return 0; 33 | } 34 | 35 | /// 36 | public IEnumerator GetEnumerator() 37 | { 38 | throw new NotImplementedException(); 39 | } 40 | } 41 | 42 | public PackerTests(ITestOutputHelper output) 43 | { 44 | this.output = output; 45 | } 46 | private readonly ITestOutputHelper output; 47 | 48 | public static IEnumerable PackUnpackExpressionData() 49 | { 50 | var expressions = new Expression[] { 51 | (Expression>)(() => !true), 52 | (Expression>)(() => +1), 53 | (Expression>)(() => -1), 54 | (Expression>)(() => ~1), 55 | (Expression>)(() => 1 << 2), 56 | (Expression>)(() => 1 >> 2), 57 | (Expression>)(() => 1 - 2), 58 | (Expression>)(() => 1 + 2), 59 | (Expression>)(() => 1 * 2), 60 | (Expression>)(() => 1 / 2), 61 | (Expression>)(() => 1 % 2), 62 | (Expression>)(() => 1 != 2), 63 | (Expression>)(() => 1 == 2), 64 | (Expression>)(() => 1 > 2), 65 | (Expression>)(() => 1 >= 2), 66 | (Expression>)(() => 1 <= 2), 67 | (Expression>)(() => 1 < 2), 68 | (Expression>)(() => 1 < 2 || 1 > 2), 69 | (Expression>)(() => 1 < 2 | 1 > 2), 70 | (Expression>)(() => 1 < 2 & 1 > 2), 71 | (Expression>)(() => 1 < 2 && 1 > 2), 72 | (Expression>)(() => 1 < 2 ^ 1 > 2), 73 | (Expression>)(() => default(int?) ?? 1), 74 | (Expression>)(() => 1 < 2 ? 1 : 2), 75 | Expression.Lambda>(Expression.ArrayLength(Expression.Constant(null, typeof(int[])))), 76 | (Expression>)(() => default(int[])[0]), 77 | //(Expression>)(() => default(int[,])[0,0]), 78 | (Expression>)(() => string.Empty.IndexOf('0')), 79 | (Expression>)(() => (int)Math.E), 80 | (Expression>)(() => default(Func)()), 81 | (Expression>>)(() => new List { 10, 100 }), 82 | (Expression>)(() => new MyTestClass(10) { 83 | PublicField = 1, 84 | PublicProperty = 2, 85 | SubClassField = { 86 | PublicField = 1, 87 | SubClassField = { 88 | { 10, string.Empty }, 89 | { 10 }, 90 | } 91 | } 92 | }), 93 | (Expression>)(() => new [] { 10 }), 94 | (Expression>)(() => new int[10]), 95 | (Expression>)(p => p), 96 | (Expression>)(() => default(object) as Expression), 97 | (Expression>)(() => string.Empty is string), 98 | }; 99 | return (from expr in expressions 100 | select new object[] { CSharpExpression.Format(expr), expr }); 101 | } 102 | 103 | [Theory] 104 | [MemberData(nameof(PackUnpackExpressionData))] 105 | public void PackUnpackExpression(string expr, LambdaExpression lambdaExpression) 106 | { 107 | this.output.WriteLine("Original: " + lambdaExpression.ToString()); 108 | 109 | var packedExpression = ExpressionPacker.Pack(lambdaExpression); 110 | 111 | this.output.WriteLine("Packed: " + JsonConvert.SerializeObject(packedExpression, Formatting.Indented)); 112 | 113 | var syntaxTree = new SyntaxTreeNode(packedExpression); 114 | var binder = new Binder(lambdaExpression.Parameters, lambdaExpression.Body.Type); 115 | var unpackedExpression = binder.Bind(syntaxTree); 116 | 117 | this.output.WriteLine("Unpacked: " + unpackedExpression.ToString()); 118 | 119 | Assert.NotNull(unpackedExpression); 120 | Assert.Equal(lambdaExpression.Body.NodeType, unpackedExpression.Body.NodeType); 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Tests/PatternStringTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | using Assets; 4 | using GameDevWare.Dynamic.Expressions.CSharp; 5 | using Xunit; 6 | using Xunit.Abstractions; 7 | 8 | namespace GameDevWare.Dynamic.Expressions.Tests 9 | { 10 | public class PatternStringTests 11 | { 12 | private class TestClass 13 | { 14 | #pragma warning disable 414 15 | public int IntField; 16 | public string StringProperty; 17 | public TestClass Other; 18 | #pragma warning restore 414 19 | } 20 | 21 | private readonly ITestOutputHelper output; 22 | public PatternStringTests(ITestOutputHelper output) 23 | { 24 | this.output = output; 25 | } 26 | 27 | [Theory] 28 | [InlineData("a test string", "a test string")] 29 | [InlineData("a test {IntField} string", "a test 1 string")] 30 | [InlineData("a test {IntField} string {StringProperty}", "a test 1 string 2")] 31 | [InlineData("a test {IntField} string {StringProperty}{StringProperty}", "a test 1 string 22")] 32 | [InlineData("a test {IntField} string {StringProperty}{StringProperty}{StringProperty}", "a test 1 string 222")] 33 | [InlineData("a test {Other.IntField} string", "a test 3 string")] 34 | [InlineData("{Other.StringProperty}", "4")] 35 | [InlineData("{Other.Other}", "")] 36 | [InlineData("{Other.StringProperty} aaa", "4 aaa")] 37 | [InlineData("aaa{Other.StringProperty}", "aaa4")] 38 | public void GenericInvocationTest(string expression, string expected) 39 | { 40 | var actual = PatternString.TransformPattern(expression, new TestClass { IntField = 1, StringProperty = "2", Other = new TestClass { IntField = 3, StringProperty = "4"} }); 41 | this.output.WriteLine("Transformed: " + actual); 42 | 43 | Assert.Equal(expected, actual); 44 | } 45 | 46 | [Fact] 47 | public void Test() 48 | { 49 | var parser = new InputParser(); 50 | parser.Parse(); 51 | } 52 | 53 | public class InputParser 54 | { 55 | 56 | public void Parse() 57 | { 58 | var input = "Move(up,5)"; 59 | var myGlobal = new MyGlobal(); 60 | RunAction(myGlobal, input); 61 | 62 | } 63 | 64 | public static void RunAction(MyGlobal global, string expression) 65 | { 66 | var tokens = Tokenizer.Tokenize(expression); 67 | var parseTree = Parser.Parse(tokens); 68 | var expressionTree = parseTree.ToSyntaxTree(cSharpExpression: expression); 69 | var expressionBinder = new Binder(new ParameterExpression[0], resultType: typeof(void)); 70 | var globalExpression = Expression.Constant(global); 71 | var boundExpression = (Expression)expressionBinder.Bind(expressionTree, globalExpression); 72 | boundExpression.CompileAot().Invoke(); 73 | } 74 | } 75 | 76 | public class MyGlobal 77 | { 78 | public string up = "upward"; // just example 79 | 80 | public void Move(string direction, int distance) 81 | { 82 | Console.WriteLine($"player moves {direction} {distance} spaces"); 83 | } 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Tests/TestStruct.cs: -------------------------------------------------------------------------------- 1 | namespace GameDevWare.Dynamic.Expressions.Tests 2 | { 3 | public struct TestStruct 4 | { 5 | public int IntField; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Tests/sn.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deniszykov/csharp-eval-unity3d/f3251f389b4c430862a3de1896d88effe4c7cdad/src/GameDevWare.Dynamic.Expressions.Tests/sn.snk -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.2017/Assets/Plugins.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b5a306b28d7b0d44ba1f9e13694be5f4 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.2017/Assets/Plugins/GameDevWare.Dynamic.Expressions.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: da6e6838a9034c844a7857b3c8f52f5c 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.2017/Assets/Plugins/GameDevWare.Dynamic.Expressions/GameDevWare.Dynamic.Expressions.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deniszykov/csharp-eval-unity3d/f3251f389b4c430862a3de1896d88effe4c7cdad/src/GameDevWare.Dynamic.Expressions.Unity.2017/Assets/Plugins/GameDevWare.Dynamic.Expressions/GameDevWare.Dynamic.Expressions.dll -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.2017/Assets/Plugins/GameDevWare.Dynamic.Expressions/GameDevWare.Dynamic.Expressions.dll.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f43ae84aec1edd941b49a1f99a8fdd97 3 | PluginImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | iconMap: {} 7 | executionOrder: {} 8 | defineConstraints: [] 9 | isPreloaded: 0 10 | isOverridable: 0 11 | isExplicitlyReferenced: 0 12 | validateReferences: 1 13 | platformData: 14 | - first: 15 | Any: 16 | second: 17 | enabled: 1 18 | settings: {} 19 | - first: 20 | Editor: Editor 21 | second: 22 | enabled: 0 23 | settings: 24 | DefaultValueInitialized: true 25 | - first: 26 | Windows Store Apps: WindowsStoreApps 27 | second: 28 | enabled: 0 29 | settings: 30 | CPU: AnyCPU 31 | userData: 32 | assetBundleName: 33 | assetBundleVariant: 34 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.2017/Assets/Plugins/GameDevWare.Dynamic.Expressions/GameDevWare.Dynamic.Expressions.xml.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6eed8d3d517c5b34ca4d6102b1ee6ee0 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.2017/Assets/Plugins/GameDevWare.Dynamic.Expressions/link.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.2017/Assets/Plugins/GameDevWare.Dynamic.Expressions/link.xml.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: df03a5df82c84cc45b980bb7dde76cf4 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.2017/Assets/Plugins/GameDevWare.Dynamic.Expressions/readme.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 722d7df47fa918c42bd03e56e10b0979 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.2017/Assets/Plugins/GameDevWare.Dynamic.Expressions/readme.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deniszykov/csharp-eval-unity3d/f3251f389b4c430862a3de1896d88effe4c7cdad/src/GameDevWare.Dynamic.Expressions.Unity.2017/Assets/Plugins/GameDevWare.Dynamic.Expressions/readme.pdf -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.2017/Assets/Plugins/GameDevWare.Dynamic.Expressions/readme.pdf.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 10f8f2e4826dfab41b88fd9c79b82d70 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.2017/Assets/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bd813db484eb6214583a3e4a4c1228bc 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.2017/Assets/Scripts/Benchmark.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4a9883bb85edeb84787627a0a24bb12a 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.2017/Assets/Scripts/Benchmark/Benchmark.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b5f88a592a9058f4c9ff44fda653d6dc 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.2017/Assets/Scripts/Benchmark/Benchmark.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8247745d54061cd4fab5bad8e12dc084 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.2017/Assets/Scripts/Example.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e0891460d136bf64aa373220157365d3 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.2017/Assets/Scripts/Example/PatternString.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e9613ff2fc4f57449939ed755c755ee4 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.2021/Assets/Plugins/GameDevWare.Dynamic.Expressions/GameDevWare.Dynamic.Expressions.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deniszykov/csharp-eval-unity3d/f3251f389b4c430862a3de1896d88effe4c7cdad/src/GameDevWare.Dynamic.Expressions.Unity.2021/Assets/Plugins/GameDevWare.Dynamic.Expressions/GameDevWare.Dynamic.Expressions.dll -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.2021/Assets/Plugins/GameDevWare.Dynamic.Expressions/link.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.2021/Assets/Plugins/GameDevWare.Dynamic.Expressions/readme.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deniszykov/csharp-eval-unity3d/f3251f389b4c430862a3de1896d88effe4c7cdad/src/GameDevWare.Dynamic.Expressions.Unity.2021/Assets/Plugins/GameDevWare.Dynamic.Expressions/readme.pdf -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.3.4/Assets/Plugins/GameDevWare.Dynamic.Expressions/GameDevWare.Dynamic.Expressions.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deniszykov/csharp-eval-unity3d/f3251f389b4c430862a3de1896d88effe4c7cdad/src/GameDevWare.Dynamic.Expressions.Unity.3.4/Assets/Plugins/GameDevWare.Dynamic.Expressions/GameDevWare.Dynamic.Expressions.dll -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.3.4/Assets/Plugins/GameDevWare.Dynamic.Expressions/link.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.3.4/Assets/Plugins/GameDevWare.Dynamic.Expressions/readme.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deniszykov/csharp-eval-unity3d/f3251f389b4c430862a3de1896d88effe4c7cdad/src/GameDevWare.Dynamic.Expressions.Unity.3.4/Assets/Plugins/GameDevWare.Dynamic.Expressions/readme.pdf -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.3.4/Assets/Scripts/Benchmark/Benchmark.unity: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!29 &1 4 | OcclusionCullingSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_OcclusionBakeSettings: 8 | smallestOccluder: 5 9 | smallestHole: 0.25 10 | backfaceThreshold: 100 11 | m_SceneGUID: 00000000000000000000000000000000 12 | m_OcclusionCullingData: {fileID: 0} 13 | --- !u!104 &2 14 | RenderSettings: 15 | m_ObjectHideFlags: 0 16 | serializedVersion: 9 17 | m_Fog: 0 18 | m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} 19 | m_FogMode: 3 20 | m_FogDensity: 0.01 21 | m_LinearFogStart: 0 22 | m_LinearFogEnd: 300 23 | m_AmbientSkyColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} 24 | m_AmbientEquatorColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} 25 | m_AmbientGroundColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} 26 | m_AmbientIntensity: 1 27 | m_AmbientMode: 3 28 | m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} 29 | m_SkyboxMaterial: {fileID: 0} 30 | m_HaloStrength: 0.5 31 | m_FlareStrength: 1 32 | m_FlareFadeSpeed: 3 33 | m_HaloTexture: {fileID: 0} 34 | m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} 35 | m_DefaultReflectionMode: 0 36 | m_DefaultReflectionResolution: 128 37 | m_ReflectionBounces: 1 38 | m_ReflectionIntensity: 1 39 | m_CustomReflection: {fileID: 0} 40 | m_Sun: {fileID: 0} 41 | m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} 42 | m_UseRadianceAmbientProbe: 0 43 | --- !u!196 &3 44 | NavMeshSettings: 45 | serializedVersion: 2 46 | m_ObjectHideFlags: 0 47 | m_BuildSettings: 48 | serializedVersion: 2 49 | agentTypeID: 0 50 | agentRadius: 0.5 51 | agentHeight: 2 52 | agentSlope: 45 53 | agentClimb: 0.4 54 | ledgeDropHeight: 0 55 | maxJumpAcrossDistance: 0 56 | minRegionArea: 2 57 | manualCellSize: 0 58 | cellSize: 0.16666667 59 | manualTileSize: 0 60 | tileSize: 256 61 | accuratePlacement: 0 62 | debug: 63 | m_Flags: 0 64 | m_NavMeshData: {fileID: 0} 65 | --- !u!157 &4 66 | LightmapSettings: 67 | m_ObjectHideFlags: 0 68 | serializedVersion: 11 69 | m_GIWorkflowMode: 1 70 | m_GISettings: 71 | serializedVersion: 2 72 | m_BounceScale: 1 73 | m_IndirectOutputScale: 1 74 | m_AlbedoBoost: 1 75 | m_TemporalCoherenceThreshold: 1 76 | m_EnvironmentLightingMode: 0 77 | m_EnableBakedLightmaps: 1 78 | m_EnableRealtimeLightmaps: 0 79 | m_LightmapEditorSettings: 80 | serializedVersion: 10 81 | m_Resolution: 1 82 | m_BakeResolution: 50 83 | m_AtlasSize: 1024 84 | m_AO: 1 85 | m_AOMaxDistance: 1 86 | m_CompAOExponent: 1 87 | m_CompAOExponentDirect: 0 88 | m_Padding: 2 89 | m_LightmapParameters: {fileID: 0} 90 | m_LightmapsBakeMode: 1 91 | m_TextureCompression: 0 92 | m_FinalGather: 0 93 | m_FinalGatherFiltering: 1 94 | m_FinalGatherRayCount: 256 95 | m_ReflectionCompression: 2 96 | m_MixedBakeMode: 1 97 | m_BakeBackend: 0 98 | m_PVRSampling: 1 99 | m_PVRDirectSampleCount: 32 100 | m_PVRSampleCount: 500 101 | m_PVRBounces: 2 102 | m_PVRFilterTypeDirect: 0 103 | m_PVRFilterTypeIndirect: 0 104 | m_PVRFilterTypeAO: 0 105 | m_PVRFilteringMode: 0 106 | m_PVRCulling: 1 107 | m_PVRFilteringGaussRadiusDirect: 1 108 | m_PVRFilteringGaussRadiusIndirect: 5 109 | m_PVRFilteringGaussRadiusAO: 2 110 | m_PVRFilteringAtrousPositionSigmaDirect: 0.5 111 | m_PVRFilteringAtrousPositionSigmaIndirect: 2 112 | m_PVRFilteringAtrousPositionSigmaAO: 1 113 | m_ShowResolutionOverlay: 1 114 | m_LightingDataAsset: {fileID: 0} 115 | m_UseShadowmask: 0 116 | --- !u!1 &5 117 | GameObject: 118 | m_ObjectHideFlags: 0 119 | m_CorrespondingSourceObject: {fileID: 0} 120 | m_PrefabInternal: {fileID: 0} 121 | serializedVersion: 6 122 | m_Component: 123 | - component: {fileID: 6} 124 | - component: {fileID: 7} 125 | m_Layer: 0 126 | m_Name: GameObject 127 | m_TagString: Untagged 128 | m_Icon: {fileID: 0} 129 | m_NavMeshLayer: 0 130 | m_StaticEditorFlags: 0 131 | m_IsActive: 1 132 | --- !u!4 &6 133 | Transform: 134 | m_ObjectHideFlags: 0 135 | m_CorrespondingSourceObject: {fileID: 0} 136 | m_PrefabInternal: {fileID: 0} 137 | m_GameObject: {fileID: 5} 138 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 139 | m_LocalPosition: {x: 0, y: 0, z: 0} 140 | m_LocalScale: {x: 1, y: 1, z: 1} 141 | m_Children: [] 142 | m_Father: {fileID: 0} 143 | m_RootOrder: 0 144 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 145 | --- !u!114 &7 146 | MonoBehaviour: 147 | m_ObjectHideFlags: 0 148 | m_CorrespondingSourceObject: {fileID: 0} 149 | m_PrefabInternal: {fileID: 0} 150 | m_GameObject: {fileID: 5} 151 | m_Enabled: 1 152 | m_EditorHideFlags: 0 153 | m_Script: {fileID: 11500000, guid: 628b01c0a7f61704e9b272cda9315199, type: 3} 154 | m_Name: 155 | m_EditorClassIdentifier: 156 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.5.4/Assets/Plugins.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1ae58046e47cbdf44b7b99fcf5acbad9 3 | folderAsset: yes 4 | timeCreated: 1570568401 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.5.4/Assets/Plugins/GameDevWare.Dynamic.Expressions.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9d69cc97fad449347b018421372d9578 3 | folderAsset: yes 4 | timeCreated: 1570568401 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.5.4/Assets/Plugins/GameDevWare.Dynamic.Expressions/GameDevWare.Dynamic.Expressions.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deniszykov/csharp-eval-unity3d/f3251f389b4c430862a3de1896d88effe4c7cdad/src/GameDevWare.Dynamic.Expressions.Unity.5.4/Assets/Plugins/GameDevWare.Dynamic.Expressions/GameDevWare.Dynamic.Expressions.dll -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.5.4/Assets/Plugins/GameDevWare.Dynamic.Expressions/GameDevWare.Dynamic.Expressions.dll.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: efb9d3f82887dc64592dd6db14316602 3 | timeCreated: 1570568405 4 | licenseType: Free 5 | PluginImporter: 6 | serializedVersion: 1 7 | iconMap: {} 8 | executionOrder: {} 9 | isPreloaded: 0 10 | platformData: 11 | Any: 12 | enabled: 1 13 | settings: {} 14 | Editor: 15 | enabled: 0 16 | settings: 17 | DefaultValueInitialized: true 18 | WindowsStoreApps: 19 | enabled: 0 20 | settings: 21 | CPU: AnyCPU 22 | userData: 23 | assetBundleName: 24 | assetBundleVariant: 25 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.5.4/Assets/Plugins/GameDevWare.Dynamic.Expressions/GameDevWare.Dynamic.Expressions.xml.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d0f1cba9739d30f4a954358611fa0f7c 3 | timeCreated: 1570568411 4 | licenseType: Free 5 | TextScriptImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.5.4/Assets/Plugins/GameDevWare.Dynamic.Expressions/link.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.5.4/Assets/Plugins/GameDevWare.Dynamic.Expressions/link.xml.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4ee46deb0448f89448651eadd1d43ded 3 | timeCreated: 1570568411 4 | licenseType: Free 5 | TextScriptImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.5.4/Assets/Plugins/GameDevWare.Dynamic.Expressions/readme.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2e51d62792a3e984fb9a41493aa5744c 3 | timeCreated: 1570568401 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.5.4/Assets/Plugins/GameDevWare.Dynamic.Expressions/readme.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deniszykov/csharp-eval-unity3d/f3251f389b4c430862a3de1896d88effe4c7cdad/src/GameDevWare.Dynamic.Expressions.Unity.5.4/Assets/Plugins/GameDevWare.Dynamic.Expressions/readme.pdf -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.5.4/Assets/Plugins/GameDevWare.Dynamic.Expressions/readme.pdf.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dcd3c46b3d781624fb22e9d7632e064c 3 | timeCreated: 1570568401 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.5.4/Assets/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8b719686ce99db64da8578f0252d9b61 3 | folderAsset: yes 4 | timeCreated: 1570568401 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.5.4/Assets/Scripts/Benchmark.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 930c3c63753ab284097bbfb0ce9ca613 3 | folderAsset: yes 4 | timeCreated: 1570568401 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.5.4/Assets/Scripts/Benchmark/Benchmark.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f0d68e26ce28dac4e9d9bc18a36cda1c 3 | timeCreated: 1570568407 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.5.4/Assets/Scripts/Benchmark/Benchmark.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deniszykov/csharp-eval-unity3d/f3251f389b4c430862a3de1896d88effe4c7cdad/src/GameDevWare.Dynamic.Expressions.Unity.5.4/Assets/Scripts/Benchmark/Benchmark.unity -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.5.4/Assets/Scripts/Benchmark/Benchmark.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2f9a93fb08c01b54b9574973c88ef871 3 | timeCreated: 1570568401 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.5.4/Assets/Scripts/Example.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ca1146a2c08fc2348a941a96398c438d 3 | folderAsset: yes 4 | timeCreated: 1570568401 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.Unity.5.4/Assets/Scripts/Example/PatternString.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8f0e4adbd63505442b6c037e9e2d5085 3 | timeCreated: 1570568407 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GameDevWare.Dynamic.Expressions", "GameDevWare.Dynamic.Expressions\GameDevWare.Dynamic.Expressions.csproj", "{7F3A50D9-2B2D-49AF-8B53-84688AFB173B}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{B71D05C3-DFA6-4729-A9FE-F72441F14EE5}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GameDevWare.Dynamic.Expressions.Tests", "GameDevWare.Dynamic.Expressions.Tests\GameDevWare.Dynamic.Expressions.Tests.csproj", "{A630347B-70E5-4520-8673-9D2D139D1742}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {7F3A50D9-2B2D-49AF-8B53-84688AFB173B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {7F3A50D9-2B2D-49AF-8B53-84688AFB173B}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {7F3A50D9-2B2D-49AF-8B53-84688AFB173B}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {7F3A50D9-2B2D-49AF-8B53-84688AFB173B}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {A630347B-70E5-4520-8673-9D2D139D1742}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {A630347B-70E5-4520-8673-9D2D139D1742}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {A630347B-70E5-4520-8673-9D2D139D1742}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {A630347B-70E5-4520-8673-9D2D139D1742}.Release|Any CPU.Build.0 = Release|Any CPU 26 | EndGlobalSection 27 | GlobalSection(SolutionProperties) = preSolution 28 | HideSolutionNode = FALSE 29 | EndGlobalSection 30 | GlobalSection(NestedProjects) = preSolution 31 | {A630347B-70E5-4520-8673-9D2D139D1742} = {B71D05C3-DFA6-4729-A9FE-F72441F14EE5} 32 | EndGlobalSection 33 | EndGlobal 34 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/.gitignore: -------------------------------------------------------------------------------- 1 | *.bat 2 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/ArrayUtils.cs: -------------------------------------------------------------------------------- 1 | 2 | 3 | using System; 4 | 5 | namespace GameDevWare.Dynamic.Expressions 6 | { 7 | internal static class ArrayUtils 8 | { 9 | private class EmptyArray 10 | { 11 | public static T[] Value = new T[0]; 12 | } 13 | 14 | public static ResultT[] ConvertAll(this T[] array, 15 | #if NETSTANDARD 16 | Func converter 17 | #else 18 | Converter converter 19 | #endif 20 | ) 21 | { 22 | if (array == null) throw new ArgumentNullException("array"); 23 | if (converter == null) throw new ArgumentNullException("converter"); 24 | 25 | #if NETSTANDARD 26 | var result = new ResultT[array.Length]; 27 | for (var i = 0; i < array.Length; i++) 28 | result[i] = converter(array[i]); 29 | return result; 30 | #else 31 | 32 | return Array.ConvertAll(array, converter); 33 | #endif 34 | } 35 | public static T[] Empty() 36 | { 37 | #if NETCOREAPP 38 | return Array.Empty(); 39 | #else 40 | return EmptyArray.Value; 41 | #endif 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/AssemblyTypeResolver.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ 16 | 17 | using System; 18 | using System.Collections.Generic; 19 | using System.Linq; 20 | using System.Reflection; 21 | 22 | namespace GameDevWare.Dynamic.Expressions 23 | { 24 | /// 25 | /// which allows any public () type from specified (or multiple . 26 | /// 27 | public sealed class AssemblyTypeResolver : KnownTypeResolver 28 | { 29 | #if UNITY_5 || UNITY_4 || UNITY_3_3 || UNITY_3_4 || UNITY_3_5 30 | public static readonly AssemblyTypeResolver UnityEngine = new AssemblyTypeResolver(typeof(UnityEngine.Application).Assembly); 31 | #endif 32 | 33 | /// 34 | /// Creates new from list of assemblies. 35 | /// 36 | /// List of assemblies to add as source of known types. 37 | public AssemblyTypeResolver(params Assembly[] assemblies) 38 | : this((IEnumerable)assemblies, null) 39 | { 40 | 41 | } 42 | /// 43 | /// Creates new from list of assemblies. 44 | /// 45 | /// List of assemblies to add as source of known types. 46 | public AssemblyTypeResolver(IEnumerable assemblies) 47 | : this(assemblies, null) 48 | { 49 | } 50 | /// 51 | /// Creates new from list of assemblies. 52 | /// 53 | /// Backup type resolver used if current can't find a type. 54 | /// List of assemblies to add as source of known types. 55 | public AssemblyTypeResolver(IEnumerable assemblies, ITypeResolver otherTypeResolver) 56 | : base(GetAssembliesPublicTypes(assemblies ?? ArrayUtils.Empty()), otherTypeResolver) 57 | { 58 | if (assemblies == null) throw new ArgumentNullException("assemblies"); 59 | } 60 | 61 | #if NETSTANDARD 62 | private static IEnumerable GetAssembliesPublicTypes(IEnumerable assemblies) 63 | { 64 | if (assemblies == null) throw new ArgumentNullException("assemblies"); 65 | 66 | foreach (var assembly in assemblies) 67 | { 68 | foreach (var type in assembly.DefinedTypes) 69 | { 70 | if (type.IsPublic) 71 | yield return type.AsType(); 72 | } 73 | } 74 | } 75 | #else 76 | private static IEnumerable GetAssembliesPublicTypes(IEnumerable assemblies) 77 | { 78 | if (assemblies == null) throw new ArgumentNullException("assemblies"); 79 | 80 | foreach (var assembly in assemblies) 81 | { 82 | foreach (var type in assembly.GetTypes()) 83 | { 84 | if (type.IsPublic) 85 | yield return type; 86 | } 87 | } 88 | } 89 | #endif 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Binding/ConditionBinder.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ 16 | 17 | using System; 18 | using System.Diagnostics; 19 | using System.Linq.Expressions; 20 | 21 | namespace GameDevWare.Dynamic.Expressions.Binding 22 | { 23 | internal static class ConditionBinder 24 | { 25 | public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError) 26 | { 27 | if (node == null) throw new ArgumentNullException("node"); 28 | if (bindingContext == null) throw new ArgumentNullException("bindingContext"); 29 | if (expectedType == null) throw new ArgumentNullException("expectedType"); 30 | 31 | bindingError = null; 32 | boundExpression = null; 33 | 34 | var test = node.GetTestExpression(throwOnError: true); 35 | var ifTrue = node.GetIfTrueExpression(throwOnError: true); 36 | var ifFalse = node.GetIfFalseExpression(throwOnError: true); 37 | var testExpression = default(Expression); 38 | var ifTrueBranch = default(Expression); 39 | var ifFalseBranch = default(Expression); 40 | 41 | if (AnyBinder.TryBindInNewScope(test, bindingContext, TypeDescription.GetTypeDescription(typeof(bool)), out testExpression, out bindingError) == false) 42 | return false; 43 | if (AnyBinder.TryBindInNewScope(ifTrue, bindingContext, TypeDescription.ObjectType, out ifTrueBranch, out bindingError) == false) 44 | return false; 45 | if (AnyBinder.TryBindInNewScope(ifFalse, bindingContext, TypeDescription.ObjectType, out ifFalseBranch, out bindingError) == false) 46 | return false; 47 | 48 | Debug.Assert(testExpression != null, "testExpression != null"); 49 | Debug.Assert(ifTrueBranch != null, "ifTrueBranch != null"); 50 | Debug.Assert(ifFalseBranch != null, "ifFalseBranch != null"); 51 | 52 | if (ExpressionUtils.TryPromoteBinaryOperation(ref ifTrueBranch, ref ifFalseBranch, ExpressionType.Conditional, out boundExpression) == false) 53 | { 54 | if (ifTrueBranch.Type != ifFalseBranch.Type) 55 | { 56 | float quality; 57 | ExpressionUtils.TryCoerceType(ref ifTrueBranch, ifFalseBranch.Type, out quality); 58 | } 59 | 60 | boundExpression = Expression.Condition(testExpression, ifTrueBranch, ifFalseBranch); 61 | } 62 | return true; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Binding/ConstantBinder.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ 16 | 17 | using System; 18 | using System.Linq.Expressions; 19 | using System.Reflection; 20 | 21 | namespace GameDevWare.Dynamic.Expressions.Binding 22 | { 23 | internal static class ConstantBinder 24 | { 25 | public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError) 26 | { 27 | if (node == null) throw new ArgumentNullException("node"); 28 | if (bindingContext == null) throw new ArgumentNullException("bindingContext"); 29 | if (expectedType == null) throw new ArgumentNullException("expectedType"); 30 | 31 | boundExpression = null; 32 | bindingError = null; 33 | 34 | var valueObj = node.GetValue(throwOnError: true); 35 | var typeName = node.GetTypeName(throwOnError: true); 36 | var type = default(Type); 37 | if (bindingContext.TryResolveType(typeName, out type) == false) 38 | { 39 | bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETORESOLVETYPE, typeName), node); 40 | return false; 41 | } 42 | 43 | var typeDescription = TypeDescription.GetTypeDescription(type); 44 | if (valueObj == null && (typeDescription.IsNullable || typeDescription.IsValueType == false)) 45 | { 46 | boundExpression = Expression.Constant(null, type); 47 | } 48 | else 49 | { 50 | var value = ChangeType(valueObj, type); 51 | boundExpression = Expression.Constant(value, type); 52 | } 53 | 54 | return true; 55 | } 56 | 57 | public static object ChangeType(object value, Type toType) 58 | { 59 | if (toType == null) throw new ArgumentNullException("toType"); 60 | 61 | if (toType.GetTypeInfo().IsEnum) 62 | return Enum.Parse(toType, Convert.ToString(value, Constants.DefaultFormatProvider)); 63 | else 64 | return Convert.ChangeType(value, toType, Constants.DefaultFormatProvider); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Binding/DefaultBinder.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ 16 | 17 | using System; 18 | using System.Linq.Expressions; 19 | 20 | namespace GameDevWare.Dynamic.Expressions.Binding 21 | { 22 | internal static class DefaultBinder 23 | { 24 | public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError) 25 | { 26 | if (node == null) throw new ArgumentNullException("node"); 27 | if (bindingContext == null) throw new ArgumentNullException("bindingContext"); 28 | if (expectedType == null) throw new ArgumentNullException("expectedType"); 29 | 30 | boundExpression = null; 31 | bindingError = null; 32 | 33 | var typeName = node.GetTypeName(throwOnError: true); 34 | var type = default(Type); 35 | if (bindingContext.TryResolveType(typeName, out type) == false) 36 | { 37 | bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETORESOLVETYPE, typeName), node); 38 | return false; 39 | } 40 | 41 | var typeDescription = TypeDescription.GetTypeDescription(type); 42 | boundExpression = typeDescription.DefaultExpression; 43 | 44 | return true; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Binding/GroupBinder.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ 16 | 17 | using System; 18 | using System.Linq.Expressions; 19 | 20 | namespace GameDevWare.Dynamic.Expressions.Binding 21 | { 22 | internal static class GroupBinder 23 | { 24 | public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError) 25 | { 26 | if (node == null) throw new ArgumentNullException("node"); 27 | if (bindingContext == null) throw new ArgumentNullException("bindingContext"); 28 | if (expectedType == null) throw new ArgumentNullException("expectedType"); 29 | 30 | boundExpression = null; 31 | bindingError = null; 32 | 33 | var expressionNode = node.GetExpression(throwOnError: true); 34 | 35 | return AnyBinder.TryBindInNewScope(expressionNode, bindingContext, expectedType, out boundExpression, out bindingError); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Binding/IndexBinder.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ 16 | 17 | using System; 18 | using System.Diagnostics; 19 | using System.Linq.Expressions; 20 | using GameDevWare.Dynamic.Expressions.Properties; 21 | 22 | namespace GameDevWare.Dynamic.Expressions.Binding 23 | { 24 | internal static class IndexBinder 25 | { 26 | public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError) 27 | { 28 | boundExpression = null; 29 | bindingError = null; 30 | 31 | var useNullPropagation = node.GetUseNullPropagation(throwOnError: false); 32 | var arguments = node.GetArguments(throwOnError: true); 33 | var targetNode = node.GetExpression(throwOnError: true); 34 | var target = default(Expression); 35 | if (AnyBinder.TryBind(targetNode, bindingContext, TypeDescription.ObjectType, out target, out bindingError) == false) 36 | return false; 37 | 38 | Debug.Assert(target != null, "target != null"); 39 | 40 | var targetTypeDescription = TypeDescription.GetTypeDescription(target.Type); 41 | if (target.Type.IsArray) 42 | { 43 | var indexType = TypeDescription.Int32Type; 44 | var indexingExpressions = new Expression[arguments.Count]; 45 | for (var i = 0; i < indexingExpressions.Length; i++) 46 | { 47 | var argument = default(SyntaxTreeNode); 48 | if (arguments.TryGetValue(i, out argument) == false) 49 | { 50 | bindingError = new ExpressionParserException(string.Format(Resources.EXCEPTION_BIND_MISSINGMETHODPARAMETER, i), node); 51 | return false; 52 | } 53 | 54 | if (AnyBinder.TryBindInNewScope(argument, bindingContext, indexType, out indexingExpressions[i], out bindingError) == false) 55 | return false; 56 | 57 | Debug.Assert(indexingExpressions[i] != null, "indexingExpressions[i] != null"); 58 | } 59 | 60 | try 61 | { 62 | if (indexingExpressions.Length == 1) 63 | boundExpression = Expression.ArrayIndex(target, indexingExpressions[0]); 64 | else 65 | boundExpression = Expression.ArrayIndex(target, indexingExpressions); 66 | } 67 | catch (Exception exception) 68 | { 69 | bindingError = new ExpressionParserException(exception.Message, exception, node); 70 | return false; 71 | } 72 | } 73 | else 74 | { 75 | var selectedIndexerQuality = MemberDescription.QUALITY_INCOMPATIBLE; 76 | foreach (var indexer in targetTypeDescription.Indexers) 77 | { 78 | var indexerQuality = MemberDescription.QUALITY_INCOMPATIBLE; 79 | var indexerCall = default(Expression); 80 | if (indexer.TryMakeCall(target, arguments, bindingContext, out indexerCall, out indexerQuality) == false) 81 | continue; 82 | if (indexerQuality <= selectedIndexerQuality) 83 | continue; 84 | 85 | boundExpression = indexerCall; 86 | selectedIndexerQuality = indexerQuality; 87 | } 88 | } 89 | if (boundExpression == null) 90 | { 91 | bindingError = new ExpressionParserException(string.Format(Resources.EXCEPTION_BIND_UNABLETOBINDINDEXER, target.Type), node); 92 | return false; 93 | } 94 | 95 | if (useNullPropagation && targetTypeDescription.CanBeNull) 96 | bindingContext.RegisterNullPropagationTarget(target); 97 | 98 | return true; 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Binding/ListInitBinder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace GameDevWare.Dynamic.Expressions.Binding 5 | { 6 | internal class ListInitBinder 7 | { 8 | public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError) 9 | { 10 | if (node == null) throw new ArgumentNullException("node"); 11 | if (bindingContext == null) throw new ArgumentNullException("bindingContext"); 12 | if (expectedType == null) throw new ArgumentNullException("expectedType"); 13 | 14 | boundExpression = null; 15 | bindingError = null; 16 | 17 | var newNode = node.GetNewExpression(throwOnError: true); 18 | var newExpression = default(Expression); 19 | if (AnyBinder.TryBind(newNode, bindingContext, TypeDescription.ObjectType, out newExpression, out bindingError) == false || 20 | newExpression is NewExpression == false) 21 | { 22 | if (bindingError == null) 23 | bindingError = new ExpressionParserException(Properties.Resources.EXCEPTION_BIND_FAILEDTOBINDNEWEXPRESSION, node); 24 | return false; 25 | } 26 | 27 | var initializers = default(ElementInit[]); 28 | if (TryGetListInitializers(node, bindingContext, out initializers, out bindingError) == false) 29 | { 30 | if (bindingError == null) 31 | bindingError = new ExpressionParserException(Properties.Resources.EXCEPTION_BIND_FAILEDTOBINDLISTINITIALIZERS, node); 32 | return false; 33 | } 34 | 35 | boundExpression = Expression.ListInit((NewExpression)newExpression, initializers); 36 | return true; 37 | } 38 | 39 | internal static bool TryGetListInitializers(SyntaxTreeNode listNode, BindingContext bindingContext, out ElementInit[] initializers, out Exception bindingError) 40 | { 41 | if (listNode == null) throw new ArgumentNullException("listNode"); 42 | if (bindingContext == null) throw new ArgumentNullException("bindingContext"); 43 | 44 | bindingError = null; 45 | var initializerNodes = listNode.GetInitializers(throwOnError: true); 46 | initializers = new ElementInit[initializerNodes.Count]; 47 | for (var i = 0; i < initializers.Length; i++) 48 | { 49 | var index = Constants.GetIndexAsString(i); 50 | var initializerObj = default(object); 51 | if (initializerNodes.TryGetValue(index, out initializerObj) == false || initializerObj is SyntaxTreeNode == false) 52 | { 53 | return false; // failed to get initializer #i 54 | } 55 | var initializerNode = (SyntaxTreeNode)initializerObj; 56 | var addMethodName = initializerNode.GetMethodName(throwOnError: true); 57 | var addMethod = default(MemberDescription); 58 | if (bindingContext.TryResolveMember(addMethodName, out addMethod) == false || addMethod.IsMethod == false) 59 | { 60 | return false; // failed to resolve 'Add' method 61 | } 62 | 63 | var argumentNodes = initializerNode.GetArguments(throwOnError: true); 64 | var arguments = new Expression[argumentNodes.Count]; 65 | for (var p = 0; p < arguments.Length; p++) 66 | { 67 | var parameter = addMethod.GetParameter(p); 68 | var parameterType = TypeDescription.GetTypeDescription(parameter.ParameterType); 69 | var argumentNode = default(SyntaxTreeNode); 70 | if (argumentNodes.TryGetValue(p, out argumentNode) == false && argumentNodes.TryGetValue(parameter.Name, out argumentNode) == false) 71 | { 72 | return false; // failed to find argument #p 73 | } 74 | 75 | if (AnyBinder.TryBindInNewScope(argumentNode, bindingContext, parameterType, out arguments[p], out bindingError) == false) 76 | { 77 | return false; // failed to bind argument #p 78 | } 79 | } 80 | initializers[i] = Expression.ElementInit(addMethod, arguments); 81 | } 82 | return true; 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Binding/MemberInitBinder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | using System.Reflection; 4 | 5 | namespace GameDevWare.Dynamic.Expressions.Binding 6 | { 7 | internal static class MemberInitBinder 8 | { 9 | public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError) 10 | { 11 | if (node == null) throw new ArgumentNullException("node"); 12 | if (bindingContext == null) throw new ArgumentNullException("bindingContext"); 13 | if (expectedType == null) throw new ArgumentNullException("expectedType"); 14 | 15 | boundExpression = null; 16 | bindingError = null; 17 | 18 | var newNode = node.GetNewExpression(throwOnError: true); 19 | var newExpression = default(Expression); 20 | if (AnyBinder.TryBind(newNode, bindingContext, TypeDescription.ObjectType, out newExpression, out bindingError) == false || 21 | newExpression is NewExpression == false) 22 | { 23 | if (bindingError == null) 24 | bindingError = new ExpressionParserException(Properties.Resources.EXCEPTION_BIND_FAILEDTOBINDNEWEXPRESSION, node); 25 | return false; 26 | } 27 | 28 | var bindings = default(MemberBinding[]); 29 | if (TryGetBindings(node, bindingContext, out bindings, out bindingError) == false) 30 | { 31 | return false; 32 | } 33 | 34 | boundExpression = Expression.MemberInit((NewExpression)newExpression, bindings); 35 | return true; 36 | } 37 | private static bool TryGetBindings(SyntaxTreeNode node, BindingContext bindingContext, out MemberBinding[] bindings, out Exception bindingError) 38 | { 39 | if (node == null) throw new ArgumentNullException("node"); 40 | if (bindingContext == null) throw new ArgumentNullException("bindingContext"); 41 | 42 | var bindingNodes = node.GetBindings(throwOnError: true); 43 | bindingError = null; 44 | 45 | bindings = new MemberBinding[bindingNodes.Count]; 46 | for (var i = 0; i < bindings.Length; i++) 47 | { 48 | if (TryGetBinding(bindingNodes[Constants.GetIndexAsString(i)], bindingContext, out bindings[i], out bindingError)) 49 | continue; 50 | 51 | bindingError = bindingError ?? new ExpressionParserException(Properties.Resources.EXCEPTION_BIND_FAILEDTOBINDMEMBERBINDINGS, node); 52 | return false; 53 | } 54 | 55 | return true; 56 | } 57 | private static bool TryGetBinding(object bindingNode, BindingContext bindingContext, out MemberBinding memberBinding, out Exception bindingError) 58 | { 59 | bindingError = null; 60 | memberBinding = null; 61 | var bindingNodeTree = bindingNode as SyntaxTreeNode; 62 | if (bindingNodeTree == null) 63 | { 64 | return false; 65 | } 66 | 67 | var bindingType = (string)bindingNodeTree.GetTypeName(throwOnError: true); 68 | var memberObj = bindingNodeTree.GetMember(throwOnError: true); 69 | var member = default(MemberDescription); 70 | if (bindingContext.TryResolveMember(memberObj, out member) == false) 71 | { 72 | return false; 73 | } 74 | var memberValueType = TypeDescription.GetTypeDescription(member.ResultType); 75 | 76 | // ReSharper disable once SwitchStatementMissingSomeCases 77 | switch (bindingType) 78 | { 79 | case "Assignment": 80 | var expressionNode = bindingNodeTree.GetExpression(throwOnError: true); 81 | var expression = default(Expression); 82 | if (AnyBinder.TryBindInNewScope(expressionNode, bindingContext, memberValueType, out expression, out bindingError) == false) 83 | { 84 | return false; // file to bind member's value 85 | } 86 | 87 | if (member.IsMethod) 88 | memberBinding = Expression.Bind((MethodInfo)member, expression); 89 | else 90 | memberBinding = Expression.Bind((MemberInfo)member, expression); 91 | return true; 92 | case "MemberBinding": 93 | var bindings = default(MemberBinding[]); 94 | if (TryGetBindings(bindingNodeTree, bindingContext, out bindings, out bindingError) == false) 95 | { 96 | return false; // failed to resolve bindings 97 | } 98 | if (member.IsMethod) 99 | memberBinding = Expression.MemberBind((MethodInfo)member, bindings); 100 | else 101 | memberBinding = Expression.MemberBind((MemberInfo)member, bindings); 102 | return true; 103 | case "ListBinding": 104 | var initializers = default(ElementInit[]); 105 | if (ListInitBinder.TryGetListInitializers(bindingNodeTree, bindingContext, out initializers, out bindingError) == false) 106 | { 107 | return false; // failed to resolve list initializers 108 | } 109 | if (member.IsMethod) 110 | memberBinding = Expression.ListBind((MethodInfo)member, initializers); 111 | else 112 | memberBinding = Expression.ListBind((MemberInfo)member, initializers); 113 | return true; 114 | } 115 | 116 | return false; 117 | } 118 | 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Binding/NewArrayBoundsBinder.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ 16 | 17 | using System; 18 | using System.Diagnostics; 19 | using System.Linq.Expressions; 20 | 21 | namespace GameDevWare.Dynamic.Expressions.Binding 22 | { 23 | internal static class NewArrayBoundsBinder 24 | { 25 | public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError) 26 | { 27 | if (node == null) throw new ArgumentNullException("node"); 28 | if (bindingContext == null) throw new ArgumentNullException("bindingContext"); 29 | if (expectedType == null) throw new ArgumentNullException("expectedType"); 30 | 31 | boundExpression = null; 32 | bindingError = null; 33 | 34 | var typeName = node.GetTypeName(throwOnError: true); 35 | var type = default(Type); 36 | if (bindingContext.TryResolveType(typeName, out type) == false) 37 | { 38 | bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETORESOLVETYPE, typeName), node); 39 | return false; 40 | } 41 | 42 | var indexTypeDescription = TypeDescription.Int32Type; 43 | var arguments = node.GetArguments(throwOnError: true); 44 | var argumentExpressions = new Expression[arguments.Count]; 45 | for (var i = 0; i < arguments.Count; i++) 46 | { 47 | var argument = default(SyntaxTreeNode); 48 | if (arguments.TryGetValue(i, out argument) == false) 49 | { 50 | bindingError = new ExpressionParserException(Properties.Resources.EXCEPTION_BOUNDEXPR_ARGSDOESNTMATCHPARAMS, node); 51 | return false; 52 | } 53 | 54 | if (AnyBinder.TryBindInNewScope(argument, bindingContext, indexTypeDescription, out argumentExpressions[i], out bindingError) == false) 55 | return false; 56 | 57 | Debug.Assert(argumentExpressions[i] != null, "argumentExpressions[i] != null"); 58 | } 59 | 60 | boundExpression = Expression.NewArrayBounds(type, argumentExpressions); 61 | return true; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Binding/NewArrayInitBinder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace GameDevWare.Dynamic.Expressions.Binding 5 | { 6 | internal static class NewArrayInitBinder 7 | { 8 | public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError) 9 | { 10 | if (node == null) throw new ArgumentNullException("node"); 11 | if (bindingContext == null) throw new ArgumentNullException("bindingContext"); 12 | if (expectedType == null) throw new ArgumentNullException("expectedType"); 13 | 14 | boundExpression = null; 15 | bindingError = null; 16 | 17 | var typeName = node.GetTypeName(throwOnError: true); 18 | var type = default(Type); 19 | if (bindingContext.TryResolveType(typeName, out type) == false) 20 | { 21 | bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETORESOLVETYPE, typeName), node); 22 | return false; 23 | } 24 | 25 | var elementType = TypeDescription.GetTypeDescription(type); 26 | var arguments = node.GetArguments(throwOnError: true); 27 | var argumentExpressions = new Expression[arguments.Count]; 28 | for (var i = 0; i < arguments.Count; i++) 29 | { 30 | var argument = default(SyntaxTreeNode); 31 | if (arguments.TryGetValue(i, out argument) == false) 32 | { 33 | bindingError = new ExpressionParserException(Properties.Resources.EXCEPTION_BOUNDEXPR_ARGSDOESNTMATCHPARAMS, node); 34 | return false; 35 | } 36 | 37 | if (AnyBinder.TryBindInNewScope(argument, bindingContext, elementType, out argumentExpressions[i], out bindingError) == false) 38 | return false; 39 | } 40 | 41 | boundExpression = Expression.NewArrayInit(type, argumentExpressions); 42 | return true; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Binding/NumberUtils.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ 16 | 17 | using System; 18 | namespace GameDevWare.Dynamic.Expressions.Binding 19 | { 20 | internal static class NumberUtils 21 | { 22 | private static readonly int[] SignedIntegerTypes; 23 | private static readonly int[] UnsignedIntegerTypes; 24 | private static readonly int[] NumberTypes; 25 | 26 | static NumberUtils() 27 | { 28 | SignedIntegerTypes = new[] { (int)TypeCode.SByte, (int)TypeCode.Int16, (int)TypeCode.Int32, (int)TypeCode.Int64 }; 29 | UnsignedIntegerTypes = new[] { (int)TypeCode.Byte, (int)TypeCode.UInt16, (int)TypeCode.UInt32, (int)TypeCode.UInt64 }; 30 | NumberTypes = new[] 31 | { 32 | (int)TypeCode.SByte, (int)TypeCode.Int16, (int)TypeCode.Int32, (int)TypeCode.Int64, 33 | (int)TypeCode.Byte, (int)TypeCode.UInt16, (int)TypeCode.UInt32, (int)TypeCode.UInt64, 34 | (int)TypeCode.Single, (int)TypeCode.Double, (int)TypeCode.Decimal, 35 | }; 36 | Array.Sort(NumberTypes); 37 | Array.Sort(SignedIntegerTypes); 38 | Array.Sort(UnsignedIntegerTypes); 39 | } 40 | 41 | public static bool IsNumber(Type type) 42 | { 43 | if (type == null) throw new ArgumentNullException("type"); 44 | 45 | return IsNumber(ReflectionUtils.GetTypeCode(type)); 46 | } 47 | public static bool IsNumber(TypeCode type) 48 | { 49 | return Array.BinarySearch(NumberTypes, (int) type) >= 0; 50 | } 51 | 52 | public static bool IsSignedInteger(Type type) 53 | { 54 | if (type == null) throw new ArgumentNullException("type"); 55 | 56 | return IsSignedInteger(ReflectionUtils.GetTypeCode(type)); 57 | } 58 | public static bool IsSignedInteger(TypeCode type) 59 | { 60 | return Array.BinarySearch(SignedIntegerTypes, (int)type) >= 0; 61 | } 62 | 63 | public static bool IsUnsignedInteger(Type type) 64 | { 65 | if (type == null) throw new ArgumentNullException("type"); 66 | 67 | return IsUnsignedInteger(ReflectionUtils.GetTypeCode(type)); 68 | } 69 | public static bool IsUnsignedInteger(TypeCode type) 70 | { 71 | return Array.BinarySearch(UnsignedIntegerTypes, (int)type) >= 0; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Binding/ParameterBinder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace GameDevWare.Dynamic.Expressions.Binding 5 | { 6 | internal static class ParameterBinder 7 | { 8 | public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError) 9 | { 10 | if (node == null) throw new ArgumentNullException("node"); 11 | if (bindingContext == null) throw new ArgumentNullException("bindingContext"); 12 | if (expectedType == null) throw new ArgumentNullException("expectedType"); 13 | 14 | bindingError = null; 15 | 16 | var name = node.GetMemberName(throwOnError: true); 17 | 18 | if (bindingContext.TryGetParameter(name, out boundExpression)) 19 | return true; 20 | 21 | var typeName = node.GetTypeName(throwOnError: false); 22 | var type = default(Type); 23 | if (bindingContext.TryResolveType(typeName, out type) == false) 24 | { 25 | bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETORESOLVETYPE, typeName), node); 26 | return false; 27 | } 28 | 29 | boundExpression = Expression.Parameter(type, name); 30 | return true; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Binding/QuoteBinder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace GameDevWare.Dynamic.Expressions.Binding 5 | { 6 | internal static class QuoteBinder 7 | { 8 | public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError) 9 | { 10 | bindingError = null; 11 | 12 | boundExpression = null; 13 | bindingError = null; 14 | 15 | var operandNode = node.GetExpression(throwOnError: true); 16 | var operand = default(Expression); 17 | 18 | if (AnyBinder.TryBindInNewScope(operandNode, bindingContext, TypeDescription.ObjectType, out operand, out bindingError) == false) 19 | return false; 20 | 21 | boundExpression = Expression.Quote(operand); 22 | return true; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Binding/TypeBinaryBinder.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ 16 | 17 | using System; 18 | using System.Diagnostics; 19 | using System.Linq.Expressions; 20 | 21 | namespace GameDevWare.Dynamic.Expressions.Binding 22 | { 23 | internal static class TypeBinaryBinder 24 | { 25 | public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError) 26 | { 27 | if (node == null) throw new ArgumentNullException("node"); 28 | if (bindingContext == null) throw new ArgumentNullException("bindingContext"); 29 | if (expectedType == null) throw new ArgumentNullException("expectedType"); 30 | 31 | boundExpression = null; 32 | bindingError = null; 33 | 34 | var expressionType = node.GetExpressionType(throwOnError: true); 35 | var targetNode = node.GetExpression(throwOnError: true); 36 | var typeName = node.GetTypeName(throwOnError: true); 37 | var type = default(Type); 38 | if (bindingContext.TryResolveType(typeName, out type) == false) 39 | { 40 | bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETORESOLVETYPE, typeName), node); 41 | return false; 42 | } 43 | 44 | var target = default(Expression); 45 | if (AnyBinder.TryBindInNewScope(targetNode, bindingContext, TypeDescription.ObjectType, out target, out bindingError) == false) 46 | return false; 47 | 48 | Debug.Assert(target != null, "target != null"); 49 | 50 | switch (expressionType) 51 | { 52 | case Constants.EXPRESSION_TYPE_TYPE_IS: 53 | boundExpression = Expression.TypeIs(target, type); 54 | break; 55 | case Constants.EXPRESSION_TYPE_TYPE_AS: 56 | boundExpression = Expression.TypeAs(target, type); 57 | break; 58 | case Constants.EXPRESSION_TYPE_CONVERT: 59 | boundExpression = Expression.Convert(target, type); 60 | break; 61 | case Constants.EXPRESSION_TYPE_CONVERT_CHECKED: 62 | boundExpression = Expression.ConvertChecked(target, type); 63 | break; 64 | default: 65 | boundExpression = null; 66 | bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNKNOWNEXPRTYPE, expressionType), node); 67 | return false; 68 | } 69 | return true; 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Binding/TypeCache.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ 16 | 17 | using System; 18 | using System.Collections.Generic; 19 | 20 | namespace GameDevWare.Dynamic.Expressions.Binding 21 | { 22 | internal sealed class TypeCache 23 | { 24 | private readonly Dictionary types; 25 | private readonly TypeCache parentCache; 26 | 27 | public Dictionary.ValueCollection Values { get { return this.types.Values; } } 28 | 29 | public TypeCache(TypeCache parentCache = null) 30 | { 31 | this.parentCache = parentCache; 32 | this.types = new Dictionary(); 33 | } 34 | 35 | public bool TryGetValue(Type type, out TypeDescription typeDescription) 36 | { 37 | if (type == null) throw new ArgumentNullException("type"); 38 | 39 | if (this.types.TryGetValue(type, out typeDescription)) 40 | return true; 41 | 42 | if (this.parentCache == null) 43 | return false; 44 | 45 | lock (this.parentCache) 46 | return this.parentCache.TryGetValue(type, out typeDescription); 47 | } 48 | public bool TryAdd(Type type, ref TypeDescription typeDescription) 49 | { 50 | if (type == null) throw new ArgumentNullException("type"); 51 | if (typeDescription == null) throw new ArgumentNullException("typeDescription"); 52 | 53 | var existingValue = default(TypeDescription); 54 | if (this.TryGetValue(type, out existingValue)) 55 | { 56 | typeDescription = existingValue; 57 | return false; 58 | } 59 | 60 | this.types[type] = typeDescription; 61 | return true; 62 | } 63 | public void Add(Type type, TypeDescription typeDescription) 64 | { 65 | if (type == null) throw new ArgumentNullException("type"); 66 | if (typeDescription == null) throw new ArgumentNullException("typeDescription"); 67 | 68 | if (this.TryAdd(type, ref typeDescription) == false) 69 | throw new ArgumentException(string.Format("TypeDescription for types '{0}' is already exists in cache.", typeDescription), "type"); 70 | } 71 | public TypeDescription GetOrCreateTypeDescription(Type type) 72 | { 73 | if (type == null) throw new ArgumentNullException("type"); 74 | 75 | var typeDescription = default(TypeDescription); 76 | if (this.TryGetValue(type, out typeDescription)) 77 | return typeDescription; 78 | 79 | typeDescription = new TypeDescription(type, this); 80 | return typeDescription; 81 | } 82 | 83 | public void Merge(TypeCache otherCache) 84 | { 85 | if (otherCache == null) throw new ArgumentNullException("otherCache"); 86 | 87 | foreach (var kv in otherCache.types) 88 | this.types[kv.Key] = kv.Value; 89 | } 90 | 91 | public override string ToString() 92 | { 93 | return this.types.ToString(); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Binding/TypeOfBinder.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ 16 | 17 | using System; 18 | using System.Linq.Expressions; 19 | 20 | namespace GameDevWare.Dynamic.Expressions.Binding 21 | { 22 | internal static class TypeOfBinder 23 | { 24 | public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError) 25 | { 26 | if (node == null) throw new ArgumentNullException("node"); 27 | if (bindingContext == null) throw new ArgumentNullException("bindingContext"); 28 | if (expectedType == null) throw new ArgumentNullException("expectedType"); 29 | 30 | boundExpression = null; 31 | bindingError = null; 32 | 33 | var typeName = node.GetTypeName(throwOnError: true); 34 | var type = default(Type); 35 | if (bindingContext.TryResolveType(typeName, out type) == false) 36 | { 37 | bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETORESOLVETYPE, typeName), node); 38 | return false; 39 | } 40 | 41 | boundExpression = Expression.Constant(type, typeof(Type)); 42 | return true; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Binding/TypeTuple.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ 16 | 17 | using System; 18 | 19 | namespace GameDevWare.Dynamic.Expressions.Binding 20 | { 21 | internal struct TypeTuple : IEquatable 22 | { 23 | private readonly int hashCode; 24 | 25 | public readonly Type[] Types; 26 | 27 | public TypeTuple(params Type[] types) 28 | { 29 | if (types == null) throw new ArgumentNullException("types"); 30 | 31 | this.Types = types; 32 | 33 | unchecked 34 | { 35 | this.hashCode = 17; 36 | foreach (var type in types) 37 | { 38 | if (type == null) throw new ArgumentException("One of array's element is null.", "types"); 39 | 40 | this.hashCode = this.hashCode * 23 + type.GetHashCode(); 41 | } 42 | } 43 | } 44 | 45 | public bool Equals(TypeTuple other) 46 | { 47 | if (this.Types == other.Types) return true; 48 | if (this.Types == null || other.Types == null) return false; 49 | if (this.Types.Length != other.Types.Length) return false; 50 | 51 | for (var i = 0; i < this.Types.Length; i++) 52 | if (this.Types[i] != other.Types[i]) 53 | return false; 54 | return true; 55 | } 56 | public override int GetHashCode() 57 | { 58 | return this.hashCode; 59 | } 60 | public override bool Equals(object obj) 61 | { 62 | if (obj is TypeTuple) 63 | return this.Equals((TypeTuple)obj); 64 | return false; 65 | } 66 | 67 | public override string ToString() 68 | { 69 | if (this.Types != null) 70 | { 71 | var sb = new System.Text.StringBuilder(); 72 | foreach (var type in this.Types) 73 | sb.Append(type.Name).Append(", "); 74 | if (sb.Length > 2) 75 | sb.Length -= 2; 76 | return sb.ToString(); 77 | } 78 | else 79 | return "empty"; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Binding/TypeTuple2.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ 16 | 17 | using System; 18 | 19 | namespace GameDevWare.Dynamic.Expressions.Binding 20 | { 21 | internal struct TypeTuple2 : IEquatable 22 | { 23 | private readonly int hashCode; 24 | 25 | public readonly Type Type1; 26 | public readonly Type Type2; 27 | 28 | public TypeTuple2(Type type1, Type type2) 29 | { 30 | if (type1 == null) throw new ArgumentNullException("type1"); 31 | if (type2 == null) throw new ArgumentNullException("type2"); 32 | 33 | this.Type1 = type1; 34 | this.Type2 = type2; 35 | 36 | unchecked 37 | { 38 | this.hashCode = 17; 39 | this.hashCode = this.hashCode * 23 + this.Type1.GetHashCode(); 40 | this.hashCode = this.hashCode * 23 + this.Type2.GetHashCode(); 41 | } 42 | } 43 | 44 | public bool Equals(TypeTuple2 other) 45 | { 46 | return this.Type1 == other.Type1 && this.Type2 == other.Type2; 47 | } 48 | public override int GetHashCode() 49 | { 50 | return this.hashCode; 51 | } 52 | public override bool Equals(object obj) 53 | { 54 | if (obj is TypeTuple2) 55 | return this.Equals((TypeTuple2)obj); 56 | return false; 57 | } 58 | 59 | public override string ToString() 60 | { 61 | if (this.Type1 != null && this.Type2 != null) 62 | return this.Type1.Name + "/" + this.Type2.Name; 63 | else 64 | return "empty"; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Binding/UnaryBinder.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ 16 | 17 | using System; 18 | using System.Diagnostics; 19 | using System.Linq.Expressions; 20 | 21 | namespace GameDevWare.Dynamic.Expressions.Binding 22 | { 23 | internal static class UnaryBinder 24 | { 25 | public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError) 26 | { 27 | if (node == null) throw new ArgumentNullException("node"); 28 | if (bindingContext == null) throw new ArgumentNullException("bindingContext"); 29 | if (expectedType == null) throw new ArgumentNullException("expectedType"); 30 | 31 | boundExpression = null; 32 | bindingError = null; 33 | 34 | var expressionType = node.GetExpressionType(throwOnError: true); 35 | var operandNode = node.GetExpression(throwOnError: true); 36 | var operand = default(Expression); 37 | var methodName = node.GetMethodName(throwOnError: false); 38 | var methodMember = default(MemberDescription); 39 | 40 | if (AnyBinder.TryBindInNewScope(operandNode, bindingContext, TypeDescription.ObjectType, out operand, out bindingError) == false) 41 | return false; 42 | 43 | if (methodName != null) 44 | { 45 | bindingContext.TryResolveMember(methodName, out methodMember); 46 | } 47 | 48 | Debug.Assert(operand != null, "operand != null"); 49 | 50 | switch (expressionType) 51 | { 52 | case Constants.EXPRESSION_TYPE_NEGATE: 53 | if (ExpressionUtils.TryPromoteUnaryOperation(ref operand, ExpressionType.Negate, out boundExpression) == false) 54 | { 55 | // fixing b_u_g in mono expression compiler: Negate on float or double = exception 56 | if (operand.Type == typeof(double) || operand.Type == typeof(float)) 57 | boundExpression = Expression.Multiply(operand, operand.Type == typeof(float) ? ExpressionUtils.NegativeSingle : ExpressionUtils.NegativeDouble); 58 | else 59 | boundExpression = Expression.Negate(operand, methodMember); 60 | } 61 | break; 62 | case Constants.EXPRESSION_TYPE_NEGATE_CHECKED: 63 | if (ExpressionUtils.TryPromoteUnaryOperation(ref operand, ExpressionType.NegateChecked, out boundExpression) == false) 64 | { 65 | // fixing b_u_g in mono expression compiler: Negate on float or double = exception 66 | if (operand.Type == typeof(double) || operand.Type == typeof(float)) 67 | boundExpression = Expression.Multiply(operand, operand.Type == typeof(float) ? ExpressionUtils.NegativeSingle : ExpressionUtils.NegativeDouble); 68 | else 69 | boundExpression = Expression.NegateChecked(operand, methodMember); 70 | } 71 | break; 72 | case Constants.EXPRESSION_TYPE_COMPLEMENT: 73 | case Constants.EXPRESSION_TYPE_NOT: 74 | if (ExpressionUtils.TryPromoteUnaryOperation(ref operand, ExpressionType.Not, out boundExpression) == false) 75 | boundExpression = Expression.Not(operand, methodMember); 76 | break; 77 | case Constants.EXPRESSION_TYPE_UNARY_PLUS: 78 | if (ExpressionUtils.TryPromoteUnaryOperation(ref operand, ExpressionType.UnaryPlus, out boundExpression) == false) 79 | boundExpression = Expression.UnaryPlus(operand, methodMember); 80 | break; 81 | case Constants.EXPRESSION_TYPE_ARRAY_LENGTH: 82 | boundExpression = Expression.ArrayLength(operand); 83 | break; 84 | default: 85 | bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNKNOWNEXPRTYPE, expressionType), node); 86 | return false; 87 | } 88 | return true; 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/CSharp/CSharpTypeNameAlias.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace GameDevWare.Dynamic.Expressions.CSharp 7 | { 8 | internal static class CSharpTypeNameAlias 9 | { 10 | private static readonly Dictionary TypeNameByAlias; 11 | private static readonly Dictionary AliasByTypeName; 12 | 13 | static CSharpTypeNameAlias() 14 | { 15 | TypeNameByAlias = new Dictionary 16 | { 17 | // ReSharper disable StringLiteralTypo 18 | { "void", typeof(void).FullName }, 19 | { "char", typeof(char).FullName }, 20 | { "bool", typeof(bool).FullName }, 21 | { "byte", typeof(byte).FullName }, 22 | { "sbyte", typeof(sbyte).FullName }, 23 | { "decimal", typeof(decimal).FullName }, 24 | { "double", typeof(double).FullName }, 25 | { "float", typeof(float).FullName }, 26 | { "int", typeof(int).FullName }, 27 | { "uint", typeof(uint).FullName }, 28 | { "long", typeof(long).FullName }, 29 | { "ulong", typeof(ulong).FullName }, 30 | { "object", typeof(object).FullName }, 31 | { "short", typeof(short).FullName }, 32 | { "ushort", typeof(ushort).FullName }, 33 | { "string", typeof(string).FullName } 34 | // ReSharper restore StringLiteralTypo 35 | }; 36 | AliasByTypeName = TypeNameByAlias.ToDictionary(kv => kv.Value, kv => kv.Key); 37 | } 38 | 39 | public static bool TryGetTypeName(string alias, out string typeName) 40 | { 41 | if (alias == null) throw new ArgumentNullException("alias"); 42 | 43 | return TypeNameByAlias.TryGetValue(alias, out typeName); 44 | } 45 | public static bool TryGetAlias(string typeName, out string alias) 46 | { 47 | if (typeName == null) throw new ArgumentNullException("typeName"); 48 | 49 | return AliasByTypeName.TryGetValue(typeName, out alias); 50 | } 51 | #if NETFRAMEWORK 52 | public static bool TryGetAlias(Type typeInfo, out string alias) 53 | { 54 | if (typeInfo == null) throw new ArgumentNullException("typeInfo"); 55 | 56 | return TryGetAlias(typeInfo.FullName, out alias); 57 | } 58 | #else 59 | public static bool TryGetAlias(TypeInfo typeInfo, out string alias) 60 | { 61 | if (typeInfo == null) throw new ArgumentNullException("typeInfo"); 62 | 63 | return TryGetAlias(typeInfo.FullName, out alias); 64 | } 65 | #endif 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/CSharp/ListExtensions.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ 16 | 17 | using System; 18 | using System.Collections.Generic; 19 | 20 | namespace GameDevWare.Dynamic.Expressions.CSharp 21 | { 22 | internal static class ListExtensions 23 | { 24 | public static T Dequeue(this List list) 25 | { 26 | if (list == null) throw new ArgumentNullException("list"); 27 | if (list.Count == 0) throw new ArgumentException(Properties.Resources.EXCEPTION_LIST_LISTISEMPTY, "list"); 28 | 29 | var first = list[0]; 30 | list.RemoveAt(0); 31 | return first; 32 | } 33 | public static T Pop(this List list) 34 | { 35 | if (list == null) throw new ArgumentNullException("list"); 36 | if (list.Count == 0) throw new ArgumentException(Properties.Resources.EXCEPTION_LIST_LISTISEMPTY, "list"); 37 | 38 | var value = list[list.Count - 1]; 39 | list.RemoveAt(list.Count - 1); 40 | return value; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/CSharp/Token.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ 16 | 17 | namespace GameDevWare.Dynamic.Expressions.CSharp 18 | { 19 | /// 20 | /// Tokenizer's token data. 21 | /// 22 | public struct Token : ILineInfo 23 | { 24 | /// 25 | /// Type of token. 26 | /// 27 | public readonly TokenType Type; 28 | /// 29 | /// Value of token. 30 | /// 31 | public readonly string Value; 32 | /// 33 | /// Line number of token (position). 34 | /// 35 | public readonly int LineNumber; 36 | /// 37 | /// Column number of token (position). 38 | /// 39 | public readonly int ColumnNumber; 40 | /// 41 | /// Length of token (position). 42 | /// 43 | public readonly int TokenLength; 44 | 45 | /// 46 | /// Returns true if token is valid. 47 | /// 48 | public bool IsValid { get { return this.Type != TokenType.None; } } 49 | /// 50 | /// Returns token's position as string. 51 | /// 52 | public string Position { get { return string.Format("{0}:{1}+{2}", this.LineNumber.ToString(), this.ColumnNumber.ToString(), this.TokenLength.ToString()); } } 53 | 54 | int ILineInfo.GetLineNumber() 55 | { 56 | return this.LineNumber; 57 | } 58 | int ILineInfo.GetColumnNumber() 59 | { 60 | return this.ColumnNumber; 61 | } 62 | int ILineInfo.GetTokenLength() 63 | { 64 | return this.TokenLength; 65 | } 66 | 67 | /// 68 | /// Creates new token. 69 | /// 70 | public Token(TokenType type, string value, int line, int col, int len) 71 | { 72 | this.Type = type; 73 | this.Value = value; 74 | this.LineNumber = line; 75 | this.ColumnNumber = col; 76 | this.TokenLength = len; 77 | } 78 | 79 | /// 80 | /// Converts token to string for debugging. 81 | /// 82 | public override string ToString() 83 | { 84 | return this.Type + (this.Type == TokenType.Number || this.Type == TokenType.Identifier || this.Type == TokenType.Literal ? "(" + this.Value + ")" : ""); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/CSharp/TokenAttribute.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ 16 | 17 | using System; 18 | 19 | namespace GameDevWare.Dynamic.Expressions.CSharp 20 | { 21 | [AttributeUsage(AttributeTargets.Field, AllowMultiple = true)] 22 | internal class TokenAttribute : Attribute 23 | { 24 | public string Value { get; set; } 25 | 26 | public TokenAttribute(string value) 27 | { 28 | this.Value = value; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/CSharp/TokenType.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ 16 | 17 | #pragma warning disable 1591 18 | namespace GameDevWare.Dynamic.Expressions.CSharp 19 | { 20 | /// 21 | /// Types of tokens 22 | /// 23 | public enum TokenType 24 | { 25 | None, 26 | Number, 27 | Literal, 28 | Identifier, 29 | // arithmetic 30 | [Token("+")] 31 | Add, 32 | Plus, 33 | [Token("-")] 34 | Subtract, 35 | Minus, 36 | [Token("/")] 37 | Division, 38 | [Token("*")] 39 | Multiplication, 40 | [Token("**")] 41 | Power, 42 | [Token("%")] 43 | Modulo, 44 | // bitwise 45 | [Token("&")] 46 | And, 47 | [Token("|")] 48 | Or, 49 | [Token("^")] 50 | Xor, 51 | [Token("~")] 52 | Complement, 53 | [Token("<<")] 54 | LeftShift, 55 | [Token(">>")] 56 | RightShift, 57 | // logical 58 | [Token("&&")] 59 | AndAlso, 60 | [Token("||")] 61 | OrElse, 62 | [Token("!")] 63 | Not, 64 | [Token(">")] 65 | GreaterThan, 66 | [Token(">=")] 67 | GreaterThanOrEquals, 68 | [Token("<")] 69 | LesserThan, 70 | [Token("<=")] 71 | LesserThanOrEquals, 72 | [Token("==")] 73 | EqualsTo, 74 | [Token("!=")] 75 | NotEqualsTo, 76 | // other 77 | [Token("?")] 78 | Conditional, 79 | [Token("is")] 80 | Is, 81 | [Token("as")] 82 | As, 83 | [Token(":")] 84 | Colon, 85 | [Token(",")] 86 | Comma, 87 | [Token("??")] 88 | Coalesce, 89 | [Token("new")] 90 | New, 91 | // structure 92 | [Token(".")] 93 | Resolve, 94 | [Token("?.")] 95 | NullResolve, 96 | [Token("(")] 97 | LeftParentheses, 98 | [Token(")")] 99 | RightParentheses, 100 | [Token("[")] 101 | LeftBracket, 102 | [Token("?[")] 103 | NullIndex, 104 | [Token("]")] 105 | RightBracket, 106 | [Token("=>")] 107 | Lambda, 108 | Call, 109 | Arguments, 110 | Convert, 111 | Typeof, 112 | Default, 113 | Group, 114 | CheckedScope, 115 | UncheckedScope 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/DelegateUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | 4 | namespace GameDevWare.Dynamic.Expressions 5 | { 6 | public static class DelegateUtils 7 | { 8 | public static Delegate CreateDelegate(Type delegateType, MethodInfo method, bool throwOnBindingFailure = true) 9 | { 10 | if (delegateType == null) throw new ArgumentNullException("delegateType"); 11 | if (method == null) throw new ArgumentNullException("method"); 12 | 13 | #if NETSTANDARD 14 | try 15 | { 16 | return method.CreateDelegate(delegateType); 17 | } 18 | catch 19 | { 20 | if (throwOnBindingFailure) 21 | throw; 22 | else 23 | return null; 24 | } 25 | #else 26 | return Delegate.CreateDelegate(delegateType, method, throwOnBindingFailure); 27 | #endif 28 | } 29 | #if NETSTANDARD 30 | public static MethodInfo GetMethodInfo(this Delegate delegateInstance) 31 | { 32 | if (delegateInstance == null) throw new ArgumentNullException("delegateInstance"); 33 | 34 | return RuntimeReflectionExtensions.GetMethodInfo(delegateInstance); 35 | } 36 | #else 37 | public static MethodInfo GetMethodInfo(this Delegate delegateInstance) 38 | { 39 | if (delegateInstance == null) throw new ArgumentNullException("delegateInstance"); 40 | 41 | return delegateInstance.Method; 42 | } 43 | #endif 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Execution/ArrayIndexNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace GameDevWare.Dynamic.Expressions.Execution 5 | { 6 | internal sealed class ArrayIndexNode : ExecutionNode 7 | { 8 | private readonly Expression expression; 9 | private readonly ExecutionNode targetNode; 10 | private readonly ExecutionNode indexNode; 11 | private readonly CallNode methodCallNode; 12 | 13 | public ArrayIndexNode(Expression expression, ConstantExpression[] constExpressions, ParameterExpression[] parameterExpressions) 14 | { 15 | if (expression == null) throw new ArgumentNullException("expression"); 16 | if (constExpressions == null) throw new ArgumentNullException("constExpressions"); 17 | if (parameterExpressions == null) throw new ArgumentNullException("parameterExpressions"); 18 | 19 | var binaryExpression = expression as BinaryExpression; 20 | var methodCallExpression = expression as MethodCallExpression; 21 | if (binaryExpression != null) 22 | { 23 | this.targetNode = AotCompiler.Compile(binaryExpression.Left, constExpressions, parameterExpressions); 24 | this.indexNode = AotCompiler.Compile(binaryExpression.Right, constExpressions, parameterExpressions); 25 | } 26 | else 27 | { 28 | this.methodCallNode = new CallNode(methodCallExpression, constExpressions, parameterExpressions); 29 | } 30 | 31 | this.expression = expression; 32 | } 33 | 34 | /// 35 | public override object Run(Closure closure) 36 | { 37 | if (this.methodCallNode != null) 38 | { 39 | return this.methodCallNode.Run(closure); 40 | } 41 | else 42 | { 43 | var target = closure.Unbox(this.targetNode.Run(closure)); 44 | 45 | if (target == null) 46 | throw new NullReferenceException(string.Format(Properties.Resources.EXCEPTION_EXECUTION_EXPRESSIONGIVESNULLRESULT, this.expression)); 47 | 48 | var index = this.indexNode.Run(closure); 49 | return closure.Is(index) 50 | ? target.GetValue(closure.Unbox(index)) 51 | : target.GetValue(closure.Unbox(index)); 52 | } 53 | } 54 | 55 | /// 56 | public override string ToString() 57 | { 58 | return this.expression.ToString(); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Execution/ArrayLengthNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace GameDevWare.Dynamic.Expressions.Execution 5 | { 6 | internal sealed class ArrayLengthNode : ExecutionNode 7 | { 8 | private readonly UnaryExpression unaryExpression; 9 | private readonly ExecutionNode targetNode; 10 | 11 | public ArrayLengthNode(UnaryExpression unaryExpression, ConstantExpression[] constExpressions, ParameterExpression[] parameterExpressions) 12 | { 13 | this.unaryExpression = unaryExpression; 14 | if (unaryExpression == null) throw new ArgumentNullException("unaryExpression"); 15 | if (constExpressions == null) throw new ArgumentNullException("constExpressions"); 16 | if (parameterExpressions == null) throw new ArgumentNullException("parameterExpressions"); 17 | 18 | this.targetNode = AotCompiler.Compile(unaryExpression.Operand, constExpressions, parameterExpressions); 19 | } 20 | 21 | /// 22 | public override object Run(Closure closure) 23 | { 24 | var target = closure.Unbox(this.targetNode.Run(closure)); 25 | if (target == null) 26 | throw new NullReferenceException(string.Format(Properties.Resources.EXCEPTION_EXECUTION_EXPRESSIONGIVESNULLRESULT, this.unaryExpression.Operand)); 27 | 28 | return closure.Box(target.Length); 29 | } 30 | 31 | /// 32 | public override string ToString() 33 | { 34 | return this.unaryExpression.ToString(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Execution/CallNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace GameDevWare.Dynamic.Expressions.Execution 5 | { 6 | internal sealed class CallNode : ExecutionNode 7 | { 8 | private readonly MethodCallExpression methodCallExpression; 9 | private readonly ExecutionNode targetNode; 10 | private readonly ExecutionNode[] argumentNodes; 11 | private readonly FastCall.Invoker fastCallInvoker; 12 | private readonly bool isStatic; 13 | 14 | public CallNode(MethodCallExpression methodCallExpression, ConstantExpression[] constExpressions, ParameterExpression[] parameterExpressions) 15 | { 16 | if (methodCallExpression == null) throw new ArgumentNullException("methodCallExpression"); 17 | if (constExpressions == null) throw new ArgumentNullException("constExpressions"); 18 | if (parameterExpressions == null) throw new ArgumentNullException("parameterExpressions"); 19 | 20 | this.methodCallExpression = methodCallExpression; 21 | this.targetNode = AotCompiler.Compile(methodCallExpression.Object, constExpressions, parameterExpressions); 22 | this.argumentNodes = new ExecutionNode[methodCallExpression.Arguments.Count]; 23 | for (var i = 0; i < this.argumentNodes.Length; i++) 24 | this.argumentNodes[i] = AotCompiler.Compile(methodCallExpression.Arguments[i], constExpressions, parameterExpressions); 25 | this.fastCallInvoker = FastCall.TryCreate(methodCallExpression.Method); 26 | this.isStatic = this.methodCallExpression.Method.IsStatic; 27 | } 28 | 29 | /// 30 | public override object Run(Closure closure) 31 | { 32 | if (this.fastCallInvoker != null) 33 | { 34 | return this.fastCallInvoker(closure, this.argumentNodes); 35 | } 36 | else 37 | { 38 | var target = this.targetNode.Run(closure); 39 | 40 | if (this.isStatic == false && target == null) 41 | throw new NullReferenceException(string.Format(Properties.Resources.EXCEPTION_EXECUTION_EXPRESSIONGIVESNULLRESULT, this.methodCallExpression.Object)); 42 | 43 | var arguments = new object[this.argumentNodes.Length]; 44 | for (var i = 0; i < arguments.Length; i++) 45 | arguments[i] = closure.Unbox(this.argumentNodes[i].Run(closure)); 46 | 47 | return this.methodCallExpression.Method.Invoke(target, arguments); 48 | } 49 | } 50 | 51 | /// 52 | public override string ToString() 53 | { 54 | return this.methodCallExpression.ToString(); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Execution/Closure.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GameDevWare.Dynamic.Expressions.Execution 4 | { 5 | internal sealed class Closure 6 | { 7 | public readonly object[] Constants; 8 | public readonly object[] Locals; // first two locals is reserved, third and others is parameters 9 | 10 | public Closure(object[] constants, object[] locals) 11 | { 12 | if (constants == null) throw new ArgumentNullException("constants"); 13 | if (locals == null) throw new ArgumentNullException("locals"); 14 | this.Constants = constants; 15 | this.Locals = locals; 16 | } 17 | 18 | public object Box(T value) 19 | { 20 | return value; 21 | } 22 | 23 | public T Unbox(object boxed) 24 | { 25 | //if (boxed is StrongBox) 26 | // return ((StrongBox)boxed).Value; 27 | //else if (boxed is IStrongBox) 28 | // boxed = ((IStrongBox)boxed).Value; 29 | 30 | if (boxed is T || boxed == null) 31 | return (T)boxed; 32 | else 33 | return (T)Convert.ChangeType(boxed, typeof(T)); 34 | } 35 | 36 | public bool Is(object boxed) 37 | { 38 | return boxed is T; 39 | } 40 | 41 | public Type GetType(object left) 42 | { 43 | if (left == null) 44 | return typeof(object); 45 | return left.GetType(); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Execution/CoalesceNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace GameDevWare.Dynamic.Expressions.Execution 5 | { 6 | internal sealed class CoalesceNode : ExecutionNode 7 | { 8 | private readonly BinaryExpression binaryExpression; 9 | private readonly ExecutionNode leftNode; 10 | private readonly ExecutionNode rightNode; 11 | 12 | public CoalesceNode(BinaryExpression binaryExpression, ConstantExpression[] constExpressions, ParameterExpression[] parameterExpressions) 13 | { 14 | if (binaryExpression == null) throw new ArgumentNullException("binaryExpression"); 15 | if (constExpressions == null) throw new ArgumentNullException("constExpressions"); 16 | if (parameterExpressions == null) throw new ArgumentNullException("parameterExpressions"); 17 | 18 | this.binaryExpression = binaryExpression; 19 | this.leftNode = AotCompiler.Compile(binaryExpression.Left, constExpressions, parameterExpressions); 20 | this.rightNode = AotCompiler.Compile(binaryExpression.Right, constExpressions, parameterExpressions); 21 | } 22 | /// 23 | public override object Run(Closure closure) 24 | { 25 | var left = closure.Unbox(this.leftNode.Run(closure)); 26 | if (left != null) 27 | return left; 28 | else 29 | return this.rightNode.Run(closure); 30 | } 31 | 32 | /// 33 | public override string ToString() 34 | { 35 | return this.binaryExpression.ToString(); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Execution/ConditionalNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace GameDevWare.Dynamic.Expressions.Execution 5 | { 6 | internal sealed class ConditionalNode : ExecutionNode 7 | { 8 | private readonly ConditionalExpression conditionalExpression; 9 | private readonly ExecutionNode trueBranchNode; 10 | private readonly ExecutionNode falseBranchNode; 11 | private readonly ExecutionNode conditionTestNode; 12 | 13 | public ConditionalNode(ConditionalExpression conditionalExpression, ConstantExpression[] constExpressions, ParameterExpression[] parameterExpressions) 14 | { 15 | if (conditionalExpression == null) throw new ArgumentNullException("conditionalExpression"); 16 | if (constExpressions == null) throw new ArgumentNullException("constExpressions"); 17 | if (parameterExpressions == null) throw new ArgumentNullException("parameterExpressions"); 18 | 19 | this.conditionalExpression = conditionalExpression; 20 | 21 | this.trueBranchNode = AotCompiler.Compile(conditionalExpression.IfTrue, constExpressions, parameterExpressions); 22 | this.falseBranchNode = AotCompiler.Compile(conditionalExpression.IfFalse, constExpressions, parameterExpressions); 23 | this.conditionTestNode = AotCompiler.Compile(conditionalExpression.Test, constExpressions, parameterExpressions); 24 | } 25 | 26 | /// 27 | public override object Run(Closure closure) 28 | { 29 | var testValue = closure.Unbox(this.conditionTestNode.Run(closure)); 30 | var value = testValue ? this.trueBranchNode.Run(closure) : this.falseBranchNode.Run(closure); 31 | return value; 32 | } 33 | 34 | /// 35 | public override string ToString() 36 | { 37 | return this.conditionalExpression.ToString(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Execution/ConstantNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace GameDevWare.Dynamic.Expressions.Execution 5 | { 6 | internal sealed class ConstantNode : ExecutionNode 7 | { 8 | private readonly ConstantExpression constantExpression; 9 | private readonly int constantIndex; 10 | 11 | public ConstantNode(ConstantExpression constantExpression, ConstantExpression[] constExpressions) 12 | { 13 | if (constantExpression == null) throw new ArgumentNullException("constantExpression"); 14 | if (constExpressions == null) throw new ArgumentNullException("constExpressions"); 15 | 16 | this.constantExpression = constantExpression; 17 | this.constantIndex = Array.IndexOf(constExpressions, constantExpression); 18 | 19 | if (this.constantIndex < 0) 20 | throw new ArgumentException("Constant expression is not found in passed constant list.", "constantExpression"); 21 | } 22 | 23 | /// 24 | public override object Run(Closure closure) 25 | { 26 | var constant = closure.Constants[this.constantIndex]; 27 | return constant; 28 | } 29 | 30 | /// 31 | public override string ToString() 32 | { 33 | return this.constantExpression.ToString(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Execution/ConstantsCollector.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq.Expressions; 3 | 4 | namespace GameDevWare.Dynamic.Expressions.Execution 5 | { 6 | internal sealed class ConstantsCollector : ExpressionVisitor 7 | { 8 | public readonly List Constants = new List(); 9 | 10 | protected override Expression VisitConstant(ConstantExpression constantExpression) 11 | { 12 | this.Constants.Add(constantExpression); 13 | return constantExpression; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Execution/ExecutionNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace GameDevWare.Dynamic.Expressions.Execution 5 | { 6 | internal abstract class ExecutionNode 7 | { 8 | public const int LOCAL_OPERAND1 = 0; 9 | public const int LOCAL_OPERAND2 = 1; 10 | public const int LOCAL_SLOT1 = 2; 11 | public const int LOCAL_FIRST_PARAMETER = 3; // this is offset of first parameter in Closure locals 12 | 13 | public abstract object Run(Closure closure); 14 | 15 | protected static bool IsNullable(Expression expression) 16 | { 17 | if (expression == null) throw new ArgumentException("expression"); 18 | 19 | var constantExpression = expression as ConstantExpression; 20 | if (constantExpression != null && constantExpression.Type == typeof(Object) && constantExpression.Value == null) 21 | return true; 22 | 23 | return IsNullable(expression.Type); 24 | } 25 | protected static bool IsNullable(Type type) 26 | { 27 | if (type == null) throw new ArgumentException("type"); 28 | 29 | return Nullable.GetUnderlyingType(type) != null; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Execution/InvocationNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace GameDevWare.Dynamic.Expressions.Execution 5 | { 6 | internal sealed class InvocationNode : ExecutionNode 7 | { 8 | private readonly InvocationExpression invocationExpression; 9 | private readonly ExecutionNode target; 10 | private readonly ExecutionNode[] argumentNodes; 11 | 12 | public InvocationNode(InvocationExpression invocationExpression, ConstantExpression[] constExpressions, ParameterExpression[] parameterExpressions) 13 | { 14 | if (invocationExpression == null) throw new ArgumentNullException("invocationExpression"); 15 | if (constExpressions == null) throw new ArgumentNullException("constExpressions"); 16 | if (parameterExpressions == null) throw new ArgumentNullException("parameterExpressions"); 17 | 18 | this.invocationExpression = invocationExpression; 19 | this.target = AotCompiler.Compile(invocationExpression.Expression, constExpressions, parameterExpressions); 20 | this.argumentNodes = new ExecutionNode[invocationExpression.Arguments.Count]; 21 | for (var i = 0; i < this.argumentNodes.Length; i++) 22 | this.argumentNodes[i] = AotCompiler.Compile(invocationExpression.Arguments[i], constExpressions, parameterExpressions); 23 | } 24 | 25 | /// 26 | public override object Run(Closure closure) 27 | { 28 | var targetDelegate = closure.Unbox(this.target.Run(closure)); 29 | var invokeArguments = new object[this.argumentNodes.Length]; 30 | for (var i = 0; i < invokeArguments.Length; i++) 31 | invokeArguments[i] = closure.Unbox(this.argumentNodes[i].Run(closure)); 32 | 33 | if (targetDelegate == null) 34 | throw new NullReferenceException(string.Format(Properties.Resources.EXCEPTION_EXECUTION_EXPRESSIONGIVESNULLRESULT, this.invocationExpression.Expression)); 35 | 36 | return targetDelegate.DynamicInvoke(invokeArguments); 37 | } 38 | 39 | /// 40 | public override string ToString() 41 | { 42 | return this.invocationExpression.ToString(); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Execution/LambdaNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Reflection; 6 | 7 | namespace GameDevWare.Dynamic.Expressions.Execution 8 | { 9 | internal sealed class LambdaNode : ExecutionNode 10 | { 11 | private readonly LambdaExpression lambdaExpression; 12 | private readonly ParameterExpression[] parameterExpressions; 13 | private readonly MethodInfo prepareMethod; 14 | 15 | public LambdaNode(LambdaExpression lambdaExpression, ParameterExpression[] parameterExpressions) 16 | { 17 | if (lambdaExpression == null) throw new ArgumentNullException("lambdaExpression"); 18 | if (parameterExpressions == null) throw new ArgumentNullException("parameterExpressions"); 19 | 20 | this.lambdaExpression = lambdaExpression; 21 | this.parameterExpressions = parameterExpressions; 22 | 23 | var lambdaExpressionType = lambdaExpression.Type.GetTypeInfo(); 24 | if (lambdaExpressionType.IsGenericType == false) 25 | throw new NotSupportedException(Properties.Resources.EXCEPTION_COMPIL_ONLYFUNCLAMBDASISSUPPORTED); 26 | 27 | var funcDefinition = lambdaExpression.Type.GetGenericTypeDefinition(); 28 | if (funcDefinition != typeof(Func<>) && funcDefinition != typeof(Func<,>) && funcDefinition != typeof(Func<,,>) && funcDefinition != typeof(Func<,,,>) && funcDefinition != typeof(Func<,,,,>)) 29 | throw new NotSupportedException(Properties.Resources.EXCEPTION_COMPIL_ONLYFUNCLAMBDASISSUPPORTED); 30 | 31 | var funcArguments = lambdaExpressionType.GetGenericArguments(); 32 | var prepareMethodDefinition = typeof(AotCompiler) 33 | .GetTypeInfo() 34 | .GetDeclaredMethods() 35 | .Single(m => 36 | m.Name == Constants.EXECUTE_PREPARE_NAME && 37 | m.GetGenericArguments().Length == funcArguments.Length); 38 | 39 | this.prepareMethod = prepareMethodDefinition.MakeGenericMethod(funcArguments); 40 | } 41 | 42 | /// 43 | public override object Run(Closure closure) 44 | { 45 | var body = this.lambdaExpression.Body; 46 | var parameters = this.lambdaExpression.Parameters; 47 | 48 | // substitute captured parameters 49 | if (this.parameterExpressions.Length > 0) 50 | { 51 | var substitutions = new Dictionary(this.parameterExpressions.Length); 52 | foreach (var parameterExpr in this.parameterExpressions) 53 | { 54 | var parameterValue = closure.Locals[LOCAL_FIRST_PARAMETER + Array.IndexOf(this.parameterExpressions, parameterExpr)]; 55 | substitutions.Add(parameterExpr, Expression.Constant(parameterValue, parameterExpr.Type)); 56 | } 57 | body = ExpressionSubstitutor.Visit(body, substitutions); 58 | } 59 | 60 | // prepare lambda 61 | return this.prepareMethod.Invoke(null, new object[] { body, parameters }); 62 | } 63 | 64 | /// 65 | public override string ToString() 66 | { 67 | return this.lambdaExpression.ToString(); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Execution/ListInitNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | using System.Reflection; 5 | 6 | namespace GameDevWare.Dynamic.Expressions.Execution 7 | { 8 | internal sealed class ListInitNode : ExecutionNode 9 | { 10 | private readonly ListInitExpression listInitExpression; 11 | private readonly KeyValuePair[] initializationNodes; 12 | private readonly NewNode newNode; 13 | 14 | public ListInitNode(ListInitExpression listInitExpression, ConstantExpression[] constExpressions, ParameterExpression[] parameterExpressions) 15 | { 16 | if (listInitExpression == null) throw new ArgumentNullException("listInitExpression"); 17 | if (constExpressions == null) throw new ArgumentNullException("constExpressions"); 18 | if (parameterExpressions == null) throw new ArgumentNullException("parameterExpressions"); 19 | 20 | this.listInitExpression = listInitExpression; 21 | 22 | this.newNode = new NewNode(listInitExpression.NewExpression, constExpressions, parameterExpressions); 23 | this.initializationNodes = new KeyValuePair[listInitExpression.Initializers.Count]; 24 | for (var i = 0; i < this.initializationNodes.Length; i++) 25 | { 26 | var initialization = listInitExpression.Initializers[i]; 27 | var argumentNodes = new ExecutionNode[initialization.Arguments.Count]; 28 | for (var a = 0; a < initialization.Arguments.Count; a++) 29 | argumentNodes[a] = AotCompiler.Compile(initialization.Arguments[a], constExpressions, parameterExpressions); 30 | this.initializationNodes[i] = new KeyValuePair(initialization.AddMethod, argumentNodes); 31 | } 32 | } 33 | 34 | /// 35 | public override object Run(Closure closure) 36 | { 37 | var list = closure.Unbox(this.newNode.Run(closure)); 38 | 39 | if (this.initializationNodes.Length == 0) 40 | return list; 41 | 42 | foreach (var listInit in this.initializationNodes) 43 | { 44 | var addMethod = listInit.Key; 45 | var argumentNodes = listInit.Value; 46 | var addArguments = new object[argumentNodes.Length]; 47 | 48 | for (var i = 0; i < argumentNodes.Length; i++) 49 | addArguments[i] = closure.Unbox(argumentNodes[i].Run(closure)); 50 | 51 | addMethod.Invoke(list, addArguments); 52 | } 53 | return list; 54 | } 55 | 56 | /// 57 | public override string ToString() 58 | { 59 | return this.listInitExpression.ToString(); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Execution/LocalNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GameDevWare.Dynamic.Expressions.Execution 4 | { 5 | internal sealed class LocalNode : ExecutionNode 6 | { 7 | public static readonly LocalNode Operand1 = new LocalNode(LOCAL_OPERAND1); 8 | public static readonly LocalNode Operand2 = new LocalNode(LOCAL_OPERAND2); 9 | 10 | private readonly int localIndex; 11 | 12 | public LocalNode(int localIndex) 13 | { 14 | if (localIndex < 0) throw new ArgumentOutOfRangeException("localIndex"); 15 | 16 | this.localIndex = localIndex; 17 | } 18 | 19 | /// 20 | public override object Run(Closure closure) 21 | { 22 | var constant = closure.Locals[this.localIndex]; 23 | return constant; 24 | } 25 | 26 | /// 27 | public override string ToString() 28 | { 29 | return this.localIndex.ToString(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Execution/MemberAccessNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | using System.Reflection; 4 | 5 | namespace GameDevWare.Dynamic.Expressions.Execution 6 | { 7 | internal sealed class MemberAccessNode : ExecutionNode 8 | { 9 | private readonly MemberExpression memberExpression; 10 | private readonly ExecutionNode targetNode; 11 | private readonly FieldInfo fieldInfo; 12 | private readonly MethodInfo propertyGetter; 13 | private readonly bool isStatic; 14 | 15 | public MemberAccessNode(MemberExpression memberExpression, ConstantExpression[] constExpressions, ParameterExpression[] parameterExpressions) 16 | { 17 | if (memberExpression == null) throw new ArgumentNullException("memberExpression"); 18 | if (constExpressions == null) throw new ArgumentNullException("constExpressions"); 19 | if (parameterExpressions == null) throw new ArgumentNullException("parameterExpressions"); 20 | 21 | this.memberExpression = memberExpression; 22 | 23 | this.targetNode = AotCompiler.Compile(memberExpression.Expression, constExpressions, parameterExpressions); 24 | 25 | var member = this.memberExpression.Member; 26 | this.fieldInfo = member as FieldInfo; 27 | 28 | var properFieldInfo = member as PropertyInfo; 29 | if (properFieldInfo != null) 30 | this.propertyGetter = properFieldInfo.GetAnyGetter(); 31 | 32 | this.isStatic = this.fieldInfo != null ? this.fieldInfo.IsStatic : this.propertyGetter != null && this.propertyGetter.IsStatic; 33 | } 34 | 35 | /// 36 | public override object Run(Closure closure) 37 | { 38 | var target = closure.Unbox(this.targetNode.Run(closure)); 39 | 40 | if (this.isStatic == false && target == null) 41 | throw new NullReferenceException(string.Format(Properties.Resources.EXCEPTION_EXECUTION_EXPRESSIONGIVESNULLRESULT, this.memberExpression.Expression)); 42 | 43 | if (this.fieldInfo != null) 44 | { 45 | return this.fieldInfo.GetValue(target); 46 | } 47 | else if (this.propertyGetter != null) 48 | { 49 | return this.propertyGetter.Invoke(target, null); 50 | } 51 | else 52 | { 53 | throw new InvalidOperationException(string.Format(Properties.Resources.EXCEPTION_EXECUTION_INVALIDMEMBERFOREXPRESSION, this.memberExpression.Member)); 54 | } 55 | } 56 | 57 | /// 58 | public override string ToString() 59 | { 60 | return this.memberExpression.ToString(); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Execution/MemberAssignmentsNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.ObjectModel; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Reflection; 6 | 7 | namespace GameDevWare.Dynamic.Expressions.Execution 8 | { 9 | internal sealed class MemberAssignmentsNode : ExecutionNode 10 | { 11 | public static readonly MemberAssignmentsNode Empty = new MemberAssignmentsNode(new ReadOnlyCollection(new MemberBinding[0]), new ConstantExpression[0], new ParameterExpression[0]); 12 | 13 | internal struct PreparedMemberAssignment 14 | { 15 | public readonly MemberInfo Member; 16 | public readonly ExecutionNode ValueNode; 17 | 18 | public PreparedMemberAssignment(MemberInfo member, ExecutionNode valueNode) 19 | { 20 | this.Member = member; 21 | this.ValueNode = valueNode; 22 | } 23 | } 24 | 25 | private readonly PreparedMemberAssignment[] memberAssignments; 26 | 27 | public MemberAssignmentsNode(ReadOnlyCollection bindings, ConstantExpression[] constExpressions, ParameterExpression[] parameterExpressions) 28 | { 29 | if (bindings == null) throw new ArgumentNullException("bindings"); 30 | if (constExpressions == null) throw new ArgumentNullException("constExpressions"); 31 | if (parameterExpressions == null) throw new ArgumentNullException("parameterExpressions"); 32 | 33 | this.memberAssignments = new PreparedMemberAssignment[bindings.Count(b => b is MemberAssignment)]; 34 | var i = 0; 35 | foreach (var binding in bindings) 36 | { 37 | var memberAssignment = binding as MemberAssignment; 38 | if (memberAssignment == null) 39 | continue; 40 | 41 | this.memberAssignments[i++] = new PreparedMemberAssignment(memberAssignment.Member, AotCompiler.Compile(memberAssignment.Expression, constExpressions, parameterExpressions)); 42 | } 43 | } 44 | /// 45 | public override object Run(Closure closure) 46 | { 47 | var instance = closure.Unbox(closure.Locals[LOCAL_OPERAND1]); 48 | 49 | if (this.memberAssignments.Length == 0) 50 | return instance; 51 | 52 | foreach (var assignFn in this.memberAssignments) 53 | { 54 | var member = assignFn.Member; 55 | var valueFn = assignFn.ValueNode; 56 | var value = closure.Unbox(valueFn.Run(closure)); 57 | var fieldInfo = member as FieldInfo; 58 | var propertyInfo = member as PropertyInfo; 59 | 60 | if (instance == null) 61 | throw new NullReferenceException(); 62 | 63 | if (fieldInfo != null) 64 | fieldInfo.SetValue(instance, value); 65 | else if (propertyInfo != null) 66 | propertyInfo.SetValue(instance, value, null); 67 | else 68 | throw new InvalidOperationException(string.Format(Properties.Resources.EXCEPTION_EXECUTION_INVALIDMEMBERFOREXPRESSION, member)); 69 | } 70 | 71 | return instance; 72 | } 73 | 74 | /// 75 | public override string ToString() 76 | { 77 | return string.Join(", ", this.memberAssignments.Select(m => m.Member.Name).ToArray()); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Execution/MemberInitNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Linq.Expressions; 4 | 5 | namespace GameDevWare.Dynamic.Expressions.Execution 6 | { 7 | internal sealed class MemberInitNode : ExecutionNode 8 | { 9 | private readonly MemberInitExpression memberInitExpression; 10 | private readonly NewNode newNode; 11 | private readonly MemberAssignmentsNode memberAssignmentNode; 12 | private readonly MemberListBindingsNode listBindingNode; 13 | private readonly MemberMemberBindingsNode memberMemberBindingNode; 14 | 15 | public MemberInitNode(MemberInitExpression memberInitExpression, ConstantExpression[] constExpressions, ParameterExpression[] parameterExpressions) 16 | { 17 | if (memberInitExpression == null) throw new ArgumentNullException("memberInitExpression"); 18 | if (constExpressions == null) throw new ArgumentNullException("constExpressions"); 19 | if (parameterExpressions == null) throw new ArgumentNullException("parameterExpressions"); 20 | 21 | this.memberInitExpression = memberInitExpression; 22 | 23 | this.newNode = new NewNode(memberInitExpression.NewExpression, constExpressions, parameterExpressions); 24 | this.memberAssignmentNode = memberInitExpression.Bindings.Any(b => b is MemberAssignment) ? 25 | new MemberAssignmentsNode(memberInitExpression.Bindings, constExpressions, parameterExpressions) : 26 | MemberAssignmentsNode.Empty; 27 | 28 | this.listBindingNode = memberInitExpression.Bindings.Any(b => b is MemberListBinding) ? 29 | new MemberListBindingsNode(memberInitExpression.Bindings, constExpressions, parameterExpressions) : 30 | MemberListBindingsNode.Empty; 31 | 32 | this.memberMemberBindingNode = memberInitExpression.Bindings.Any(b => b is MemberMemberBinding) ? 33 | new MemberMemberBindingsNode(memberInitExpression.Bindings, constExpressions, parameterExpressions) : 34 | MemberMemberBindingsNode.Empty; 35 | } 36 | 37 | /// 38 | public override object Run(Closure closure) 39 | { 40 | var instance = closure.Unbox(this.newNode.Run(closure)); 41 | 42 | if (ReferenceEquals(this.memberAssignmentNode, MemberAssignmentsNode.Empty) == false) 43 | { 44 | closure.Locals[LOCAL_OPERAND1] = instance; 45 | this.memberAssignmentNode.Run(closure); 46 | } 47 | 48 | if (ReferenceEquals(this.listBindingNode, MemberListBindingsNode.Empty) == false) 49 | { 50 | closure.Locals[LOCAL_OPERAND1] = instance; 51 | this.listBindingNode.Run(closure); 52 | } 53 | 54 | if (ReferenceEquals(this.memberMemberBindingNode, MemberMemberBindingsNode.Empty) == false) 55 | { 56 | closure.Locals[LOCAL_OPERAND1] = instance; 57 | this.memberMemberBindingNode.Run(closure); 58 | } 59 | 60 | closure.Locals[LOCAL_OPERAND1] = null; 61 | 62 | return instance; 63 | } 64 | 65 | /// 66 | public override string ToString() 67 | { 68 | return this.memberInitExpression.ToString(); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Execution/MemberListBindingsNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.ObjectModel; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Reflection; 6 | 7 | namespace GameDevWare.Dynamic.Expressions.Execution 8 | { 9 | internal sealed class MemberListBindingsNode : ExecutionNode 10 | { 11 | public static readonly MemberListBindingsNode Empty = new MemberListBindingsNode(new ReadOnlyCollection(new MemberBinding[0]), new ConstantExpression[0], new ParameterExpression[0]); 12 | 13 | internal struct PreparedListBinding 14 | { 15 | public readonly MemberInfo Member; 16 | public readonly MethodInfo AddMethod; 17 | public readonly ExecutionNode[] AddMethodArguments; 18 | 19 | public PreparedListBinding(MemberInfo member, MethodInfo addMethod, ExecutionNode[] addArguments) 20 | { 21 | this.Member = member; 22 | this.AddMethod = addMethod; 23 | this.AddMethodArguments = addArguments; 24 | } 25 | } 26 | 27 | private readonly ILookup bindingsByMember; 28 | 29 | public MemberListBindingsNode(ReadOnlyCollection bindings, ConstantExpression[] constExpressions, ParameterExpression[] parameterExpressions) 30 | { 31 | if (bindings == null) throw new ArgumentNullException("bindings"); 32 | if (constExpressions == null) throw new ArgumentNullException("constExpressions"); 33 | if (parameterExpressions == null) throw new ArgumentNullException("parameterExpressions"); 34 | 35 | var listBindings = new PreparedListBinding[bindings.Sum(b => b is MemberListBinding ? ((MemberListBinding)b).Initializers.Count : 0)]; 36 | var i = 0; 37 | foreach (var binding in bindings) 38 | { 39 | var memberListBinding = binding as MemberListBinding; 40 | if (memberListBinding == null) 41 | continue; 42 | 43 | foreach (var elementInitializer in memberListBinding.Initializers) 44 | { 45 | var arguments = new ExecutionNode[elementInitializer.Arguments.Count]; 46 | for (var a = 0; a < arguments.Length; a++) 47 | arguments[a] = AotCompiler.Compile(elementInitializer.Arguments[a], constExpressions, parameterExpressions); 48 | 49 | listBindings[i++] = new PreparedListBinding(memberListBinding.Member, elementInitializer.AddMethod, arguments); 50 | } 51 | } 52 | 53 | this.bindingsByMember = listBindings.ToLookup(b => b.Member); 54 | } 55 | 56 | /// 57 | public override object Run(Closure closure) 58 | { 59 | var instance = closure.Unbox(closure.Locals[LOCAL_OPERAND1]); 60 | if (this.bindingsByMember.Count == 0) 61 | return instance; 62 | 63 | foreach (var bindings in this.bindingsByMember) 64 | { 65 | var member = bindings.Key; 66 | var addTarget = default(object); 67 | var fieldInfo = member as FieldInfo; 68 | var propertyInfo = member as PropertyInfo; 69 | 70 | if (fieldInfo != null) 71 | { 72 | if (fieldInfo.IsStatic == false && instance == null) 73 | throw new NullReferenceException(); 74 | addTarget = fieldInfo.GetValue(instance); 75 | } 76 | else if (propertyInfo != null) 77 | { 78 | if (propertyInfo.IsStatic() == false && instance == null) 79 | throw new NullReferenceException(); 80 | 81 | addTarget = propertyInfo.GetValue(instance, null); 82 | } 83 | else 84 | { 85 | throw new InvalidOperationException(string.Format(Properties.Resources.EXCEPTION_EXECUTION_INVALIDMEMBERFOREXPRESSION, member)); 86 | } 87 | 88 | foreach (var bindGroup in bindings) 89 | { 90 | var addMethod = bindGroup.AddMethod; 91 | var addArgumentNodes = bindGroup.AddMethodArguments; 92 | var addArguments = new object[addArgumentNodes.Length]; 93 | for (var i = 0; i < addArgumentNodes.Length; i++) 94 | addArguments[i] = closure.Unbox(addArgumentNodes[i].Run(closure)); 95 | 96 | addMethod.Invoke(addTarget, addArguments); 97 | } 98 | } 99 | return instance; 100 | } 101 | 102 | /// 103 | public override string ToString() 104 | { 105 | return string.Join(", ", this.bindingsByMember.Select(m => m.Key.Name).ToArray()); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Execution/NewArrayBoundsNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace GameDevWare.Dynamic.Expressions.Execution 5 | { 6 | internal sealed class NewArrayBoundsNode : ExecutionNode 7 | { 8 | private readonly NewArrayExpression newArrayExpression; 9 | private readonly ExecutionNode[] rankNodes; 10 | 11 | public NewArrayBoundsNode(NewArrayExpression newArrayExpression, ConstantExpression[] constExpressions, ParameterExpression[] parameterExpressions) 12 | { 13 | if (newArrayExpression == null) throw new ArgumentNullException("newArrayExpression"); 14 | if (constExpressions == null) throw new ArgumentNullException("constExpressions"); 15 | if (parameterExpressions == null) throw new ArgumentNullException("parameterExpressions"); 16 | 17 | this.newArrayExpression = newArrayExpression; 18 | 19 | this.rankNodes = new ExecutionNode[newArrayExpression.Expressions.Count]; 20 | for (var i = 0; i < this.rankNodes.Length; i++) 21 | this.rankNodes[i] = AotCompiler.Compile(newArrayExpression.Expressions[i], constExpressions, parameterExpressions); 22 | } 23 | 24 | /// 25 | public override object Run(Closure closure) 26 | { 27 | var ranks = new int[this.rankNodes.Length]; 28 | for (var i = 0; i < this.rankNodes.Length; i++) 29 | ranks[i] = closure.Unbox(this.rankNodes[i].Run(closure)); 30 | 31 | // ReSharper disable once AssignNullToNotNullAttribute 32 | var array = Array.CreateInstance(this.newArrayExpression.Type.GetElementType(), ranks); 33 | return array; 34 | } 35 | 36 | /// 37 | public override string ToString() 38 | { 39 | return this.newArrayExpression.ToString(); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Execution/NewArrayInitNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace GameDevWare.Dynamic.Expressions.Execution 5 | { 6 | internal sealed class NewArrayInitNode : ExecutionNode 7 | { 8 | private readonly NewArrayExpression newArrayExpression; 9 | private readonly ExecutionNode[] initializationValueNodes; 10 | 11 | public NewArrayInitNode(NewArrayExpression newArrayExpression, ConstantExpression[] constExpressions, ParameterExpression[] parameterExpressions) 12 | { 13 | if (newArrayExpression == null) throw new ArgumentNullException("newArrayExpression"); 14 | if (constExpressions == null) throw new ArgumentNullException("constExpressions"); 15 | if (parameterExpressions == null) throw new ArgumentNullException("parameterExpressions"); 16 | 17 | this.newArrayExpression = newArrayExpression; 18 | 19 | this.initializationValueNodes = new ExecutionNode[newArrayExpression.Expressions.Count]; 20 | for (var i = 0; i < this.initializationValueNodes.Length; i++) 21 | this.initializationValueNodes[i] = AotCompiler.Compile(newArrayExpression.Expressions[i], constExpressions, parameterExpressions); 22 | } 23 | 24 | /// 25 | public override object Run(Closure closure) 26 | { 27 | // ReSharper disable once AssignNullToNotNullAttribute 28 | var array = Array.CreateInstance(this.newArrayExpression.Type.GetElementType(), this.initializationValueNodes.Length); 29 | for (var i = 0; i < this.initializationValueNodes.Length; i++) 30 | { 31 | var initializationValue = this.initializationValueNodes[i].Run(closure); 32 | array.SetValue(closure.Unbox(initializationValue), i); 33 | } 34 | 35 | return array; 36 | } 37 | 38 | /// 39 | public override string ToString() 40 | { 41 | return this.newArrayExpression.ToString(); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Execution/NewNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | using System.Reflection; 4 | 5 | namespace GameDevWare.Dynamic.Expressions.Execution 6 | { 7 | internal sealed class NewNode : ExecutionNode 8 | { 9 | private static readonly object[] EmptyArguments = new object[0]; 10 | 11 | private readonly NewExpression newExpression; 12 | private readonly ExecutionNode[] initializationValueNodes; 13 | private readonly int constructorParametersCount; 14 | private readonly bool isNullableType; 15 | 16 | public NewNode(NewExpression newExpression, ConstantExpression[] constExpressions, ParameterExpression[] parameterExpressions) 17 | { 18 | if (newExpression == null) throw new ArgumentNullException("newExpression"); 19 | if (constExpressions == null) throw new ArgumentNullException("constExpressions"); 20 | if (parameterExpressions == null) throw new ArgumentNullException("parameterExpressions"); 21 | 22 | this.newExpression = newExpression; 23 | 24 | this.initializationValueNodes = new ExecutionNode[newExpression.Arguments.Count]; 25 | for (var i = 0; i < this.initializationValueNodes.Length; i++) 26 | this.initializationValueNodes[i] = AotCompiler.Compile(newExpression.Arguments[i], constExpressions, parameterExpressions); 27 | this.constructorParametersCount = newExpression.Constructor.GetParameters().Length; 28 | this.isNullableType = IsNullable(newExpression.Type); 29 | } 30 | 31 | /// 32 | public override object Run(Closure closure) 33 | { 34 | var initializationValues = new object[this.initializationValueNodes.Length]; 35 | for (var i = 0; i < initializationValues.Length; i++) 36 | initializationValues[i] = closure.Unbox(this.initializationValueNodes[i].Run(closure)); 37 | 38 | var constructorArguments = EmptyArguments; 39 | if (this.constructorParametersCount > 0) 40 | { 41 | constructorArguments = new object[this.constructorParametersCount]; 42 | Array.Copy(initializationValues, constructorArguments, this.constructorParametersCount); 43 | } 44 | 45 | var newInstance = this.isNullableType ? null : Activator.CreateInstance(this.newExpression.Type, constructorArguments); 46 | if (newInstance == null) 47 | throw new NullReferenceException(string.Format(Properties.Resources.EXCEPTION_EXECUTION_EXPRESSIONGIVESNULLRESULT, this.newExpression)); 48 | 49 | return newInstance; 50 | } 51 | 52 | /// 53 | public override string ToString() 54 | { 55 | return this.newExpression.ToString(); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Execution/NullNode.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace GameDevWare.Dynamic.Expressions.Execution 3 | { 4 | internal sealed class NullNode : ExecutionNode 5 | { 6 | public static readonly NullNode Instance = new NullNode(); 7 | 8 | /// 9 | public override object Run(Closure closure) 10 | { 11 | return null; 12 | } 13 | 14 | /// 15 | public override string ToString() 16 | { 17 | return "null"; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Execution/ParameterNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace GameDevWare.Dynamic.Expressions.Execution 5 | { 6 | internal sealed class ParameterNode : ExecutionNode 7 | { 8 | private readonly ParameterExpression parameterExpression; 9 | private readonly int parameterIndex; 10 | 11 | public ParameterNode(ParameterExpression parameterExpression, ParameterExpression[] parameterExpressions) 12 | { 13 | if (parameterExpression == null) throw new ArgumentNullException("parameterExpression"); 14 | if (parameterExpressions == null) throw new ArgumentNullException("parameterExpressions"); 15 | 16 | this.parameterExpression = parameterExpression; 17 | this.parameterIndex = Array.IndexOf(parameterExpressions, parameterExpression); 18 | 19 | if (this.parameterIndex < 0) 20 | throw new ArgumentException("Parameter expression is not found in passed parameter list.", "parameterExpression"); 21 | } 22 | /// 23 | public override object Run(Closure closure) 24 | { 25 | var parameter = closure.Locals[LOCAL_FIRST_PARAMETER + this.parameterIndex]; 26 | return parameter; 27 | } 28 | 29 | /// 30 | public override string ToString() 31 | { 32 | return this.parameterExpression.ToString(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Execution/QuoteNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace GameDevWare.Dynamic.Expressions.Execution 5 | { 6 | internal sealed class QuoteNode : ExecutionNode 7 | { 8 | private readonly UnaryExpression unaryExpression; 9 | 10 | public QuoteNode(UnaryExpression unaryExpression) 11 | { 12 | if (unaryExpression == null) throw new ArgumentNullException("unaryExpression"); 13 | 14 | this.unaryExpression = unaryExpression; 15 | } 16 | 17 | /// 18 | public override object Run(Closure closure) 19 | { 20 | return this.unaryExpression.Operand; 21 | } 22 | 23 | /// 24 | public override string ToString() 25 | { 26 | return this.unaryExpression.ToString(); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Execution/TypeAsNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | using GameDevWare.Dynamic.Expressions.Binding; 4 | 5 | namespace GameDevWare.Dynamic.Expressions.Execution 6 | { 7 | internal sealed class TypeAsNode : ExecutionNode 8 | { 9 | private readonly UnaryExpression typeAsExpression; 10 | private readonly ConvertNode convertNode; 11 | private readonly ExecutionNode targetNode; 12 | private readonly TypeDescription targetType; 13 | 14 | public TypeAsNode(UnaryExpression typeAsExpression, ConstantExpression[] constExpressions, ParameterExpression[] parameterExpressions) 15 | { 16 | if (typeAsExpression == null) throw new ArgumentNullException("typeAsExpression"); 17 | if (constExpressions == null) throw new ArgumentNullException("constExpressions"); 18 | if (parameterExpressions == null) throw new ArgumentNullException("parameterExpressions"); 19 | 20 | this.typeAsExpression = typeAsExpression; 21 | 22 | this.targetType = TypeDescription.GetTypeDescription(typeAsExpression.Type); 23 | if (this.targetType.IsValueType) 24 | this.convertNode = new ConvertNode(typeAsExpression, constExpressions, parameterExpressions); 25 | else 26 | this.targetNode = AotCompiler.Compile(typeAsExpression.Operand, constExpressions, parameterExpressions); 27 | } 28 | 29 | /// 30 | public override object Run(Closure closure) 31 | { 32 | if (this.convertNode != null) 33 | return this.convertNode.Run(closure); 34 | 35 | var target = closure.Unbox(this.targetNode.Run(closure)); 36 | if (target == null) 37 | return null; 38 | 39 | if (this.targetType.IsAssignableFrom(target.GetType()) == false) 40 | return null; 41 | 42 | return target; 43 | } 44 | 45 | /// 46 | public override string ToString() 47 | { 48 | return this.typeAsExpression.ToString(); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Execution/TypeIsNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | using GameDevWare.Dynamic.Expressions.Binding; 4 | 5 | namespace GameDevWare.Dynamic.Expressions.Execution 6 | { 7 | internal sealed class TypeIsNode : ExecutionNode 8 | { 9 | private readonly TypeBinaryExpression typeBinaryExpression; 10 | private readonly ExecutionNode targetNode; 11 | private readonly TypeDescription targetType; 12 | 13 | public TypeIsNode(TypeBinaryExpression typeBinaryExpression, ConstantExpression[] constExpressions, ParameterExpression[] parameterExpressions) 14 | { 15 | if (typeBinaryExpression == null) throw new ArgumentNullException("typeBinaryExpression"); 16 | if (constExpressions == null) throw new ArgumentNullException("constExpressions"); 17 | if (parameterExpressions == null) throw new ArgumentNullException("parameterExpressions"); 18 | 19 | this.typeBinaryExpression = typeBinaryExpression; 20 | this.targetType = TypeDescription.GetTypeDescription(this.typeBinaryExpression.TypeOperand); 21 | this.targetNode = AotCompiler.Compile(typeBinaryExpression.Expression, constExpressions, parameterExpressions); 22 | } 23 | 24 | /// 25 | public override object Run(Closure closure) 26 | { 27 | var target = closure.Unbox(this.targetNode.Run(closure)); 28 | if (target == null) 29 | return Constants.FalseObject; 30 | 31 | return this.targetType.IsAssignableFrom(target.GetType()) ? Constants.TrueObject : Constants.FalseObject; 32 | } 33 | 34 | /// 35 | public override string ToString() 36 | { 37 | return this.typeBinaryExpression.ToString(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Execution/UnaryNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace GameDevWare.Dynamic.Expressions.Execution 5 | { 6 | internal sealed class UnaryNode : ExecutionNode 7 | { 8 | private readonly UnaryExpression unaryExpression; 9 | private readonly Intrinsic.UnaryOperation operation; 10 | private readonly ExecutionNode operandNode; 11 | private readonly bool isNullable; 12 | 13 | private UnaryNode( 14 | UnaryExpression unaryExpression, 15 | ConstantExpression[] constExpressions, 16 | ParameterExpression[] parameterExpressions, 17 | string unaryOperationMethodName) 18 | { 19 | this.unaryExpression = unaryExpression; 20 | if (unaryExpression == null) throw new ArgumentNullException("unaryExpression"); 21 | if (constExpressions == null) throw new ArgumentNullException("constExpressions"); 22 | if (parameterExpressions == null) throw new ArgumentNullException("parameterExpressions"); 23 | 24 | this.operandNode = AotCompiler.Compile(unaryExpression.Operand, constExpressions, parameterExpressions); 25 | this.isNullable = IsNullable(unaryExpression.Operand); 26 | this.operation = Intrinsic.WrapUnaryOperation(unaryExpression.Method) ?? 27 | (unaryOperationMethodName == null ? null : Intrinsic.WrapUnaryOperation(unaryExpression.Operand.Type, unaryOperationMethodName)); 28 | } 29 | 30 | /// 31 | public override object Run(Closure closure) 32 | { 33 | var operand = this.operandNode.Run(closure); 34 | 35 | if (this.isNullable && operand == null) 36 | return null; 37 | 38 | return Intrinsic.InvokeUnaryOperation(closure, operand, this.unaryExpression.NodeType, this.operation); 39 | } 40 | 41 | public static ExecutionNode Create(UnaryExpression unaryExpression, ConstantExpression[] constExpressions, ParameterExpression[] parameterExpressions) 42 | { 43 | switch (unaryExpression.NodeType) 44 | { 45 | case ExpressionType.UnaryPlus: return new UnaryNode(unaryExpression, constExpressions, parameterExpressions, "op_UnaryPlus"); 46 | case ExpressionType.Negate: 47 | case ExpressionType.NegateChecked: return new UnaryNode(unaryExpression, constExpressions, parameterExpressions, "op_UnaryNegation"); 48 | case ExpressionType.Not: return new UnaryNode(unaryExpression, constExpressions, parameterExpressions, "op_OnesComplement"); 49 | default: throw new InvalidOperationException(string.Format(Properties.Resources.EXCEPTION_COMPIL_UNKNOWNEXPRTYPE, unaryExpression.Type)); 50 | } 51 | } 52 | 53 | /// 54 | public override string ToString() 55 | { 56 | return this.unaryExpression.ToString(); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/ExpressionKnownTypeAttribute.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ 16 | 17 | using System; 18 | 19 | namespace GameDevWare.Dynamic.Expressions 20 | { 21 | /// 22 | /// Marker for to discover additional types with specified type (on which attribute is placed). 23 | /// 24 | [AttributeUsage(AttributeTargets.Class)] 25 | public sealed class ExpressionKnownTypeAttribute : Attribute 26 | { 27 | /// 28 | /// Additional type to discover. 29 | /// 30 | public Type Type { get; private set; } 31 | 32 | /// 33 | /// Creates new with specified type. 34 | /// 35 | /// Additional type to discover. Not null. 36 | public ExpressionKnownTypeAttribute(Type type) 37 | { 38 | if (type == null) throw new ArgumentNullException("type"); 39 | 40 | this.Type = type; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/ExpressionLookupVisitor.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ 16 | 17 | using System; 18 | using System.Collections.Generic; 19 | using System.Linq.Expressions; 20 | 21 | namespace GameDevWare.Dynamic.Expressions 22 | { 23 | internal sealed class ExpressionLookupVisitor : ExpressionVisitor 24 | { 25 | private readonly List lookupList; 26 | private int found = 0; 27 | 28 | public ExpressionLookupVisitor(List lookupList) 29 | { 30 | if (lookupList == null) throw new ArgumentNullException("lookupList"); 31 | 32 | this.lookupList = lookupList; 33 | } 34 | 35 | protected override Expression VisitBinary(BinaryExpression binaryExpression) 36 | { 37 | if (this.lookupList.Contains(binaryExpression)) 38 | this.found++; 39 | 40 | return base.VisitBinary(binaryExpression); 41 | } 42 | protected override Expression VisitConditional(ConditionalExpression conditionalExpression) 43 | { 44 | if (this.lookupList.Contains(conditionalExpression)) 45 | this.found++; 46 | 47 | return base.VisitConditional(conditionalExpression); 48 | } 49 | protected override Expression VisitConstant(ConstantExpression constantExpression) 50 | { 51 | if (this.lookupList.Contains(constantExpression)) 52 | this.found++; 53 | 54 | return base.VisitConstant(constantExpression); 55 | } 56 | protected override Expression VisitInvocation(InvocationExpression invocationExpression) 57 | { 58 | if (this.lookupList.Contains(invocationExpression)) 59 | this.found++; 60 | 61 | return base.VisitInvocation(invocationExpression); 62 | } 63 | protected override Expression VisitLambda(LambdaExpression lambda) 64 | { 65 | if (this.lookupList.Contains(lambda)) 66 | this.found++; 67 | 68 | return base.VisitLambda(lambda); 69 | } 70 | protected override Expression VisitListInit(ListInitExpression listInitExpression) 71 | { 72 | if (this.lookupList.Contains(listInitExpression)) 73 | this.found++; 74 | 75 | return base.VisitListInit(listInitExpression); 76 | 77 | } 78 | protected override Expression VisitMemberAccess(MemberExpression memberExpression) 79 | { 80 | if (this.lookupList.Contains(memberExpression)) 81 | this.found++; 82 | 83 | return base.VisitMemberAccess(memberExpression); 84 | } 85 | protected override Expression VisitMemberInit(MemberInitExpression memberInitExpression) 86 | { 87 | if (this.lookupList.Contains(memberInitExpression)) 88 | this.found++; 89 | 90 | return base.VisitMemberInit(memberInitExpression); 91 | } 92 | protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) 93 | { 94 | if (this.lookupList.Contains(methodCallExpression)) 95 | this.found++; 96 | 97 | return base.VisitMethodCall(methodCallExpression); 98 | } 99 | protected override NewExpression VisitNew(NewExpression newExpression) 100 | { 101 | if (this.lookupList.Contains(newExpression)) 102 | this.found++; 103 | 104 | return base.VisitNew(newExpression); 105 | } 106 | protected override Expression VisitNewArray(NewArrayExpression newArrayExpression) 107 | { 108 | if (this.lookupList.Contains(newArrayExpression)) 109 | this.found++; 110 | 111 | return base.VisitNewArray(newArrayExpression); 112 | } 113 | protected override Expression VisitParameter(ParameterExpression parameterExpression) 114 | { 115 | if (this.lookupList.Contains(parameterExpression)) 116 | this.found++; 117 | 118 | return base.VisitParameter(parameterExpression); 119 | } 120 | protected override Expression VisitTypeIs(TypeBinaryExpression typeBinaryExpression) 121 | { 122 | if (this.lookupList.Contains(typeBinaryExpression)) 123 | this.found++; 124 | 125 | return base.VisitTypeIs(typeBinaryExpression); 126 | } 127 | protected override Expression VisitUnary(UnaryExpression unaryExpression) 128 | { 129 | if (this.lookupList.Contains(unaryExpression)) 130 | this.found++; 131 | 132 | return base.VisitUnary(unaryExpression); 133 | } 134 | 135 | public static bool Lookup(Expression expression, List lookupList) 136 | { 137 | var visitor = new ExpressionLookupVisitor(lookupList); 138 | visitor.Visit(expression); 139 | return visitor.found == lookupList.Count; 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/ExpressionPacker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | using GameDevWare.Dynamic.Expressions.Binding; 5 | using GameDevWare.Dynamic.Expressions.Packing; 6 | 7 | namespace GameDevWare.Dynamic.Expressions 8 | { 9 | public static class ExpressionPacker 10 | { 11 | public static Dictionary Pack(Expression expression) 12 | { 13 | if (expression == null) throw new ArgumentNullException("expression"); 14 | 15 | return AnyPacker.Pack(expression); 16 | } 17 | public static Expression Unpack(IDictionary packedExpression, ITypeResolver typeResolver = null, Expression global = null, Type expectedType = null) 18 | { 19 | if (packedExpression == null) throw new ArgumentNullException("packedExpression"); 20 | if(typeResolver == null) typeResolver = KnownTypeResolver.Default; 21 | if (expectedType == null) expectedType = typeof(object); 22 | 23 | var syntaxTree = new SyntaxTreeNode(packedExpression); 24 | var bindingContext = new BindingContext(typeResolver, Constants.EmptyReadonlyParameters, expectedType, global); 25 | var boundExpression = default(Expression); 26 | var bindingError = default(Exception); 27 | 28 | if (AnyBinder.TryBindInNewScope(syntaxTree, bindingContext, TypeDescription.GetTypeDescription(expectedType), out boundExpression, out bindingError) == false) 29 | throw bindingError; 30 | 31 | return boundExpression; 32 | } 33 | public static LambdaExpression UnpackLambda(Type delegateType, IDictionary packedExpression, ITypeResolver typeResolver = null, Expression global = null) 34 | { 35 | if (delegateType == null) throw new ArgumentNullException("delegateType"); 36 | if (packedExpression == null) throw new ArgumentNullException("packedExpression"); 37 | 38 | var syntaxTree = new SyntaxTreeNode(packedExpression); 39 | var binder = new Binder(delegateType, typeResolver); 40 | var unpackedExpression = binder.Bind(syntaxTree, global); 41 | return unpackedExpression; 42 | } 43 | public static Expression UnpackLambda(IDictionary expressionTree, ITypeResolver typeResolver = null, Expression global = null) 44 | { 45 | if (expressionTree == null) throw new ArgumentNullException("expressionTree"); 46 | 47 | return (Expression)UnpackLambda(typeof(DelegateT), expressionTree, typeResolver, global); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/ExpressionParserException.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ 16 | 17 | using System; 18 | 19 | namespace GameDevWare.Dynamic.Expressions 20 | { 21 | /// 22 | /// Expression parsing exception. 23 | /// 24 | public sealed class ExpressionParserException : Exception, ILineInfo 25 | { 26 | /// 27 | /// Line number related to exception. 28 | /// 29 | public int LineNumber { get; set; } 30 | /// 31 | /// Column number related to exception. 32 | /// 33 | public int ColumnNumber { get; set; } 34 | /// 35 | /// Length of token related to exception. 36 | /// 37 | public int TokenLength { get; set; } 38 | 39 | internal ExpressionParserException() 40 | { 41 | 42 | } 43 | internal ExpressionParserException(string message, int lineNumber = 0, int columnNumber = 0, int tokenLength = 0) 44 | : base(message) 45 | { 46 | this.LineNumber = lineNumber; 47 | this.ColumnNumber = columnNumber; 48 | this.TokenLength = tokenLength; 49 | } 50 | internal ExpressionParserException(string message, Exception innerException, int lineNumber = 0, int columnNumber = 0, int tokenLength = 0) 51 | : base(message, innerException) 52 | { 53 | this.LineNumber = lineNumber; 54 | this.ColumnNumber = columnNumber; 55 | this.TokenLength = tokenLength; 56 | } 57 | internal ExpressionParserException(string message, ILineInfo lineInfo) 58 | : base(message) 59 | { 60 | if (lineInfo == null) 61 | return; 62 | 63 | this.LineNumber = lineInfo.GetLineNumber(); 64 | this.ColumnNumber = lineInfo.GetColumnNumber(); 65 | this.TokenLength = lineInfo.GetTokenLength(); 66 | } 67 | internal ExpressionParserException(string message, Exception innerException, ILineInfo lineInfo) 68 | : base(message, innerException) 69 | { 70 | if (lineInfo == null) 71 | return; 72 | 73 | this.LineNumber = lineInfo.GetLineNumber(); 74 | this.ColumnNumber = lineInfo.GetColumnNumber(); 75 | this.TokenLength = lineInfo.GetTokenLength(); 76 | } 77 | #if !NETSTANDARD 78 | // ReSharper disable once UnusedMember.Local 79 | private ExpressionParserException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) 80 | : base(info, context) 81 | { 82 | this.LineNumber = info.GetInt32("LineNumber"); 83 | this.ColumnNumber = info.GetInt32("ColumnNumber"); 84 | this.TokenLength = info.GetInt32("TokenLength"); 85 | } 86 | 87 | /// 88 | /// Return data for binary serialization. 89 | /// 90 | public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) 91 | { 92 | info.AddValue("LineNumber", (int)this.LineNumber); 93 | info.AddValue("ColumnNumber", (int)this.ColumnNumber); 94 | info.AddValue("TokenLength", (int)this.TokenLength); 95 | 96 | base.GetObjectData(info, context); 97 | } 98 | #endif 99 | 100 | int ILineInfo.GetLineNumber() 101 | { 102 | return this.LineNumber; 103 | } 104 | int ILineInfo.GetColumnNumber() 105 | { 106 | return this.ColumnNumber; 107 | } 108 | int ILineInfo.GetTokenLength() 109 | { 110 | return this.TokenLength; 111 | } 112 | 113 | /// 114 | /// Converts exception to string representation for debug purpose. 115 | /// 116 | /// 117 | public override string ToString() 118 | { 119 | if (this.TokenLength != 0) 120 | return string.Format("[{0},{1}+{2}]{3}", this.LineNumber.ToString(), this.ColumnNumber.ToString(), this.TokenLength.ToString(), base.ToString()); 121 | else 122 | return base.ToString(); 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/ExpressionPosition.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ 16 | 17 | using System; 18 | 19 | namespace GameDevWare.Dynamic.Expressions 20 | { 21 | internal struct ExpressionPosition : ILineInfo, IEquatable, IEquatable 22 | { 23 | public readonly int LineNumber; 24 | public readonly int ColumnNumber; 25 | public readonly int TokenLength; 26 | 27 | public ExpressionPosition(int lineNumber, int columnNumber, int tokenLength) 28 | { 29 | this.LineNumber = lineNumber; 30 | this.ColumnNumber = columnNumber; 31 | this.TokenLength = tokenLength; 32 | } 33 | 34 | public static ExpressionPosition Parse(string positionString) 35 | { 36 | if (positionString == null) throw new ArgumentNullException("positionString"); 37 | 38 | var colonIdx = positionString.IndexOf(':'); 39 | var plusIdx = positionString.IndexOf('+'); 40 | if (colonIdx < 0 || plusIdx < 0) 41 | throw new FormatException(); 42 | 43 | var line = int.Parse(positionString.Substring(0, colonIdx), Constants.DefaultFormatProvider); 44 | var column = int.Parse(positionString.Substring(colonIdx + 1, plusIdx - colonIdx - 1), Constants.DefaultFormatProvider); 45 | var length = int.Parse(positionString.Substring(plusIdx + 1), Constants.DefaultFormatProvider); 46 | 47 | return new ExpressionPosition(line, column, length); 48 | } 49 | 50 | /// 51 | public override bool Equals(object obj) 52 | { 53 | if (obj is ExpressionPosition) 54 | return this.Equals((ExpressionPosition)obj); 55 | else if (obj is ILineInfo) 56 | return this.Equals((ILineInfo)obj); 57 | else 58 | return false; 59 | } 60 | /// 61 | public bool Equals(ExpressionPosition other) 62 | { 63 | return this.LineNumber == other.LineNumber && this.ColumnNumber == other.ColumnNumber && this.TokenLength == other.TokenLength; 64 | } 65 | /// 66 | public bool Equals(ILineInfo other) 67 | { 68 | if (other == null) return false; 69 | 70 | return this.LineNumber == other.GetLineNumber() && this.ColumnNumber == other.GetColumnNumber() && this.TokenLength == other.GetTokenLength(); 71 | } 72 | /// 73 | public override int GetHashCode() 74 | { 75 | unchecked 76 | { 77 | var hashCode = this.LineNumber; 78 | hashCode = (hashCode * 397) ^ this.ColumnNumber; 79 | hashCode = (hashCode * 397) ^ this.TokenLength; 80 | return hashCode; 81 | } 82 | } 83 | 84 | int ILineInfo.GetLineNumber() 85 | { 86 | return this.LineNumber; 87 | } 88 | int ILineInfo.GetColumnNumber() 89 | { 90 | return this.ColumnNumber; 91 | } 92 | int ILineInfo.GetTokenLength() 93 | { 94 | return this.TokenLength; 95 | } 96 | 97 | /// 98 | public override string ToString() 99 | { 100 | return string.Format(Constants.DefaultFormatProvider, "{0}:{1}+{2}", this.LineNumber.ToString(), this.ColumnNumber.ToString(), this.TokenLength.ToString()); 101 | } 102 | 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/ExpressionSubstitutor.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ 16 | 17 | using System; 18 | using System.Collections.Generic; 19 | using System.Linq.Expressions; 20 | 21 | namespace GameDevWare.Dynamic.Expressions 22 | { 23 | 24 | internal class ExpressionSubstitutor : ExpressionVisitor 25 | { 26 | private readonly Dictionary substitutions; 27 | 28 | private ExpressionSubstitutor(Dictionary substitutions) 29 | { 30 | if (substitutions == null) throw new ArgumentNullException("substitutions"); 31 | 32 | this.substitutions = substitutions; 33 | } 34 | protected override Expression VisitParameter(ParameterExpression parameterExpression) 35 | { 36 | var substitutionParameter = default(Expression); 37 | if (this.substitutions.TryGetValue(parameterExpression, out substitutionParameter)) 38 | return substitutionParameter; 39 | return base.VisitParameter(parameterExpression); 40 | } 41 | protected override Expression VisitConstant(ConstantExpression constantExpression) 42 | { 43 | var substitutionParameter = default(Expression); 44 | if (this.substitutions.TryGetValue(constantExpression, out substitutionParameter)) 45 | return substitutionParameter; 46 | return base.VisitConstant(constantExpression); 47 | } 48 | 49 | public static Expression Visit(Expression expression, Dictionary substitutions) 50 | { 51 | if (expression == null) throw new ArgumentNullException("expression"); 52 | if (substitutions == null) throw new ArgumentNullException("substitutions"); 53 | 54 | var substitutor = new ExpressionSubstitutor(substitutions); 55 | return substitutor.Visit(expression); 56 | } 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/GameDevWare.Dynamic.Expressions.csproj.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | No 3 | 4 | 5 | 6 | CSharp40 7 | True -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/ILineInfo.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ 16 | 17 | namespace GameDevWare.Dynamic.Expressions 18 | { 19 | internal interface ILineInfo 20 | { 21 | int GetLineNumber(); 22 | int GetColumnNumber(); 23 | int GetTokenLength(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/ITypeResolver.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ 16 | using System; 17 | 18 | namespace GameDevWare.Dynamic.Expressions 19 | { 20 | /// 21 | /// Interface for type resolution services. 22 | /// 23 | public interface ITypeResolver 24 | { 25 | /// 26 | /// Tries to retrieve type by it's name and generic parameters. 27 | /// 28 | /// Type name. Not null. Not 29 | /// Found type or null. 30 | /// True if type is found. Overwise is false. 31 | bool TryGetType(TypeReference typeReference, out Type foundType); 32 | /// 33 | /// Checks if specified type is known by current type resolver; 34 | /// 35 | /// Type to lookup. Not null. 36 | /// True if type is known by this resolver. Overwise false. 37 | bool IsKnownType(Type type); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/JitSupportDetector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | #if !NETSTANDARD1_3 3 | using System.Reflection.Emit; 4 | #endif 5 | 6 | namespace GameDevWare.Dynamic.Expressions 7 | { 8 | internal sealed class JitSupportDetector 9 | { 10 | private static bool? IsDynamicCompilationResult; 11 | 12 | public static bool IsDynamicCompilationAvailable() 13 | { 14 | if (AotCompilation.IsAotRuntime) 15 | { 16 | return false; 17 | } 18 | 19 | if (IsDynamicCompilationResult.HasValue) 20 | { 21 | return IsDynamicCompilationResult.Value; 22 | } 23 | 24 | try 25 | { 26 | #if NETSTANDARD1_3 27 | // check lambdas are supported 28 | System.Linq.Expressions.Expression.Lambda>(System.Linq.Expressions.Expression.Constant(true)).Compile(); 29 | #else 30 | // check dynamic methods are supported 31 | var voidDynamicMethod = new DynamicMethod("TestVoidMethod", typeof(void), Type.EmptyTypes, restrictedSkipVisibility: true); 32 | var il = voidDynamicMethod.GetILGenerator(); 33 | il.Emit(OpCodes.Nop); 34 | voidDynamicMethod.CreateDelegate(typeof(Action)); 35 | #endif 36 | IsDynamicCompilationResult = true; 37 | } 38 | catch (Exception) { IsDynamicCompilationResult = false; } 39 | 40 | return IsDynamicCompilationResult.Value; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Packing/ArrayIndexPacker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | 6 | namespace GameDevWare.Dynamic.Expressions.Packing 7 | { 8 | internal static class ArrayIndexPacker 9 | { 10 | public static Dictionary Pack(Expression expression) 11 | { 12 | if (expression == null) throw new ArgumentNullException("expression"); 13 | 14 | var binaryExpression = expression as BinaryExpression; 15 | var methodCall = expression as MethodCallExpression; 16 | var arguments = default(Expression[]); 17 | var argumentNames = default(string[]); 18 | var operand = default(Expression); 19 | if (methodCall != null) 20 | { 21 | arguments = methodCall.Arguments.ToArray(); 22 | operand = methodCall.Object; 23 | argumentNames = ArrayUtils.ConvertAll(methodCall.Method.GetParameters(), p => p.Name); 24 | } 25 | else if (binaryExpression != null) 26 | { 27 | arguments = new[] { binaryExpression.Right }; 28 | operand = binaryExpression.Left; 29 | } 30 | else 31 | { 32 | throw new InvalidOperationException("Invalid expression type for this packer."); 33 | } 34 | 35 | return new Dictionary(4) { 36 | {Constants.EXPRESSION_TYPE_ATTRIBUTE, Constants.EXPRESSION_TYPE_INDEX}, 37 | {Constants.EXPRESSION_ATTRIBUTE, AnyPacker.Pack(operand)}, 38 | {Constants.ARGUMENTS_ATTRIBUTE, AnyPacker.Pack(arguments, argumentNames)} 39 | }; 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Packing/ArrayLengthPacker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | 5 | namespace GameDevWare.Dynamic.Expressions.Packing 6 | { 7 | internal static class ArrayLengthPacker 8 | { 9 | public static Dictionary Pack(UnaryExpression expression) 10 | { 11 | if (expression == null) throw new ArgumentNullException("expression"); 12 | 13 | return new Dictionary(2) { 14 | {Constants.EXPRESSION_TYPE_ATTRIBUTE, Constants.EXPRESSION_TYPE_ARRAY_LENGTH}, 15 | {Constants.EXPRESSION_ATTRIBUTE, AnyPacker.Pack(expression.Operand)}, 16 | }; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Packing/BinaryPacker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | 5 | namespace GameDevWare.Dynamic.Expressions.Packing 6 | { 7 | internal static class BinaryPacker 8 | { 9 | public static Dictionary Pack(BinaryExpression expression) 10 | { 11 | if (expression == null) throw new ArgumentNullException("expression"); 12 | 13 | var expressionType = string.Empty; 14 | // ReSharper disable once SwitchStatementMissingSomeCases 15 | switch (expression.NodeType) 16 | { 17 | case ExpressionType.RightShift: expressionType = Constants.EXPRESSION_TYPE_RIGHT_SHIFT; break; 18 | case ExpressionType.Subtract: expressionType = Constants.EXPRESSION_TYPE_SUBTRACT; break; 19 | case ExpressionType.SubtractChecked: expressionType = Constants.EXPRESSION_TYPE_SUBTRACT_CHECKED; break; 20 | case ExpressionType.Power: expressionType = Constants.EXPRESSION_TYPE_POWER; break; 21 | case ExpressionType.NotEqual: expressionType = Constants.EXPRESSION_TYPE_NOT_EQUAL; break; 22 | case ExpressionType.Or: expressionType = Constants.EXPRESSION_TYPE_OR; break; 23 | case ExpressionType.OrElse: expressionType = Constants.EXPRESSION_TYPE_OR_ELSE; break; 24 | case ExpressionType.MultiplyChecked: expressionType = Constants.EXPRESSION_TYPE_MULTIPLY_CHECKED; break; 25 | case ExpressionType.Multiply: expressionType = Constants.EXPRESSION_TYPE_MULTIPLY; break; 26 | case ExpressionType.Modulo: expressionType = Constants.EXPRESSION_TYPE_MODULO; break; 27 | case ExpressionType.LessThan: expressionType = Constants.EXPRESSION_TYPE_LESS_THAN; break; 28 | case ExpressionType.LessThanOrEqual: expressionType = Constants.EXPRESSION_TYPE_LESS_THAN_OR_EQUAL; break; 29 | case ExpressionType.LeftShift: expressionType = Constants.EXPRESSION_TYPE_LEFT_SHIFT; break; 30 | case ExpressionType.GreaterThanOrEqual: expressionType = Constants.EXPRESSION_TYPE_GREATER_THAN_OR_EQUAL; break; 31 | case ExpressionType.GreaterThan: expressionType = Constants.EXPRESSION_TYPE_GREATER_THAN; break; 32 | case ExpressionType.ExclusiveOr: expressionType = Constants.EXPRESSION_TYPE_EXCLUSIVE_OR; break; 33 | case ExpressionType.Equal: expressionType = Constants.EXPRESSION_TYPE_EQUAL; break; 34 | case ExpressionType.Divide: expressionType = Constants.EXPRESSION_TYPE_DIVIDE; break; 35 | case ExpressionType.Coalesce: expressionType = Constants.EXPRESSION_TYPE_COALESCE; break; 36 | case ExpressionType.AndAlso: expressionType = Constants.EXPRESSION_TYPE_AND_ALSO; break; 37 | case ExpressionType.And: expressionType = Constants.EXPRESSION_TYPE_AND; break; 38 | case ExpressionType.AddChecked: expressionType = Constants.EXPRESSION_TYPE_ADD_CHECKED; break; 39 | case ExpressionType.Add: expressionType = Constants.EXPRESSION_TYPE_ADD; break; 40 | default: throw new InvalidOperationException("Invalid expression type for this packer."); 41 | } 42 | 43 | var node = new Dictionary(4) { 44 | {Constants.EXPRESSION_TYPE_ATTRIBUTE, expressionType}, 45 | {Constants.LEFT_ATTRIBUTE, AnyPacker.Pack(expression.Left)}, 46 | {Constants.RIGHT_ATTRIBUTE, AnyPacker.Pack(expression.Right)} 47 | }; 48 | if (expression.Method != null) 49 | { 50 | node.Add(Constants.METHOD_ATTRIBUTE, AnyPacker.Pack(expression.Method)); 51 | } 52 | if (expression.Conversion != null) 53 | { 54 | node.Add(Constants.CONVERSION_ATTRIBUTE, AnyPacker.Pack(expression.Conversion)); 55 | } 56 | return node; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Packing/CallPacker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | 6 | namespace GameDevWare.Dynamic.Expressions.Packing 7 | { 8 | internal static class CallPacker 9 | { 10 | public static Dictionary Pack(MethodCallExpression expression) 11 | { 12 | if (expression == null) throw new ArgumentNullException("expression"); 13 | 14 | var arguments = expression.Arguments.ToArray(); 15 | var argumentNames = ArrayUtils.ConvertAll(expression.Method.GetParameters(), p => p.Name); 16 | 17 | return new Dictionary(4) { 18 | {Constants.EXPRESSION_TYPE_ATTRIBUTE, Constants.EXPRESSION_TYPE_CALL}, 19 | {Constants.EXPRESSION_ATTRIBUTE, AnyPacker.Pack(expression.Object)}, 20 | {Constants.METHOD_ATTRIBUTE, AnyPacker.Pack(expression.Method)}, 21 | {Constants.ARGUMENTS_ATTRIBUTE, AnyPacker.Pack(arguments, argumentNames)}, 22 | }; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Packing/ConditionPacker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | 5 | namespace GameDevWare.Dynamic.Expressions.Packing 6 | { 7 | internal static class ConditionPacker 8 | { 9 | public static Dictionary Pack(ConditionalExpression expression) 10 | { 11 | if (expression == null) throw new ArgumentNullException("expression"); 12 | 13 | return new Dictionary(4) { 14 | {Constants.EXPRESSION_TYPE_ATTRIBUTE, Constants.EXPRESSION_TYPE_CONDITION}, 15 | {Constants.TEST_ATTRIBUTE, AnyPacker.Pack(expression.Test)}, 16 | {Constants.IF_TRUE_ATTRIBUTE, AnyPacker.Pack(expression.IfTrue)}, 17 | {Constants.IF_FALSE_ATTRIBUTE, AnyPacker.Pack(expression.IfFalse)}, 18 | }; 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Packing/ConstantPacker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | 5 | namespace GameDevWare.Dynamic.Expressions.Packing 6 | { 7 | internal static class ConstantPacker 8 | { 9 | public static Dictionary Pack(ConstantExpression expression) 10 | { 11 | if (expression == null) throw new ArgumentNullException("expression"); 12 | 13 | return new Dictionary(3) { 14 | {Constants.EXPRESSION_TYPE_ATTRIBUTE, Constants.EXPRESSION_TYPE_CONSTANT}, 15 | {Constants.TYPE_ATTRIBUTE, AnyPacker.Pack(expression.Type)}, 16 | {Constants.VALUE_ATTRIBUTE, expression.Value}, 17 | }; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Packing/ConvertPacker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | 5 | namespace GameDevWare.Dynamic.Expressions.Packing 6 | { 7 | internal static class ConvertPacker 8 | { 9 | public static Dictionary Pack(UnaryExpression expression) 10 | { 11 | if (expression == null) throw new ArgumentNullException("expression"); 12 | 13 | return new Dictionary(3) { 14 | {Constants.EXPRESSION_TYPE_ATTRIBUTE, expression.NodeType == ExpressionType.Convert ? 15 | Constants.EXPRESSION_TYPE_CONVERT : 16 | Constants.EXPRESSION_TYPE_CONVERT_CHECKED}, 17 | {Constants.EXPRESSION_ATTRIBUTE, AnyPacker.Pack(expression.Operand)}, 18 | {Constants.TYPE_ATTRIBUTE, AnyPacker.Pack(expression.Type)}, 19 | }; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Packing/InvokePacker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | 6 | namespace GameDevWare.Dynamic.Expressions.Packing 7 | { 8 | internal static class InvokePacker 9 | { 10 | public static Dictionary Pack(InvocationExpression expression) 11 | { 12 | if (expression == null) throw new ArgumentNullException("expression"); 13 | 14 | var arguments = expression.Arguments.ToArray(); 15 | 16 | return new Dictionary(3) { 17 | {Constants.EXPRESSION_TYPE_ATTRIBUTE, Constants.EXPRESSION_TYPE_INVOKE}, 18 | {Constants.EXPRESSION_ATTRIBUTE, AnyPacker.Pack(expression.Expression)}, 19 | {Constants.ARGUMENTS_ATTRIBUTE, AnyPacker.Pack(arguments, null)}, 20 | }; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Packing/LambdaPacker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | 5 | namespace GameDevWare.Dynamic.Expressions.Packing 6 | { 7 | internal static class LambdaPacker 8 | { 9 | public static Dictionary Pack(LambdaExpression expression) 10 | { 11 | if (expression == null) throw new ArgumentNullException("expression"); 12 | 13 | var arguments = new Dictionary(expression.Parameters.Count); 14 | for (var p = 0; p < expression.Parameters.Count; p++) 15 | { 16 | var key = Constants.GetIndexAsString(p); 17 | arguments[key] = AnyPacker.Pack(expression.Parameters[p]); 18 | } 19 | 20 | return new Dictionary(4) { 21 | { Constants.EXPRESSION_TYPE_ATTRIBUTE, Constants.EXPRESSION_TYPE_LAMBDA }, 22 | { Constants.TYPE_ATTRIBUTE, AnyPacker.Pack(expression.Type) }, 23 | { Constants.EXPRESSION_ATTRIBUTE, AnyPacker.Pack(expression.Body) }, 24 | { Constants.ARGUMENTS_ATTRIBUTE, arguments } 25 | }; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Packing/ListInitPacker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | 5 | namespace GameDevWare.Dynamic.Expressions.Packing 6 | { 7 | internal static class ListInitPacker 8 | { 9 | public static Dictionary Pack(ListInitExpression expression) 10 | { 11 | if (expression == null) throw new ArgumentNullException("expression"); 12 | 13 | return new Dictionary(3) { 14 | {Constants.EXPRESSION_TYPE_ATTRIBUTE, Constants.EXPRESSION_TYPE_LIST_INIT}, 15 | {Constants.NEW_ATTRIBUTE, AnyPacker.Pack(expression.NewExpression)}, 16 | {Constants.INITIALIZERS_ATTRIBUTE, MemberInitPacker.Pack(expression.Initializers)}, 17 | }; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Packing/MemberAccessPacker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | 5 | namespace GameDevWare.Dynamic.Expressions.Packing 6 | { 7 | internal static class MemberAccessPacker 8 | { 9 | public static Dictionary Pack(MemberExpression expression) 10 | { 11 | if (expression == null) throw new ArgumentNullException("expression"); 12 | 13 | 14 | if (expression.Expression != null) 15 | { 16 | var memberAccessExpression = new Dictionary(3) { 17 | { Constants.EXPRESSION_TYPE_ATTRIBUTE, Constants.EXPRESSION_TYPE_MEMBER_RESOLVE }, 18 | { Constants.NAME_ATTRIBUTE, expression.Member.Name }, 19 | { Constants.EXPRESSION_ATTRIBUTE, AnyPacker.Pack(expression.Expression) }, 20 | }; 21 | return memberAccessExpression; 22 | } 23 | else 24 | { 25 | var memberAccessExpression = new Dictionary(2) { 26 | { Constants.EXPRESSION_TYPE_ATTRIBUTE, Constants.EXPRESSION_TYPE_MEMBER_RESOLVE }, 27 | { Constants.MEMBER_ATTRIBUTE, AnyPacker.Pack(expression.Member) } 28 | }; 29 | return memberAccessExpression; 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Packing/MemberInitPacker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Linq; 5 | using System.Linq.Expressions; 6 | 7 | namespace GameDevWare.Dynamic.Expressions.Packing 8 | { 9 | internal static class MemberInitPacker 10 | { 11 | public static Dictionary Pack(MemberInitExpression expression) 12 | { 13 | if (expression == null) throw new ArgumentNullException("expression"); 14 | 15 | return new Dictionary(3) { 16 | {Constants.EXPRESSION_TYPE_ATTRIBUTE, Constants.EXPRESSION_TYPE_MEMBER_INIT}, 17 | {Constants.NEW_ATTRIBUTE, AnyPacker.Pack(expression.NewExpression)}, 18 | {Constants.BINDINGS_ATTRIBUTE, Pack(expression.Bindings)}, 19 | }; 20 | } 21 | public static Dictionary Pack(ReadOnlyCollection expressionBindings) 22 | { 23 | if (expressionBindings == null) throw new ArgumentNullException("expressionBindings"); 24 | 25 | var bindingList = new Dictionary(expressionBindings.Count); 26 | for (var i = 0; i < expressionBindings.Count; i++) 27 | { 28 | var key = Constants.GetIndexAsString(i); 29 | var binding = expressionBindings[i]; 30 | switch (binding.BindingType) 31 | { 32 | case MemberBindingType.Assignment: 33 | bindingList.Add(key, Pack((MemberAssignment)binding)); 34 | break; 35 | case MemberBindingType.MemberBinding: 36 | bindingList.Add(key, Pack((MemberMemberBinding)binding)); 37 | break; 38 | case MemberBindingType.ListBinding: 39 | bindingList.Add(key, Pack((MemberListBinding)binding)); 40 | break; 41 | default: throw new ArgumentOutOfRangeException(); 42 | } 43 | } 44 | return bindingList; 45 | } 46 | public static Dictionary Pack(MemberListBinding memberListBinding) 47 | { 48 | if (memberListBinding == null) throw new ArgumentNullException("memberListBinding"); 49 | 50 | return new Dictionary(3) 51 | { 52 | { Constants.TYPE_ATTRIBUTE, "ListBinding" }, 53 | { Constants.MEMBER_ATTRIBUTE, AnyPacker.Pack(memberListBinding.Member) }, 54 | { Constants.INITIALIZERS_ATTRIBUTE, Pack(memberListBinding.Initializers) } 55 | }; 56 | } 57 | public static Dictionary Pack(MemberMemberBinding memberMemberBinding) 58 | { 59 | if (memberMemberBinding == null) throw new ArgumentNullException("memberMemberBinding"); 60 | 61 | return new Dictionary(3) 62 | { 63 | { Constants.TYPE_ATTRIBUTE, "MemberBinding" }, 64 | { Constants.MEMBER_ATTRIBUTE, AnyPacker.Pack(memberMemberBinding.Member) }, 65 | { Constants.BINDINGS_ATTRIBUTE, Pack(memberMemberBinding.Bindings) } 66 | }; 67 | } 68 | public static Dictionary Pack(MemberAssignment memberAssignment) 69 | { 70 | if (memberAssignment == null) throw new ArgumentNullException("memberAssignment"); 71 | 72 | return new Dictionary 73 | { 74 | { Constants.TYPE_ATTRIBUTE, "Assignment" }, 75 | { Constants.MEMBER_ATTRIBUTE, AnyPacker.Pack(memberAssignment.Member) }, 76 | { Constants.EXPRESSION_ATTRIBUTE, AnyPacker.Pack(memberAssignment.Expression) } 77 | }; 78 | } 79 | public static Dictionary Pack(ElementInit elementInit) 80 | { 81 | if (elementInit == null) throw new ArgumentNullException("elementInit"); 82 | 83 | var arguments = elementInit.Arguments.ToArray(); 84 | 85 | return new Dictionary(2) 86 | { 87 | { Constants.METHOD_ATTRIBUTE, AnyPacker.Pack(elementInit.AddMethod) }, 88 | { Constants.ARGUMENTS_ATTRIBUTE, AnyPacker.Pack(arguments, null) } 89 | }; 90 | } 91 | 92 | internal static Dictionary Pack(ReadOnlyCollection elementInitializers) 93 | { 94 | if (elementInitializers == null) throw new ArgumentNullException("elementInitializers"); 95 | 96 | var initializers = new Dictionary(); 97 | for (var i = 0; i < elementInitializers.Count; i++) 98 | { 99 | var key = Constants.GetIndexAsString(i); 100 | var value = Pack(elementInitializers[i]); 101 | initializers[key] = value; 102 | } 103 | 104 | return initializers; 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Packing/NewArrayPacker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Reflection; 6 | 7 | namespace GameDevWare.Dynamic.Expressions.Packing 8 | { 9 | internal static class NewArrayPacker 10 | { 11 | public static Dictionary Pack(NewArrayExpression expression) 12 | { 13 | if (expression == null) throw new ArgumentNullException("expression"); 14 | 15 | var arguments = expression.Expressions.ToArray(); 16 | var elementType = expression.Type.GetTypeInfo().GetElementType(); 17 | // ReSharper disable once SwitchStatementMissingSomeCases 18 | switch (expression.NodeType) 19 | { 20 | case ExpressionType.NewArrayBounds: 21 | return new Dictionary(3) { 22 | {Constants.EXPRESSION_TYPE_ATTRIBUTE, Constants.EXPRESSION_TYPE_NEW_ARRAY_BOUNDS}, 23 | {Constants.TYPE_ATTRIBUTE, AnyPacker.Pack(elementType)}, 24 | {Constants.ARGUMENTS_ATTRIBUTE, AnyPacker.Pack(arguments, names: null)}, 25 | }; 26 | case ExpressionType.NewArrayInit: 27 | return new Dictionary(3) { 28 | {Constants.EXPRESSION_TYPE_ATTRIBUTE, Constants.EXPRESSION_TYPE_NEW_ARRAY_INIT}, 29 | {Constants.TYPE_ATTRIBUTE, AnyPacker.Pack(elementType)}, 30 | {Constants.ARGUMENTS_ATTRIBUTE, AnyPacker.Pack(arguments, names: null)}, 31 | }; 32 | default: throw new InvalidOperationException("Invalid expression type for this packer."); 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Packing/NewPacker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | 6 | namespace GameDevWare.Dynamic.Expressions.Packing 7 | { 8 | internal static class NewPacker 9 | { 10 | public static Dictionary Pack(NewExpression expression) 11 | { 12 | if (expression == null) throw new ArgumentNullException("expression"); 13 | 14 | var arguments = expression.Arguments.ToArray(); 15 | var argumentNames = ArrayUtils.ConvertAll(expression.Constructor.GetParameters(), p => p.Name); 16 | 17 | return new Dictionary(3) { 18 | {Constants.EXPRESSION_TYPE_ATTRIBUTE, Constants.EXPRESSION_TYPE_NEW}, 19 | {Constants.METHOD_ATTRIBUTE, AnyPacker.Pack(expression.Constructor)}, 20 | {Constants.ARGUMENTS_ATTRIBUTE, AnyPacker.Pack(arguments, argumentNames)}, 21 | }; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Packing/ParameterPacker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | 5 | namespace GameDevWare.Dynamic.Expressions.Packing 6 | { 7 | internal static class ParameterPacker 8 | { 9 | public static Dictionary Pack(ParameterExpression expression) 10 | { 11 | if (expression == null) throw new ArgumentNullException("expression"); 12 | 13 | return new Dictionary(3) { 14 | {Constants.EXPRESSION_TYPE_ATTRIBUTE, Constants.EXPRESSION_TYPE_PARAMETER}, 15 | {Constants.TYPE_ATTRIBUTE, AnyPacker.Pack(expression.Type)}, 16 | {Constants.NAME_ATTRIBUTE, expression.Name}, 17 | }; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Packing/QuotePacker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | 5 | namespace GameDevWare.Dynamic.Expressions.Packing 6 | { 7 | internal static class QuotePacker 8 | { 9 | public static Dictionary Pack(UnaryExpression expression) 10 | { 11 | if (expression == null) throw new ArgumentNullException("expression"); 12 | 13 | return new Dictionary(2) { 14 | {Constants.EXPRESSION_TYPE_ATTRIBUTE, Constants.EXPRESSION_TYPE_QUOTE}, 15 | {Constants.EXPRESSION_ATTRIBUTE, AnyPacker.Pack(expression.Operand)} 16 | }; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Packing/TypeAsPacker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | 5 | namespace GameDevWare.Dynamic.Expressions.Packing 6 | { 7 | internal static class TypeAsPacker 8 | { 9 | public static Dictionary Pack(UnaryExpression expression) 10 | { 11 | if (expression == null) throw new ArgumentNullException("expression"); 12 | 13 | return new Dictionary(3) { 14 | {Constants.EXPRESSION_TYPE_ATTRIBUTE, Constants.EXPRESSION_TYPE_TYPE_AS}, 15 | {Constants.EXPRESSION_ATTRIBUTE, AnyPacker.Pack(expression.Operand)}, 16 | {Constants.TYPE_ATTRIBUTE, AnyPacker.Pack(expression.Type)} 17 | }; 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Packing/TypeIsPacker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | 5 | namespace GameDevWare.Dynamic.Expressions.Packing 6 | { 7 | internal static class TypeIsPacker 8 | { 9 | public static Dictionary Pack(TypeBinaryExpression expression) 10 | { 11 | if (expression == null) throw new ArgumentNullException("expression"); 12 | 13 | return new Dictionary(3) { 14 | {Constants.EXPRESSION_TYPE_ATTRIBUTE, Constants.EXPRESSION_TYPE_TYPE_IS}, 15 | {Constants.EXPRESSION_ATTRIBUTE, AnyPacker.Pack(expression.Expression)}, 16 | {Constants.TYPE_ATTRIBUTE, AnyPacker.Pack(expression.TypeOperand)}, 17 | }; 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Packing/UnaryPacker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | 5 | namespace GameDevWare.Dynamic.Expressions.Packing 6 | { 7 | internal static class UnaryPacker 8 | { 9 | public static Dictionary Pack(UnaryExpression expression) 10 | { 11 | if (expression == null) throw new ArgumentNullException("expression"); 12 | 13 | var expressionType = string.Empty; 14 | // ReSharper disable once SwitchStatementMissingSomeCases 15 | switch (expression.NodeType) 16 | { 17 | case ExpressionType.Not: 18 | expressionType = Constants.EXPRESSION_TYPE_NOT; 19 | break; 20 | case ExpressionType.NegateChecked: 21 | expressionType = Constants.EXPRESSION_TYPE_NEGATE_CHECKED; 22 | break; 23 | case ExpressionType.Negate: 24 | expressionType = Constants.EXPRESSION_TYPE_NEGATE; 25 | break; 26 | case ExpressionType.UnaryPlus: 27 | expressionType = Constants.EXPRESSION_TYPE_UNARY_PLUS; 28 | break; 29 | default: throw new InvalidOperationException("Invalid expression type for this packer."); 30 | } 31 | 32 | var node = new Dictionary(3) { 33 | {Constants.EXPRESSION_TYPE_ATTRIBUTE, expressionType}, 34 | {Constants.EXPRESSION_ATTRIBUTE, AnyPacker.Pack(expression.Operand)} 35 | }; 36 | if (expression.Method != null) 37 | { 38 | node.Add(Constants.METHOD_ATTRIBUTE, AnyPacker.Pack(expression.Method)); 39 | } 40 | return node; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("GameDevWare.Dynamic.Expressions.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010021F869E3CEA7567284CCBA18B3BF95FC07F6D167E57B70A20C6ED4F590882E933FFAACA29F1650CC38A1921BD799BAF08CBE3F68C44C88B606E37856DE7C82F7FFA6FB3F3081CEC54D65B51F88CABF44BD2EE5A7B11C25890110480EFD40052D20C1928F2B063513802E2346AD2469C8DCA2D0B7AFD3451837CAC0658746B5BC")] 4 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/TypeDiscoveryOptions.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Denis Zykov, GameDevWare.com 3 | 4 | This a part of "C# Eval()" Unity Asset - https://www.assetstore.unity3d.com/en/#!/content/56706 5 | 6 | THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND 7 | REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 8 | IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY, 9 | FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE 10 | AND THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING. 11 | 12 | This source code is distributed via Unity Asset Store, 13 | to use it in your project you should accept Terms of Service and EULA 14 | https://unity3d.com/ru/legal/as_terms 15 | */ 16 | 17 | using System; 18 | 19 | namespace GameDevWare.Dynamic.Expressions 20 | { 21 | /// 22 | /// Options of type discovery on specified types. 23 | /// 24 | [Flags] 25 | public enum TypeDiscoveryOptions 26 | { 27 | /// 28 | /// Only specified types is known. 29 | /// 30 | Default = 0, 31 | /// 32 | /// All interfaces on specified types are known. 33 | /// 34 | Interfaces = 0x1 << 1, 35 | /// 36 | /// All generic arguments on specified types are known. 37 | /// 38 | GenericArguments = 0x1 << 2, 39 | /// 40 | /// All types from on specified types are known. 41 | /// 42 | KnownTypes = 0x1 << 3, 43 | /// 44 | /// All (recursively) on specified types are known. 45 | /// 46 | DeclaringTypes = 0x1 << 4, 47 | 48 | /// 49 | /// All discovery options are active. 50 | /// 51 | All = Interfaces | GenericArguments | KnownTypes | DeclaringTypes 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/TypeNameFormatOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GameDevWare.Dynamic.Expressions 4 | { 5 | [Flags] 6 | internal enum TypeNameFormatOptions 7 | { 8 | None, 9 | // ReSharper disable once ShiftExpressionRealShiftCountIsZero 10 | IncludeDeclaringType = 0x1 << 0, 11 | IncludeNamespace = 0x1 << 1 | IncludeDeclaringType, 12 | IncludeGenericArguments = 0x1 << 2, 13 | IncludeGenericSuffix = 0x1 << 3, 14 | UseAliases = 0x1 << 4, 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/TypeScriptResources.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="false" hostspecific="true" language="C#" linePragmas="true" #> 2 | <#@ assembly name="System.Windows.Forms" #> 3 | <#@ assembly name="System.Core" #> 4 | <#@ import namespace="System.Collections" #> 5 | <#@ import namespace="System.IO" #> 6 | <#@ import namespace="System.Linq" #> 7 | <#@ import namespace="System.Resources" #> 8 | <#@ output extension=".ts" #> 9 | <# 10 | var resources = ReadResX(this.Host.ResolvePath(@"./Properties/Resources.resx")); 11 | #> 12 | /* 13 | Copyright (c) 2015 Denis Zykov 14 | 15 | This is part of Charon Game Data Editor Unity Plugin. 16 | 17 | Charon Game Data Editor Unity Plugin is free software: you can redistribute it and/or modify 18 | it under the terms of the GNU General Public License as published by 19 | the Free Software Foundation, either version 3 of the License, or 20 | (at your option) any later version. 21 | 22 | This program is distributed in the hope that it will be useful, 23 | but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | GNU General Public License for more details. 26 | 27 | You should have received a copy of the GNU General Public License 28 | along with this program. If not, see http://www.gnu.org/licenses. 29 | */ 30 | //------------------------------------------------------------------------------ 31 | // 32 | // This code was generated by a tool. 33 | // 34 | // Changes to this file may cause incorrect behavior and will be lost if 35 | // the code is regenerated. 36 | // 37 | //------------------------------------------------------------------------------ 38 | 39 | // tslint:disable:max-line-length 40 | 41 | export class ExpressionResources { 42 | <# 43 | 44 | 45 | foreach(var key in resources.Keys.Cast().OrderBy(k => k)) 46 | { 47 | #> 48 | public static readonly <#= key #>: string = '<#= Convert.ToString(resources[key]).Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("'", "\\'") #>'; 49 | <# 50 | } 51 | #> 52 | } 53 | 54 | <#+ 55 | public static Hashtable ReadResX(string path) 56 | { 57 | var result = new Hashtable(StringComparer.OrdinalIgnoreCase); 58 | var resourceReader = new ResXResourceReader(File.OpenRead(path)); 59 | foreach(DictionaryEntry kv in resourceReader) 60 | result[(string)kv.Key] = kv.Value; 61 | 62 | return result; 63 | } 64 | #> 65 | -------------------------------------------------------------------------------- /src/GameDevWare.Dynamic.Expressions/sn.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deniszykov/csharp-eval-unity3d/f3251f389b4c430862a3de1896d88effe4c7cdad/src/GameDevWare.Dynamic.Expressions/sn.snk --------------------------------------------------------------------------------