Skip to content

Commit

Permalink
Proposed Enhancement for issue matheval#7
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Telford authored and Michael Telford committed Dec 9, 2022
1 parent 8aeb54d commit 21fba19
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 1 deletion.
29 changes: 29 additions & 0 deletions Math expression eval/UnitTest/TestAll.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1188,5 +1188,34 @@ public void Or_Operator_Test()
.Bind("b", 1);
Assert.AreEqual(true, expr4.Eval<bool>());
}


[TestMethod]
public void Custom_Function_Test()
{
//register new custom function
Parser.RegisterFunction("CUSTOM", typeof(customFunction));

//call function
var expr = new Expression("CUSTOM('1','a','#')");
Assert.AreEqual("1-a-#", expr.Eval<string>());
}

public class customFunction : org.matheval.Functions.IFunction
{
public List<org.matheval.Functions.FunctionDef> GetInfo()
{
return new List<org.matheval.Functions.FunctionDef> { new org.matheval.Functions.FunctionDef("custom", new Type[] { typeof(string), typeof(string), typeof(string) }, typeof(string), 3) };
}

public object Execute(Dictionary<string, object> args, ExpressionContext dc)
{
string a1 = (string)args["1"];
string a2 = (string)args["2"];
string a3 = (string)args["3"];

return string.Join("-", a1, a2, a3);
}
}
}
}
27 changes: 26 additions & 1 deletion Math expression eval/org.matheval/Parser/Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,28 @@ namespace org.matheval
{
public class Parser
{
private static Dictionary<string, Type> _registeredFunctions;

/// <summary>
/// Registers a new custom function to all new Parsers
/// @param name function name as used in the expression
/// @param functionType type that implements the IFunction interface and will be used to handle the custom function call
/// </summary>
/// <param name="op">op</param>
public static void RegisterFunction(string name, Type functionType)
{
if (_registeredFunctions == null)
{
_registeredFunctions = new Dictionary<string, Type>();
}
//sanity check the provided type
//Additional checks could be done here to if needed.
if (functionType.IsAbstract || functionType.IsGenericType || !typeof(IFunction).IsAssignableFrom(functionType))
throw new ArgumentException(functionType.Name + " is not a concrete, non-generic type that implements the org.matheval.Functions.IFunction interface");

_registeredFunctions[name.ToLowerInvariant()] = functionType;
}

/// <summary>
/// Create object Lexer
/// </summary>
Expand Down Expand Up @@ -344,7 +366,10 @@ private Implements.Node ParseIdentifier()
IFunction funcExecuter;
try
{
Type t = Type.GetType("org.matheval.Functions." + identifierStr.ToLowerInvariant() + "Function", true);
if (_registeredFunctions == null || !_registeredFunctions.TryGetValue(identifierStr.ToLowerInvariant(), out Type t))
{
t = Type.GetType("org.matheval.Functions." + identifierStr.ToLowerInvariant() + "Function", true);
}
Object obj = (Activator.CreateInstance(t));

if (obj == null)
Expand Down

0 comments on commit 21fba19

Please sign in to comment.