Current section

Files

Jump to
lfe doc man lfe_gen.3
Raw

doc/man/lfe_gen.3

.\" Automatically generated by Pandoc 2.11.2
.\"
.TH "lfe_gen" "3" "2008-2016" "" ""
.hy
.SH NAME
.PP
lfe_gen - Lisp Flavoured Erlang (LFE) dynamic code generator
.SH SYNOPSIS
.PP
This module provides an experimental interface for dynamically
generating modules.
.SH DATA TYPES
.PP
\f[B]sexpr()\f[R]
.PP
An LFE s-expression, a list structure.
.SH EXPORTS
.PP
\f[B]new_module(Name) -> ModDef.\f[R]
.PP
\f[B]add_exports([[Name,Arity]], ModDef) -> ModDef.\f[R]
.PP
\f[B]add_imports([from,Module|Functions], ModDef) -> ModDef.\f[R]
.PP
\f[B]add_imports([rename,Module|Renames], ModDef) -> ModDef.\f[R]
.PP
\f[B]add_attribute(Attribute, ModDef) -> ModDef.\f[R]
.PP
\f[B]add_form(Form, ModDef) -> ModDef.\f[R]
.PP
\f[B]build_mod(ModDef) -> Forms.\f[R]
.PP
\f[B]compile_mod(Mod) -> CompRet\f[R]
.PP
where
.IP
.nf
\f[C]
CompRet = BinRet | ErrRet
BinRet = {ok,ModuleName,Binary,Warnings}
ErrRet = {error,Errors,Warnings}
\f[R]
.fi
.PP
These functions are used to incrementally create a module which can at
the end be compiled by \f[C]compile_mod/1\f[R].
The various components have the same formats as they do when defining a
module in a file.
A simple module which defines one function \f[C]a/0\f[R] could be
defined with:
.IP
.nf
\f[C]
M0 = lfe_gen:new_module(foo),
M1 = lfe_gen:add_exports([[a,0]], M0),
M2 = lfe_gen:add_form([defun,a,[],[quote,yes]], M1),
lfe_gen:compile_mod(M2)
\f[R]
.fi
.SH EXAMPLE
.PP
In this example we build a module of parameters where each parameter has
a number of features which each have a value.
We will create one function for each parameter and the feature is the
functions argument.
The value for each feature is returned.
.PP
We are creating code equivalent to:
.IP
.nf
\f[C]
-module(Name).
-export([<param1>/1,...]).
<param1>(Feature) ->
case Feature of
<feature1> -> <value1>;
...
_ -> erlang:error({unknown_feature,<param1>,Feature)
end.
\&...
\f[R]
.fi
.PP
but generating it and compiling it directly in memory without generating
a text file.
We assume that we have collected the data and have it in the form:
.IP
.nf
\f[C]
Params = [{Parameter,[{Feature,Value}]}]
\f[R]
.fi
.PP
The equivalent LFE code which we will be generating is:
.IP
.nf
\f[C]
(defmodule Name
(export (<param1> 1) (<param2> 1) ... ))
(defun <param1> (f)
(case f
(\[aq]<feature1> \[aq]<value1>)
...
(f (: erlang error (tuple \[aq]unknown_feature \[aq]<param1> f)))))
\&...
\f[R]
.fi
.PP
The following code builds and compiles a module from the parameter data:
.IP
.nf
\f[C]
make_module(Name, Params) ->
Mod0 = lfe_gen:new_module(Name),
Exps = lists:map(fun ({Param,_}) -> [Param,1] end, Params),
Mod1 = lfe_gen:add_exports(Exps, Mod0),
Mod2 = make_funcs(Params, Mod1),
lfe_gen:compile_mod(Mod2).
make_funcs([{Param,Fs}|Ps], Mod) ->
%% Define catch-all which generates more explicit exit value.
CatchAll = [f,[\[aq]:\[aq],erlang,error,
[tuple,unknown_feature,[quote,Param],f]]],
%% Build case clauses
Fold = fun ({Feature,Value}, Cls) ->
[[[quote,Feature],[quote,Value]]|Cls]
end
Cls = lists:foldr(Fold, [CatchAll], Params),
%% Build function.
Func = [defun,Param,[f],[\[aq]case\[aq],f,Cls]],
make_funcs(Ps, lfe_gen:add_form(Func, Mod));
make_funcs([], Mod) -> Mod. %All done
\f[R]
.fi
.PP
This module could be generated and then be loaded into the system by
doing:
.IP
.nf
\f[C]
{ok,ModuleName,Binary,Warnings} = make_module(Name, Params),
code:load_binary(ModuleName, \[dq]nofile\[dq], Binary)
\f[R]
.fi
.PP
The second argument to \f[C]code:load_binary/3\f[R], here
\f[C]\[dq]nofile\[dq]\f[R], is irrelevant in this case.
.SH ERROR INFORMATION
.PP
The ErrorInfo mentioned above is the standard ErrorInfo structure which
is returned from all IO modules.
It has the following format:
.PP
\f[B]{ErrorLine,Module,ErrorDescriptor}\f[R]
.PP
A string describing the error is obtained with the following call:
.IP
.nf
\f[C]
apply(Module, format_error, ErrorDescriptor)
\f[R]
.fi
.SH SEE ALSO
.PP
\f[B]lfe_comp(3)\f[R], \f[B]lfe_macro(3)\f[R]
.SH AUTHORS
Robert Virding.