ExpressionEvaluator icon indicating copy to clipboard operation
ExpressionEvaluator copied to clipboard

A Simple Math and Pseudo C# Expression Evaluator in One C# File. Can also execute small C# like scripts

Results 31 ExpressionEvaluator issues
Sort by recently updated
recently updated
newest added

Running the sample project mentioned in readme: https://dotnetfiddle.net/up4x3W I'm changing `expression` value to `string expression = "1+.5";` which should be identical to `string expression = "1+0.5";` (it is a valid...

Strong name

[{"_id":"662c823a2186caae7809835c","body":"Bump","issue_id":1660251387190,"origin_id":1755264707,"user_origin_id":80263149,"create_time":1696940260,"update_time":1696940260,"id":1714192954847,"updated_at":"2024-04-27T04:42:34.847000Z","created_at":"2024-04-27T04:42:34.847000Z"}] comment

Hi, Would it be possible for the assembly to have a strong name? This way it can be referenced from strong-named assemblies.

Syntax error in Functions

[{"_id":"6380b43ebc25e83db00a98f8","body":"There are more such bugs...\r\n\r\nI was very surprised to see that the evaluator not uses a parser.\r\nI think it would greatly profit from one.\r\nYou can manage syntax way easier, and jump around the tree for loops etc.\r\nThe code now is to complex for me to help with bugfixes.\r\n\r\n(It must not be a 1 file project, you could manage code easier if it would be splitted (node lexer parser definitions etc.) You can combine them easy with a regex for a 1 file version)","issue_id":1660251387193,"origin_id":1159328299,"user_origin_id":103534710,"create_time":1655514689,"update_time":1655514689,"id":1669379134023,"updated_at":"2022-11-25T12:25:34.023000Z","created_at":"2022-11-25T12:25:34.023000Z"},{"_id":"6380b43ebc25e83db00a98f9","body":"I see now #58...\r\n\r\nI coded such a parser once, only for math expresions. But it was at the beginning of my c# lerning, so the code is terrible and I can not but it in to public.\r\n\r\nBut I can sey, your project would greatly benefit from a tree parser.\r\nI don't even know how you get it done without. I found this project in the hope I could replace my old code.\r\n\r\nHope you can upgrade it. You will need then less code and coplexity.","issue_id":1660251387193,"origin_id":1159753899,"user_origin_id":103534710,"create_time":1655651957,"update_time":1655651957,"id":1669379134027,"updated_at":"2022-11-25T12:25:34.026000Z","created_at":"2022-11-25T12:25:34.026000Z"},{"_id":"6380b43ebc25e83db00a98fa","body":"@Alisis33 feel free to check https:\/\/github.com\/WattleScript\/wattlescript. Currently I'm working on gradual typing, help is welcome :)\r\nSyntax is described in wiki proposals & tests\r\nEE is great (and I love one file\/minimal dependencies way it works) but due to its nature it doesn't scale well. \r\n\r\n@codingseb in case you'd be interested we would definitely welcome your contributions as well <3","issue_id":1660251387193,"origin_id":1159785408,"user_origin_id":10260230,"create_time":1655661811,"update_time":1655661901,"id":1669379134030,"updated_at":"2022-11-25T12:25:34.029000Z","created_at":"2022-11-25T12:25:34.029000Z"}] comment

The evaluator not throw a exeption it too many parameters ar given. Sin(1,2,3,4) (Similar to Sign error 1 * ---+-+-2)

bug
enhancement

Linq Select throws exception (ValueTuple?) issue?

