我正在使用Antlr和Expression树编写语言。
我已经为我的Tree Parser定义了一个标准工厂方法,以便在生成加法时使用它,它对于内置的整数类型非常有效,现在我正在转向更一般的类型。
目前它非常天真,它只是这样做(正在进行的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#规范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'.
足够公平 - 我反映System.String,确实运算符确实没有定义。在测试方法中生成表达式树,如下所示:
Expression<Func<string, string, string>> e = (s1, s2) => s1 + s2;
显示确实创建了Add BinaryExpression,但实现方法设置为string.Concat
方法之一。
我知道在某些情况下我不得不考虑做这样的事情,但有多少其他类型以这种方式定义了添加?它只是string
吗?
它是嵌入在C#编译器中的规则 - 还是有某种可发现的元数据可用于在其他类型上自动发现此类方法?
提前致谢!
答案 0 :(得分:1)
在回答我自己的问题时,我似乎有一个很好的路线!
道歉,这个答案可以更好地格式化,但我的HTC愿望和它的键盘不支持所有符号!
似乎没有办法在运行时“发现”这些规则,主持人语言有责任决定如何实现字符串添加等内容。 C#适应添加中连续项的数量,调用最恰当匹配的.Concat方法。
因此,如果我希望我的语言支持添加没有为其定义运算符的类实例,例如,我可以简单地编写或找到一个静态方法来执行它(当然是正确的签名!)和然后通过硬连线语言在这种情况下使用它。这里的一个典型示例是是否通过静态数组方法支持array1 + array2。
至于运算符的发现,Expression.Add方法负责处理,但它不会自动执行任何转换,因此,正如我在问题中引用的积分/浮点提升方法一样,它再次启动在尝试构建表达式之前,确定是否需要其他转换的语言规则。
因此,最好先反映运算符,看看是否为这两种类型定义了运算符,然后再考虑转换(如果存在)。