查看源码 erl_syntax_lib (语法工具 v3.2.1)

抽象 Erlang 语法树的支持库。

此模块包含用于处理模块 erl_syntax 中定义的抽象数据类型的实用工具函数。

概要

函数

返回被调用函数的名称。

分析属性节点。

返回 export 属性声明的函数名称列表。

返回 file 属性的文件名和行号。

分析“源代码形式”节点。

分析一系列“程序形式”。

返回函数定义的名称和元数。

返回语法树表示的函数名称。

返回隐式 fun 表达式“fun F”的名称。

返回模块名称和(如果存在)import 属性声明的函数名称列表。

返回模块名称和模块属性声明的可能参数。

返回记录声明属性的名称和字段列表。

返回记录表达式的记录名称和字段名称/名称。

返回记录字段说明符的标签、值表达式和类型。

返回使用的类型的名称。

返回语法树表示的类型名称。

返回“wild”属性的名称和值。

在语法树中的节点上添加或更新注解。

在语法树中的节点上添加或更新注解。

将函数折叠到语法树的所有节点上。

将函数折叠到语法树的直接子树上。

类似于 lists:foldl/3,但适用于列表的列表。

创建从相应的短名称到完整函数名称的映射。

如果 Tree 表示一个永远不会正常终止的表达式,则返回 true

等效于使用文本 "..." 作为默认替换的 limit(Tree, Depth, Text)

将语法树限制为指定的深度。

将函数应用于语法树的每个节点。

将函数应用于语法树的每个直接子树。

在单个操作中组合 map 和 fold。

对语法树的直接子树执行 mapfold 操作。

类似于 lists:mapfoldl/3,但适用于列表的列表。

返回一个不在集合 Used 中的原子。

返回一个不在集合 Used 中的用户命名原子。

类似于 new_variable_name/1,但生成 N 个新名称的列表。

类似于 new_variable_name/2,但生成 N 个新名称的列表。

从语法树的所有节点中删除所有注释。

等效于使用默认格式化函数 Fto_comment(Tree, Prefix, F)

将语法树转换为抽象注释。

返回语法树中出现的变量的名称。

类型

链接到此类型

appFunName()

查看源码 (未导出)
-type appFunName() :: {atom(), arity()} | {atom(), {atom(), arity()}}.
-type field() :: {atom(), {field_default(), field_type()}}.
链接到此类型

field_default()

查看源码 (未导出)
-type field_default() :: none | syntaxTree().
链接到此类型

field_type()

查看源码 (未导出)
-type field_type() :: none | syntaxTree().
-type fields() :: [field()].
链接到此类型

functionN()

查看源码 (未导出)
-type functionN() :: atom() | {atom(), arity()}.
链接到此类型

functionName()

查看源码 (未导出)
-type functionName() :: functionN() | {atom(), functionN()}.
-type info() :: {atom(), [{atom(), syntaxTree()}]} | {atom(), atom()} | atom().
-type info_pair() :: {key(), term()}.
-type key() :: attributes | errors | exports | functions | imports | module | records | warnings.
-type name() :: shortname() | {atom(), shortname()}.
-type ordset(T) :: ordsets:ordset(T).
-type set(T) :: sets:set(T).
链接到此类型

shortname()

查看源码 (未导出)
-type shortname() :: atom() | {atom(), arity()}.
链接到此类型

syntaxTree()

查看源码 (未导出)
-type syntaxTree() :: erl_syntax:syntaxTree().

抽象语法树。有关详细信息,请参阅 erl_syntax 模块。

链接到此类型

typeName()

查看源码 (未导出)
-type typeName() :: atom() | {module(), {atom(), arity()}} | {atom(), arity()}.

函数

链接到此函数

analyze_application(Node)

查看源码
-spec analyze_application(syntaxTree()) -> appFunName() | arity().

返回被调用函数的名称。

如果 Node 表示函数应用程序“F(X_1, ..., X_A)”,则结果是被应用函数 F/A 的名称的表示形式。如果该函数未明确命名(即,F 由某些表达式给出),则仅返回元数 A

如果 Node 不表示格式正确的应用程序表达式,则求值将抛出 syntax_error

另请参见: analyze_function_name/1

链接到此函数

analyze_attribute(Node)

查看源码
-spec analyze_attribute(syntaxTree()) -> preprocessor | {atom(), term()}.

