IronPython DSL将常量转换为C#类型 [英] IronPython DSL casting constants to C# types

查看:78
本文介绍了IronPython DSL将常量转换为C#类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