Module smerl

Copyright © 2006-2007, 2016 AUTHORS Smerl is an Erlang library that simplifies the creation and manipulation of Erlang modules in runtime. You don't need to know Smerl in order to use ErlyWeb; Smerl is included in ErlyWeb because ErlyWeb uses it internally. Smerl uses Erlang's capabilities for hot code swapping and abstract syntax tree transformations to do its magic. Smerl is inspired by the rdbms_codegen.erl module in the RDBMS application written by Ulf Wiger. RDBMS is part of Jungerl ([http://jungerl.sf.net]). Here's a quick example illustrating how to use Smerl: ``` test_smerl() -> M1 = smerl:new(foo), {ok, M2} = smerl:add_func(M1, "bar() -> 1 + 1."), smerl:compile(M2), foo:bar(), % returns 2`` smerl:has_func(M2, bar, 0). % returns true ''' New functions can be expressed either as strings of Erlang code or as abstract forms. For more information, read the Abstract Format section in the ERTS User's guide ([http://erlang.org/doc/doc-5.5/erts-5.5/doc/html/absform.html#4]). Using the abstract format, the 3rd line of the above example would be written as ``` {ok,M2} = smerl:add_func(M1, {function,1,bar,0, [{clause,1,[],[], [{op,1,'+',{integer,1,1},{integer,1,1}}]}]). ''' <p>The abstact format may look more verbose in this example, but it's also easier to manipulate in code.</p>

Authors: Yariv Sadan.

Description

Simple Metaprogramming for Erlang

Data Types

args()

args() = term() | [term()]

error_t()

error_t(Error) = ok | {error, Error}

export()

export() = {Function :: atom(), Arity :: arity()}

exports()

exports() = [export()]

A list of export()s.

func_form()

func_form() = erl_parse:abstract_form()

The abstract form for the function, as described in the ERTS Users' manual.

func_forms()

func_forms() = [func_form()]

A list of func_form()s.

meta_mod()

meta_mod() = 
    #meta_mod{module = module(),
              file = undefined | file:filename(),
              exports = exports(),
              forms = func_forms(),
              export_all = boolean()}

A data structure holding the abstract representation for a module.

ok_t()

ok_t(Value) = {ok, Value} | error

result()

result(Value, Error) = {ok, Value} | {error, Error}

result()

result(Value) = result(Value, term())

Function Index

add_func/2Add a new exported function to MetaMod.
add_func/3Add Function to MetaMod and return the new meta_mod().
compile/1Compile MetaMod and load the resulting BEAM into the emulator.
compile/2Compile MetaMod and load the resulting BEAM into the emulator.
curry/2Get the curried form for Form with Args.
curry/4Curry Module:Function/Arity with the given Args.
curry/5Curry Module:Function/Aritywith the given Args, renaming it to NewName and return the renamed form.
curry_add/3Add Form curried with Args to MetaMod.
curry_add/4Add Function/Arity curried with Args to MetaMod.
curry_add/5Curry MetaMod:Function/Arity and add it to MetaMod as NewName.
curry_add/6Curry Module:Function/Arity and add it to MetaMod as NewName.
curry_replace/3Replace the function represented by Form in MetaMod with its curried form.
curry_replace/4Replace Function/Arity in MetaMod with its curried form.
embed_all/2Apply embed_args/2 with Values to all forms in MetaMod.
embed_args/2Replace the arguments of the function represented by Form, where the argument's Name matches an element from Vals with the corresponding Value.
embed_args/4Equivalent to embed_args(MetaMod, Name, Arity, Values, Name).
embed_args/5Apply embed_args/2 to MetaMod:Function/Arity and add the resulting function to MetMod, after renaming it to NewName.
extend/2Add aliases for Parent's functions missing from Child to Child.
extend/3Similar to extend/2, with the addition of ArityDiff, which indicates the difference in arities Smerl should use when figuring out which functions to generate based on the modules' exports.
extend/4
for_file/1Equivalent to for_file(SrcFilePath, []).
for_file/2Equivalent to for_file(SrcFilePath, IncludePaths, []).
for_file/3Create a meta_mod for a module from its source file.
for_module/1Equivalent to for_module(ModuleName, []).
for_module/2Equivalent to for_module(ModuleName, IncludePaths, []).
for_module/3Create a meta_mod tuple for an existing module.
get_attribute/2Get the value of MetaMod's Key attribute.
get_export_all/1Get the export_all value for MetaMod.
get_exports/1Return the list of exports in the meta_mod.
get_forms/1Return the list of function forms in the meta_mod.
get_func/3Attempt to get the func_form() for MetaMod:Function/Arity.
get_module/1Return the module name for the meta_mod.
has_func/3Check whether MetaMod has a function Function/Arity.
new/1Create a new meta_mod for a module with the given name.
remove_export/3Remove an export {Function, Arity} from the list of exports in MetaMod.
remove_func/3Try to remove Function from MetaMod.
rename/2Change the name of the function represented by Form to NewName.
replace_func/2Replace an existing function with a new one.
set_export_all/2Set the export_all value for MetaMod.
set_exports/2Set the MetaMod's export list to Exports.
set_forms/2
set_module/2Set the meta_mod's module name.
to_src/1Return the pretty-printed source code for MetaMod.
to_src/2Equivalent to file:write_file(Filename, to_src(MetaMod)).

Function Details

add_func/2

add_func(MetaMod, Form) -> result(meta_mod(), parse_error)

Equivalent to add_func(MetaMod, Form, true).

Add a new exported function to MetaMod.

add_func/3

add_func(MetaMod, Func, Export) -> result(meta_mod(), parse_error)

Add Function to MetaMod and return the new meta_mod(). If Export is true, add Function to MetaMod's exports.

compile/1

compile(MetaMod :: meta_mod()) -> error_t(term())

Equivalent to compile(MetaMod, []).

Compile MetaMod and load the resulting BEAM into the emulator.

compile/2

compile(MetaMod, Options) -> error_t(term())

Equivalent to compile(MetaMod, [report_errprs, report_warnings, return_errors]).

Compile MetaMod and load the resulting BEAM into the emulator. Options is a list of options as described in the compile module in the Erlang documentation. If an outdir is provided, write the .beam file to it.

curry/2

curry(Form :: func_form(), Args :: args()) -> result(func_form())

Get the curried form for Form with Args. Here, "currying" involves replacing one or more of the function's leading arguments with predefined values.

curry/4

curry(Module, Function, Arity, Args) -> result(func_form())

Curry Module:Function/Arity with the given Args.

curry/5

curry(Module, Function, Arity, Args, NewName) ->
         result(func_form())

Curry Module:Function/Aritywith the given Args, renaming it to NewName and return the renamed form.

curry_add/3

curry_add(MetaMod, Form, Args) -> result(meta_mod())

Add Form curried with Args to MetaMod.

curry_add/4

curry_add(MetaMod, Function, Arity, Args) -> result(meta_mod())

Add Function/Arity curried with Args to MetaMod.

curry_add/5

curry_add(MetaMod, Function, Arity, Args, NewName) -> Result

Curry MetaMod:Function/Arity and add it to MetaMod as NewName.

curry_add/6

curry_add(MetaMod, Module, Function, Arity, Args, NewName) ->
             Result

Curry Module:Function/Arity and add it to MetaMod as NewName.

curry_replace/3

curry_replace(MetaMod, Form, Args) -> result(meta_mod())

Replace the function represented by Form in MetaMod with its curried form.

curry_replace/4

curry_replace(MetaMod, Function, Arity, Args) ->
                 result(meta_mod())

Replace Function/Arity in MetaMod with its curried form.

embed_all/2

embed_all(MetaMod, Values) -> NewMod

Apply embed_args/2 with Values to all forms in MetaMod. exports for functions whose arities change are preserved.

embed_args/2

embed_args(Form, Vals) -> NewForm

Replace the arguments of the function represented by Form, where the argument's Name matches an element from Vals with the corresponding Value.

embed_args/4

embed_args(MetaMod, Function, Arity, Values) -> result(meta_mod())

Equivalent to embed_args(MetaMod, Name, Arity, Values, Name).

embed_args/5

embed_args(MetaMod, Function, Arity, Values, NewName) -> Result

Apply embed_args/2 to MetaMod:Function/Arity and add the resulting function to MetMod, after renaming it to NewName.

See also: rename/2.

extend/2

extend(Parent, Child) -> NewChildMod

Add aliases for Parent's functions missing from Child to Child. The new functions in Child are shallow, i.e. they have the name and arity of the corresponding functions in Parent, but instead of implementing their logic they call the Parent functions.

extend/3

extend(Parent, Child, ArityDiff) -> NewChildMod

Similar to extend/2, with the addition of ArityDiff, which indicates the difference in arities Smerl should use when figuring out which functions to generate based on the modules' exports. This is sometimes useful when calling extend/3 followed by embed_all/2.

extend/4

extend(Parent, Child, ArityDiff, Options) -> NewChildMod

for_file/1

for_file(SrcFilePath) -> any()

Equivalent to for_file(SrcFilePath, []).

for_file/2

for_file(SrcFilePath, IncludePaths) -> any()

Equivalent to for_file(SrcFilePath, IncludePaths, []).

for_file/3

for_file(SrcFilePath, IncludePaths, Macros) -> Result

Create a meta_mod for a module from its source file.

for_module/1

for_module(ModuleName) -> any()

Equivalent to for_module(ModuleName, []).

for_module/2

for_module(ModuleName, IncludePaths) -> any()

Equivalent to for_module(ModuleName, IncludePaths, []).

for_module/3

for_module(ModuleName, IncludePaths, Macros) -> result(meta_mod)

Create a meta_mod tuple for an existing module. If ModuleName is a string, it is interpreted as a file name (this is the same as calling for_file/3). If ModuleName is an atom, Smerl attempts to find its abstract represtation either from its source file or from its .beam file directly (if it has been compiled with debug_info). If the abstract representation can't be found, this function returns an error.

The IncludePaths argument is used when ModuleName is a file name.

get_attribute/2

get_attribute(MetaMod :: meta_mod(), Key :: atom()) ->
                 result(term())

Get the value of MetaMod's Key attribute.

get_export_all/1

get_export_all(MetaMod :: meta_mod()) -> boolean()

Get the export_all value for MetaMod.

get_exports/1

get_exports(MetaMod :: meta_mod()) -> exports()

Return the list of exports in the meta_mod.

get_forms/1

get_forms(MetaMod :: meta_mod()) -> func_forms()

Return the list of function forms in the meta_mod.

get_func/3

get_func(MetaMod, Function, Arity) -> result(func_form())

Attempt to get the func_form() for MetaMod:Function/Arity.

get_module/1

get_module(MetaMod :: meta_mod()) -> module()

Return the module name for the meta_mod.

has_func/3

has_func(MetaMod, Function, Arity) -> boolean()

Check whether MetaMod has a function Function/Arity.

new/1

new(Module :: module()) -> meta_mod()

Create a new meta_mod for a module with the given name.

remove_export/3

remove_export(MetaMod, Function, Arity) -> NewMod

Remove an export {Function, Arity} from the list of exports in MetaMod.

remove_func/3

remove_func(MetaMod, Function, Arity) -> NewMod

Try to remove Function from MetaMod. If the function exists, return the new meta_mod(). Otherwise, return MetaMod.

rename/2

rename(Form :: func_form(), NewName :: atom()) -> func_form()

Change the name of the function represented by Form to NewName.

replace_func/2

replace_func(MetaMod, Function) -> result(meta_mod())

Replace an existing function with a new one. If a matching function doesn't exist, add Function to MetaMod. This is tantamount to calling remove_func/3 followed by add_func/2.

set_export_all/2

set_export_all(MetaMod, Value) -> NewMod

Set the export_all value for MetaMod.

set_exports/2

set_exports(MetaMod, Exports) -> NewMod

Set the MetaMod's export list to Exports.

set_forms/2

set_forms(MetaMod, Forms) -> NewMod

set_module/2

set_module(MetaMod, NewName) -> NewMod

Set the meta_mod's module name.

to_src/1

to_src(MetaMod :: meta_mod()) -> Source :: string()

Return the pretty-printed source code for MetaMod.

to_src/2

to_src(MetaMod, Filename) -> error_t(term())

Equivalent to file:write_file(Filename, to_src(MetaMod)).