分析属性节点。

如果 Node 表示预处理器指令,则返回原子 preprocessor。否则,如果 Node 表示模块属性“-Name...”,则返回一个元组 {Name, Info},其中 Info 取决于 Name,如下所示

  • {module, Info} - 其中 Info = analyze_module_attribute(Node)

  • {export, Info} - 其中 Info = analyze_export_attribute(Node)

  • {import, Info} - 其中 Info = analyze_import_attribute(Node)

  • {file, Info} - 其中 Info = analyze_file_attribute(Node)

  • {record, Info} - 其中 Info = analyze_record_attribute(Node)

  • {Name, Info} - 其中 {Name, Info} = analyze_wild_attribute(Node)

如果 Node 不表示格式正确的模块属性,则求值将抛出 syntax_error

另请参见: analyze_export_attribute/1analyze_file_attribute/1analyze_import_attribute/1analyze_module_attribute/1analyze_record_attribute/1analyze_wild_attribute/1

链接到此函数

analyze_export_attribute(Node)

查看源码
-spec analyze_export_attribute(syntaxTree()) -> [functionName()].

返回 export 属性声明的函数名称列表。

我们不保证每个名称在列表中最多出现一次。列表的顺序未定义。

如果 Node 不表示格式正确的 export 属性,则求值将抛出 syntax_error

另请参见: analyze_attribute/1

链接到此函数

analyze_file_attribute(Node)

查看源码
-spec analyze_file_attribute(syntaxTree()) -> {string(), integer()}.

返回 file 属性的文件名和行号。

如果 Node 表示“-file(File, Line).”,则结果是 {File, Line} 对。

如果 Node 不表示格式正确的 file 属性,则求值将抛出 syntax_error

另请参见: analyze_attribute/1

-spec analyze_form(syntaxTree()) -> {atom(), term()} | atom().

分析“源代码形式”节点。

如果 Node 是“form”类型(请参阅 erl_syntax:is_form/1),则返回的值是一个元组 {Type, Info},其中 Type 是节点类型,而 Info 取决于 Type,如下所示

  • {attribute, Info} - 其中 Info = analyze_attribute(Node)

  • {error_marker, Info} - 其中 Info = erl_syntax:error_marker_info(Node)

  • {function, Info} - 其中 Info = analyze_function(Node)

  • {warning_marker, Info} - 其中 Info = erl_syntax:warning_marker_info(Node)

对于其他类型的形式,仅返回节点类型。

如果 Node 格式不正确,则评估会抛出 syntax_error

另请参阅:analyze_attribute/1analyze_function/1erl_syntax:error_marker_info/1erl_syntax:is_form/1erl_syntax:warning_marker_info/1

链接到此函数

analyze_forms(Forms)

查看源码
-spec analyze_forms(erl_syntax:forms()) -> [info_pair()].

分析一系列“程序形式”。

给定的 Forms 可以是 form_list 类型的单个语法树,也可以是“程序形式”语法树的列表。返回的值是一个 {Key, Info} 对的列表,其中 Key 的每个值在列表中最多出现一次;特定键的缺失表示该键没有定义明确的值。

