2

我正在使用 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);
}

WherePromote7_2_6_2生成遵循 C# 规范 7.2.6.2 规定的积分提升规则的 Convert 表达式(该语言将类似于 C#,但将与 JScript 交叉以及具有其他全新的关键字)。

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

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

很公平 - 我反映 System.String 并且确实没有定义该运算符。在这样的测试方法中生成表达式树:

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

表明确实创建了 Add BinaryExpression,但实现方法设置为其中一种string.Concat方法。

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

它是嵌入在 C# 编译器中的规则 - 还是有某种可发现的元数据可用于在其他类型上自动发现此类方法?

提前致谢!

4

1 回答 1

1

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

抱歉,这个答案的格式可能更好,但我对 HTC 的渴望,它的键盘不支持所有符号!

似乎没有办法在运行时“发现”这些规则,宿主语言有责任决定如何实现诸如字符串添加之类的事情。C# 适应加法中的连续术语的数量,调用最适合匹配的 .Concat 方法。

因此,如果我希望我的语言支持添加未为其定义运算符的类实例,例如,我可以简单地编写或找到一个静态方法来完成它(当然是正确的签名!),然后硬连线在这种情况下使用它的语言。这里的一个经典例子是是否通过静态 Array 方法支持 array1 + array2。

至于运算符的发现,Expression.Add 方法会处理这个问题,但它不会自动执行任何转换,因此,与我在问题中引用的积分/浮点提升方法一样,这又取决于语言的在尝试构建表达式之前确定是否需要其他转换的规则。

因此,最好先反映运算符,看看是否为这两种类型定义了一个,然后再考虑是否存在转换。

于 2010-09-17T20:34:10.463 回答