0

IronPythonでDSLを実装しています。

Iron pythonで使用するためにC#で実装された値階層があるとします。

 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でこれを行うことができます。

 # a, b are of type Value
 def Sum(a,b):
    return a + b

そして、すべてが正常に機能し、関数はタイプ=Valueのオブジェクトを返します。

しかし、PythonConstantを使用したい場合:

 # a is of type Value
 def Sum5(a):
     return a + 5

定数5は値型ではないため、エラー型が発生します。

1つの解決策は、+演算子をオーバーロードして、次のようなintを機能させることです。

public DoubleValue operator+(DoubleValue, int)

しかし、その後、可能な組み合わせが大量に発生し、Valueフレームワークで何百ものオーバーロードが発生します。とにかく、あなたはまだこの問題を抱えています:

def ReturnFive():
    return 5

この場合、戻り値は値型ではないため、次のようにする必要があります。

def ReturnFive():
    return DoubleValue(5.0)

しかし、それは私のDSLにとってはかなり醜い構文です。

あなたは何をお勧めします?

どうもありがとうございます。

4

1 に答える 1

1

これはDSELの主要な問題です。ネイティブタイプで常にうまく機能するとは限りません。通常、ネイティブタイプをラップする必要があります。_1つのオプションは、渡された値をラップし、演算子のオーバーロードをトリガーする非常に短い名前(など)の関数を導入することです。

IronPythonには、System.Int32(int)、System.Double(float)、およびSystem.Numerics.BigInteger(long)の3つの数値タイプしかありません。したがって、処理するケースはそれほど多くありません。

C#側では、次のようになります。

class Value {
    static Value WrapLiteral(object literal) {
        if(literal is System.Double) {
            return DoubleValue((System.Double)literal);
        } // etc ...
    }
}

ユーザースクリプトのスコープを作成するときに、その関数を短い名前で追加します。

scope.SetVariable("_", Value.WrapLiteral);

次に、ユーザー側から、ユーザーは次のことを行うだけで済みます。

def ReturnFive():
    return _(5)

まだ少し醜いですが、それほど悪くはありません。

于 2012-06-01T22:10:19.253 に答える