结果列表中的每个条目都包含以下关于程序形式的相应信息

  • {attributes, Attributes}

    • Attributes = [{atom(), term()}]

    Attributes 是一个对列表,表示 Forms 中出现的所有所谓的“通配符”属性的名称和相应值(例如,“-compile(...)”)(请参阅 analyze_wild_attribute/1)。我们不保证每个名称在列表中最多出现一次。列表的顺序未定义。

  • {errors, Errors}

    • Errors = [term()]

    ErrorsForms 中出现的所有 error_marker 节点的错误描述符列表。列表的顺序未定义。

  • {exports, Exports}

    • Exports = [FunctionName]
    • FunctionName = atom() | {atom(), integer()} | {ModuleName, FunctionName}

    • ModuleName = atom()

    ExportsForms 中导出声明属性列出的函数名称的表示形式列表(请参阅 analyze_export_attribute/1)。我们不保证每个名称在列表中最多出现一次。列表的顺序未定义。

  • {functions, Functions}

    • Functions = [{atom(), integer()}]

    Functions 是在 Forms 中定义的函数名称列表(请参阅 analyze_function/1)。我们不保证每个名称在列表中最多出现一次。列表的顺序未定义。

  • {imports, Imports}

    • Imports = [{Module, Names}]
    • Module = atom()
    • Names = [FunctionName]
    • FunctionName = atom() | {atom(), integer()} | {ModuleName, FunctionName}

    • ModuleName = atom()

    Imports 是一个对列表,表示 Forms 中导入声明属性列出的模块名称和相应的函数名称(请参阅 analyze_import_attribute/1),其中每个 ModuleImports 中最多出现一次。我们不保证每个名称在函数名称列表中最多出现一次。列表的顺序未定义。

  • {module, ModuleName}

    • ModuleName = atom()

    ModuleNameForms 中模块属性声明的名称。如果 Forms 中未定义模块名称,则结果将不包含 module 键的条目。如果出现多个模块名称声明,则将忽略除第一个之外的所有声明。

  • {records, Records}

    • Records = [{atom(), Fields}]
    • Fields = [{atom(), {Default, Type}}]
    • Default = none | syntaxTree()

    • Type = none | syntaxTree()

    Records 是一个对列表,表示 Forms 中出现的所有记录声明属性的名称和相应的字段声明。对于声明时没有默认值的字段,Default 的对应值是原子 none。类似地,对于声明时没有类型的字段,Type 的对应值是原子 none(请参阅 analyze_record_attribute/1)。我们不保证每个记录名称在列表中最多出现一次。列表的顺序未定义。

  • {warnings, Warnings}

    • Warnings = [term()]

    WarningsForms 中出现的所有 warning_marker 节点的错误描述符列表。列表的顺序未定义。

如果遇到格式错误的 Erlang 构造,则评估会抛出 syntax_error

另请参阅:analyze_export_attribute/1analyze_function/1analyze_import_attribute/1analyze_record_attribute/1analyze_wild_attribute/1erl_syntax:error_marker_info/1erl_syntax:warning_marker_info/1

链接到此函数

analyze_function(Node)

查看源码
-spec analyze_function(syntaxTree()) -> {atom(), arity()}.

返回函数定义的名称和元数。

如果 Node 表示函数定义“Name(P_1, ..., P_A) -> ...”,则结果为 {Name, A} 对。

如果 Node 不表示格式正确的函数定义,则评估会抛出 syntax_error

链接到此函数

analyze_function_name(Node)

查看源码
-spec analyze_function_name(syntaxTree()) -> functionName().

返回语法树表示的函数名称。

如果 Node 表示函数名称,例如“foo/1”或“bloggs:fred/2”,则会返回该名称的统一表示形式。语法树中元数和模块名称限定符的不同嵌套不会影响结果。

如果 Node 不表示格式正确的函数名称,则评估会抛出 syntax_error

链接到此函数

analyze_implicit_fun(Node)

查看源码
-spec analyze_implicit_fun(syntaxTree()) -> functionName().

返回隐式 fun 表达式“fun F”的名称。

结果是函数名称 F 的表示形式。(请参阅 analyze_function_name/1。)

如果 Node 不表示格式正确的隐式 fun,则评估会抛出 syntax_error

另请参见: analyze_function_name/1

链接到此函数

analyze_import_attribute(Node)

查看源码
-spec analyze_import_attribute(syntaxTree()) -> {atom(), [functionName()]} | atom().

返回模块名称和(如果存在)import 属性声明的函数名称列表。

返回的值是一个原子 Module 或一个对 {Module, Names},其中 Names 是声明为从 Module 指定的模块导入的函数名称列表。我们不保证每个名称在 Names 中最多出现一次。列表的顺序未定义。

如果 Node 不表示格式正确的导入属性,则评估会抛出 syntax_error

另请参见: analyze_attribute/1

链接到此函数

analyze_module_attribute(Node)

查看源码
-spec analyze_module_attribute(syntaxTree()) -> atom() | {atom(), [atom()]}.

返回模块名称和模块属性声明的可能参数。

如果属性是一个简单的模块声明,例如 -module(name),则结果是模块名称。如果属性是参数化的模块声明,则结果是一个元组,其中包含模块名称和参数变量名称列表。

如果 Node 不表示格式正确的模块属性,则求值将抛出 syntax_error

另请参见: analyze_attribute/1

链接到此函数

analyze_record_attribute(Node)

查看源码
-spec analyze_record_attribute(syntaxTree()) -> {atom(), fields()}.

返回记录声明属性的名称和字段列表。

