非常教程

Erlang 20参考手册

syntax_tools

igor

模块

igor

模块摘要

模块合并和更名。

描述

模块合并和更名。

程序 Igor 将一个或多个 Erlang 模块的源代码合并到一个模块中,然后该模块可以替换原始的一组模块。Igor 也可以重命名一组(可能相互依存的)模块,而不必将它们连接到一个模块中。

主用户界面由功能merge/3rename/3。另请参阅该功能parse_transform/2

警告注意:当将远程函数的名称传递给内置函数时,Igor不能对这种情况做任何处理。applyspawn除非模块和函数的名称在调用中显式地声明,如在例如。apply(lists, reverse, [Xs])在所有其他情况下,Igor都保持这种调用不变,并警告用户手动编辑可能是必要的。

还请注意,Erlang记录将根据需要重新命名,以避免使用相同记录名的非等效定义。如果源代码访问此类记录元组的name字段,则此操作不起作用。element/2或者类似的方法。如果可能,始终使用记录语法来处理记录元组。

免责声明:本程序的作者不对所产生的输出的正确性或其执行的任何影响负责。特别是,如果Igor在结果中包括已故疯子的代码,提交人可能不承担责任。

关于Igors一般情况的进一步信息,见“青年弗兰肯斯坦”,Mel Brooks,1974和“The Five Elephant”,Terry Pratchett,1999年。

数据类型

