模組 Ast_mapper

module Ast_mapper: sig .. end

-ppx 重寫器的介面

-ppx 重寫器是一個程式,它接受序列化的抽象語法樹並輸出另一個可能經過修改的抽象語法樹。此模組封裝了編譯器和 -ppx 重寫器之間的介面,處理諸如序列化格式、命令行標誌的轉發和狀態存儲等細節。

Ast_mapper.mapper 啟用使用開放遞迴的 AST 重寫。一個典型的對應器將基於 Ast_mapper.default_mapper,一個深度恆等對應器,並且對於它不修改的語法將回退到它。例如

open Asttypes
open Parsetree
open Ast_mapper

let test_mapper argv =
  { default_mapper with
    expr = fun mapper expr ->
      match expr with
      | { pexp_desc = Pexp_extension ({ txt = "test" }, PStr [])} ->
        Ast_helper.Exp.constant (Pconst_integer ("42", None))
      | other -> default_mapper.expr mapper other; }

let () =
  register "ppx_test" test_mapper

這個 -ppx 重寫器,它將表達式中的 [%test] 替換為常數 42,可以使用 ocamlc -o ppx_test -I +compiler-libs ocamlcommon.cma ppx_test.ml 進行編譯。

警告:此模組不穩定,是 compiler-libs 的一部分。


一個通用的 Parsetree 對應器

type mapper = {
   attribute : mapper -> Parsetree.attribute -> Parsetree.attribute;
   attributes : mapper -> Parsetree.attribute list -> Parsetree.attribute list;
   binding_op : mapper -> Parsetree.binding_op -> Parsetree.binding_op;
   case : mapper -> Parsetree.case -> Parsetree.case;
   cases : mapper -> Parsetree.case list -> Parsetree.case list;
   class_declaration : mapper ->
Parsetree.class_declaration -> Parsetree.class_declaration
;
   class_description : mapper ->
Parsetree.class_description -> Parsetree.class_description
;
   class_expr : mapper -> Parsetree.class_expr -> Parsetree.class_expr;
   class_field : mapper -> Parsetree.class_field -> Parsetree.class_field;
   class_signature : mapper -> Parsetree.class_signature -> Parsetree.class_signature;
   class_structure : mapper -> Parsetree.class_structure -> Parsetree.class_structure;
   class_type : mapper -> Parsetree.class_type -> Parsetree.class_type;
   class_type_declaration : mapper ->
Parsetree.class_type_declaration -> Parsetree.class_type_declaration
;
   class_type_field : mapper -> Parsetree.class_type_field -> Parsetree.class_type_field;
   constant : mapper -> Parsetree.constant -> Parsetree.constant;
   constructor_declaration : mapper ->
Parsetree.constructor_declaration -> Parsetree.constructor_declaration
;
   directive_argument : mapper ->
Parsetree.directive_argument -> Parsetree.directive_argument
;
   expr : mapper -> Parsetree.expression -> Parsetree.expression;
   extension : mapper -> Parsetree.extension -> Parsetree.extension;
   extension_constructor : mapper ->
Parsetree.extension_constructor -> Parsetree.extension_constructor
;
   include_declaration : mapper ->
Parsetree.include_declaration -> Parsetree.include_declaration
;
   include_description : mapper ->
Parsetree.include_description -> Parsetree.include_description
;
   label_declaration : mapper ->
Parsetree.label_declaration -> Parsetree.label_declaration
;
   location : mapper -> Location.t -> Location.t;
   module_binding : mapper -> Parsetree.module_binding -> Parsetree.module_binding;
   module_declaration : mapper ->
Parsetree.module_declaration -> Parsetree.module_declaration
;
   module_substitution : mapper ->
Parsetree.module_substitution -> Parsetree.module_substitution
;
   module_expr : mapper -> Parsetree.module_expr -> Parsetree.module_expr;
   module_type : mapper -> Parsetree.module_type -> Parsetree.module_type;
   module_type_declaration : mapper ->
Parsetree.module_type_declaration -> Parsetree.module_type_declaration
;
   open_declaration : mapper -> Parsetree.open_declaration -> Parsetree.open_declaration;
   open_description : mapper -> Parsetree.open_description -> Parsetree.open_description;
   pat : mapper -> Parsetree.pattern -> Parsetree.pattern;
   payload : mapper -> Parsetree.payload -> Parsetree.payload;
   signature : mapper -> Parsetree.signature -> Parsetree.signature;
   signature_item : mapper -> Parsetree.signature_item -> Parsetree.signature_item;
   structure : mapper -> Parsetree.structure -> Parsetree.structure;
   structure_item : mapper -> Parsetree.structure_item -> Parsetree.structure_item;
   toplevel_directive : mapper ->
Parsetree.toplevel_directive -> Parsetree.toplevel_directive
;
   toplevel_phrase : mapper -> Parsetree.toplevel_phrase -> Parsetree.toplevel_phrase;
   typ : mapper -> Parsetree.core_type -> Parsetree.core_type;
   type_declaration : mapper -> Parsetree.type_declaration -> Parsetree.type_declaration;
   type_extension : mapper -> Parsetree.type_extension -> Parsetree.type_extension;
   type_exception : mapper -> Parsetree.type_exception -> Parsetree.type_exception;
   type_kind : mapper -> Parsetree.type_kind -> Parsetree.type_kind;
   value_binding : mapper -> Parsetree.value_binding -> Parsetree.value_binding;
   value_description : mapper ->
Parsetree.value_description -> Parsetree.value_description
;
   with_constraint : mapper -> Parsetree.with_constraint -> Parsetree.with_constraint;
}