如果 Node 表示“-record(Name, {...}).”,则结果为 {Name, Fields} 对,其中 Fields 是每个字段“Label”、“Label = Default”、“Label :: Type”或“Label = Default :: Type”的 {Label, {Default, Type}} 对列表,按从左到右的顺序列出。如果字段没有默认值声明,则 Default 的值将是原子 none。如果字段没有类型声明,则 Type 的值将是原子 none。我们不保证每个标签在列表中最多出现一次。

如果 Node 不表示格式正确的记录声明属性,则评估会抛出 syntax_error

另请参阅:analyze_attribute/1analyze_record_field/1

链接到此函数

analyze_record_expr(Node)

查看源码
-spec analyze_record_expr(syntaxTree()) -> {atom(), info()} | atom().

返回记录表达式的记录名称和字段名称/名称。

如果 Node 的类型为 record_exprrecord_index_exprrecord_access,则返回一个对 {Type, Info},否则返回一个原子 TypeTypeNode 的节点类型,而 Info 取决于 Type,如下所示

  • record_expr- {atom(), [{atom(), Value}]}

  • record_access- {atom(), atom()}

  • record_index_expr- {atom(), atom()}

对于 record_expr 节点,Info 表示记录名称和所涉及字段的描述符列表,按它们出现的顺序列出。如果 Node 表示“Label = Value”,则字段描述符是一个对 {Label, Value}。对于 record_access 节点,Info 表示记录名称和字段名称。对于 record_index_expr 节点,Info 表示记录名称和字段名称。

如果 Node 表示格式不正确的记录表达式,则评估会抛出 syntax_error

另请参阅:analyze_record_attribute/1analyze_record_field/1

链接到此函数

analyze_record_field(Node)

查看源码
-spec analyze_record_field(syntaxTree()) -> field().

返回记录字段说明符的标签、值表达式和类型。

如果 Node 表示“Label”、“Label = Default”、“Label :: Type”或“Label = Default :: Type”,则结果为 {Label, {Default, Type}} 对。如果字段没有值表达式,则 Default 的值将是原子 none。如果字段没有类型,则 Type 的值将是原子 none

如果 Node 不表示格式正确的记录字段说明符,则评估会抛出 syntax_error

另请参阅:analyze_record_attribute/1analyze_record_expr/1

链接到此函数

analyze_type_application(Node)

查看源码
-spec analyze_type_application(syntaxTree()) -> typeName().

返回使用的类型的名称。

如果 Node 表示本地(用户)类型应用程序“N(T_1, ..., T_A)”,则结果是使用的预定义或本地类型 N/A 的名称的表示形式;如果 Node 表示远程用户类型应用程序“M:N(T_1, ..., T_A)”,则结果是使用的远程类型 M:N/A 的名称的表示形式。

如果 Node 不表示格式正确的(用户)类型应用程序表达式,则评估会抛出 syntax_error

另请参阅:analyze_type_name/1

链接到此函数

analyze_type_name(Node)

查看源码
-spec analyze_type_name(syntaxTree()) -> typeName().

返回语法树表示的类型名称。

如果 Node 表示类型名称,例如“foo/1”或“bloggs:fred/2”,则会返回该名称的统一表示形式。

如果 Node 不表示格式正确的类型名称,则评估会抛出 syntax_error

链接到此函数

analyze_wild_attribute(Node)

查看源码
-spec analyze_wild_attribute(syntaxTree()) -> {atom(), term()}.

返回“wild”属性的名称和值。

如果 Node 表示“-Name(Value)”,则结果为 {Name, Value} 对。

请注意,不会检查 Name 是否是保留的属性名称,例如 moduleexport:假定该属性是“通配符”。

如果 Node 不表示格式正确的通配符属性,则评估会抛出 syntax_error

另请参见: analyze_attribute/1

链接到此函数

annotate_bindings(Tree)

查看源码
-spec annotate_bindings(syntaxTree()) -> syntaxTree().

在语法树中的节点上添加或更新注解。

等效于 annotate_bindings(Tree, Bindings),其中顶级环境 Bindings 取自 Tree 的根节点上的注释 {env, Bindings}。如果不存在这样的注释,则会引发异常。

另请参阅:annotate_bindings/2

链接到此函数

annotate_bindings(Tree, Env)