filename()= file:filename()** stubDescriptor()= {ModuleName,Functions,Attribute} **

  • ModuleName = atom()
  • Functions={FunctionName,{ModuleName,FunctionName}
  • FunctionName = {atom(),integer()}
  • Attribute = {atom(),term()}

存根模块描述符包含模块名称,导出函数列表和模块属性列表。每个函数都由其名称(包括它的名称)以及它调用的相应模块和函数来描述。(这些元素应该始终匹配。)属性仅由键值对来描述。

syntaxTree()= erl_syntax:syntaxTree()

抽象语法树。见erl_syntax模块获取详细信息。

出口

create_stubs(Stubs::[stubDescriptor()], Options::[term()]) -> [string()]

创建与给定存根描述符对应的存根模块源文件。返回的值是创建的文件的名称列表。见merge_sources/3有关存根描述符的更多信息。

备选方案:

{backup_suffix, string()}{backups, boolean()}{printer, Function}{stub_dir, filename()}{suffix, string()}{verbose, boolean()}

merge/3有关这些选项的详细信息。

另见: merge/3merge_sources/3

merge(Name::atom(), Files::[filename()]) -> [filename()]

相当于merge(Name, Files, [])

merge(Name::atom(), Files::[filename()], Options::[term()]) -> [filename()]

将源代码文件合并到单个文件。Name指定结果模块的名称 - 不是输出文件的名称。Files是要读取和合并的源模块的文件名和/或模块名称的列表(merge_files/4详情请参阅参考资料)。所有输入模块必须明确命名。

生成的源代码被写入一个名为“<em>Name</em>.erl“在当前目录中,除非选项另有规定diroutfile下文介绍。

例子:

  • 给定模块m档案“m.erl“它使用标准库模块。lists,呼叫igor:merge(m, [m, lists])将创建一个新文件“m.erl中包含的代码m并导出相同的函数,其中包括lists模块。原始文件将重命名为“m.erl.bak
  • 给定的模块,m1m2在相应的文件中,调用igor:merge(m, [m1, m2])将创建一个文件“ m.erl”,其中包含来自m1和的代码m2并导出其功能m1

存根模块文件对于那些由目标模块被导出模块创建(见选项exportstubsstub_dir)。

函数返回所有已创建模块的文件名列表,包括任何自动创建的存根模块。目标模块的文件名总是列表中的第一位。

注意:如果在尝试合并文件(并且您知道这些文件是正确的)时收到“语法错误”消息,请尝试该preprocess选项。它通常意味着你的代码包含了太奇怪的宏而无需实际执行预处理器扩展。

备选方案:

{backup_suffix, string()}

指定创建备份文件时要使用的文件名后缀; 默认值是".bak"

{backups, boolean()}

如果值为true,则在新文件打开写入之前,现有文件将被重命名。新名称是通过将由backup_suffix选项给出的字符串附加到原始名称而形成的。默认值是true

{dir, filename()}

指定要写入输出文件的目录的名称。空字符串被解释为当前目录。默认情况下,将使用当前目录。

{outfile, filename()}

指定将生成的源代码写入的文件的名称(无后缀)。默认情况下,这与Name参数相同。

{preprocess, boolean()}

如果值是true,在读取源代码时将进行预处理。见merge_files/4关于细节。

{printer, Function}

  • Function = (syntaxTree()) -> string()

为漂亮的Erlang语法树指定一个函数。这用于输出生成的模块定义,以及用于创建存根文件。假定函数返回给定语法树的格式化文本,并且如果发生错误应该引发异常。默认的格式化函数调用erl_prettypr:format/2。

{stub_dir,filename()}

指定任何生成的存根模块文件写入的目录的名称。默认值是 “存根”。

{stubs,boolean()}

如果该值为true,则会为所有与目标模块名称不同的导出模块自动生成存根模块文件。默认值是 true。

{suffix,string()}

指定用于输出文件名称的后缀; 默认值是“.erl”。

有关更多选项,请参阅merge_files/4。

另请参阅: merge/2, merge_files/4.

merge_files(Name::atom(), Files::[filename()], Options::[term()]) -> {syntaxTree(), [stubDescriptor()]}

相当于 merge_files(Name, [], Files, Options).

merge_files(Name::atom(), Sources::[Forms], Files::[filename()], Options::[term()]) -> {syntaxTree(), [stubDescriptor()]}

类型

Forms = syntaxTree() | [ syntaxTree() ]

将源代码文件和语法树合并到单个语法树中。这是merge_sources / 3的文件读取前端 。名称指定生成的模块的名称 - 不是输出文件的名称。 Sources是一组语法树和/或“源代码形式”语法树列表,每个条目代表一个模块定义。文件是要读取和包括的源模块的文件名和/或模块名称的列表。所有输入模块必须明确命名。

如果Files中的名称不是现有文件的名称,则Igor假定它代表模块名称,并尝试查找并读取相应的源文件。解析后的文件被附加到源文件并传递到 merge_sources/3,即源 文件中的条目在从文件读取条目之前列出。

如果导出选项未列出任何导出(详情请参阅 merge_sources/3),则如果Name 也是其中一个输入模块的名称,则该模块将被导出; 否则,第一个列出的模块将被导出。参看 merge/3下的例子。

结果是一对{Tree,Stubs},其中 Tree表示合并源和文件中所有代码的源代码,而Stubs是存根模块描述符的列表(有关详细信息,请参阅 merge_sources/3)。

选项:

{comments,boolean()}

如果该值为true,则原始文件中的源代码注释将保留在输出中。默认值是true。

{find_src_rules,[{string(),string()}]}

指定将对象文件与源文件相关联的规则列表,以传递给函数 filelib:find_source/2。这可以用来改变Igor寻找源文件的方式。如果未指定此选项,则使用默认系统规则。此选项的第一次出现完全覆盖选项列表中的任何后面的内容。

{includes,[filename()]}

指定Erlang预处理器的目录名称列表(如果使用)搜索包含文件(参见 预处理选项)。默认值是空列表。源文件的目录和当前目录会自动附加到列表中。

{macros, [{atom(), term()}]}

指定Erlang预处理器的“预定义”宏定义列表(参见预处理选项)。默认值是空列表。

{preprocess,boolean()}

如果该值为false,Igor将读取源文件而不通过Erlang预处理器(epp),以避免扩展预处理器指令,如-include(...)。, - 定义 (...)。和-ifdef(...)以及宏调用(例如?LINE和?MY_MACRO(x,y))。默认值为false,即未执行预处理。(有关详细信息,请参阅模块epp_dodger。)

注意:如果一个文件包含太宏观的定义或宏的使用,不经过预处理就无法读取它。此外,Igor目前不尝试对同一个文件的多个包含进行排序,或者重新定义相同的宏名称。因此,当预处理关闭时,可能需要编辑生成的源代码,删除这种重新包含和重新定义。

有关更多选项,请参阅merge_sources / 3。

另请参阅: epp_dodgerfilelib:find_source / 2merge / 3merge_files / 3merge_sources / 3

merge_sources(Name :: atom(),Sources :: [Forms],Options :: [term()]) - > { syntaxTree(),[ stubDescriptor() ]}

类型

Forms = syntaxTree() | [ syntaxTree() ]

将语法树合并到单个语法树中。这是合并“引擎”的主要代码。名称指定生成的模块的名称。Sources是类型为form_list的语法树列表和/或“源代码形式”语法树列表,每个条目代表模块定义。所有输入模块必须明确命名。

除非选项另有规定,否则假定所有模块至少为“静态”,并且除目标模块外的所有模块均假定为“安全”。有关 详细信息,请参阅静态和安全选项。

如果Name也是其中一个输入模块的名称,则该模块中的代码将出现在结果代码的顶部,并且不会添加额外的“标题”注释。换句话说,该模块的外观将被保留。

结果是一对{Tree,Stubs},其中 Tree代表合并源代码中所有代码的源代码,而Stubs 是存根模块描述符(见下文)的列表。

存根包含每个导出输入模块的一个条目(参见导出选项),每个条目都描述了一个存根模块,用于将原始模块中的函数调用重定向到新模块中对应的(可能更名的)函数。存根描述符可用于自动生成存根模块; 请参阅create_stubs/2。

选项:

{export,[atom()]}

指定接口应由输出模块导出的输入模块的名称列表。为每个指定模块生成一个存根描述符,除非其名称是 Name。如果没有指定模块,那么如果 Name也是输入模块的名称,那么该模块将被导出; 否则将导出源中第一个列出的模块。默认值是空列表。

{export_all,boolean()}

如果该值为true,则相当于在导出 选项中列出所有输入模块。默认值是false。

{file_attributes, Preserve}

  • Preserve = yes | comment | no

如果值是yes-file(...)输入源中的所有文件属性将保留在生成的代码中。如果值是comment,则它们将转换为注释,但仍保留在代码中相对于其他源代码表单的原始位置。如果值是no,除非它们有附加注释,否则所有文件属性将从代码中移除,在这种情况下,它们将按照案例进行处理comment。默认值是no

{no_banner, boolean()}

如果值为true,则即使目标模块与任何输入模块名称不同,也不会在结果模块的顶部添加横幅注释。相反,Igor会尝试保留代码位于输出顶部的模块的外观。默认值是false

{no_headers, boolean()}

如果值是true,在来自特定输入模块的代码的每个部分开始时,不会向结果模块添加任何头注释。默认值是false,这意味着当合并了两个或多个模块时,通常会添加节标题。

{no_imports, boolean()}

如果值是true-import(...)结果将扩展原始代码中的声明;否则,将尽可能保留原始导入声明。默认值是false...

{notes, Notes}

  • Notes = always | yes | no

如果值是yes,则在代码中进行重要更改的地方将插入注释。如果值是always,则将对代码的所有更改进行评论。如果该值是no,则更改将被做出而没有评论。默认值是yes

{redirect, [{atom(), atom()}]}

指定一对模块名称的列表,表示从旧名称到新名称的映射。旧名称集合可能不包括输入模块的任何名称。对列出的旧模块的所有调用都将被重写,以引用相应的新模块。即使新目的地位于一个输入模块中,重定向调用也不会被进一步处理。此选项主要用于支持模块重命名;cf。rename/3默认值是空列表。

{safe, [atom()]}

指定输入模块的名称列表,以便对这些“安全”模块的调用可以转换为直接本地调用,而不用测试代码替换。通常,这可以用于例如标准库模块。如果一个模块是“安全”的,则每个定义也是“静态的”(参见下文)。该列表可能为空。默认情况下,除目标模块外的所有相关模块均被视为“安全”。

{static, [atom()]}

指定输入模块的名称列表,假定永远不会被替换(重新加载),除非目标模块也被首先替换。该列表可能为空。无论此选项的值如何,目标模块本身(也可能是其中一个输入模块)始终被视为“静态”。默认情况下,所有涉及的模块都被假定为静态的。

{tidy, boolean()}

如果值是true,则将使用erl_tidy模块处理生成的代码,该模块将删除未使用的函数并进行常规代码清理。(请参阅erl_tidy:module/2其他选项。)默认值为true

{verbose, boolean()}

如果值为true,程序运行时将输出进度消息; 默认值是false

注意:为了不打破动态代码替换的语义,“静态”和“安全”模块之间的区别是必要的。除非目标模块也是如此,否则“静态”源模块将不会被替换。现在想象一下,通过将每个状态的代码放置在一个单独的模块中来实现状态机,并假设我们想将其合并到单个目标模块中,将所有源模块标记为静态。在原始代码中从一个模块到另一个模块进行呼叫的每个点(即状态转换),预计将检测代码替换。那么,如果我们在合并代码中不检查这些点是否为目标模块(合并的结果)已被替换,我们无法确定一般情况下我们将能够执行合并状态机的代码替换 - 它可以永久运行而不会检测到代码更改。因此,所有这些调用都必须保持远程调用(检测代码更改),但可以直接调用目标模块。

如果我们确信这种情况不会发生,我们可以将涉及的模块指定为“安全”,它们之间的所有调用都将变成本地的。注意,如果目标模块本身被指定为安全模块,则对其自身的“远程”调用将被转换为本地调用。这将破坏例如典型服务器循环的代码替换属性。

另请参阅: create_stubs/2rename/3erl_tidy:module/2

parse_transform(Forms::[syntaxTree()], Options::[term()]) -> [syntaxTree()]

允许Igor作为Erlang编译器的一个组件工作。{parse_transform, igor}在编译Erlang模块(参见compile:file/2)时将这个术语包含在编译选项中,将会调用Igor来处理源代码,从而允许自动包含其他源文件。使用此功能时不会创建或覆盖文件。

伊戈尔会找条件{igor, List}在编译选项中,其中List是特定于Igor的选项列表,如下所示:

{files, [filename()]}

该值指定要与正在编译的文件合并的源文件的列表; 比照 merge_files/4

merge_files/4为进一步的选择。但是,请注意,某些选项是由此函数预先设置的,用户不能覆盖这些选项;特别是,为了提高效率,关闭了所有外观功能。预处理打开。

另见: compile:file/2merge_files/4

rename(Files::[filename()], Renamings) -> [string()]

相当于rename(Files, Renamings, [])

rename(Files::[filename()], Renamings, Options::[term()]) -> [string()]

类型

重命名一组可能相互依赖的源代码模块。Files要处理的源模块的文件名列表。Renamings模块名,表示从旧名称到新名称的映射。返回的值是输出文件名的列表。

列表中的每个文件将被单独读取和处理。对于每一个文件中,每个参考一些组件M,使得存在一个条目{<em>M</em>, <em>M1</em>}Renamings,将被改变为相应的M1。此外,如果一个文件F定义的模块M,并且有一个条目{<em>M</em>, <em>M1</em>}Renamings,命名为新的文件<em>M1</em>.erl将在相同的目录为F被创建,包含用于模块M中的源代码,重命名为M1。如果M没有输入Renamings,模块不会被重命名,只会更新,并且生成的源代码被写入<em>M</em>.erl(通常会覆盖原始文件)。该suffix选项(见下文)可用于更改.erl生成文件的默认“ ”后缀。

存根模块将自动为每个重命名的模块创建(请参阅下面的选项stubsstub_dir选项)。这些可以用来重定向任何仍然使用旧模块名称的调用。存根文件在与源文件相同的目录中创建(通常覆盖原始文件)。

备选方案:

{backup_suffix, string()}{backups, boolean()}{printer, Function}{stubs, boolean()}{suffix, string()}

merge/3有关这些选项的详细信息。

{comments, boolean()}{preprocess, boolean()}

merge_files/4有关这些选项的详细信息。

{no_banner, boolean()}

rename函数,此选项为true默认情况下。见merge_sources/3关于细节。

{tidy, boolean()}

rename函数,此选项为false默认情况下。见merge_sources/3关于细节。

{no_headers, boolean()}{stub_dir, filename()}

这些选项由rename函数,用户不能重写。

merge_sources/3为进一步的选择。

另请参阅: merge/3merge_files/4merge_sources/3

Erlang 20

Erlang 是一种通用的面向并发的编程语言,可应付大规模开发活动的程序设计语言和运行环境。

主页 https://www.erlang.org/
源码 https://github.com/erlang/otp
版本 20
发布版本 20.1