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

AOT safe #2

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ _ReSharper*/
src/**/obj/
src/**/bin/
project.lock.json
*.meta
46 changes: 42 additions & 4 deletions src/Dahomey.ExpressionEvaluator/ExpressionLexer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ internal enum TokenType
Mult,
Div,
Mod,
Pow,
Cos,
Sin,
Tan,
Abs,
Sqrt,
BitwiseAnd,
BitwiseOr,
BitwiseXor,
Expand Down Expand Up @@ -63,7 +69,7 @@ internal class ExpressionLexer

public ExpressionLexer(string expression)
{
this.expression = expression;
this.expression = expression.Replace("Pi", $"{Math.PI}").Replace("Pow","").Replace(',','^');
Advance();
NextToken();
}
Expand Down Expand Up @@ -242,7 +248,31 @@ private bool TryScanName()
case "false":
currentTokenType = TokenType.False;
break;


case "Sin":
currentTokenType = TokenType.Sin;
break;

case "Cos":
currentTokenType = TokenType.Cos;
break;

case "Tan":
currentTokenType = TokenType.Tan;
break;

case "Abs":
currentTokenType = TokenType.Abs;
break;

case "Sqrt":
currentTokenType = TokenType.Sqrt;
break;

case "Pow":
currentTokenType = TokenType.Pow;
break;

default:
currentTokenType = TokenType.Identifier;
break;
Expand Down Expand Up @@ -322,7 +352,15 @@ private bool TryScanOperatorOrPunctuation()

case '^':
Advance();
currentTokenType = TokenType.BitwiseXor;
if (currentChar == '^')
{
Advance();
currentTokenType = TokenType.BitwiseXor;
}
else
{
currentTokenType = TokenType.Pow;
}
break;

case '~':
Expand Down Expand Up @@ -470,4 +508,4 @@ public Exception BuildException(Exception innerException, string message, params
return BuildException(innerException, string.Format(message, args));
}
}
}
}
124 changes: 81 additions & 43 deletions src/Dahomey.ExpressionEvaluator/ExpressionParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,10 @@ private IExpression MultiplicativeExpression()
else if (lexer.Accept(TokenType.Mod))
{
op = Operator.Mod;
}
else if(lexer.Accept(TokenType.Pow))
{
op = Operator.Pow;
}
else
{
Expand Down Expand Up @@ -330,6 +334,46 @@ private IExpression UnaryExpression()
LeftExpr = (INumericExpression)PrimaryExpression()
};
}
else if (lexer.Accept(TokenType.Cos))
{
return new NumericArithmeticExpression
{
Operator = Operator.Cos,
LeftExpr = (INumericExpression)PrimaryExpression()
};
}
else if (lexer.Accept(TokenType.Sin))
{
return new NumericArithmeticExpression
{
Operator = Operator.Sin,
LeftExpr = (INumericExpression)PrimaryExpression()
};
}
else if (lexer.Accept(TokenType.Tan))
{
return new NumericArithmeticExpression
{
Operator = Operator.Tan,
LeftExpr = (INumericExpression)PrimaryExpression()
};
}
else if (lexer.Accept(TokenType.Abs))
{
return new NumericArithmeticExpression
{
Operator = Operator.Abs,
LeftExpr = (INumericExpression)PrimaryExpression()
};
}
else if (lexer.Accept(TokenType.Sqrt))
{
return new NumericArithmeticExpression
{
Operator = Operator.Sin,
LeftExpr = (INumericExpression)PrimaryExpression()
};
}
else if (lexer.Accept(TokenType.BitwiseComplement))
{
return new NumericArithmeticExpression
Expand Down Expand Up @@ -362,7 +406,6 @@ private IExpression PrimaryExpression()
{
return VariableExpression();
}

return Literal();
}