查看源码
-spec annotate_bindings(syntaxTree(), ordset(atom())) -> syntaxTree().

在语法树中的节点上添加或更新注解。

Bindings 指定顶级节点环境中的绑定变量集。以下注释会受到影响

  • {env, Vars},表示子树的输入环境。
  • {bound, Vars},表示在子树中绑定的变量。
  • {free, Vars},表示子树中的自由变量。

BindingsVars 是表示变量名称的原子有序集列表(请参阅模块 ordsets)。

另请参阅://stdlib/ordsetsannotate_bindings/1

-spec fold(fun((syntaxTree(), term()) -> term()), term(), syntaxTree()) -> term().

将函数折叠到语法树的所有节点上。

结果是 Function(X1, Function(X2, ... Function(Xn, Start) ... )) 的值,其中 [X1, X2, ..., Xn]Tree 树的后序遍历节点。

另请参阅:fold_subtrees/3, foldl_listlist/3

链接到此函数

fold_subtrees(F, S, Tree)

查看源码
-spec fold_subtrees(fun((syntaxTree(), term()) -> term()), term(), syntaxTree()) -> term().

将函数折叠到语法树的直接子树上。

这类似于 fold/3,但只作用于 Tree 的直接子树,按从左到右的顺序;不包括 Tree 的根节点。

另请参阅:fold/3

-spec foldl_listlist(fun((term(), term()) -> term()), term(), [[term()]]) -> term().

类似于 lists:foldl/3,但适用于列表的列表。

另请参阅://stdlib/lists:foldl/3, fold/3

链接到此函数

function_name_expansions(Fs)

查看源码
-spec function_name_expansions([name()]) -> [{shortname(), name()}].

创建从相应的短名称到完整函数名称的映射。

名称由原子和整数的嵌套元组表示(请参阅 analyze_function_name/1)。结果是一个列表,其中包含给定列表中每个元素 Name 的一个键值对 {ShortName, Name},其中对应的 ShortNameName 最右侧最内层部分。因此,该列表表示从非限定名称到对应的限定名称的有限映射。

请注意,对于同一个 ShortName,结果列表可能包含多个元组 {ShortName, Name},可能对应不同的 Name 值,具体取决于给定的列表。

另请参见: analyze_function_name/1

-spec is_fail_expr(syntaxTree()) -> boolean().

如果 Tree 表示一个永远不会正常终止的表达式,则返回 true

请注意,反之则不成立。目前,检测到的情况是对 exit/1throw/1erlang:error/1erlang:error/2 的调用。

另请参阅://erts/erlang:error/1//erts/erlang:error/2//erts/erlang:exit/1//erts/erlang:throw/1

-spec limit(syntaxTree(), integer()) -> syntaxTree().

等效于使用文本 "..." 作为默认替换的 limit(Tree, Depth, Text)

另请参阅:limit/3, erl_syntax:text/1

链接到此函数

limit(Tree, Depth, Node)

查看源码
-spec limit(syntaxTree(), integer(), syntaxTree()) -> syntaxTree().

将语法树限制为指定的深度。

在给定的 Depth 深度,将 Tree 中的所有非叶子子树替换为 Node。如果 Depth 为负数,则结果始终为 Node,即使 Tree 没有子树。

当一组子树(例如,application 节点的参数列表)处于指定的深度,并且该组中有两个或多个子树时,即使它们是叶子节点,也会被统一替换为 Node。位于指定深度之上的子树组的大小会受到限制,就好像组中的每个后续树都比前一个树深一层一样。例如,如果 Tree 表示一个整数列表 "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]",则 limit(Tree, 5) 的结果将表示 [1, 2, 3, 4, ...]

生成的语法树通常仅用于美化打印或类似的视觉格式化。

另请参阅:limit/2

-spec map(fun((syntaxTree()) -> syntaxTree()), syntaxTree()) -> syntaxTree().

将函数应用于语法树的每个节点。

每次应用的结果会替换对应的原始节点。遍历顺序是从下往上。

另请参阅:map_subtrees/2

链接到此函数

map_subtrees(F, Tree)

查看源码
-spec map_subtrees(fun((syntaxTree()) -> syntaxTree()), syntaxTree()) -> syntaxTree().

将函数应用于语法树的每个直接子树。

每次应用的结果都会替换对应的原始节点。

另请参阅:map/2

