Skip to content

Commit e4589fb

Browse files
authored
🚚 Split Parser.cs (#318)
* Add ParseException.Create * Move MethodData and IndexerData to their own files. * Introduce TypeUtils to handle Type checks and operations * Move _concatMethod and _toStringMethod to ReflectionExtensions * Move InterpreterExpression to its own file * Add MethodResolution class * Introduce MemberFinder * Extract LateBinders
1 parent 75c25c7 commit e4589fb

File tree

12 files changed

+1198
-1128
lines changed

12 files changed

+1198
-1128
lines changed

‎src/DynamicExpresso.Core/Exceptions/ParseException.cs‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,12 @@ public ParseException(string message, int position, Exception innerException)
2626

2727
public int Position { get; private set; }
2828

29-
#if !NETSTANDARD1_6
29+
public static ParseException Create(int pos, string format, params object[] args)
30+
{
31+
return new ParseException(string.Format(format, args), pos);
32+
}
33+
34+
#if !NETSTANDARD1_6
3035
protected ParseException(
3136
SerializationInfo info,
3237
StreamingContext context)

‎src/DynamicExpresso.Core/Parameter.cs‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Linq.Expressions;
33

44
namespace DynamicExpresso
@@ -49,4 +49,18 @@ public static Parameter Create<T>(string name, T value)
4949

5050
public ParameterExpression Expression { get; private set; }
5151
}
52+
53+
/// <summary>
54+
/// Parameter with its position in the expression.
55+
/// </summary>
56+
internal class ParameterWithPosition : Parameter
57+
{
58+
public ParameterWithPosition(int pos, string name, Type type)
59+
: base(name, type)
60+
{
61+
Position = pos;
62+
}
63+
64+
public int Position { get; }
65+
}
5266
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Linq.Expressions;
5+
using DynamicExpresso.Exceptions;
6+
using DynamicExpresso.Reflection;
7+
8+
namespace DynamicExpresso.Parsing
9+
{
10+
internal class InterpreterExpression : Expression
11+
{
12+
private readonly Interpreter _interpreter;
13+
private readonly string _expressionText;
14+
private readonly IList<Parameter> _parameters;
15+
private Type _type;
16+
17+
public InterpreterExpression(ParserArguments parserArguments, string expressionText, params ParameterWithPosition[] parameters)
18+
{
19+
var settings = parserArguments.Settings.Clone();
20+
_interpreter = new Interpreter(settings);
21+
_expressionText = expressionText;
22+
_parameters = parameters;
23+
24+
// Take the parent expression's parameters and set them as an identifier that
25+
// can be accessed by any lower call
26+
// note: this doesn't impact the initial settings, because they're cloned
27+
foreach (var dp in parserArguments.DeclaredParameters)
28+
{
29+
// Have to mark the parameter as "Used" otherwise we can get a compilation error.
30+
parserArguments.TryGetParameters(dp.Name, out var pe);
31+
_interpreter.SetIdentifier(new Identifier(dp.Name, pe));
32+
}
33+
34+
foreach (var myParameter in parameters)
35+
{
36+
if (settings.Identifiers.ContainsKey(myParameter.Name))
37+
{
38+
throw new ParseException($"A local or parameter named '{myParameter.Name}' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter", myParameter.Position);
39+
}
40+
}
41+
42+
// prior to evaluation, we don't know the generic arguments types
43+
_type = ReflectionExtensions.GetFuncType(parameters.Length);
44+
}
45+
46+
public IList<Parameter> Parameters
47+
{
48+
get { return _parameters; }
49+
}
50+
51+
public override Type Type
52+
{
53+
get { return _type; }
54+
}
55+
56+
internal LambdaExpression EvalAs(Type delegateType)
57+
{
58+
if (!IsCompatibleWithDelegate(delegateType))
59+
return null;
60+
61+
var lambdaExpr = _interpreter.ParseAsExpression(delegateType, _expressionText, _parameters.Select(p => p.Name).ToArray());
62+
_type = lambdaExpr.Type;
63+
return lambdaExpr;
64+
}
65+
66+
internal bool IsCompatibleWithDelegate(Type target)
67+
{
68+
if (!target.IsGenericType || target.BaseType != typeof(MulticastDelegate))
69+
return false;
70+
71+
var genericTypeDefinition = target.GetGenericTypeDefinition();
72+
return genericTypeDefinition == ReflectionExtensions.GetFuncType(_parameters.Count)
73+
|| genericTypeDefinition == ReflectionExtensions.GetActionType(_parameters.Count);
74+
}
75+
}
76+
}

0 commit comments

Comments
 (0)