[{"_id":"6380adec70db72139b1146d1","body":"EDIT: Seems like it's an issue when using ValueTuple.... Maybe this is not supported?\r\n\r\n[Here is a simple .NET fiddle example which shows the unexpected behaviour:](https:\/\/dotnetfiddle.net\/dPqjBp)","issue_id":1660251387195,"origin_id":1148825803,"user_origin_id":43808309,"create_time":1654615656,"update_time":1654618574,"id":1669377516517,"updated_at":"2022-11-25T11:58:36.517000Z","created_at":"2022-11-25T11:58:36.517000Z"},{"_id":"6380adec70db72139b1146d2","body":"This line breaks it: https:\/\/github.com\/codingseb\/ExpressionEvaluator\/blob\/365551a87cda0de63a18d603f257354460b1f8c3\/CodingSeb.ExpressionEvaluator\/ExpressionEvaluator.cs#L3425\r\n\r\nFor some reason the internalDelegate args contains 1 item, and should contain 2 in this case... \r\nhttps:\/\/github.com\/codingseb\/ExpressionEvaluator\/blob\/365551a87cda0de63a18d603f257354460b1f8c3\/CodingSeb.ExpressionEvaluator\/ExpressionEvaluator.cs#L3504-L3516\r\n\r\nI guess this overload requires some special handling?\r\n","issue_id":1660251387195,"origin_id":1149102707,"user_origin_id":43808309,"create_time":1654631716,"update_time":1654631752,"id":1669377516520,"updated_at":"2022-11-25T11:58:36.520000Z","created_at":"2022-11-25T11:58:36.520000Z"},{"_id":"6380adec70db72139b1146d3","body":"FYI this is still an issue in 1.5.0-alpha releases","issue_id":1660251387195,"origin_id":1263506955,"user_origin_id":43808309,"create_time":1664540737,"update_time":1664540737,"id":1669377516523,"updated_at":"2022-11-25T11:58:36.522000Z","created_at":"2022-11-25T11:58:36.522000Z"}] comment

```csharp context.AddVariable("list1", new int[] { 1, 2, 3, 8 }); context.AddVariable("list2", new int[] { 4, 5, 6, 7 }); var test = context.Evaluate("list1.Cast().Select((item, i) => item - list1[i]).Cast().Sum()"); ``` throws:...

Need Investigations

Hello! I don't really know how to name this issue, but I experience a bug, which can be easily reproduced as the following: ```bash $ dotnet new console $ dotnet...

bug

The handling of numbers types could be more tollerant/intelligente. Not only casting to double. This could be used for easy and simple formulas, without the neet of a exact type...

enhancement
Need Investigations

There is a syntax error in the handling of the sign. It allows multiple sign symbols. Only one sign shold be allowed? 1 * +++-+-++---2

bug

How do I convert a string into a Predicate<T>?

[{"_id":"6380ba3d70db72139b115397","body":"Hello @Toxic-Cookie.\r\nThere is nothing in ExpressionEvaluator to return a compiled predicate or a other delegate.\r\nAs everything is evaluate on the fly and do not compile.\r\nIf you are not concern about performance you could encapsulate it like this : \r\n\r\n```c#\r\nstring predicateText = \"x.Equals(1)\";\r\n\r\nPredicate<int> predicate = x => (bool)(new ExpressionEvaluator(new {x=x}).Evaluate(predicateText));\r\n\r\nConsole.WriteLine(predicate(1)); \/\/ true\r\nConsole.WriteLine(predicate(5)); \/\/ false\r\n```\r\n\r\nOtherwise there are others libraries like [DynamicExpresso](https:\/\/github.com\/dynamicexpresso\/DynamicExpresso) that support this use case with better performances :\r\n\r\n","issue_id":1660251387206,"origin_id":965219098,"user_origin_id":15038327,"create_time":1636553085,"update_time":1636553085,"id":1669380669094,"updated_at":"2022-11-25T12:51:09.094000Z","created_at":"2022-11-25T12:51:09.094000Z"}] comment

My goal is to convert a string into a predicate like so: ``` string = "x => x.Equals(1)"; Predicate predicate = (Predicate)ExpressionEvaluator.Evaluate(string); ``` Is this possible? If so how can...

question

Implementing a syntaxicTree for version 2.0 of ExpressionEvaluator