Expand Down Expand Up @@ -413,63 +456,58 @@ private IExpression ElementExpression(IExpression expr)
private IExpression VariableOrFunctionExpression()
{
string identifier = lexer.Identifier();

// function
if (lexer.Peek(TokenType.OpenParenthesis))
Type identifierType;
// variable
if (variableTypes.TryGetValue(identifier, out identifierType))
{
ListExpression argsExpr = (ListExpression)InvocationExpression();

Delegate function;

if (!functions.TryGetValue(identifier, out function))
{
throw BuildException("Unknown function '{0}()'", identifier);
}

MethodInfo methodInfo = function.Method;

if (ReflectionHelper.IsNumber(methodInfo.ReturnType))
if (ReflectionHelper.IsNumber(identifierType))
{
return new NumericFuncExpression(identifier, function, argsExpr);
return new NumericVariableExpression(identifier, identifierType);
}
else
{
return new ObjectFuncExpression(identifier, function, argsExpr);
return new ObjectVariableExpression(identifier, identifierType);
}
}
// variable or enum
else
{
Type identifierType;
// variable
if (variableTypes.TryGetValue(identifier, out identifierType))
identifierType = ReflectionHelper.GetType(assemblies, identifier);
// enum

if (identifier != null && identifierType.IsEnum)
{
if (ReflectionHelper.IsNumber(identifierType))
{
return new NumericVariableExpression(identifier, identifierType);
}
else
{
return new ObjectVariableExpression(identifier, identifierType);
}
lexer.Expect(TokenType.Dot);
string enumValue = lexer.Identifier();

Enum value = (Enum) Enum.Parse(identifierType, enumValue);
return new EnumLiteralExpression(value);
}
else
{
identifierType = ReflectionHelper.GetType(assemblies, identifier);
// enum

if (identifier != null && identifierType.IsEnum)
{
// function
if (lexer.Peek(TokenType.OpenParenthesis))
{
lexer.Expect(TokenType.Dot);
string enumValue = lexer.Identifier();
ListExpression argsExpr = (ListExpression) InvocationExpression();

Enum value = (Enum)Enum.Parse(identifierType, enumValue);
return new EnumLiteralExpression(value);
}
else
{
throw BuildException(string.Format("Unknown variable '{0}'", identifier));
Delegate function;

if (!functions.TryGetValue(identifier, out function))
{
throw BuildException("Unknown function '{0}()'", identifier);
}

MethodInfo methodInfo = function.Method;

if (ReflectionHelper.IsNumber(methodInfo.ReturnType))
{
return new NumericFuncExpression(identifier, function, argsExpr);
}
else
{
return new ObjectFuncExpression(identifier, function, argsExpr);
}
}
throw BuildException(string.Format("Unknown variable '{0}'", identifier));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ public double Evaluate(Dictionary<string, object> variables)
switch (Operator)
{
case Operator.Plus:
return RightExpr == null ?
LeftExpr.Evaluate(variables) :
LeftExpr.Evaluate(variables) + RightExpr.Evaluate(variables);
return RightExpr == null
? LeftExpr.Evaluate(variables)
: LeftExpr.Evaluate(variables) + RightExpr.Evaluate(variables);

case Operator.Minus:
return RightExpr == null ?
-LeftExpr.Evaluate(variables) :
LeftExpr.Evaluate(variables) - RightExpr.Evaluate(variables);
return RightExpr == null
? -LeftExpr.Evaluate(variables)
: LeftExpr.Evaluate(variables) - RightExpr.Evaluate(variables);

case Operator.Mult:
return LeftExpr.Evaluate(variables) * RightExpr.Evaluate(variables);
Expand All @@ -41,23 +41,41 @@ public double Evaluate(Dictionary<string, object> variables)
case Operator.Mod:
return LeftExpr.Evaluate(variables) % RightExpr.Evaluate(variables);

case Operator.Pow:
return Math.Pow(LeftExpr.Evaluate(variables), RightExpr.Evaluate(variables));

case Operator.Sin:
return Math.Sin(LeftExpr.Evaluate(variables));

case Operator.Cos:
return Math.Cos(LeftExpr.Evaluate(variables));

case Operator.Tan:
return Math.Tan(LeftExpr.Evaluate(variables));

case Operator.Abs:
return Math.Abs(LeftExpr.Evaluate(variables));

case Operator.Sqrt:
return Math.Sqrt(LeftExpr.Evaluate(variables));

case Operator.BitwiseAnd:
return (int)LeftExpr.Evaluate(variables) & (int)RightExpr.Evaluate(variables);
return (int) LeftExpr.Evaluate(variables) & (int) RightExpr.Evaluate(variables);

case Operator.BitwiseOr:
return (int)LeftExpr.Evaluate(variables) | (int)RightExpr.Evaluate(variables);
return (int) LeftExpr.Evaluate(variables) | (int) RightExpr.Evaluate(variables);

case Operator.BitwiseXor:
return (int)LeftExpr.Evaluate(variables) ^ (int)RightExpr.Evaluate(variables);
return (int) LeftExpr.Evaluate(variables) ^ (int) RightExpr.Evaluate(variables);

case Operator.BitwiseComplement:
return ~(int)LeftExpr.Evaluate(variables);
return ~(int) LeftExpr.Evaluate(variables);

case Operator.LeftShift:
return (int)LeftExpr.Evaluate(variables) << (int)RightExpr.Evaluate(variables);
return (int) LeftExpr.Evaluate(variables) << (int) RightExpr.Evaluate(variables);

case Operator.RightShift:
return (int)LeftExpr.Evaluate(variables) >> (int)RightExpr.Evaluate(variables);
return (int) LeftExpr.Evaluate(variables) >> (int) RightExpr.Evaluate(variables);

default:
throw new NotSupportedException(string.Format("operator {0} not support", Operator));
Expand All @@ -83,4 +101,4 @@ public override string ToString()
return sb.ToString();
}
}
}
}
32 changes: 28 additions & 4 deletions src/Dahomey.ExpressionEvaluator/Operator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,14 @@ public enum Operator
Mult, // *
Div, // /
Mod, // %
Pow, // ^
Minus, // -
Plus, // +
Cos, // Cos
Sin, // Sin
Tan, // Tan
Abs, // Abs
Sqrt, // Sqrt
LeftShift, // <<
RightShift, // >>
LessThan, // <
Expand All @@ -26,15 +32,15 @@ public enum Operator
Equal, // ==
NotEqual, // !=
BitwiseAnd, // &
BitwiseXor, // ^
BitwiseXor, // ^^
BitwiseOr, // |
BitwiseComplement, // ~
Not, // !
And, // &&
Or, // ||
}

internal static class OperatorExtension
public static class OperatorExtension
{
public static string PrettyPrint(this Operator op)
{
Expand All @@ -51,10 +57,28 @@ public static string PrettyPrint(this Operator op)

case Operator.Minus:
return "-";

case Operator.Pow:
return "^";

case Operator.Plus:
return "+";


case Operator.Sin:
return "Sin";

case Operator.Cos:
return "Cos";

case Operator.Abs:
return "Abs";

case Operator.Tan:
return "Tan";

case Operator.Sqrt:
return "Sqrt";

case Operator.LeftShift:
return "<<";

Expand Down Expand Up @@ -86,7 +110,7 @@ public static string PrettyPrint(this Operator op)
return "|";

case Operator.BitwiseXor:
return "^";
return "^^";

case Operator.BitwiseComplement:
return "~";
Expand Down