我一直在尝试使用最近开源的Roslyn中的C#编译器进行实验,看看是否可以添加语言特性。
现在我正在尝试添加一些语法糖,一个新的前缀运算符,它基本上是一种缩写形式。目前,我正在利用已有的“&”“取地址”(在
我想要扩展的模式如下:
现在我正在尝试添加一些语法糖,一个新的前缀运算符,它基本上是一种缩写形式。目前,我正在利用已有的“&”“取地址”(在
unsafe
环境之外)。我想要扩展的模式如下:
&n
相当于:Property.Bind(v => n = v, () => n)
假设库中有一个名为Property.Bind
的方法,其签名如下:
public static IProperty<T> Bind<T>(Action<T> set, Func<T> get)
实质上,我需要合成两个lambda:
- 将其参数绑定为
n
的lvalue,并将其参数分配给n
。 - 没有参数,评估
n
。然后,我需要调用Property.Bind
并将这两个lambda作为参数传递。
我的以前的实验比这个容易得多,因为它们能够依赖于易于找到的现有功能,所以几乎没有什么工作要做!
但是这一次,我很难找到与我正在进行的工作类似的内容。到目前为止,我一直在逐步了解编译器如何从源代码构建BoundLambda
,而这正在变得非常混乱。我正在修改Binder_Operators.cs
中的BindAddressOfExpression
,使其在安全上下文中开始附加一个额外的if
语句:
private BoundExpression BindAddressOfExpression(PrefixUnaryExpressionSyntax node, DiagnosticBag diagnostics)
{
if (!this.InUnsafeRegion)
{
BoundExpression rValue = BindValue(node.Operand, diagnostics, BindValueKind.RValue);
BoundExpression lValue = BindValue(node.Operand, diagnostics, BindValueKind.Assignment);
var valueParamSymbol = new SourceSimpleParameterSymbol(null, rValue.Type, 0, RefKind.None, "__v", ImmutableArray<Location>.Empty);
var valueParam = new BoundParameter(node, valueParamSymbol);
var assignment = new BoundAssignmentOperator(node, lValue, valueParam, RefKind.None, rValue.Type);
var assignmentStatement = new BoundExpressionStatement(node, assignment);
var assignmentBlock = new BoundBlock(node, ImmutableArray<LocalSymbol>.Empty, ImmutableArray.Create<BoundStatement>(assignmentStatement)) { WasCompilerGenerated = true };
assignmentBlock = FlowAnalysisPass.AppendImplicitReturn(assignmentBlock);
所以(假设!)现在我有第一个lambda的赋值块,但是要完整地将BoundLambda
包装起来似乎是一个全新的挑战。
我在想:是否有一种“作弊”的方法可以获得这种语法糖,通过请求解析器/绑定器处理C#字符串,就像它出现在实际代码的位置一样?那样,手动构建所有部分并将它们拼接在一起就不再必要了。毕竟,现有的编译器非常适合这个问题!
&
进行实验。如果我能让它正常工作,我计划定义一个新的运算符%
来模仿 C++/CLI 和 C++/CX。 - Daniel Earwicker