I am implementing a DSL in IronPython.
Suppose I have a value hierachy implemented in C# to be used in iron python:
public abstract Value
{
}
public abstract DoubleValue : Value
{
// Constructors...
public double magnitude;
// Arithmetic operators overloaded...
}
public abstract FractionValue : Value
{
// Constructors....
public int numerator;
public int denominator;
// Arithmetic operators overloaded...
}
Due to the operator overloading in C#, i can do this in Python:
# a, b are of type Value
def Sum(a,b):
return a + b
And everything works fine, the function returns an object of type = Value.
But if i want to use a PythonConstant:
# a is of type Value
def Sum5(a):
return a + 5
you get an error type, because the constant 5 is not of Value type.
One solution would be to overload the + operator to work ints like:
public DoubleValue operator+(DoubleValue, int)
but then you get a huge amount of possible combinations and end up with
hundreds of overloads in the Value framework. Anyway you still get
this problem:
def ReturnFive():
return 5
In this case the returned value is not of Value type, you should do something like:
def ReturnFive():
return DoubleValue(5.0)
But it is a pretty ugly syntax for my DSL.
What would you recommend?
Thank you very much.
This is the major issues with DSELs: they don’t always play well with native types. Generally you need to wrap the native types; one option is to introduce a function with a very short name (such as
_) that wraps the passed-in value and triggers the operator overloads.IronPython only has three number types of interest — System.Int32 (int), System.Double (float), and System.Numerics.BigInteger (long) — so there aren’t too many cases to take care of.
On the C# side you would have something like:
When you create the scope for your user scripts, add that function with the short name:
Then from the user side, the users only have to do:
It’s still a bit ugly, but not too bad.