Skip to content

Commit

Permalink
🚚 Split Parser.cs (#318)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
metoule authored Aug 19, 2024
1 parent 75c25c7 commit e4589fb
Show file tree
Hide file tree
Showing 12 changed files with 1,198 additions and 1,128 deletions.
7 changes: 6 additions & 1 deletion src/DynamicExpresso.Core/Exceptions/ParseException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ public ParseException(string message, int position, Exception innerException)

public int Position { get; private set; }

#if !NETSTANDARD1_6
public static ParseException Create(int pos, string format, params object[] args)
{
return new ParseException(string.Format(format, args), pos);
}

#if !NETSTANDARD1_6
protected ParseException(
SerializationInfo info,
StreamingContext context)
Expand Down
16 changes: 15 additions & 1 deletion src/DynamicExpresso.Core/Parameter.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Linq.Expressions;

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

public ParameterExpression Expression { get; private set; }
}

/// <summary>
/// Parameter with its position in the expression.
/// </summary>
internal class ParameterWithPosition : Parameter
{
public ParameterWithPosition(int pos, string name, Type type)
: base(name, type)
{
Position = pos;
}

public int Position { get; }
}
}
76 changes: 76 additions & 0 deletions src/DynamicExpresso.Core/Parsing/InterpreterExpression.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using DynamicExpresso.Exceptions;
using DynamicExpresso.Reflection;

namespace DynamicExpresso.Parsing
{
internal class InterpreterExpression : Expression
{
private readonly Interpreter _interpreter;
private readonly string _expressionText;
private readonly IList<Parameter> _parameters;
private Type _type;

public InterpreterExpression(ParserArguments parserArguments, string expressionText, params ParameterWithPosition[] parameters)
{
var settings = parserArguments.Settings.Clone();
_interpreter = new Interpreter(settings);
_expressionText = expressionText;
_parameters = parameters;

// Take the parent expression's parameters and set them as an identifier that
// can be accessed by any lower call
// note: this doesn't impact the initial settings, because they're cloned
foreach (var dp in parserArguments.DeclaredParameters)
{
// Have to mark the parameter as "Used" otherwise we can get a compilation error.
parserArguments.TryGetParameters(dp.Name, out var pe);
_interpreter.SetIdentifier(new Identifier(dp.Name, pe));
}

foreach (var myParameter in parameters)
{
if (settings.Identifiers.ContainsKey(myParameter.Name))
{
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);
}
}

// prior to evaluation, we don't know the generic arguments types
_type = ReflectionExtensions.GetFuncType(parameters.Length);
}

public IList<Parameter> Parameters
{
get { return _parameters; }
}

public override Type Type
{
get { return _type; }
}

internal LambdaExpression EvalAs(Type delegateType)
{
if (!IsCompatibleWithDelegate(delegateType))
return null;

var lambdaExpr = _interpreter.ParseAsExpression(delegateType, _expressionText, _parameters.Select(p => p.Name).ToArray());
_type = lambdaExpr.Type;
return lambdaExpr;
}

internal bool IsCompatibleWithDelegate(Type target)
{
if (!target.IsGenericType || target.BaseType != typeof(MulticastDelegate))
return false;

var genericTypeDefinition = target.GetGenericTypeDefinition();
return genericTypeDefinition == ReflectionExtensions.GetFuncType(_parameters.Count)
|| genericTypeDefinition == ReflectionExtensions.GetActionType(_parameters.Count);
}
}
}
Loading

0 comments on commit e4589fb

Please sign in to comment.