igor

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“在当前目录中,除非选项另有规定dir和outfile下文介绍。

例子:

  • 给定模块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()

  • 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