一個映射器紀錄為每個語法類別實現一個「方法」,使用開放遞迴風格:每個方法的第一個參數是要應用於語法樹中子節點的映射器。

val default_mapper : mapper

一個預設的映射器,實作「深度身分」映射。

將對應器應用於編譯單元

val tool_name : unit -> string

可以在 ppx 前處理器內使用,以了解是哪個工具在呼叫它,例如 "ocamlc""ocamlopt""ocamldoc""ocamldep""ocaml" 等等。一些反映命令列選項的全域變數會在呼叫工具和 ppx 前處理器之間自動同步:Clflags.include_dirsClflags.hidden_include_dirsLoad_pathClflags.open_modulesClflags.for_packageClflags.debug

val apply : source:string -> target:string -> mapper -> unit

將一個映射器(以單元名稱參數化)應用於在 source 檔案中找到的已傾印語法樹,並將結果放入 target 檔案。映射器的 structuresignature 欄位會應用於實作或介面。

val run_main : (string list -> mapper) -> unit

從映射器實作獨立的 -ppx 重寫器的呼叫進入點,以命令列參數參數化。目前的單元名稱可以從 Location.input_name 取得。此函數為未捕獲的例外實作了適當的錯誤報告。

註冊 API

val register_function : (string -> (string list -> mapper) -> unit) ref
val register : string -> (string list -> mapper) -> unit

套用 register_function。預設行為是立即執行映射器,從處理序命令列取得引數。這是為了支援將映射器連結為獨立執行檔的案例。

可以覆寫 register_function 以定義 "-ppx 驅動程式",它將多個映射器組合在單一處理序中。通常,驅動程式會先將 register_function 定義為自訂實作,然後讓 ppx 重寫器(靜態或動態連結)註冊自己,然後執行全部或其中一部分。也可以讓 -ppx 驅動程式將重寫器僅應用於 AST 的特定部分。

register 的第一個引數是 ppx 驅動程式要使用的符號名稱。

用於編寫對應器的便捷函式

val map_opt : ('a -> 'b) -> 'a option -> 'b option
val extension_of_error : Location.error -> Parsetree.extension

將錯誤編碼到一個 'ocaml.error' 擴充節點中,該節點可以插入到產生的 Parsetree 中。編譯器將負責報告錯誤。

val attribute_of_warning : Location.t -> string -> Parsetree.attribute

將警告訊息編碼到一個 'ocaml.ppwarning' 屬性中,該屬性可以插入到產生的 Parsetree 中。編譯器將負責報告警告。

用於呼叫外部對應器的輔助函式

val add_ppx_context_str : tool_name:string -> Parsetree.structure -> Parsetree.structure

從目前環境提取資訊,並將其編碼為屬性,該屬性會附加到結構項目清單中,以便將資訊傳遞到外部處理器。

val add_ppx_context_sig : tool_name:string -> Parsetree.signature -> Parsetree.signature

add_ppx_context_str 相同,但用於簽名。

val drop_ppx_context_str : restore:bool -> Parsetree.structure -> Parsetree.structure

從結構中刪除 ocaml.ppx.context 屬性。如果 restore 為 true,也還原目前處理序中的相關資料。

val drop_ppx_context_sig : restore:bool -> Parsetree.signature -> Parsetree.signature

drop_ppx_context_str 相同,但用於簽名。

Cookies

當從 OCaml 頂層(或其他支援 Cookie 的工具)呼叫時,Cookie 用於將資訊從 ppx 處理器傳遞到自己的進一步呼叫。

val set_cookie : string -> Parsetree.expression -> unit
val get_cookie : string -> Parsetree.expression option