报价时
<@ 1 + 1 @>
我想要“1 + 1”
代替
"Call (None, Int32 op_Addition[Int32,Int32,Int32](Int32, Int32),
[Value (1), Value (1)])"
报价时
<@ 1 + 1 @>
我想要“1 + 1”
代替
"Call (None, Int32 op_Addition[Int32,Int32,Int32](Int32, Int32),
[Value (1), Value (1)])"
你必须自己写。请参阅F# 引文可视化器代码作为转换引文抽象语法树的指南。
我已经实现了一个报价反编译器,作为一个更大的开源项目Unquote的一部分。它可以将许多简单的 F# 引用表达式反编译为单行非轻量级语法字符串(有关反编译器功能列表,请参见项目主页)。例如,
> decompile <@ (11 + 3) / 2 = String.length ("hello world".Substring(4, 5)) @>;;
val it : string =
"(11 + 3) / 2 = String.length ("hello world".Substring(4, 5))"
@Kurt Schelfthout 对于将 F# 引号反编译为人类可读形式时面临的许多挑战是正确的。但从我目前的工作来看,我相信可以编写一个能够生成正确F# 代码的引号反编译器。以匹配表达式和计算表达式为例,Unquote 反编译器可以在以下简单情况下生成正确的 F# 代码:
> decompile <@ match true with | true -> "hi" | _ -> "bye" @>;;
val it : string =
"let matchValue = true in if matchValue then "hi" else "bye""
> decompile <@ seq {yield 1; yield 2} @>;;
val it : string =
"seq (Seq.delay (fun unitVar -> Seq.append (Seq.singleton 1) (Seq.delay (fun unitVar -> Seq.singleton 2))))"
中缀和前缀运算符并不太难(正如您在第一个示例中看到的那样),但是诸如换行和缩进之类的源结构是一个有趣的话题(尽管我认为并不是非常困难)。但是,单行非轻量级语法足以满足 Unquote 的要求。
没有,也不是那么容易,除非在非常简单的情况下。例如,主要问题之一是匹配构造。它是一大堆 if 和 switch 语句的语法糖(尝试打印带有匹配的引用,你会看到)。另一个大问题是计算表达式,但我想你可以先跳过那些。
然后有一个歧义的兔子洞,你必须解决,像管道运算符开始一个新行,让开始一个新行,缩进,中缀,前缀,特殊情况,如 (::) 运算符等约定向前。
总而言之,可行,但并非微不足道。有点像反编译。