aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler
diff options
context:
space:
mode:
authorStavros Aronis <[email protected]>2010-05-30 23:42:34 +0300
committerHenrik Nord <[email protected]>2011-10-07 17:08:03 +0200
commit493262e2f024d3a0773b8a062c24de84b5cf21d5 (patch)
tree2b35e1b3e1f11be37609108dd62ae94baa513696 /lib/compiler
parent0edb6a4d2d76960846fd04ecce3aa00b3348691b (diff)
downloadotp-493262e2f024d3a0773b8a062c24de84b5cf21d5.tar.gz
otp-493262e2f024d3a0773b8a062c24de84b5cf21d5.tar.bz2
otp-493262e2f024d3a0773b8a062c24de84b5cf21d5.zip
Automatically generate 'behaviour_info' function from '-callback' attributes
'behaviour_info(callbacks)' is a special function that is defined in a module which describes a behaviour and returns a list of its callbacks. This function is now automatically generated using the '-callback' specs. An error is returned by lint if user defines both '-callback' attributes and the behaviour_info/1 function. If no type info is needed for a callback use a generic spec for it.
Diffstat (limited to 'lib/compiler')
-rw-r--r--lib/compiler/src/sys_pre_expand.erl36
1 files changed, 34 insertions, 2 deletions
diff --git a/lib/compiler/src/sys_pre_expand.erl b/lib/compiler/src/sys_pre_expand.erl
index 249bd7a8e7..0fa1fea09f 100644
--- a/lib/compiler/src/sys_pre_expand.erl
+++ b/lib/compiler/src/sys_pre_expand.erl
@@ -43,6 +43,7 @@
mod_imports, %Module Imports
compile=[], %Compile flags
attributes=[], %Attributes
+ callbacks=[], %Callbacks
defined=[], %Defined functions
vcount=0, %Variable counter
func=[], %Current function
@@ -172,10 +173,41 @@ define_functions(Forms, #expand{defined=Predef}=St) ->
end, Predef, Forms),
St#expand{defined=ordsets:from_list(Fs)}.
-module_attrs(St) ->
- {[{attribute,Line,Name,Val} || {Name,Line,Val} <- St#expand.attributes],St}.
+module_attrs(#expand{attributes=Attributes}=St) ->
+ Attrs = [{attribute,Line,Name,Val} || {Name,Line,Val} <- Attributes],
+ Callbacks = [Callback || {_,_,callback,_}=Callback <- Attrs],
+ {Attrs,St#expand{callbacks=Callbacks}}.
module_predef_funcs(St) ->
+ {Mpf1,St1}=module_predef_func_beh_info(St),
+ {Mpf2,St2}=module_predef_funcs_mod_info(St1),
+ {Mpf1++Mpf2,St2}.
+
+module_predef_func_beh_info(#expand{callbacks=[]}=St) ->
+ {[], St};
+module_predef_func_beh_info(#expand{callbacks=Callbacks,defined=Defined,
+ exports=Exports}=St) ->
+ PreDef=[{behaviour_info,1}],
+ PreExp=PreDef,
+ {[gen_beh_info(Callbacks)],
+ St#expand{defined=union(from_list(PreDef), Defined),
+ exports=union(from_list(PreExp), Exports)}}.
+
+gen_beh_info(Callbacks) ->
+ List = make_list(Callbacks),
+ {function,0,behaviour_info,1,
+ [{clause,0,[{atom,0,callbacks}],[],
+ [List]}]}.
+
+make_list([]) -> {nil,0};
+make_list([{_,_,_,[{{Name,Arity},_}]}|Rest]) ->
+ {cons,0,
+ {tuple,0,
+ [{atom,0,Name},
+ {integer,0,Arity}]},
+ make_list(Rest)}.
+
+module_predef_funcs_mod_info(St) ->
PreDef = [{module_info,0},{module_info,1}],
PreExp = PreDef,
{[{function,0,module_info,0,