我正在使用ANTLR和表达树编写语言。

我为生成添加时定义了一种标准的工厂方法,可用于我的树解析器,并且它适用于内置的整体类型,现在我正在转向更多的一般类型。

目前,它是非常幼稚的,它只是这样做的(在进行中TDD代码通常看起来很天真!?):

protected Expression GenerateAdd(Expression left, Expression right)
{
  if (left.Type.Equals(right.Type))
    return Expression.Add(left, right);
  if (left.Type.IsValueType && right.Type.IsValueType)
    Promote7_2_6_2(ref left, ref right);
  return Expression.Add(left, right);
}

在哪里 Promote7_2_6_2 生成遵循C#Spec 7.2.6.2列出的积分促销规则的转换表达式(该语言将与C#相似,但会与JScript交叉,并具有其他全新的关键字)。

自然,我继续测试字符串添加 - 即 "a" + "b"; 我得到错误:

System.InvalidOperationException: The binary operator Add is not defined for the types 'System.String' and 'System.String'.

足够公平 - 我反映了系统。斯特林和确保确实没有定义操作员。在这样的测试方法中生成表达树:

Expression<Func<string, string, string>> e = (s1, s2) => s1 + s2;

表明确实创建了添加二进制表达,但是将实现方法设置为 string.Concat 方法。

我知道在某些情况下,我将不得不考虑这样做,但是有多少其他类型可以通过这种方式定义添加?是 string?

它是嵌入C#编译器中的规则吗?还是可以使用某种可发现的元数据来自动发现其他类型的此类方法?

提前致谢!

有帮助吗?

解决方案

看来我在回答自己的问题方面做得很好!

我很抱歉,这个答案可以更好地格式化,但是我遵循我的HTC欲望,其键盘并不支持所有符号!

似乎没有办法在运行时“发现”这些规则,主机语言的责任是决定如何实现诸如字符串添加之类的内容。 C#在加法中适应了连续项的数量,调用最适当匹配的.concat方法。

因此,如果我希望我的语言支持不为其定义运算符的集体实例的添加,例如,我可以简单地编写或找到静态方法(当然是正确的签名!)在这种情况下使用它的语言。这里的一个经典示例是是否通过静态数组方法支持Array1 + Array2。

至于发现运算符,ADD.ADD方法会考虑到这一点,但是它不会自动执行任何转换,因此,就像我在问题中引用的积分/浮点促销方法一样,这再次取决于语言的在尝试构建表达式之前,确定是否需要其他转换。

因此,最好首先反映操作员,看看是否为两种类型定义了操作员,然后在考虑转换之前是否存在。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top