Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🚚 Split Parser.cs #318

Merged
merged 9 commits into from
Aug 19, 2024
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
Loading