我将以下属性附加到节点
[@profiling.mark [ "label1"; "label2"; "label3" ]]
,这给了我这个 AST:
[{attr_name = {txt = "profiling.mark"};
attr_payload =
PStr
[{pstr_desc =
Pstr_eval
({pexp_desc =
Pexp_construct ({txt = Lident "::"},
Some
{pexp_desc =
Pexp_tuple
[{pexp_desc =
Pexp_constant
(Pconst_string ("label1", ...));
pexp_loc_stack = []};
{pexp_desc =
Pexp_construct ({txt = Lident "::"},
Some
{pexp_desc =
Pexp_tuple
[{pexp_desc =
Pexp_constant
(Pconst_string ("label2", ...));
pexp_loc_stack = []};
{pexp_desc =
Pexp_construct
({txt = Lident "::"},
Some
{pexp_desc =
Pexp_tuple
[{pexp_desc =
Pexp_constant
(Pconst_string ("label3",
...));
pexp_loc_stack = []};
{pexp_desc =
Pexp_construct
({txt = Lident "[]"},
None);
pexp_loc_stack = []}];
pexp_loc_stack = []});
pexp_loc_stack = []}];
pexp_loc_stack = []});
pexp_loc_stack = []}];
pexp_loc_stack = []});
pexp_loc_stack = []},
...)}]}]
如果我想提取标签,我需要破坏一个
Pstr_construct
,所以我这样做了:
Ppxlib.PStr
[
[%stri
[%e?
{
pexp_desc =
Pexp_construct
( { txt = Lident "::"; _ },
Some { pexp_desc = Pexp_tuple labels; _ } );
_;
}]];
] ->
{ metadata = labels }
首先,我尝试使用metaquot来销毁列表,但找不到方法。但最重要的是
labels
是 expression list
而不是 expression
,所以我无法用 [%e labels]
重建它。
然后我想出了一个不同的方法:
Ppxlib.PStr
[
[%stri
[%e?
{
pexp_desc =
Pexp_construct ({ txt = Lident "::"; _ }, Some labels);
_;
}]];
] ->
{ metadata = Some labels }
但是当我阅读预处理文件时,我看到了这个:
("label1", ["label2"; "label3"])
。我没有列表,但有一个包含元素和列表的元组。就我而言,我需要["label1"; "label2"; "label3"]
。
我是不是做错了什么或者遗漏了什么?
提取列表可以通过
完成let rec extract_list =function
| [%expr [%e? h] :: [%e? r] ] -> Option.map (List.cons h) (extract_list r)
| [%expr [] ] -> Some []
| _ -> None
重建列表类似:
let rec embed_list loc = function
| [] -> [%expr []]
| [e] -> [%expr [[%e e]] ]
| a::q -> [%expr [%e a]::[%e embed_list loc q] ]