[{"_id":"6380bdfb70db72139b1156ca","body":"I've been making a little investigation and found that this library make something \"like\" the version 2 of this library should make.\r\nhttps:\/\/github.com\/zzzprojects\/System.Linq.Dynamic.Core\r\nIt has a parselamba method wich parse a string into an AST abtract syntactic tree. Using linq.Expressions. so you can compile at the end and get an amazing fast lambda wich make whatever you want.\r\nThis library can manage a Context (because can be strongly typed). however it doesn't have variables functionality, does not support ?. or ?? operators... and has a lot of other database functionality that is innecesary.\r\nWe should study it...\r\nTomorrow I'm gonna post a little demo that I did.","issue_id":1660251387209,"origin_id":883825040,"user_origin_id":16392893,"create_time":1626832660,"update_time":1627406755,"id":1669381627731,"updated_at":"2022-11-25T13:07:07.731000Z","created_at":"2022-11-25T13:07:07.731000Z"},{"_id":"6380bdfb70db72139b1156cb","body":"This is the context\r\n```\r\npublic class Person\r\n{\r\n public string Name { get; set; }\r\n public decimal Value { get; set; }\r\n}\r\n\r\n```\r\n\r\nthose the usings\r\n```\r\nusing System.Linq.Dynamic.Core;\r\nusing System.Linq.Expressions;\r\nusing System.Diagnostics;\r\n```\r\n\r\nand this is the main test\r\n\r\n```\r\nList<Person> MyList = new List<Person>();\r\n\r\nfor(int i= 0; i< 100000; i++)\r\n{\r\n MyList.Add(new Person { Name = \"Theo\" + i, Value = i + 0.11m });\r\n}\r\n\r\nvar testFunc = Test3();\r\n\r\nStopwatch Reloj = new Stopwatch();\r\n\r\nReloj.Start();\r\n\r\nforeach (var p in MyList)\r\n{\r\n var rtn = testFunc(p);\r\n if(rtn) Console.WriteLine(rtn + p.Name);\r\n}\r\n\r\nReloj.Stop();\r\n\r\nConsole.WriteLine(Reloj.ElapsedMilliseconds + \" milisecs\");\r\n```\r\n\r\n\r\n```\r\npublic static Func<Person, decimal> Test2()\r\n{\r\n var arbol = DynamicExpressionParser.ParseLambda<Person, decimal>(new ParsingConfig() { }, false, \"Value + 3.3m\");\r\n return arbol.Compile();\r\n}\r\npublic static Func<Person, bool> Test3()\r\n{\r\n var tree = DynamicExpressionParser.ParseLambda<Person, bool>(new ParsingConfig() { }, false, \"Name.Trim() == \\\"Theo45\\\"\");\r\n \/\/ at this point you have the expression tree (in Linq.Expressions) in tree and walk trought it.\r\n \/\/ at the end we compile\r\n return tree.Compile();\r\n}\r\n```\r\n\r\n\r\nIn my machine, I get 3 miliseconds for the 100,000 iterations.\r\nmaking something similar with codingSeb it took 24000 miliseconds","issue_id":1660251387209,"origin_id":884245013,"user_origin_id":16392893,"create_time":1626878495,"update_time":1626878495,"id":1669381627735,"updated_at":"2022-11-25T13:07:07.734000Z","created_at":"2022-11-25T13:07:07.734000Z"},{"_id":"6380bdfb70db72139b1156cc","body":"@TheoVC Thanks for your your investigation and your tests. Yes I think syntaxic tree or compilation are a big speed enhencement for multiple execution. Speed is a big drawdown of EE. \r\nI will investigate a bit on how it is done. The issue I see for now, is that a lot of current functionalities available in current version of EE seems to be hard to implement with these kind of systems. On the fly evaluations events, syntax customization and script evaluations for example. I need to investigate more to find solutions to implement them.","issue_id":1660251387209,"origin_id":885906960,"user_origin_id":15038327,"create_time":1627073430,"update_time":1627073477,"id":1669381627738,"updated_at":"2022-11-25T13:07:07.737000Z","created_at":"2022-11-25T13:07:07.737000Z"},{"_id":"6380bdfb70db72139b1156cd","body":"I investigated a bit in the wonderful world of `System.Linq.Expressions`.\r\nWhat I see for now and reflect on\r\n* The gains in performance are enormous.\r\n* Some recurring EE Pitfalls are easier to manage or handle automatically (Method override selection, && and || right operand evaluation versus syntax exception)\r\n* Everything need to be typed and so a lot of casting need to be done compared the duck typing of the current version of EE.\r\n* So variables types must be defined at parsing time and can not change for each evaluation.\r\n* On the fly events equivalent should occurs at parsing time to define the type of the value to return and define a delegate to call at evaluation time.\r\n* A lot of options and syntax customization will applied at parsing time.\r\n* After compilation a lot of stuffs are rigid.\r\n* async await asked in #76 are not supported in `System.Linq.Expressions` for now (refs : [stackoverflow](https:\/\/stackoverflow.com\/questions\/31543468\/async-lambda-to-expressionfunctask), [Microsoft](https:\/\/docs.microsoft.com\/en-us\/dotnet\/csharp\/expression-trees-summary#limitations))","issue_id":1660251387209,"origin_id":905242600,"user_origin_id":15038327,"create_time":1629875425,"update_time":1629875425,"id":1669381627741,"updated_at":"2022-11-25T13:07:07.741000Z","created_at":"2022-11-25T13:07:07.741000Z"},{"_id":"6380bdfb70db72139b1156ce","body":"For investigation purposes... I have done a recursive descent parser based on the Richard Weeks series.\r\nhttps:\/\/www.youtube.com\/watch?v=_hYV5N_NAgk&list=PLHLYG7mk_iQloafxJ55Uqxc2n7m4NnNO7&index=12\r\nand extended it to implement more complicated c# syntax. don't know if it would be usefull to you. I can send it to you if you wish.\r\nas you said everything have to be strong typed, even variables, and of course the context.\r\nso the constructor could receive the type of the context...\r\n\r\n`var evaluator = new Evaluator(typeof( PERSON ));`\r\n\r\nof maybe\r\n\r\n`var evaluator = new Evaluator<PERSONA>();`\r\n\r\nthe type could be null if you don't want a context... and just use the variables feature\r\n\r\nanother feature that would be wonderfull is that the library not just evaluates an expression, but also produce an string explaining to the user what\u2019s happening inside the expression.\r\n\r\nSomething like this:\r\n\r\nFor expression:\r\n\r\n`200.0 + variable1 + myFunction( variable2 ) + ( variable3 ? 100 : variable 4 )`\r\n\r\nproduce an explanation like this:\r\n\r\n`200.0 + \/* variable1 *\/ 200 + \/*myFunction( [variable2] 5 )*\/ 20 + ( \/* variable3 *\/ true ? 100 : variable 4 )`\r\n\r\nif you remove the coments you can have something like this;\r\n\r\n`200.0 + 200 + 20 + ( true ? 100 : variable 4 )`\r\n\r\nSo this string can be displayed by the application and easily the IT guy or even the user himself can deduce what it\u2019s going wrong? or simply to know why ??? you get that result.\r\n\r\nWe already achieve this using codingseb but has a lot of manual parsing and it\u2019s slow\u2026 \r\nI did a lot of research and there's NO library that can do it.\r\n","issue_id":1660251387209,"origin_id":905792368,"user_origin_id":16392893,"create_time":1629917860,"update_time":1630007969,"id":1669381627744,"updated_at":"2022-11-25T13:07:07.744000Z","created_at":"2022-11-25T13:07:07.744000Z"},{"_id":"6380bdfb70db72139b1156cf","body":"Hello, if that's of any help, what do you think about this library ? https:\/\/github.com\/davideicardi\/DynamicExpresso\r\nIt looks like a good starting point.","issue_id":1660251387209,"origin_id":908658394,"user_origin_id":42170,"create_time":1630354379,"update_time":1630354379,"id":1669381627748,"updated_at":"2022-11-25T13:07:07.748000Z","created_at":"2022-11-25T13:07:07.748000Z"},{"_id":"6380bdfb70db72139b1156d0","body":"> \r\n> \r\n> Hello, if that's of any help, what do you think about this library ? https:\/\/github.com\/davideicardi\/DynamicExpresso\r\n> It looks like a good starting point.\r\n\r\nYes it's a really good lib.\r\n\r\nI created a new repo where I test some partial rewriting of EE with a ExpressionTree compilation.\r\nIt work already for small operation without all variables, methods and properties access and on the fly stuffs :\r\n[CSXPression](https:\/\/github.com\/codingseb\/CSXPression).\r\n\r\nI made a lot of copy paste modify operations from EE so it's not really a Lexer\/ASTNode but I made a parser part that build a tokens tree from which I can get an expression tree and then compile to `Func<object>` delegate.","issue_id":1660251387209,"origin_id":909070955,"user_origin_id":15038327,"create_time":1630402648,"update_time":1630403281,"id":1669381627751,"updated_at":"2022-11-25T13:07:07.751000Z","created_at":"2022-11-25T13:07:07.751000Z"},{"_id":"6380bdfb70db72139b1156d1","body":"I am just a bit stuck on how to adapt the variables and on the fly events (that were for me the big cool stuff of EE with syntax customization) without doing just the same as these already existing libraries.","issue_id":1660251387209,"origin_id":909077031,"user_origin_id":15038327,"create_time":1630403161,"update_time":1630403331,"id":1669381627754,"updated_at":"2022-11-25T13:07:07.753000Z","created_at":"2022-11-25T13:07:07.753000Z"},{"_id":"6380bdfb70db72139b1156d2","body":"> \r\n> \r\n> For investigation purposes... I have done a recursive descent parser based on the Richard Weeks series.\r\n> https:\/\/www.youtube.com\/watch?v=_hYV5N_NAgk&list=PLHLYG7mk_iQloafxJ55Uqxc2n7m4NnNO7&index=12\r\n\r\nAlso very interesting stuff here thank for sharing this serie. I am watching it. And I am asking myself about the perfs of Lexer\/ASTNodes char by char parsing versus my big regex way of parsing. \r\n\r\n\r\n","issue_id":1660251387209,"origin_id":909083659,"user_origin_id":15038327,"create_time":1630403715,"update_time":1630403715,"id":1669381627756,"updated_at":"2022-11-25T13:07:07.756000Z","created_at":"2022-11-25T13:07:07.756000Z"},{"_id":"6380bdfb70db72139b1156d3","body":"@codingseb one of the cleanest architectures of hand written parser is here - https:\/\/github.com\/scriban\/scriban\r\nI would possibly use one of LL(k) parser generators not only for perf but also for ease of maintenance. \r\nCurrently I can't use EE due to perf so I put together a js-c# like language that transpiles to lua scripts and I execute them with Moonsharp (heavy clr usage makes up for slower vm compared to other lua implementations for c#). \r\n\r\nAnyway for v2 our main goal should be performance as I think we can live without cool customization when such implementaion can't be then used in real world applications. Hence a good solution would imho be able to generate bytecode for either native c# or custom vm which would then interpret this simpler language on runtime. Lua vm has only ~50 bytecode opcodes. \r\n\r\nOf almost the same importance is imho ability to properly sandbox the script evaluation as untrusted code will be interpreted in many use cases. This should include recursion depth limit, total instructions to interpret limit, no access to clr classes unless explicitly provided.\r\n\r\nLast thing I would love to see is native async \/ await support. This is becoming more and more important with each new version of c#.","issue_id":1660251387209,"origin_id":910156543,"user_origin_id":10260230,"create_time":1630492596,"update_time":1630492790,"id":1669381627759,"updated_at":"2022-11-25T13:07:07.759000Z","created_at":"2022-11-25T13:07:07.759000Z"}] comment