-spec mapfold(fun((syntaxTree(), term()) -> {syntaxTree(), term()}), term(), syntaxTree()) ->
                 {syntaxTree(), term()}.

在单个操作中组合 map 和 fold。

这类似于 map/2,但在对树进行类似于 fold/3 的后序遍历的同时,还会将每次 Function 应用的额外值传递到下一次应用。值 Start 将传递给第一个函数应用,最终结果是最后一个函数应用的结果。

另请参阅:fold/3, map/2

链接到此函数

mapfold_subtrees(F, S, Tree)

查看源码
-spec mapfold_subtrees(fun((syntaxTree(), term()) -> {syntaxTree(), term()}), term(), syntaxTree()) ->
                          {syntaxTree(), term()}.

对语法树的直接子树执行 mapfold 操作。

这类似于 mapfold/3,但只作用于 Tree 的直接子树,按从左到右的顺序;不包括 Tree 的根节点。

另请参阅:mapfold/3

-spec mapfoldl_listlist(fun((term(), term()) -> {term(), term()}), term(), [[term()]]) ->
                           {[[term()]], term()}.

类似于 lists:mapfoldl/3,但适用于列表的列表。

结果中的列表的列表与给定的列表的列表具有相同的结构。

链接到此函数

new_variable_name(S)

查看源码
-spec new_variable_name(set(atom())) -> atom().

返回一个不在集合 Used 中的原子。

这等效于 new_variable_name(Function, Used),其中 Function 将给定的整数 N 映射到名称由 "V" 后跟 N 的数字构成的原子。

另请参阅:new_variable_name/2

链接到此函数

new_variable_name(F, S)

查看源码
-spec new_variable_name(fun((integer()) -> atom()), set(atom())) -> atom().

返回一个不在集合 Used 中的用户命名原子。

原子通过将给定的 Function 应用于生成的整数而生成。整数使用一种算法生成,该算法尝试使名称在相对于集合中元素数量的合理小范围内随机分布。

此函数使用模块 rand 来生成新键。它使用的种子可以通过在首次调用此函数之前调用 rand:seed/1rand:seed/2 来初始化。

另请参阅://stdlib/rand, //stdlib/sets, new_variable_name/1

链接到此函数

new_variable_names(N, S)

查看源码
-spec new_variable_names(integer(), set(atom())) -> [atom()].

类似于 new_variable_name/1,但生成 N 个新名称的列表。

另请参阅:new_variable_name/1

链接到此函数

new_variable_names(N, F, S)

查看源码
-spec new_variable_names(integer(), fun((integer()) -> atom()), set(atom())) -> [atom()].

类似于 new_variable_name/2,但生成 N 个新名称的列表。

另请参阅:new_variable_name/2

链接到此函数

strip_comments(Tree)

查看源码
-spec strip_comments(syntaxTree()) -> syntaxTree().

从语法树的所有节点中删除所有注释。

所有其他属性(例如位置信息)保持不变。列表形式的独立注释将被删除;任何其他独立注释都会更改为空注释(无文本,无缩进)。

-spec to_comment(syntaxTree()) -> syntaxTree().

等效于 to_comment(Tree, "% ")

链接到此函数

to_comment(Tree, Prefix)

查看源码
-spec to_comment(syntaxTree(), string()) -> syntaxTree().

等效于使用默认格式化函数 Fto_comment(Tree, Prefix, F)

默认的 F 只是调用 erl_prettypr:format/1

另请参阅:to_comment/3, erl_prettypr:format/1

链接到此函数

to_comment(Tree, Prefix, F)

查看源码
-spec to_comment(syntaxTree(), string(), fun((syntaxTree()) -> string())) -> syntaxTree().

将语法树转换为抽象注释。

注释的行包含 Node 的文本,由给定的 Printer 函数生成。注释的每一行都以字符串 Prefix 作为前缀(这不包括注释行的初始 "%" 字符)。

例如,to_comment(erl_syntax:abstract([a,b,c])) 的结果表示

%% [a,b,c]

(请参阅 to_comment/1)。

注意

格式化函数返回的文本将在每个换行符处自动拆分为单独的注释行。无需额外工作。

另请参阅:to_comment/1, to_comment/2

-spec variables(syntaxTree()) -> set(atom()).

返回语法树中出现的变量的名称。

结果是由原子表示的变量名称集合。不包括宏名称。

另请参阅://stdlib/sets