IronPython DSL将常量转换为C#类型 [英] IronPython DSL casting constants to C# types
问题描述
我正在用IronPython实现DSL。
I am implementing a DSL in IronPython.
假设我有一个用C#实现的值层次结构,可用于Iron python:
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...
}
由于C#中的运算符重载,我可以在Python中执行此操作:
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
一切正常,该函数返回类型= Value的对象。
And everything works fine, the function returns an object of type = Value.
但是如果我想使用PythonConstant:
But if i want to use a PythonConstant:
# a is of type Value
def Sum5(a):
return a + 5
您会得到一个错误类型,因为常量5不是Value类型。
you get an error type, because the constant 5 is not of Value type.
一种解决方案是重载+运算符以像这样工作int:
One solution would be to overload the + operator to work ints like:
public DoubleValue operator+(DoubleValue, int)
,但是您会得到大量可能的组合并在Value框架中导致
数以百计的重载。无论如何,您仍然会遇到
的问题:
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
在这种情况下,返回值不是Value类型,您应该执行以下操作:
In this case the returned value is not of Value type, you should do something like:
def ReturnFive():
return DoubleValue(5.0)
但这对我的DSL来说是一个非常丑陋的语法。
But it is a pretty ugly syntax for my DSL.
您会推荐什么?
非常感谢。
推荐答案
这是DSEL的主要问题:它们并不总是播放原生类型很好。通常,您需要包装本机类型。一种选择是引入一个具有非常短名称的函数(例如 _
),该函数包装传入的值并触发运算符重载。
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仅具有三种感兴趣的数字类型-System.Int32(int),System.Double(float)和System.Numerics.BigInteger(long)-因此并没有太多
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.
在C#端,您将遇到以下情况:
On the C# side you would have something like:
class Value {
static Value WrapLiteral(object literal) {
if(literal is System.Double) {
return DoubleValue((System.Double)literal);
} // etc ...
}
}
在为用户脚本创建作用域时,请使用短名称添加该函数:
When you create the scope for your user scripts, add that function with the short name:
scope.SetVariable("_", Value.WrapLiteral);
然后从用户端,用户只需要做:
Then from the user side, the users only have to do:
def ReturnFive():
return _(5)
还是有点难看,但还算不错。
It's still a bit ugly, but not too bad.
这篇关于IronPython DSL将常量转换为C#类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!