I create here an issue to follow and document (first for myself but for who is interested) the evolution of the work to version 2.0 The goal is to deeply...

enhancement
explanation

Nested false inside true `if` causing result to set to null.

[{"_id":"6380b6324b97542c9a30b65e","body":"Hello @Xjph, sorry for my late response.\r\nNeed to investigate a bit.\r\nBut for now you can easily manage it by returning the`result` variable each times after if blocks:\r\n\r\n```c#\r\n--------------------------------------------\r\nresult = 0;\r\nif (true)\r\n{\r\n if (true)\r\n {\r\n result = 1;\r\n }\r\n}\r\nreturn result;\r\n---------------- Result --------------------\r\nNo type:1\r\nWith type:1\r\n\r\n--------------------------------------------\r\nresult = 0;\r\nif (false)\r\n{\r\n if (false)\r\n {\r\n result = 1;\r\n }\r\n}\r\nreturn result;\r\n---------------- Result --------------------\r\nNo type:0\r\nWith type:0\r\n\r\n--------------------------------------------\r\nresult = 0;\r\nif (false)\r\n{\r\n if (true)\r\n {\r\n result = 1;\r\n }\r\n}\r\nreturn result;\r\n---------------- Result --------------------\r\nNo type:0\r\nWith type:0\r\n\r\n--------------------------------------------\r\nresult = 0;\r\nif (true)\r\n{\r\n if (false)\r\n {\r\n result = 1;\r\n }\r\n}\r\nreturn result;\r\n---------------- Result --------------------\r\nNo type:0\r\nWith type:0\r\n```\r\nor simpler : with `evaluator.OptionScriptNeedSemicolonAtTheEndOfLastExpression = false;`\r\n\r\n```c#\r\n--------------------------------------------\r\nresult = 0;\r\nif (true)\r\n{\r\n if (true)\r\n {\r\n result = 1;\r\n }\r\n}\r\nresult\r\n---------------- Result --------------------\r\nNo type:1\r\nWith type:1\r\n\r\n--------------------------------------------\r\nresult = 0;\r\nif (false)\r\n{\r\n if (false)\r\n {\r\n result = 1;\r\n }\r\n}\r\nresult\r\n---------------- Result --------------------\r\nNo type:0\r\nWith type:0\r\n\r\n--------------------------------------------\r\nresult = 0;\r\nif (false)\r\n{\r\n if (true)\r\n {\r\n result = 1;\r\n }\r\n}\r\nresult\r\n---------------- Result --------------------\r\nNo type:0\r\nWith type:0\r\n\r\n--------------------------------------------\r\nresult = 0;\r\nif (true)\r\n{\r\n if (false)\r\n {\r\n result = 1;\r\n }\r\n}\r\nresult\r\n---------------- Result --------------------\r\nNo type:0\r\nWith type:0\r\n```\r\n","issue_id":1660251387213,"origin_id":905337249,"user_origin_id":15038327,"create_time":1629883758,"update_time":1629883758,"id":1669379634192,"updated_at":"2022-11-25T12:33:54.192000Z","created_at":"2022-11-25T12:33:54.192000Z"},{"_id":"6380b6324b97542c9a30b65f","body":"The explicit `return` is an acceptable workaround for my use case, so certainly no need to rush on this as far as I'm concerned.\r\n\r\nThanks for your time!","issue_id":1660251387213,"origin_id":905536738,"user_origin_id":455726,"create_time":1629900720,"update_time":1629900720,"id":1669379634202,"updated_at":"2022-11-25T12:33:54.201000Z","created_at":"2022-11-25T12:33:54.201000Z"}] comment

My original where I discovered the issue was more complex, but I distilled it down to the simplest reproducible case I could find which I've placed in this fiddle: https://dotnetfiddle.net/9NzZ0O...

bug