diff --git a/docs/doc/api_interface.html b/docs/doc/api_interface.html new file mode 100644 index 00000000..818cc12d --- /dev/null +++ b/docs/doc/api_interface.html @@ -0,0 +1,112 @@ + + +
+ +Authors: Huiqing Li (H.Li@kent.ac.uk).
+ +expr_to_fun/2 | Return the AST of the function to which Exp (an expression node) belongs. |
pos_to_expr/3 | Returns the largest, left-most expression enclosed by the start and end locations. |
pos_to_expr1/3 | |
pos_to_expr_list/2 | Return the expression sequence enclosed by start and end locations. |
pos_to_fun_def/2 | Returns the AST representation of the function definition in which the
+ location specified by Pos falls. |
pos_to_fun_name/2 | Returns information about the function name which occurs at the specified + position in the code. |
pos_to_node/3 | Returns the outmost Node which encloses the cursor and
+ makes Pred(Node) return true . |
pos_to_var/2 | Returns the variable node at position Pos . |
pos_to_var_name/2 | Returns the variable name that occurs at the position specified by position Pos . |
range_to_node/3 | Returns the largest, left-most Node which is enclosed by the location range specified,
+ and also makes Pred(Node) return true . |
expr_to_fun(Tree::syntaxTree(), Exp::syntaxTree()) -> {ok, syntaxTree()} | {error, none}
Return the AST of the function to which Exp (an expression node) belongs. + -spec(expr_to_fun(Tree::syntaxTree(), Exp::syntaxTree())->{ok, syntaxTree()} | {error, none}).
+ +pos_to_expr(Tree::syntaxTree(), Start::Pos, End::Pos) -> {ok, syntaxTree()} | {error, string()} +
Returns the largest, left-most expression enclosed by the start and end locations. +
+See also: pos_to_fun_def/2, pos_to_fun_name/2.
+ +pos_to_expr1(FileOrTree, Start, End) -> any()
+pos_to_expr_list(FileOrTree::filename() | syntaxTree(), X2::{Start::pos(), End::pos()}) -> [syntaxTree()]
Return the expression sequence enclosed by start and end locations.
+ +pos_to_fun_def(FileOrTree::any(), Pos::pos()) -> {ok, syntaxTree()} | {error, string()}
Returns the AST representation of the function definition in which the
+ location specified by Pos
falls.
+
See also: pos_to_fun_name/2.
+ +pos_to_fun_name(Node::syntaxTree(), Pos::{integer(), integer()}) -> {ok, {Mod, Fun, Arity, OccurPos, DefPos}} | {error, string()} +
Returns information about the function name which occurs at the specified + position in the code. If successful, the returned information contains: + the module in which the function is defined, the function name, the + function's arity, the occurrence position (same as Pos), and the defining + position of this function. +
+See also: pos_to_expr/3, pos_to_fun_def/2, pos_to_var_name/2.
+ +pos_to_node(FileOrTree::filename() | syntaxTree(), Pos::pos(), Cond::function()) -> {ok, syntaxTree()} | {error, string()}
Returns the outmost Node which encloses the cursor and
+ makes Pred(Node) return true
.
pos_to_var(Node::syntaxTree(), Pos::pos()) -> {ok, syntaxTree()} | {error, string()}
Returns the variable node at position Pos
.
pos_to_var_name(Node::syntaxTree(), Pos::{integer(), integer()}) -> {ok, {VarName, DefPos}} | {error, string()} +
Returns the variable name that occurs at the position specified by position Pos
.
See also: pos_to_expr/3, pos_to_fun_def/2, pos_to_fun_name/2.
+ +range_to_node(FileOrTree::filename() | syntaxTree(), Range::{pos(), pos()}, Cond::Pred) -> syntaxTree() | {error, string()}
Returns the largest, left-most Node which is enclosed by the location range specified,
+ and also makes Pred(Node) return true
.
Generated by EDoc, Nov 5 2015, 16:30:21.
+ + diff --git a/docs/doc/api_refac.html b/docs/doc/api_refac.html new file mode 100644 index 00000000..410f0afc --- /dev/null +++ b/docs/doc/api_refac.html @@ -0,0 +1,719 @@ + + + + +Authors: Huiqing Li (H.Li@kent.ac.uk).
+ ++This module defines the API exposed by Wrangler for users to compose +refactorings or code inspectors that meet their own needs. A refactoring +consists of two parts: program analysis and program transformation, both +of which involve various AST traversals and manipulations, and require +deep knowledge of the AST representation details. To make the processing +of writing a refactoring easier, we have extended Wrangler with a framework +that allows users to define refactorings or code inspectors in an intuitive +and concise way. With this framework, user-defined refactorings are no +second-class refactorings. Like the existing refactorings supported by Wrangler, +user-defined refactoring can also be invoked from the refactoring menu, and +also benefit the existing features such as preview of refactoring results, +layout preservation, selective refactoring, undo of refactorings, etc, for free.
+ +The user-extensibility of Wrangler is achieved by introducing a new layer on top
+ of the existing low-level API which provides direct access to the details of syntactic
+ and semantic representation of the Erlang language. We call the new layer the
+ Wrangler API
. The Wrangler API
consists of three parts:
-- A template and rule based program analysis and transformation framework that +allows users to express their analysis and transformation in an intuitive and +concise way without diving into the details of internal program representation +used by the refactoring tool;
+ +-- A generic behaviour especially for refactoring encapsulates the generic parts + that are common to all refactorings, while the user only has to provide the + parts that are specific to the refactoring under consideration. See gen_refac.
+ +-- A collection of API functions, such as API functions for abstract syntax tree + traversal, API functions for retrieving context information from AST nodes, API + functions for mapping the textual selection of program source to its internal + representation (see api_interface), etc.
+ + Here are some macros that can be used to expression transformation rules and/or + information collectors: +
+ ?T(TemplateStr).
+ With Wrangler, a template is denoted by a Erlang macro ?T
whose only argument
+is the string representation of an Erlang code fragment that may contain meta-variables.
+The template code fragment can be a sequence of expressions, a function definition,
+an attribute, or a single function clause. As a convention, a template representing a
+function/attribute should always ends with a full stop; whereas a single function
+clause must end with a semicolon, otherwise it will be interpreted as an Erlang
+function consisting of a single function clause by default.
A meta-variable is a placeholder for a syntax element in the program, or a sequence of +syntax elements of the same kind. Templates syntactically are Erlang code, therefore +the use of meta-variables in a template must not violate the syntactic correctness of +the code fragment. Templates are matched at AST level, that is, the template's AST is +matched to the program's AST. A template consists of only a single meta-variable can +match any subtrees within the AST.
+ +Syntactically a meta-variable is an Erlang variable ending with the character @
.
+ Three kinds of meta-variables are supported:
+ -- A meta-variable ending with a single @
represents a single language element,
+and matches a single subtree in the AST. For example, a remote function call which
+a placeholder for the function name can be represented as:
?T("M:F@(1, 2)")
In the template above, variable M
is an object variable, and only matches an AST node
+ representing a variable of the same name; whereas F@
is a meta- variable,
+ and therefore matches any node that represents the function name part of a remote
+ function call module name is represented by variable M
, and arguments are literals
+ 1
and 2
.
-- A meta-variable ending with@
@
represents a list meta-variable
, which matches
+an arbitrary sequence of elements of the same sort, e.g. a list of arguments of a
+function calls, a sequence of expressions in a clause body, etc. For instance the
+template:
?T("spawn(Arg@
@
)")
matches the application of function spawn
to an arbitrary number of arguments, and
+ Arg@
@
is the place holder for the sequence of argument.
+As another example, the template
?T("spawn(Arg1@, Arg2@, Args@
@)")
will match the application of function spawn
to two or more arguments, where
+ Arg1@
and Arg2@
are placeholders for the first and second argument respectively,
+ and Args@
@
is the placeholder for the remaining arguments. If there is no more
+ remaining arguments, then Args@
@
is an empty list.
In order to template an arbitrary sequence of clauses, either function clauses or
+ expression clauses, we introduce a especial meta-variable which ends with @
@
@
.
+ A meta variable ending with @
@
@
is mapped to a list, each element of which is a
+list of subtrees of the same kind. For example, a case expression with an arbitrary
+number of clauses can be template as:
?T("case Expr@ of Pats@
@
@
when Guards
@
@
@
-> Body
@
@
@")
in which Pats@@
matches the collection of patterns from each clause of the case
+ expression in the same order; Body@@
matches the collection of body expressions
+ from each clause; and Guard@@
matches the collection of guards from each clause.
+In the case that a clause does not have a guard expression, its guard is represented
+as an empty list.
Meta-atoms
. Certain syntax elements in Erlang, such as the function name part of a
+ function definition, the record name/field in an record expression, etc, can only be
+ atoms, and cannot be replaced by a variable. In order to represent a placeholder for
+ this kind of atom-only
syntax elements, we introduce the notion of
+ meta-atom
, which acts as a place holder for a single atom. Syntactically, a
+ meta-atom is an Erlang atom ending with a single @
. For example, with the use of
+meta-atom, an arbitrary function clause can be templated as
?T("f@(Args@
@
)when Guard@
@
-> Body@
@;")
where f@
is a placeholder for the function name.
+ ?FUN_APPLY(M, F, A).
+ A special conditional meta-template which can be used to match with a function application
+ node, and check if this node represents the application of function M:F/A
in one of the
+ following formats: F(Args@
@
)
, F(Args@
@
)
, fun M:F/A(Args@
@
)
,
+ fun F/A(Args@
@
)
, apply(M, F, [Args@
@
])
and apply(M, F, Args@)
, or the use of function M:F/A
in
+ one of the following ways: spawn(N@, M, F, [Args@
@
])
,
+ spawn(N@
@
, M, F, Args@)
, spawn_link(N@
@
, M, F, [Args@
@
])
,
+ spawn_link(N@
@
, M, F, Args@)
, spawn:hibernate(N@
@
, M, F, [Args@
@
])
, erlang:hibernate(M, F, Args@)
,
+ spawn_monitor(N@
@
, M, F, [Args@
@
])
, spawn_monitor(M, F, Args@)
, and
+ spawn_opts(N@
@
, M, F, [Args@
@
],Opts@)
, and spawn_opts(N@
@
, M, F, Args@, Opts@)
.
+ ?RULE(Template, NewCode, Cond).
+ A conditional transformation rule is denoted by a macro ?RULE
. In
+ ?RULE(Template, NewCode, Cond)
, Template
is a template representing the kind
+ of code fragments to search for; Cond
is an Erlang expression that evaluates to
+ either true
or false
; and NewCode
is another Erlang expression that returns
+ the new code fragment. By means of parse transform, all the meta-variables, and also
+ meta-atoms, from the Template
, are make visible to NewCode
and Cond
, therefore
+can be referred by them.
A conditional transformation rule is always used with an AST traversal strategy. An
+ AST traversal strategy takes one or more conditional transformation rules, and an AST
+ as input. It walks through the AST in a specific order, and for each node it
+ encounters, the traversal strategy tries to pattern match the AST representation of
+ the Template
part of the first rule with the current node, if the pattern matching
+ succeeds, the Cond
part of the rule is then evaluated to check whether certain
+ properties are satisfied by the nodes that matches the meta-variables/meta-atoms.
+ The NewCode
part is executed only if the evaluation of Cond
returns true
, and
+ in that case, the current node is replaced with the AST generated by NewCode
, and
+ the traversal goes on after that. However, it the first rule is not applicable either
+ because the pattern matching fails, or the Cond
evaluates to false
, the next rule
+will be tried in the same way until no more rules is available, and the traversal
+will continue to other nodes in the AST.
NewCode
specifies the AST representation of the new code after
+ the transformation. While NewCode
should evaluate to an AST node, or a sequence of
+ AST nodes, the user does not have to compose the AST manually, instead the general
+ way is to create the string representation of the new code fragment, and use the
+ macro ?TO_AST
, which is also part of the Wrangler API, to turn the string
+ representation of a code fragment into its AST representation. All the
+ meta-variables/atoms bound in Template
are visible, and can be used by NewCode
,
+ and further more, it is also possible for NewCode
to define its own meta variables
+ as shown in the example below.
+ rule({M,F,A}, N) -> + ?RULE(?T("F@(Args@@)"), + begin + NewArgs@@=delete(N, Args@@), + ?TO_AST("F@(NewArgs@@)") + end, + api_refac:fun_define_info(F@) == {M, F, A}). + + delete(N, List) -> + lists:sublist(List, N-1)++ lists:nthtail(N, List).+ +
+?COLLECT(Template,Collector, Cond).
+ +?COLLECT is a macro used to collect information from code fragements that are
+ of interest. In ?COLLECT(Template,Collector, Cond)
, Template
is a template
+ representing the kind of code fragments to search for; Cond
is an Erlang expression
+ that evaluates to either true
or false
; and Collector
is an Erlang expression
+ which extract the information needed from the current node. Information is collected
+ when the AST representation of the template pattern matches the current AST node,
+ and Cond
evaluates to true
. As an example, the macro application shown below can
+ be used to collect those clause bodies, which an unnecessary match expression at the
+ end. This collector returns the location information of those clause bodies found.
+ Two special pre-defined meta-variables are used in this macro application. One is
+ _File@
, whose value is the file name of the source code to which the macro is
+ applied to, or none
is no such information is available; and the other one is
+ _This@
, whose value if the entire subtree that pattern matches the template.
?COLLECT(?T("Body@, V@=Expr@, V@"), + {_File@, api_refac:start_end_loc(_This@)}, + api_refac:type(V@)==variable)+ +
+?COLLECT_LOC(Template, Cond).
+ +A special case of ?COLLECT, which returns the location information of the AST node that +matches the template, as shown in the previous example. The code below functions the +same the example above.
+ +?COLLEC_LOC(?T("Body@, V@=Expr@, V@"), + api_refac:type(V@)==variable)+ +
+?EQUAL(Tree1, Tree2).
+ +Returns true
if Tree1
and Tree2
are syntactically the same up to normalization.
+The normalization process includes consistent variable renaming and turning un-qualified
+function calls into qualified function calls.
+?PP(Tree).
+ +Pretty-prints the AST Tree
, and returns the string representation.
+?MATCH(Template, Tree).
+ +Pattern matches the AST representation of Template
with the AST Tree
, and returns
+ false
if the pattern matching fails, and 'true' if succeeds.
+?FULL_TD_TP(Rules, Scope).
+ +Traverses the AST in a topdown order, and for each node apply the first rule that +succeeds; after a rule has been applied to a node, the subtrees of the node will +continued to be traversed.
+ ++?STOP_TD_TP(Rules, Scope).
+ + Traverses the AST in a topdown order, and for each node apply the first rule that + succeeds; after a rule has been applied to a node, the subtrees of the node will + not to be traversed. ++?STOP_TD_TU(Collectors, Scope).
+ + Traverses the AST in a topdown order, and for each node apply the collectors one by + one, and collects information returns by each collector. +add_to_export_after/3 | Adds an entity FAtoAdd to the export list of an export attribute
+ right after another entity FA ; if FA is none then append
+ the new entity to the end of the export list. |
bound_var_names/1 | Returns all the variable names that are declared within Node . |
bound_vars/1 | Returns all the variables, including both variable name and define
+ location, that are declared within Node . |
client_files/2 | Returns those files, included in SearchPaths , which use/import
+ some of the functions defined in File . |
defined_funs/1 | Returns all the functions that are defined by an Erlang file. |
env_var_names/1 | Returns all the variable names that are visible to Node . |
env_vars/1 | Returns all the variables, including both variable name and
+ define location, that are visible to Node . |
exported_funs/1 | Returns all the functions that are exported by an Erlang file. |
exported_var_names/1 | Returns all the variable names that are declared within Node , and
+ also used by the code outside Node . |
exported_vars/1 | Returns all the variables, including both variable name and define
+ location, that are declared within Node , and also used by the
+ code outside Node . |
free_var_names/1 | Returns all the variable names that are free within Node . |
free_vars/1 | Returns all the variables, including both variable name and define
+ location, that are free within Node . |
fun_define_info/1 | Returns the MFA information attached a node that represents a + function name or a qualified function name. |
get_app_args/1 | For a function application node that matches ?FUN_APPY(M,F,A) ,
+ get the part that represents the arguments to which the function F
+ is applied. |
get_app_fun/1 | For a function application node that matches ?FUN_APPY(M,F,A) ,
+ get the part that represents the function name. |
get_app_mod/1 | For a function application node that matches ?FUN_APPLY(M,F,A) ,
+ get the part that represents the module name if M appears in
+ the application; otherwise returns none . |
get_ast/1 | Returns the AST representation of an Erlang file. |
get_module_info/1 | Returns the module-level information about the Erlang file. |
imported_funs/1 | Returns all the functions that are (auto)imported by an Erlang file. |
imported_funs/2 | Returns all the functions that are imported from ModuleName by an Erlang file. |
inscope_funs/1 | Returns all the functions that are in-scope in the current module. |
insert_an_attr/2 | Inserts an attribute before the first function definition. |
is_attribute/2 | Returns true if Node represents an attribute
+ of name Name . |
is_behaviour_instance_of/2 | Returns true if the Erlang module
+ defined in File is a behaviour instance of the module Mod . |
is_exported/2 | Returns true if {FunName, Arity} is exported by the Erlang module
+ defined in File . |
is_expr/1 | Returns true if Node represents an expression (either a general
+ expression or a guard expression), otherwise false . |
is_fun_name/1 | Returns true if a string is lexically a legal function name,
+ otherwise false . |
is_guard_expr/1 | Returns true if Node represents a guard expression, otherwise false . |
is_import/2 | Returns true if Node represents an import attribute that
+ imports module ModName |
is_pattern/1 | Returns true if Node represents a pattern, otherwise false . |
is_var_name/1 | Returns true if a string is lexically a legal variable name,
+ otherwise false . |
make_new_name/2 | Generates a new name by appending "_1" to the end of the 'BaseName'
+ until the new name is not a member of UsedNames . |
mfa_to_fun_def/2 | Returns the function form that defines MFA ; none is returns if no
+ such function definition found. |
module_name/1 | Returns the name of the module defined in File ,. |
remove_from_import/2 | Removes F/A from the entity list of the import attribute
+ represented by Node . |
start_end_loc/1 | Returns the start and end locations of the code represented
+ by Tree in the source file. |
syntax_category/1 | Returns the syntax category of Node . |
syntax_context/1 | Returns the syntax context of Node . |
type/1 | The function is the same as erl_syntax:type/1. |
update_app_args/2 | Replaces the arguments of a function application node with Args . |
update_app_fun/2 | Replaces the function name part of a function application node with FunName . |
update_app_mod/2 | Replaces the module name part of a function application node with Modname . |
var_refs/1 | Returns all the locations where a variable is used, not including
+ the locations where the variable is bound, when Node represents
+ a variable, otherwise returns an empty list. |
variable_define_pos/1 | Returns the define location of the variable represented by Node ;
+ [{0,0}] is returned is the variable is a free variable or Node is
+ not properly annotated. |
add_to_export_after(Node::attribute(), FAtoAdd::{function(), arity()}, FA::{function(), arity()} | none) -> attribute()
Adds an entity FAtoAdd
to the export list of an export attribute
+ right after another entity FA
; if FA
is none
then append
+ the new entity to the end of the export list.
bound_var_names(Node::[syntaxTree()] | syntaxTree()) -> [atom()]
Returns all the variable names that are declared within Node
.
bound_vars(Node::[syntaxTree()] | syntaxTree()) -> [{atom(), pos()}]
Returns all the variables, including both variable name and define
+ location, that are declared within Node
.
client_files(File::filename(), SearchPaths::[filename() | dir()]) -> [filename()]
Returns those files, included in SearchPaths
, which use/import
+ some of the functions defined in File
.
defined_funs(File::filename()) -> [{atom(), integer()}]
Returns all the functions that are defined by an Erlang file.
+ +env_var_names(Node::syntaxTree()) -> [atom()]
Returns all the variable names that are visible to Node
.
env_vars(Node::syntaxTree()) -> [{atom(), pos()}]
Returns all the variables, including both variable name and
+ define location, that are visible to Node
.
exported_funs(File::filename()) -> [{atom(), integer()}]
Returns all the functions that are exported by an Erlang file.
+ +exported_var_names(Node::[syntaxTree()] | syntaxTree()) -> [atom()]
Returns all the variable names that are declared within Node
, and
+ also used by the code outside Node
.
exported_vars(Nodes::[syntaxTree()] | syntaxTree()) -> [{atom(), pos()}]
Returns all the variables, including both variable name and define
+ location, that are declared within Node
, and also used by the
+ code outside Node
.
free_var_names(Node::[syntaxTree()] | syntaxTree()) -> [atom()]
Returns all the variable names that are free within Node
.
free_vars(Node::[syntaxTree()] | syntaxTree()) -> [{atom(), pos()}]
Returns all the variables, including both variable name and define
+ location, that are free within Node
.
fun_define_info(Node::syntaxTree()) -> {modulename(), functionname(), arity()} | unknown
Returns the MFA information attached a node that represents a
+ function name or a qualified function name. unknown
is returned is
+ no MFA information is annotated to this node or Node
does not
+ represent a function name.
get_app_args(AppNode::syntaxTree()) -> [syntaxTree()] | syntaxTree()
For a function application node that matches ?FUN_APPY(M,F,A)
,
+ get the part that represents the arguments to which the function F
+ is applied. This function returns the arguments as a list of AST
+ nodes if the the function application matches one of those templates"
+ with Args@
@
, as specified in the documentation of ?FUN_APPY(M,F,A)
;
+ otherwise a single AST node.
get_app_fun(AppNode::syntaxTree()) -> syntaxTree()
For a function application node that matches ?FUN_APPY(M,F,A)
,
+ get the part that represents the function name.
get_app_mod(AppNode::syntaxTree()) -> syntaxTree() | none
For a function application node that matches ?FUN_APPLY(M,F,A)
,
+ get the part that represents the module name if M appears in
+ the application; otherwise returns none
.
get_ast(File::filename()) -> syntaxTree() | {error, errorInfo()}
Returns the AST representation of an Erlang file.
+ +get_module_info(File::filename()) -> {ok, module_info()}
Returns the module-level information about the Erlang file.
+ +imported_funs(File::filename()) -> [{modulename(), functionname(), integer()}]
Returns all the functions that are (auto)imported by an Erlang file.
+ +imported_funs(File::filename(), ModuleName::modulename()) -> [{functionname(), integer()}]
Returns all the functions that are imported from ModuleName
by an Erlang file.
inscope_funs(FileOrModInfo::filename() | module_info()) -> [{atom(), atom(), integer()}]
Returns all the functions that are in-scope in the current module. + An in-scope function could be an (auto-)imported function, or a + function that is defined in the current module.
+ +insert_an_attr(AST::syntaxTree(), Attr::attribute()) -> syntaxTree()
Inserts an attribute before the first function definition.
+ +is_attribute(Node::syntaxTree(), Name::atom()) -> boolean()
Returns true
if Node
represents an attribute
+ of name Name
.
is_behaviour_instance_of(Mod::atom(), File::string()) -> boolean()
Returns true if the Erlang module
+ defined in File
is a behaviour instance of the module Mod
.
is_exported(X1::{atom(), integer()}, FileOrModInfo::filename()) -> boolean()
Returns true if {FunName, Arity}
is exported by the Erlang module
+ defined in File
.
is_expr(Node::syntaxTree()) -> boolean()
Returns true
if Node
represents an expression (either a general
+ expression or a guard expression), otherwise false
.
is_fun_name(Name::string()) -> boolean()
Returns true
if a string is lexically a legal function name,
+ otherwise false
.
is_guard_expr(Node::syntaxTree()) -> boolean()
Returns true
if Node
represents a guard expression, otherwise false
.
is_import(Node::syntaxTree(), ModName::atom()) -> boolean()
Returns true
if Node
represents an import attribute that
+ imports module ModName
is_pattern(Node::syntaxTree()) -> boolean()
Returns true
if Node
represents a pattern, otherwise false
.
is_var_name(Name::string()) -> boolean()
Returns true
if a string is lexically a legal variable name,
+ otherwise false
.
make_new_name(BaseName::atom(), UsedNames::[atom()]) -> atom()
Generates a new name by appending "_1" to the end of the 'BaseName'
+ until the new name is not a member of UsedNames
.
mfa_to_fun_def(File::filename(), MFA::mfa()) -> syntaxTree() | none
Returns the function form that defines MFA
; none is returns if no
+ such function definition found.
module_name(File::filename()) -> {ok, modulename()} | {error, any()}
Returns the name of the module defined in File
,
remove_from_import(Node::attribute(), FA::{functionname(), arity()}) -> attribute()
Removes F/A
from the entity list of the import attribute
+ represented by Node
.
start_end_loc(Tree::[syntaxTree()] | syntaxTree()) -> {pos(), pos()}
Returns the start and end locations of the code represented
+ by Tree
in the source file.
syntax_category(Node::syntaxTree()) -> pattern | expression | guard_expression | unknown
Returns the syntax category of Node
.
syntax_context(Node::syntaxTree()) -> atom()
Returns the syntax context of Node
.
type(Node::syntaxTree()) -> atom()
The function is the same as erl_syntax:type/1. It returns the
+ type tag of Node
. If Node
+ does not represent a syntax tree, evaluation fails with reason
+ badarg
. Node types currently defined are:
+
application | +arity_qualifier | +atom | +attribute | +
binary | +binary_field | +block_expr | +case_expr | +
catch_expr | +char | +class_qualifier | +clause | +
comment | +cond_expr | +conjunction | +disjunction | +
eof_marker | +error_marker | +float | +form_list | +
fun_expr | +function | +generator | +if_expr | +
implicit_fun | +infix_expr | +integer | +list | +
list_comp | +macro | +match_expr | +module_qualifier | +
nil | +operator | +parentheses | +prefix_expr | +
qualified_name | +query_expr | +receive_expr | +record_access | +
record_expr | +record_field | +record_index_expr | +rule | +
size_qualifier | +string | +text | +try_expr | +
tuple | +underscore | +variable | +warning_marker | +
update_app_args(AppNode::syntaxTree(), Args::[syntaxTree()] | syntaxTree()) -> syntaxTree()
Replaces the arguments of a function application node with Args
.
+ The node AppNode
should match one of the templates specified ?FUN_APPY(M,F,A)
.
update_app_fun(AppNode::syntaxTree(), FunName::syntaxTree()) -> syntaxTree()
Replaces the function name part of a function application node with FunName
.
+ The node AppNode
should match one of the templates specified ?FUN_APPY(M,F,A)
.
update_app_mod(AppNode::syntaxTree(), ModName::syntaxTree()) -> syntaxTree()
Replaces the module name part of a function application node with Modname
.
+ The node AppNode
should match one of the templates specified by?FUN_APPY(M,F,A)
.
var_refs(Node::syntaxTree()) -> [pos()]
Returns all the locations where a variable is used, not including
+ the locations where the variable is bound, when Node
represents
+ a variable, otherwise returns an empty list.
variable_define_pos(Node::syntaxTree()) -> [pos()]
Returns the define location of the variable represented by Node
;
+ [{0,0}] is returned is the variable is a free variable or Node
is
+ not properly annotated.
Generated by EDoc, Nov 5 2015, 16:30:22.
+ + diff --git a/docs/doc/api_wrangler.html b/docs/doc/api_wrangler.html new file mode 100644 index 00000000..ae3041ad --- /dev/null +++ b/docs/doc/api_wrangler.html @@ -0,0 +1,112 @@ + + + + +Copyright © 2006-2011 Huiqing Li, Simon Thompson +
+ +Authors: Huiqing Li, Simon Thompson [web site: http://www.cs.kent.ac.uk/projects/wrangler].
+ +All refactorings commands should be run in the context of a Wrangler application. + Use api_wrangler:start() to start a Wrangler application, and api_wrangler:stop() to stop the + application. +
+copy_mod/3 | Copy a module. |
move_fun/5 | Move a function to another module. |
refac_bug_cond/1 | For QuickCheck only. |
rename_fun/5 | Rename a function. |
rename_mod/3 | Rename a module. |
similar_code/7 | Similar code detection. |
start/0 | Start a Wrangler application. |
stop/0 | Stop a Wrangler application. |
undo/0 | Undo the previous refactoring. |
copy_mod(ModOrFileName::modulename() | filename(), NewModName::modulename(), SearchPaths::[dir()]) -> {ok, FilesChanged::[filename()]} | {error, Reason}
Copy a module. +
This refactoring affects all those modules in which the module name is used, + and returns either ok with the list of files affected by this + refactoring, or an error message.
+ +move_fun(FromModOrFileName::modulename() | filename(), FunName::atom(), Arity::integer(), ToModOrFileName::modulename() | filename(), SearchPaths::[dir()]) -> {ok, FilesChanged::[filename()]} | {error, Reason}
Move a function to another module. +
This refactoring moves the function specified, together with functions that are only used + by the function to be moved, to the target module. This refactorings affects all those + modules in which the function to be moved is used, and returns either ok with the list of + files affected by this refactoring, or an error message. +
+ +refac_bug_cond(DirOrFileList::[filename() | dir()]) -> {ok, string()} | {error, term()}
For QuickCheck only.
+ +rename_fun(ModOrFileName::modulename() | filename(), FunName::atom(), Arity::integer(), NewFunName::atom(), SearchPaths::[dir()]) -> {ok, FilesChanged::[filename()]} | {error, Reason}
Rename a function. +
This refactoring affects all those modules in which the function renamed is + used, and returns either ok with the list of files affected by this + refactoring, or an error message. +
+ +rename_mod(ModorFileName::modulename() | filename(), NewModName::modulename(), SearchPaths::[dir()]) -> {ok, FilesChanged::[filename()]} | {error, Reason}
Rename a module. +
This refactoring affects all those modules in which the module name is used, + and returns either ok with the list of files affected by this + refactoring, or an error message.
+ +similar_code(DirFileList::[filename() | dir()], MinLen::integer(), MinToks::integer(), MinFreq::integer(), MaxVars::integer(), SimiScore::float(), SearchPaths::[dir()]) -> {ok, string()} | {error, Reason}
Similar code detection. +
A similar code detector which takes an Erlang project (or just a collection of Erlang files) and
+ a set of parameters as input, performs clone detection, and reports the clone classes found.
+ Five parameters, which are of a conjunction relation, can be specified so that the user can
+ have control of the granularity of the clone classes reported. These parameters are:
+ MinLen: the minimum number of expressions included in a code clone which is a sequence of expressions;
+ MinToks: the minimum number of tokens included in a code clone (minimum value: 20);
+ MinFreq: the minimum number of duplications of a cloned code fragment (minimum value: 2);
+ MaxVars: the maximum number of new parameters of the least-general common abstraction function;
+ SimiScore: the similarity score threshold which is between 0.1 and 1.0.
+
start() -> {ok, Pid} | {error, Reason}
Start a Wrangler application.
+ +stop() -> ok
Stop a Wrangler application.
+ +undo() -> {ok, FilesChanged::[filename()]} | {error, Reason}
Undo the previous refactoring. This only works within a Wrangler application.
+Generated by EDoc, Nov 5 2015, 16:30:22.
+ + diff --git a/docs/doc/behaviour_extraction/ast_tree.html b/docs/doc/behaviour_extraction/ast_tree.html new file mode 100644 index 00000000..687a8223 --- /dev/null +++ b/docs/doc/behaviour_extraction/ast_tree.html @@ -0,0 +1,274 @@ + + + + +Copyright © (C) 2015, Pablo Lamela, Simon Thompson
+ +Authors: Pablo Lamela Seijas (P.Lamela-Seijas@kent.ac.uk), Simon Thompson (S.J.Thompson@kent.ac.uk).
+ +ast_to_tree/5 | + Transforms a Syntax Tree into a tree with isolated nodes for + easier manipulation. |
breaks_funname/2 | + Returns true if separating Node from ParentNode (assuming ParentNode is the parent node of Node), + would separate a function call (in some form) from the indicator of the name/arity/module of + the destination function. |
get_file_name/1 | + Gets the filename from the tree metadata record. |
get_fun_name/2 | + If the node represents a function it returns a tuple with the + name of the function as a string and the arity as a number. |
get_inscope_funs/1 | + Gets the list of functions in scope from the tree metadata record. |
get_left_if_node_pair/1 | + Returns the left node if it is a node pair. |
get_macro_info/1 | + Parses the AST in Tree in order to extract information about the macros defined and + used. |
get_macros_list/1 | + Gets a list of the AST blocks containing macros and information about + the macros, records, and imports provided by them. |
get_module_info/1 | + Gets the module info from the tree metadata record. |
get_placeholders_from_node/1 | + Extracts placeholders from the node. |
get_right_if_node_pair/1 | + Returns the right node if it is a node pair. |
get_search_paths/1 | + Gets the list of paths in the search path from the tree metadata record. |
get_tab_width/1 | + Gets the tab width from the tree metadata record. |
is_a_function/1 |
+ It returns true if the node represents a function, otherwise
+ it returns false . |
is_expression_or_function/1 | + Checks the category of the Node and returns true if it is + "expression" or if the node is a function declaration. |
is_function_or_macro/1 | + Returns true if the node is a macro of a function application, + (for both its alternatives). |
reparse/1 | + Reparses the AST in Tree to renew its information (like attributes). |
replace_in_node/2 | + Replaces the list of nodes Replacements in the subtrees of Node. |
set_file_name/2 | + Sets the filename in the tree metadata record. |
set_inscope_funs/2 | + Sets the list of functions in scope in the tree metadata record. |
set_module_info/2 | + Sets the module info in the tree metadata record. |
set_search_paths/2 | + Sets the list of paths in the search path in the tree metadata record. |
set_tab_width/2 | + Sets the tab width in the tree metadata record. |
show_node/1 | + Transforms a node or node pair into a compact representation for debugging. |
tree_to_ast/1 | + Extracts an AST from a Tree that contains an AST. |
tree_to_ast/2 | + Extracts an AST from a Tree that contains an AST, taking Node as the root node. |
value/1 | + Returns a "semantic" representation of the node, (which is used for + comparing two nodes and decide if they can be mergerd). |
ast_to_tree(AST::wrangler_syntax:syntaxTree(), FileName::string(), ModuleInfo::[{atom(), term()}], SearchPaths::[string()], TabWidth::integer()) -> tree:tree()
+ Transforms a Syntax Tree into a tree with isolated nodes for + easier manipulation.
+ +breaks_funname(NodePair::tree:tree_node(), ParentNode::tree:tree_node()) -> boolean()
+ Returns true if separating Node from ParentNode (assuming ParentNode is the parent node of Node), + would separate a function call (in some form) from the indicator of the name/arity/module of + the destination function.
+ +get_file_name(Tree::tree:tree()) -> string()
+ Gets the filename from the tree metadata record.
+ +get_fun_name(Node::tree:tree_node(), Tree::tree:tree()) -> {ok, {string(), non_neg_integer()}} | error
+ If the node represents a function it returns a tuple with the + name of the function as a string and the arity as a number. + The Tree must match the node if exclusive or be the left tree + if common.
+ +get_inscope_funs(Tree::tree:tree()) -> [{atom(), atom(), integer()}]
+ Gets the list of functions in scope from the tree metadata record.
+ +get_left_if_node_pair(Node::tree:tree_node()) -> tree:tree_node()
+ Returns the left node if it is a node pair.
+ +get_macro_info(Tree::tree:tree()) -> {[{wrangler_syntax:syntaxTree(), term()}], [term()]}
+ Parses the AST in Tree in order to extract information about the macros defined and
+ used. It returns the macro information gathered by wrangler_epp:parse_file/5
.
get_macros_list(Tree::tree:tree()) -> [{MacroAST::wrangler_syntax:syntaxTree(), MacroInfo::[term()]}]
+ Gets a list of the AST blocks containing macros and information about + the macros, records, and imports provided by them.
+ +get_module_info(Tree::tree:tree()) -> [{atom(), term()}]
+ Gets the module info from the tree metadata record.
+ +get_placeholders_from_node(Nodes::Node) -> [PH] +
+ Extracts placeholders from the node. It may be a node pair or + a simple node. If it is a node pair it uses the left alternative. + It uses the wrangler_tools to accumulate them.
+ +get_right_if_node_pair(Node::tree:tree_node()) -> tree:tree_node()
+ Returns the right node if it is a node pair.
+ +get_search_paths(Tree::tree:tree()) -> [string()]
+ Gets the list of paths in the search path from the tree metadata record.
+ +get_tab_width(Tree::tree:tree()) -> integer()
+ Gets the tab width from the tree metadata record.
+ +is_a_function(Node::tree:tree_node()) -> boolean()
+ It returns true
if the node represents a function, otherwise
+ it returns false
.
is_expression_or_function(Node::tree:tree_node()) -> boolean()
+ Checks the category of the Node and returns true if it is + "expression" or if the node is a function declaration. + It returns false otherwise.
+ +is_function_or_macro(Node::tree:tree_node()) -> boolean()
+ Returns true if the node is a macro of a function application, + (for both its alternatives).
+ +reparse(Tree::tree:tree()) -> tree:tree()
+ Reparses the AST in Tree to renew its information (like attributes). It + copies the node properties stored in the previous node. It requires that + the AST topology before and after reparsing is the same.
+ +replace_in_node(Replacements::[wrangler_syntax:syntaxTree()], Node::wrangler_syntax:syntaxTree()) -> wrangler_syntax:syntaxTree()
+ Replaces the list of nodes Replacements in the subtrees of Node.
+ +set_file_name(FileName::string(), Tree::tree:tree()) -> tree:tree()
+ Sets the filename in the tree metadata record.
+ +set_inscope_funs(InscopeFuns::[{atom(), atom(), integer()}], Tree::tree:tree()) -> tree:tree()
+ Sets the list of functions in scope in the tree metadata record.
+ +set_module_info(ModuleInfo::[{atom(), term()}], Tree::tree:tree()) -> tree:tree()
+ Sets the module info in the tree metadata record.
+ +set_search_paths(SearchPaths::[string()], Tree::tree:tree()) -> tree:tree()
+ Sets the list of paths in the search path in the tree metadata record.
+ +set_tab_width(TabWidth::integer(), Tree::tree:tree()) -> tree:tree()
+ Sets the tab width in the tree metadata record.
+ +show_node(Node::tree:tree_node()) -> {{node, tree:tree_ph()} | {node_pair, tree:tree_ph(), tree:tree_ph()}, any()}
+ Transforms a node or node pair into a compact representation for debugging.
+ +tree_to_ast(Tree::tree:tree()) -> AST::wrangler_syntax:syntaxTree()
+ Extracts an AST from a Tree that contains an AST.
+ +tree_to_ast(Node::tree:tree_node(), Tree::tree:tree()) -> wrangler_syntax:syntaxTree()
+ Extracts an AST from a Tree that contains an AST, taking Node as the root node.
+ +value(Node::tree:tree_node()) -> any()
+ Returns a "semantic" representation of the node, (which is used for + comparing two nodes and decide if they can be mergerd).
+Generated by EDoc, Nov 5 2015, 16:30:19.
+ + diff --git a/docs/doc/behaviour_extraction/cluster.html b/docs/doc/behaviour_extraction/cluster.html new file mode 100644 index 00000000..bdc69005 --- /dev/null +++ b/docs/doc/behaviour_extraction/cluster.html @@ -0,0 +1,149 @@ + + + + +Copyright © (C) 2015, Pablo Lamela, Simon Thompson
+ +Authors: Pablo Lamela Seijas (P.Lamela-Seijas@kent.ac.uk), Simon Thompson (S.J.Thompson@kent.ac.uk).
+ +abstract datatype: cluster(NodeType)
+ + +get_nodes/1 | + Returns a set with all the nodes in the Cluster. |
get_root/1 | + Returns the root node of the Cluster. |
has_node/2 | + Returns a boolean that indicates whether the Cluster contains the Node. |
is_indirection_cluster/1 | + Returns whether the cluster is an indirection "fake" cluster or not. |
make_indirection_cluster/0 | + Creates an indirection "fake" cluster. |
merge_clusters/2 |
+ Takes two clusters and returns a new cluster containing all the nodes or the
+ atom disjoint if they have no common nodes. |
new_cluster/1 | + Creates a cluster with a single node. |
new_parent_child_to_cluster/2 | + Creates a cluster with a Node and its ParentNode. |
remove_split/2 | + Removes the Node from the Cluster an returns the resulting subclusters created, + (those that were hold together by the removed node). |
show_cluster/1 | + Returns a more readable version of custers. |
show_cluster/2 | + Returns a more readable version of custers and takes a function + that is suppoused to make the nodes in the clusters more readable. |
size/1 | + Returns the number of nodes that the cluster has. |
get_nodes(Cluster::cluster(NodeType)) -> [NodeType]
+ Returns a set with all the nodes in the Cluster.
+ +get_root(Cluster::cluster(NodeType)) -> OutNode::NodeType
+ Returns the root node of the Cluster.
+ +has_node(Node::NodeType, Cluster::cluster(NodeType)) -> boolean() +
+ Returns a boolean that indicates whether the Cluster contains the Node.
+ +is_indirection_cluster(X1::cluster(term())) -> false | {true, reference()}
+ Returns whether the cluster is an indirection "fake" cluster or not.
+ +make_indirection_cluster() -> {reference(), cluster(term())}
+ Creates an indirection "fake" cluster.
+ +
+ Takes two clusters and returns a new cluster containing all the nodes or the
+ atom disjoint
if they have no common nodes. It assumes that the clusters
+ contain subtrees that belong to global tree, and, as such, nor the individual
+ clusters nor the result cluster should contain any loops, and no node should
+ have several parents.
new_cluster(Node::NodeType) -> cluster(NodeType)
+ Creates a cluster with a single node.
+ +new_parent_child_to_cluster(Node::N, Node::N) -> cluster(N) +
+ Creates a cluster with a Node and its ParentNode.
+ ++ Removes the Node from the Cluster an returns the resulting subclusters created, + (those that were hold together by the removed node).
+ +show_cluster(Clus::cluster(term())) -> #{}
+ Returns a more readable version of custers. This is done by + transforming dicts and sets into lists.
+ +show_cluster(Fun::fun((NodeType) -> any()), Cluster::cluster(NodeType)) -> #{}
+ Returns a more readable version of custers and takes a function + that is suppoused to make the nodes in the clusters more readable. + This is done by transforming dicts and sets into lists and by + applying the supplied function to the nodes.
+ +size(Cluster::cluster(term())) -> non_neg_integer()
+ Returns the number of nodes that the cluster has.
+Generated by EDoc, Nov 5 2015, 16:30:19.
+ + diff --git a/docs/doc/behaviour_extraction/cluster_dict.html b/docs/doc/behaviour_extraction/cluster_dict.html new file mode 100644 index 00000000..3765abcf --- /dev/null +++ b/docs/doc/behaviour_extraction/cluster_dict.html @@ -0,0 +1,109 @@ + + + + +Copyright © (C) 2015, Pablo Lamela, Simon Thompson
+ +Authors: Pablo Lamela Seijas (P.Lamela-Seijas@kent.ac.uk), Simon Thompson (S.J.Thompson@kent.ac.uk).
+ +abstract datatype: cluster_dict(Node)
+ + +extract_trivial_clusters/1 | + Removes clusters with only one node from the cluster dictionary. |
get_cluster_for_node/2 | + Finds the cluster that has the Node in the ClusterDict. |
growing_map_fold/3 | + Mapfolds a function through a clusters dictionary. |
merge_cluster/2 | + Adds a Cluster to the ClusterDict and merges the new Cluster with + the clusters with common nodes in ClusterDict. |
new/0 | + Creates a new empty cluster dictionary. |
show_cluster_dict/1 | + Returns a more readable version of custer dictionaries. |
show_cluster_dict/2 | + Returns a more readable version of custer dictionaries and takes + a function that is suppoused to make the nodes in the clusters + more readable. |
extract_trivial_clusters(Cluster_dict::cluster_dict(NodeType)) -> {[cluster:cluster(NodeType)], cluster_dict(NodeType)}
+ Removes clusters with only one node from the cluster dictionary. + It returns a list with the removed clusters.
+ +get_cluster_for_node(Node::N, Cluster_dict::cluster_dict(N)) -> {ok, Cluster::cluster:cluster(N)} | error
+ Finds the cluster that has the Node in the ClusterDict.
+ +growing_map_fold(Fun::fun((cluster:cluster(N), Acc) -> {[cluster:cluster(N)], none | cluster:cluster(N), Acc}), Acc, Cluster_dict::cluster_dict(N)) -> {cluster_dict(N), Acc}
+ Mapfolds a function through a clusters dictionary. As opposed to the
+ traditional mapfold, this one expects an extra element in the
+ returned tuple, (the first one), which specifies which new clusters
+ must be map_folded later, (in addition to the original ones
+ from the cluster dictionary). The updated cluster (second element of
+ the tuple returned by the function), can be the atom none
, this
+ means that the Cluster will not be in the resulting list.
merge_cluster(Cluster::cluster:cluster(N), ClusterDict::cluster_dict(N)) -> cluster_dict(N)
+ Adds a Cluster to the ClusterDict and merges the new Cluster with + the clusters with common nodes in ClusterDict.
+ +new() -> cluster_dict(any())
+ Creates a new empty cluster dictionary.
+ +show_cluster_dict(Clus::cluster_dict(term())) -> #{}
+ Returns a more readable version of custer dictionaries. This + is done by transforming dicts and sets into lists.
+ +show_cluster_dict(Fun::fun((NodeType) -> any()), Cluster_dict::cluster_dict(NodeType)) -> #{}
+ Returns a more readable version of custer dictionaries and takes + a function that is suppoused to make the nodes in the clusters + more readable. This is done by transforming dicts and sets into + lists and by applying the supplied function to the nodes.
+Generated by EDoc, Nov 5 2015, 16:30:18.
+ + diff --git a/docs/doc/behaviour_extraction/cluster_folding.html b/docs/doc/behaviour_extraction/cluster_folding.html new file mode 100644 index 00000000..e345b307 --- /dev/null +++ b/docs/doc/behaviour_extraction/cluster_folding.html @@ -0,0 +1,301 @@ + + + + +Copyright © (C) 2015, Pablo Lamela, Simon Thompson
+ +Authors: Pablo Lamela Seijas (P.Lamela-Seijas@kent.ac.uk), Simon Thompson (S.J.Thompson@kent.ac.uk).
+ +acc() = #acc{cluster_labels = da_map:da_map({comm | {ex, 1 | 2}, string()}, cluster:cluster(tree:tree_node())), exp_funs = sets:set({atom(), integer()})}
+Record for use as accumulator when folding through cluster borders. + Contains the following fields:
ph_map
- maps PH (tree place holders) to pairs
+ {symmetric_type, cluster_name}
+ (for creating function calls) cluster_order
- maps pairs {order_type, position} to
+ clusters (function) names cluster_labels
- da_maps (function) names to clusters cluster_info
- maps (function) names to records
+ with information about the cluster
+ (cluster_info
records) cluster_funname
- maps generated (function) names to the actual
+ name that should be displayed in the file cluster_orifunname
- maps generated (function) names to the original
+ name that it was suppoused to have cluster_dicts
- contains the cluster dictionaries
+ (cluster_dict
record) allocated_parents
- saves a set with the parents of clusters
+ whose name will be assigned by a common
+ cluster. This is checked in a first pass
+ so that we minimise the numbre of dummy
+ functions needed to balance exclusive
+ clusters tree_info
- contains the trees and the mapping
+ (tree_info
record) exp_funs
- set with the local functions to export counters
- contains counters for function_name generation
+ (counters
record) out_module
- contains the output module name
+ as an atom var_for_module
- name for the var that contains the
+ module instance name, (guaranteed to
+ be unique for both modules) root_for_new_exclusive_funnames
- prefix for the name of the generated
+ functions in exclusive modules, (all
+ existing functions are guaranteed to
+ not start by this prefix) root_for_new_common_funnames
- prefix for the name of the generated
+ functions in common module, (all existing
+ functions are guaranteed to not start by
+ this prefix) cluster_counters() = #cluster_counters{}
+Record that keeps counters used for naming + functions and ordering them in the files. + Contains the following fields:
invisible_counter
- Contains the counter for the
+ label identifiers used when the
+ used label is already provided
+ by the user common_counter
- Contains the counter for the
+ labels of the common cluster common_pos_counter
- Contains the counter for the
+ order of the common cluster exclusive_counter
- Contains the counter for the
+ labels of the exclusive
+ cluster exclusive_pos_counter_1
- Contains the counter for the
+ order of the left exclusive
+ clusters exclusive_pos_counter_2
- Contains the counter for the
+ order of the right exclusive
+ clusters cluster_dicts() = #cluster_dicts{comm_clus = cluster_dict:cluster_dict(tree:tree_node()), ex_clus1 = cluster_dict:cluster_dict(tree:tree_node()), ex_clus2 = cluster_dict:cluster_dict(tree:tree_node())}
+Record for keeping the updated cluster dictionaries. + Contains the following fields:
comm_clus
- Contains the cluster dictionary
+ with the common clusters ex_clus1
- Contains the cluster dictionary with
+ the exclusive clusters of side one ex_clus2
- Contains the cluster dictionary with
+ the exclusive clusters of side twocluster_info() = #cluster_info{}
+Record for keeping information about a particular + cluster. Contains the following fields:
cluster_type
- Whether the cluster is common,
+ exclusive1, or exclusive2 environment_info
- Contains information like the free
+ and bounded variables at the root
+ of the cluster, (environment_info
+ record) environment_info() = #environment_info{}
+Record that contains environment information + like the free and bound variables at the root + of a cluster. Contains the following fields:
free_variables
- Contains a list with
+ variables that are freefree_left
- Contains a list with variables
+ that were free in the left treefree_right
- Contains a list with variables
+ that were free in the left treeexport_variables
- Contains a list with
+ variables that are exportedexport_left
- Contains a list with variables
+ that are exported by the left treeexport_right
- Contains a list with variables
+ that are exported by the left treeis_left_leaf
- Weather the cluster has children
+ from left side (in another cluster)is_right_leaf
- Weather the cluster has children
+ from right side (in another cluster)tree_info() = #tree_info{tree1 = tree:tree(), tree2 = tree:tree(), tree1_args = dict:dict({FunName::string(), Arity::non_neg_integer()}, [ArgName::string()]), tree2_args = dict:dict({FunName::string(), Arity::non_neg_integer()}, [ArgName::string()]), mapping = da_map:da_map(tree:tree_node(), tree:tree_node())}
+Record for keeping the tree and mapping information. + Contains the following fields:
tree1
- Contains the cluster dictionary
+ with the common clusters tree2
- Contains the cluster dictionary with
+ the exclusive clusters of side one tree1_args
- Contains a dictionary with good names
+ for function arguments of tree1 tree2_args
- Contains a dictionary with good names
+ for funciton arguments of tree2 mapping
- Contains the cluster dictionary with
+ the exclusive clusters of side twofind_actual_exported_vars_for_asym_label/3 | + Gets the exported variables for the top node of the cluster linked to AsymLabel, + considering only the tree specified by Pos. |
find_actual_free_vars_for_asym_label/3 | + Gets the free variables for the top node of the cluster linked to AsymLabel, + considering only the tree specified by Pos. |
find_exported_vars_for_sym_label/3 | + Gets the exported variables for the top nodes of the clusters linked to + the Name, with type SymType. |
find_free_vars_for_sym_label/3 | + Gets the free variables for the top nodes of the clusters linked to the Name, + with type SymType. |
fold_clusters/4 | + Folds a function through the frontiers of the clusters in roughly + breadth first order. |
get_children_from_node_list/5 | + Gets all the children for a list of nodes and maps them to + the placeholders on the nodes, (their left alternative if common). |
get_frontier_children_from_node_list/5 | + Gets all the children for a list of nodes and maps them to + the placeholders on the nodes, (their left alternative if common). |
get_leaf_as_is_or_default/3 | + Obtains information about whether the cluster is a leaf or not. |
get_type_list/2 | + Returns a list with the correspondence of types, clusters, and trees. |
is_in_scope/4 | + Returns true if the function specified (Name and Arity) is in + both of sets of inscope functions (Inscope1 and Inscope2), or + false if it is in none. |
isolate_type_class/1 | + Returns the symmetric cluster type. |
merge_environments/2 | + Merges the list of free vars of two nodes. |
find_actual_exported_vars_for_asym_label(AsymLabel::{ClustType, string()}, Pos::1 | 2, Acc::cluster_folding:acc()) -> [string()] +
+ Gets the exported variables for the top node of the cluster linked to AsymLabel, + considering only the tree specified by Pos. + It first tries to get them from Acc, otherwise it infers it from the node itself.
+ +find_actual_free_vars_for_asym_label(AsymLabel::{ClustType, string()}, Pos::1 | 2, Acc::cluster_folding:acc()) -> [string()] +
+ Gets the free variables for the top node of the cluster linked to AsymLabel, + considering only the tree specified by Pos. + It first tries to get them from Acc, otherwise it infers it from the node itself.
+ +find_exported_vars_for_sym_label(SymType::comm | ex, Name::string(), Name::cluster_folding:acc()) -> [string()]
+ Gets the exported variables for the top nodes of the clusters linked to + the Name, with type SymType. It first tires to get them from Acc, + otherwise it infers it from the nodes themselves.
+ +find_free_vars_for_sym_label(SymType::comm | ex, Name::string(), Name::cluster_folding:acc()) -> [string()]
+ Gets the free variables for the top nodes of the clusters linked to the Name, + with type SymType. It first tires to get them from Acc, otherwise it infers + it from the nodes themselves.
+ +fold_clusters(Fun, AccIn::Acc, ClustInfo, TreeInfo) -> AccOut::Acc +
+ Folds a function through the frontiers of the clusters in roughly + breadth first order. + The arguments of the function are:
ClusType
- A symbol that represents the type the of
+ upper cluster of the frontier PH
- The place holder of the frontier Children
- A list of alternative nodes corresponding
+ to the place holder of the frontier Acc0
- The accumulator of the folding get_children_from_node_list(ClustType, Cluster, Tree, TreeInfo, Nodes::[Node]) -> [{PH, Children}] +
+ Gets all the children for a list of nodes and maps them to + the placeholders on the nodes, (their left alternative if common).
+ +get_frontier_children_from_node_list(ClustType, Cluster, Tree, TreeInfo, Nodes::[Node]) -> [{PH, Children}] +
+ Gets all the children for a list of nodes and maps them to + the placeholders on the nodes, (their left alternative if common). + It only gets the children that are in a different cluster, not the ones + that are in the same.
+ +get_leaf_as_is_or_default(AsymLabel::{ClustType, string()}, Pos::1 | 2, Acc::cluster_folding:acc()) -> boolean() +
+ Obtains information about whether the cluster is a leaf or not. If the + information is no there it defaults to false.
+ +get_type_list(ClustInfo::cluster_dicts(), TreeInfo::tree_info()) -> [{ClustType, ClusterDict, Tree | na}] +
+ Returns a list with the correspondence of types, clusters, and trees. + This can be used to find in which cluster and in which tree a node is.
+ +is_in_scope(Name, Arity, Inscope1::sets:set({Name, Arity}), Inscope2::sets:set({Name, Arity})) -> boolean()
+ Returns true if the function specified (Name and Arity) is in + both of sets of inscope functions (Inscope1 and Inscope2), or + false if it is in none. This implementation does not contemplate + that it may be in scope for one and not inscope for another, since + that would cause wrong behaviour in the common module.
+ +isolate_type_class(ClustType) -> SymmetricType +
+ Returns the symmetric cluster type. That is, removes the information + about which exclusive cluster it is.
+ +merge_environments(Env1::[string()], Env2::[string()]) -> [string()]
+ Merges the list of free vars of two nodes. It removes the repeated + ones.
+Generated by EDoc, Nov 5 2015, 16:30:19.
+ + diff --git a/docs/doc/behaviour_extraction/cluster_linking.html b/docs/doc/behaviour_extraction/cluster_linking.html new file mode 100644 index 00000000..be33341b --- /dev/null +++ b/docs/doc/behaviour_extraction/cluster_linking.html @@ -0,0 +1,67 @@ + + + + +Copyright © (C) 2015, Pablo Lamela, Simon Thompson
+ +Authors: Pablo Lamela Seijas (P.Lamela-Seijas@kent.ac.uk), Simon Thompson (S.J.Thompson@kent.ac.uk).
+ +get_actual_name/2 | + Get the name that the function with name Name is supposed + to have. |
get_original_name/2 | + Gets the original name that the function with name Name had. |
link_clusters/6 | + It links the clusters so as to keep the relationships in the original + trees, while keeping the calls to exclusive clusters (from common cluster) + symmetrical, and keeping the number of artifacts used to a minimum. |
get_actual_name(Name::string(), Acc::cluster_folding:acc()) -> string()
+ Get the name that the function with name Name is supposed + to have.
+ +get_original_name(Name::string(), Acc::cluster_folding:acc()) -> string()
+ Gets the original name that the function with name Name had.
+ +link_clusters(ClusterDict, ClusterDict, ClusterDict, Tree, Tree, Mapping) -> cluster_folding:acc() +
+ It links the clusters so as to keep the relationships in the original + trees, while keeping the calls to exclusive clusters (from common cluster) + symmetrical, and keeping the number of artifacts used to a minimum. + It accumulates all information in an #acc{} record that should be enough + to generate the three trees directly.
+Generated by EDoc, Nov 5 2015, 16:30:19.
+ + diff --git a/docs/doc/behaviour_extraction/cluster_mapping.html b/docs/doc/behaviour_extraction/cluster_mapping.html new file mode 100644 index 00000000..a0931d7f --- /dev/null +++ b/docs/doc/behaviour_extraction/cluster_mapping.html @@ -0,0 +1,68 @@ + + + + +Copyright © (C) 2015, Pablo Lamela, Simon Thompson
+ +Authors: Pablo Lamela Seijas (P.Lamela-Seijas@kent.ac.uk), Simon Thompson (S.J.Thompson@kent.ac.uk).
+ +col_data() = #col_data{beh_funcs = sets:set({atom(), integer()}), module_info1 = sets:set({atom(), integer()}), module_info2 = sets:set({atom(), integer()}), inscope_funs1 = [{atom(), atom(), integer()}], inscope_funs2 = [{atom(), atom(), integer()}], var_for_module = string()}
+Record for use as accumulator when mapping clusters. + It collects global information about the generated + modules. + Contains the following fields:
beh_funcs
- contains the list of functions
+ that form the behaviour and must
+ be exported by instances module_info1
- contains the information returned
+ by the parser for the left tree module_info2
- contains the information returned
+ by the parser for the right tree inscope_funs1
- contains a list with the functions
+ that do not need qualified calls from
+ the left module {Mod, Fun, Arity}inscope_funs2
- contains a list with the functions
+ that do not need qualified calls from
+ the right module {Mod, Fun, Arity}var_for_module
- name for the var that contains the
+ module instance name, (guaranteed to
+ be unique for both modules) clusters_to_ast/2 | + It generates three ASTs, one for each cluster dictionary. |
clusters_to_ast(Acc::cluster_folding:acc(), OutModule::atom()) -> [wrangler_syntax:syntaxTree()]
+ It generates three ASTs, one for each cluster dictionary.
+Generated by EDoc, Nov 5 2015, 16:30:18.
+ + diff --git a/docs/doc/behaviour_extraction/da_map.html b/docs/doc/behaviour_extraction/da_map.html new file mode 100644 index 00000000..dd0df70d --- /dev/null +++ b/docs/doc/behaviour_extraction/da_map.html @@ -0,0 +1,161 @@ + + + + +Copyright © (C) 2015, Pablo Lamela, Simon Thompson
+ +Authors: Pablo Lamela Seijas (P.Lamela-Seijas@kent.ac.uk), Simon Thompson (S.J.Thompson@kent.ac.uk).
+ +abstract datatype: da_map(Key, Value)
+ + +delete_by_key/2 | + Remove the entry with Key as key from the DaMap if it exists. |
delete_by_value/2 | + Remove the entry with Value as value from the DaMap if it exists. |
find_key/2 |
+ Returns {ok, Key} if there is an entry with Value as value
+ in the da_map, returns error otherwise. |
find_value/2 |
+ Returns {ok, Value} if there is an entry with Key as key in
+ the da_map, returns error otherwise. |
fold/3 | + Folds the function Fun through all the entries of the DaMap. |
has_key/2 | + Returns true if there is an entry with Key as key in the da_map, + returns false otherwise. |
has_pair/3 | + Returns true if there is an entry with Key as key and Value as + value in the DaMap, returns false otherwise. |
has_value/2 | + Returns true if there is an entry with Value as value in the + DaMap, returns false otherwise. |
new/0 | + It creates an empty da_map. |
put/3 | + Stores an entry with Key as key and Value as value in the DaMap. |
size/1 | + Returns the number of entries of the DaMap. |
union/2 | + Joins DaMap1 and DaMap2 by inserting all the entries of DaMap2 in + DaMap1. |
+ Remove the entry with Key as key from the DaMap if it exists.
+ +delete_by_value(Value, DaMap::da_map(Key, Value)) -> da_map(Key, Value) +
+ Remove the entry with Value as value from the DaMap if it exists.
+ +find_key(Value, DaMap::da_map(Key, Value)) -> {ok, Key} | error +
+ Returns {ok, Key}
if there is an entry with Value as value
+ in the da_map, returns error
otherwise.
find_value(Key, DaMap::da_map(Key, Value)) -> {ok, Value} | error +
+ Returns {ok, Value}
if there is an entry with Key as key in
+ the da_map, returns error
otherwise.
fold(Fun, AccIn::Acc, DaMap::da_map(Key, Value)) -> AccOut::Acc +
+ Folds the function Fun through all the entries of the DaMap.
+See also: dict:fold/3.
+ +has_key(Key, DaMap::da_map(Key, any())) -> boolean() +
+ Returns true if there is an entry with Key as key in the da_map, + returns false otherwise.
+ +has_pair(Key, Value, DaMap::da_map(Key, Value)) -> boolean() +
+ Returns true if there is an entry with Key as key and Value as + value in the DaMap, returns false otherwise.
+ +has_value(Value, DaMap::da_map(any(), Value)) -> boolean() +
+ Returns true if there is an entry with Value as value in the + DaMap, returns false otherwise.
+ +new() -> da_map(any(), any())
+ It creates an empty da_map.
+ ++ Stores an entry with Key as key and Value as value in the DaMap. + It removes all existing entries with Key as key or Value as value.
+ +size(DaMap::da_map(any(), any())) -> non_neg_integer()
+ Returns the number of entries of the DaMap.
+ +union(DaMap1::da_map(Key, Value), DaMap2::da_map(Key, Value)) -> da_map(Key, Value) +
throws da_maps_not_disjoint
++ Joins DaMap1 and DaMap2 by inserting all the entries of DaMap2 in + DaMap1. It assumes DaMap1 and DaMap2 are disjoint in terms of both + their keys and their values. It throws da_maps_not_disjoint if + DaMap1 and DaMap2 are not disjoint in terms of keys or values.
+Generated by EDoc, Nov 5 2015, 16:30:19.
+ + diff --git a/docs/doc/behaviour_extraction/erlang.png b/docs/doc/behaviour_extraction/erlang.png new file mode 100644 index 00000000..987a618e Binary files /dev/null and b/docs/doc/behaviour_extraction/erlang.png differ diff --git a/docs/doc/behaviour_extraction/fix_frontiers.html b/docs/doc/behaviour_extraction/fix_frontiers.html new file mode 100644 index 00000000..04ca9f65 --- /dev/null +++ b/docs/doc/behaviour_extraction/fix_frontiers.html @@ -0,0 +1,67 @@ + + + + +Copyright © (C) 2015, Pablo Lamela, Simon Thompson
+ +Authors: Pablo Lamela Seijas (P.Lamela-Seijas@kent.ac.uk), Simon Thompson (S.J.Thompson@kent.ac.uk).
+ +delete_trivial_clusters/1 | + Removes from the CommClusterDict and detaches from the Mapping every + cluster with a single node in it. |
fix_frontiers/5 | + Moves the frontiers of the clusters to places where function + calls can be used to divide the trees. |
node_exports_vars/2 | + Returns true if either Node (assumed to belong to Tree), exports + variables. |
delete_trivial_clusters(X1::{CommClusterDict::cluster_dict:cluster_dict(tree:tree_node()), Mapping::da_map:da_map(tree:tree_node(), tree:tree_node())}) -> {cluster_dict:cluster_dict(tree:tree_node()), da_map:da_map(tree:tree_node(), tree:tree_node())}
+ Removes from the CommClusterDict and detaches from the Mapping every + cluster with a single node in it.
+ +fix_frontiers(Pass::1 | 2, Tree1::tree:tree(), Tree2::tree:tree(), Mapping::da_map:da_map(tree:tree_node(), tree:tree_node()), CommCluster::cluster_dict:cluster_dict(tree:tree_node())) -> {cluster_dict:cluster_dict(tree:tree_node()), da_map:da_map(tree:tree_node(), tree:tree_node())}
+ Moves the frontiers of the clusters to places where function
+ calls can be used to divide the trees.
+ This function updates both the Mapping and the CommCluster
+ dictionary. The right exclusive clusters are generated from the
+ fixed Mapping at tree_clustering:cluster/3
node_exports_vars(Node::tree:tree_node(), Tree::tree:tree()) -> boolean()
+ Returns true if either Node (assumed to belong to Tree), exports + variables.
+Generated by EDoc, Nov 5 2015, 16:30:19.
+ + diff --git a/docs/doc/behaviour_extraction/fun_blocks.html b/docs/doc/behaviour_extraction/fun_blocks.html new file mode 100644 index 00000000..89e149b5 --- /dev/null +++ b/docs/doc/behaviour_extraction/fun_blocks.html @@ -0,0 +1,71 @@ + + + + +Copyright © (C) 2015, Pablo Lamela, Simon Thompson
+ +Authors: Pablo Lamela Seijas (P.Lamela-Seijas@kent.ac.uk), Simon Thompson (S.J.Thompson@kent.ac.uk).
+ +add_blocks_to_trees/6 | + Searches for functions with several consecutive mapped/unmapped + children in the frontier and groups them into block expressions. |
create_artificial_block_value/2 | + Creates a block expression with ChildrenPHs as subtrees and + sets the position and the range to something useful. |
get_body/1 | + Returns the body of a clause or block expression (ClauseOrBlock). |
replace_children_in_body/3 | + Replaces the old subtrees (OldChildren) in the body of NodeValue + with the new subtrees (NewChildren), leaving the rest untouched. |
add_blocks_to_trees(LeftTree::tree:tree(), RightTree::tree:tree(), Mapping::da_map:da_map(tree:tree_node(), tree:tree_node()), CommCluster::cluster_dict:cluster_dict(tree:tree_node()), ExLeftClus::cluster_dict:cluster_dict(tree:tree_node()), ExRightClus::cluster_dict:cluster_dict(tree:tree_node())) -> {tree:tree(), tree:tree()}
+ Searches for functions with several consecutive mapped/unmapped + children in the frontier and groups them into block expressions.
+ +create_artificial_block_value(Tree::tree:tree(), ChildrenPHs::[tree:tree_ph()]) -> wrangler_syntax:syntaxTree()
+ Creates a block expression with ChildrenPHs as subtrees and + sets the position and the range to something useful.
+ +get_body(ClauseOrBlock::wrangler_syntax:syntaxTree()) -> [wrangler_syntax:syntaxTree()]
+ Returns the body of a clause or block expression (ClauseOrBlock).
+ +replace_children_in_body(OldChildren::[El], NewChildren::[El], NodeValue::wrangler_syntax:syntaxTree()) -> wrangler_syntax:syntaxTree()
+ Replaces the old subtrees (OldChildren) in the body of NodeValue + with the new subtrees (NewChildren), leaving the rest untouched. + It assumes that the node (NodeValue) is a clause or a block expression.
+Generated by EDoc, Nov 5 2015, 16:30:18.
+ + diff --git a/docs/doc/behaviour_extraction/fun_blocks_fix.html b/docs/doc/behaviour_extraction/fun_blocks_fix.html new file mode 100644 index 00000000..48b1134c --- /dev/null +++ b/docs/doc/behaviour_extraction/fun_blocks_fix.html @@ -0,0 +1,43 @@ + + + + +Copyright © (C) 2015, Pablo Lamela, Simon Thompson
+ +Authors: Pablo Lamela Seijas (P.Lamela-Seijas@kent.ac.uk), Simon Thompson (S.J.Thompson@kent.ac.uk).
+ +export_variables/3 | + Removes blocks that are expected to return and export variables + at the same time. |
export_variables(LeftTree::tree:tree(), RightTree::tree:tree(), Mapping::da_map:da_map(tree:tree_node(), tree:tree_node())) -> {Tree::tree:tree(), Tree::tree:tree()}
+ Removes blocks that are expected to return and export variables + at the same time. If possible it will just remove the last + item from the blocks.
+Generated by EDoc, Nov 5 2015, 16:30:19.
+ + diff --git a/docs/doc/behaviour_extraction/index.html b/docs/doc/behaviour_extraction/index.html new file mode 100644 index 00000000..eabafe6c --- /dev/null +++ b/docs/doc/behaviour_extraction/index.html @@ -0,0 +1,18 @@ + + + +Copyright © (C) 2015, Pablo Lamela, Simon Thompson
+ +Authors: Pablo Lamela Seijas (P.Lamela-Seijas@kent.ac.uk), Simon Thompson (S.J.Thompson@kent.ac.uk).
+ +infer_behaviour/6 | + Takes two input files (LeftFile and RightFile) and an output + file (OutputFile), and tries to create a behaviour definition in + OutputFile with the common parts of the inputs files while + transforming the input files into behaviour instances of OutputFile. |
infer_behaviour(LeftFile::string(), RightFile::string(), OutputFile::string(), SearchPaths::[string()], Editor::atom(), TabWidth::non_neg_integer()) -> {ok, [any()]}
+ Takes two input files (LeftFile and RightFile) and an output + file (OutputFile), and tries to create a behaviour definition in + OutputFile with the common parts of the inputs files while + transforming the input files into behaviour instances of OutputFile.
+Generated by EDoc, Nov 5 2015, 16:30:19.
+ + diff --git a/docs/doc/behaviour_extraction/local_fix.html b/docs/doc/behaviour_extraction/local_fix.html new file mode 100644 index 00000000..ac5454e4 --- /dev/null +++ b/docs/doc/behaviour_extraction/local_fix.html @@ -0,0 +1,54 @@ + + + + +Copyright © (C) 2015, Pablo Lamela, Simon Thompson
+ +Authors: Pablo Lamela Seijas (P.Lamela-Seijas@kent.ac.uk), Simon Thompson (S.J.Thompson@kent.ac.uk).
+ +add_fun_to_col/3 | + Adds the Name and Arity to the field beh_funcs of ColData. |
fix_localities/4 | + Fixes the SyntaxTree to behave as it did in the original module (by + redirecting references and the ?MODULE macro). |
add_fun_to_col(ColData::cluster_mapping:col_data(), Name::string(), Arity::integer()) -> cluster_mapping:col_data()
+ Adds the Name and Arity to the field beh_funcs of ColData.
+ +fix_localities(IsLeafOrExc::boolean(), SyntaxTree::wrangler_syntax:syntaxTree(), HasFuncDec::boolean(), ColData::cluster_mapping:col_data()) -> {wrangler_syntax:syntaxTree(), cluster_mapping:col_data()}
+ Fixes the SyntaxTree to behave as it did in the original module (by + redirecting references and the ?MODULE macro). + IsLeafOrExc must be true if the tree is known to have no references + or if it is in an exclusive cluster. HasFuncDec must be true + the root of the SyntaxTree is a legacy function declaration.
+Generated by EDoc, Nov 5 2015, 16:30:19.
+ + diff --git a/docs/doc/behaviour_extraction/modules-frame.html b/docs/doc/behaviour_extraction/modules-frame.html new file mode 100644 index 00000000..01d82cdb --- /dev/null +++ b/docs/doc/behaviour_extraction/modules-frame.html @@ -0,0 +1,26 @@ + + + +ast_tree |
cluster |
cluster_dict |
cluster_folding |
cluster_linking |
cluster_mapping |
da_map |
fix_frontiers |
fun_blocks |
fun_blocks_fix |
infer_behaviour |
local_fix |
tree |
tree_clustering |
tree_mapping |
Copyright © (C) 2015 Pablo Lamela, Simon Thompson
+Authors: Pablo Lamela Seijas (P.Lamela-Seijas@kent.ac.uk), Simon Thompson (S.J.Thompson@kent.ac.uk).
+ + +This package provides a mechanism that automatically creates an Erlang behaviour by merging two modules selected by the user, which are assumed to be structurally similar, and possibly the result of copying and modifying one of them to produce the other.
+ +The algorithm consists of four main stages:
+ +tree_mapping
) - Compares the ASTs of the two input modulestree_clustering
) - Divides the contiguous mapped subtrees into clusterscluster_linking
) - Organises and links the clusters so that the order of execution from the original ASTs is preservedcluster_mapping
) - Uses the information about clusters and links to construct the three final ASTsThe process starts with two modules which are assumed to be similar. First we find commonalities between their ASTs, group the contiguous commonalities, move the commonalities to a separate module, and link the pieces together with function calls in order to preserve the original behaviour. This way we are left with three modules: the remains of the original ones and a new module with the common parts. The module with the common code will be configured as a behaviour definition, and modules with the remainings of the original ones will be configured as behaviour instances of the new module.
+ +The top level module for the algorithm is infer_behaviour
.
Generated by EDoc, Nov 12 2015, 18:43:11.
+ + diff --git a/docs/doc/behaviour_extraction/stylesheet.css b/docs/doc/behaviour_extraction/stylesheet.css new file mode 100644 index 00000000..ab170c09 --- /dev/null +++ b/docs/doc/behaviour_extraction/stylesheet.css @@ -0,0 +1,55 @@ +/* standard EDoc style sheet */ +body { + font-family: Verdana, Arial, Helvetica, sans-serif; + margin-left: .25in; + margin-right: .2in; + margin-top: 0.2in; + margin-bottom: 0.2in; + color: #000000; + background-color: #ffffff; +} +h1,h2 { + margin-left: -0.2in; +} +div.navbar { + background-color: #add8e6; + padding: 0.2em; +} +h2.indextitle { + padding: 0.4em; + background-color: #add8e6; +} +h3.function,h3.typedecl { + background-color: #add8e6; + padding-left: 1em; +} +div.spec { + margin-left: 2em; + background-color: #eeeeee; +} +a.module { + text-decoration:none +} +a.module:hover { + background-color: #eeeeee; +} +ul.definitions { + list-style-type: none; +} +ul.index { + list-style-type: none; + background-color: #eeeeee; +} + +/* + * Minor style tweaks + */ +ul { + list-style-type: square; +} +table { + border-collapse: collapse; +} +td { + padding: 3 +} diff --git a/docs/doc/behaviour_extraction/tree.html b/docs/doc/behaviour_extraction/tree.html new file mode 100644 index 00000000..7042cc3f --- /dev/null +++ b/docs/doc/behaviour_extraction/tree.html @@ -0,0 +1,301 @@ + + + + +Copyright © (C) 2015, Pablo Lamela, Simon Thompson
+ +Authors: Pablo Lamela Seijas (P.Lamela-Seijas@kent.ac.uk), Simon Thompson (S.J.Thompson@kent.ac.uk).
+ +abstract datatype: tree()
+ + +abstract datatype: tree_node()
+ + +abstract datatype: tree_ph()
+ + +breadth_fold/3 | + Folds a function through a tree in breadth first order. |
collapse_node/2 | + Removes the node from the tree, and attaches its children to + its parent in the place it was. |
copy_properties/2 | + Copies the properties stored in the nodes of OriTree into + the nodes of DestTree. |
create_node_pair/2 | + Joins two nodes into a single node (node pair). |
dict_get/3 |
+ Like dict:fetch/2 but allows to specify a default value. |
get_child_ph/1 | + Generates a placeholder for a child of the node. |
get_children/2 | + Returns the children of Node in the Tree. |
get_data/1 | + Returns the extra information stored on the tree. |
get_node/2 | + Finds a node by using its placeholder. |
get_pair_tuple/1 | + Splits a node pair into the original two nodes. |
get_parent/2 | + Returns the parent of Node in the Tree. |
get_ph/1 | + Returns the placeholder for a node or node pair Node. |
get_pos_in_parent/2 | + Finds the position of Node in the list of children + of Parent. |
get_property/2 | + Extracts the value of a property from a tree_node. |
get_root_node/1 | + Returns the root node of the Tree. |
get_value/1 | + Extracts the value from a tree_node. |
group_children/5 | + Moves the children with PH ChildrenPHs to a new node, and + puts the new node in the place of the children, it returns + both the new node and the updated tree. |
index_by/2 | + Returns a map with the nodes of the Tree as values and the + result of applying Fun to them as keys. |
is_node_pair/1 | + Returns whether a node is a node pair. |
new/0 | + Creates a empty tree. |
new_node_ph/1 | + Creates a node from a placeholder. |
replace_with_elements/3 | + Replaces the first occurrence of Pattern in List with the elements + in the list Replacement. |
set_data/2 | + Sets the extra information stored on the tree. |
set_property/3 | + Sets the value property for a tree_node. |
set_value/2 | + Sets the value for a tree_node. |
store_node/2 | + Adds a new node to the tree, or updates an existing one. |
upgrade_node/2 | + Moves a node upwards a level. |
breadth_fold(Fun::FFun, AccIn::Acc, Tree::tree()) -> AccOut::Acc +
+ Folds a function through a tree in breadth first order.
+ +collapse_node(Tree_node, Tree) -> any()
++ Removes the node from the tree, and attaches its children to + its parent in the place it was. It expects the value of the + parent to be updated appropriately.
+ +copy_properties(OriTree::tree:tree(), DestTree::tree:tree()) -> tree:tree()
+ Copies the properties stored in the nodes of OriTree into + the nodes of DestTree. Both trees must have the same exact + topology.
+ +create_node_pair(Node1::tree:tree_node(), Node2::tree:tree_node()) -> tree:tree_node()
+ Joins two nodes into a single node (node pair)
+ +dict_get(Key::KeyType, Dict::dict:dict(KeyType, ValueType), DefaultValue::ValueType) -> ValueType
+ Like dict:fetch/2
but allows to specify a default value.
get_child_ph(Tree_node::tree_node()) -> {tree_node(), tree_ph()}
+ Generates a placeholder for a child of the node. A child generated
+ with the placeholder will be linked automatically to the node.
+ For the link to be created, the version of the node updated by
+ this function must be stored in the tree afterwards,
+ store_node/2
, as well as the child generated with the
+ placeholder.
get_children(Node::tree:tree_node(), Tree::tree()) -> [tree:tree_node()]
+ Returns the children of Node in the Tree.
+ +get_data(Tree::tree:tree()) -> Data::any()
+ Returns the extra information stored on the tree.
+ This can be any term and is stored with set_data/2
.
get_node(PH::tree_ph(), Tree::tree()) -> error | {ok, tree_node()}
+ Finds a node by using its placeholder. It returns error
if it
+ cannot be found.
get_pair_tuple(NodePair::tree:tree_node()) -> {tree:tree_node(), tree:tree_node()}
+ Splits a node pair into the original two nodes
+ +get_parent(Node::tree:tree_node(), Tree::tree()) -> error | {ok, tree:tree_node()}
+ Returns the parent of Node in the Tree.
+ +get_ph(Node::tree:tree_node()) -> {node, tree:tree_ph()} | {node_pair, tree:tree_ph(), tree:tree_ph()}
+ Returns the placeholder for a node or node pair Node. That is, + an unique identifier for the Node, that is used as placeholder + in the original position of the node in its parent. + If Node is a node pair, two placeholders are returned.
+ +get_pos_in_parent(Node::tree:tree_node(), Parent::tree:tree_node()) -> error | pos_integer()
+ Finds the position of Node in the list of children + of Parent.
+ +get_property(Key::term(), Node::tree_node()) -> {ok, Value::term()} | error
+ Extracts the value of a property from a tree_node. Returns error + if it is not set.
+ +get_root_node(Tree::tree()) -> tree:tree_node()
+ Returns the root node of the Tree.
+ +get_value(Tree_node::tree_node()) -> term()
+ Extracts the value from a tree_node.
+ +group_children(Tree_node::tree_node(), ChildrenPHs::[tree_ph()], NewParentValueGen::fun((PH::tree_node()) -> Value), Value, Tree::tree()) -> {tree_node(), tree:tree()} +
+ Moves the children with PH ChildrenPHs to a new node, and + puts the new node in the place of the children, it returns + both the new node and the updated tree. + A value, both for the parent and the new node which reflect + the changes, is required. + All nodes are assumed to NOT be node pairs, (before and after).
+ +index_by(Fun::fun((Node) -> Idx), Tree::tree()) -> dict:dict(Idx, Node) +
+ Returns a map with the nodes of the Tree as values and the + result of applying Fun to them as keys.
+ +is_node_pair(Node::tree:tree_node()) -> boolean()
+ Returns whether a node is a node pair
+ +new() -> tree()
+ Creates a empty tree
+ +new_node_ph(PH::tree_ph()) -> tree_node()
+ Creates a node from a placeholder. See get_child_ph/1
.
replace_with_elements(Pattern::[El], List::[El], Replacement::[El]) -> [El] +
+ Replaces the first occurrence of Pattern in List with the elements + in the list Replacement. It assumes there no partial matches.
+ +set_data(Data::any(), Tree::tree:tree()) -> NewTree::tree:tree()
+ Sets the extra information stored on the tree.
+ This can be any term and is retrieved from the tree with
+ get_data/1
.
set_property(Key::term(), Value::term(), Node::tree_node()) -> tree_node()
+ Sets the value property for a tree_node. It does not update the tree,
+ obviously. For updating the tree the node must be stored
+ afterwards, store_node/2
.
set_value(Value::term(), Node::tree_node()) -> tree_node()
+ Sets the value for a tree_node. It does not update the tree,
+ obviously. For updating the tree the node must be stored
+ afterwards, store_node/2
.
store_node(Node::tree:tree_node(), Tree::tree()) -> tree()
+ Adds a new node to the tree, or updates an existing one.
+ +upgrade_node(Tree_node, Tree) -> any()
++ Moves a node upwards a level. It expects the value of the + two ancestors to be updated appropriately.
+Generated by EDoc, Nov 5 2015, 16:30:18.
+ + diff --git a/docs/doc/behaviour_extraction/tree_clustering.html b/docs/doc/behaviour_extraction/tree_clustering.html new file mode 100644 index 00000000..568f8531 --- /dev/null +++ b/docs/doc/behaviour_extraction/tree_clustering.html @@ -0,0 +1,47 @@ + + + + +Copyright © (C) 2015, Pablo Lamela, Simon Thompson
+ +Authors: Pablo Lamela Seijas (P.Lamela-Seijas@kent.ac.uk), Simon Thompson (S.J.Thompson@kent.ac.uk).
+ +cluster/4 | + Takes two trees and a Mapping between them, divides the + trees in contiguous clusters. |
cluster(Pass, Mapping, Tree1::tree:tree(), Tree2::tree:tree()) -> {Mapping, cluster_dict:cluster_dict(tree:tree_node()), cluster_dict:cluster_dict(tree:tree_node()), cluster_dict:cluster_dict(tree:tree_node())} +
+ Takes two trees and a Mapping between them, divides the
+ trees in contiguous clusters. The criteria for division
+ is that the nodes in a cluster must be contiguous and
+ either common to both trees, or exclusive to one of them.
+ It applies fix_frontiers:fix_frontiers/4
.
+ The function returns a tuple with three elements:
+ the list of common clusters, the list of exclusive clusters
+ for Tree1, the list of exclusive clusters for Tree2.
Generated by EDoc, Nov 5 2015, 16:30:19.
+ + diff --git a/docs/doc/behaviour_extraction/tree_mapping.html b/docs/doc/behaviour_extraction/tree_mapping.html new file mode 100644 index 00000000..cf0bb3de --- /dev/null +++ b/docs/doc/behaviour_extraction/tree_mapping.html @@ -0,0 +1,44 @@ + + + + +Copyright © (C) 2015, Pablo Lamela, Simon Thompson
+ +Authors: Pablo Lamela Seijas (P.Lamela-Seijas@kent.ac.uk), Simon Thompson (S.J.Thompson@kent.ac.uk).
+ +mapping/2 | + Takes two trees and returns a mapping between their common nodes. |
mapping(T1::tree:tree(), T2::tree:tree()) -> da_map:da_map(tree:tree_node(), tree:tree_node())
+ Takes two trees and returns a mapping between their common nodes.
+Generated by EDoc, Nov 5 2015, 16:30:19.
+ + diff --git a/docs/doc/erlang.png b/docs/doc/erlang.png new file mode 100644 index 00000000..987a618e Binary files /dev/null and b/docs/doc/erlang.png differ diff --git a/docs/doc/gen_composite_refac.html b/docs/doc/gen_composite_refac.html new file mode 100644 index 00000000..f1b4194c --- /dev/null +++ b/docs/doc/gen_composite_refac.html @@ -0,0 +1,259 @@ + + + + +gen_composite_refac
behaviour.
+
+This module defines the gen_composite_refac behaviour.
Required callback functions: composite_refac/1, input_par_prompts/0, select_focus/1.
Authors: Huiqing Li (H.Li@kent.ac.uk).
+ +This module defines the gen_composite_refac
behaviour. It provides a high-level
+abstraction of the logic work-flow of a composite refactoring process. The behaviour
+defines two callback functions that are to be implemented by the user as explained next.
input_par_prompts/0
:
+ input_par_prompts() + ===> [string()]+
input_par_prompts
returns the list of prompt strings to be used when
+ the refactorer asks the user for input at the very beginning of the composite
+ refactoring. There should be one prompt string for each input.
+ Callback function composite_refac/1
:
+ composite_refac(Args::#args{}) + ===> composite_refac()|[]
+ composite_refac
is the function in which the user could script a
+ composite refactoring. The definition of record args
is the same as the
+ the record using by the gen_refac
behaviour to be consistent, but the
+ selective
field should not be used.
args
defines the data structure that is passed to composite_refac
.
+ -record(args,{current_file_name :: filename(), %% the file name of the current Erlang buffer. + cursor_pos :: pos(), %% the current cursor position. + highlight_range :: {pos(), pos()}, %% the start and end location of the highlighted code if there is any. + user_inputs :: [string()], %% the data inputted by the user. + focus_sel :: any(), %% the focus of interest selected by the user. + search_paths ::[dir()|filename()], %% the list of directories or files which specify the scope of the project. + tabwidth =8 ::integer() %% the number of white spaces denoted by a tab key. + }).+ +
Before explaining how to scripting composite refactorings, we clarify the meaning +of some terms we use.
+ + Precondition . A precondition is a predicate over a program that returns
+ either true
or false
when applied to a program.
Transformation rule. A transformation rule maps a program from one state into another.
+ +Refactoring. A refactoring is either a elementary refactoring or a composite refactoring.
+ +Elementary refactoring. A elementary refactoring is an elementary behaviour-preserving + source-to-source program transformation that consists of a set of preconditions C, + and a set of transformation rules T. When a elementary refactoring is applied to a + program, all the preconditions are checked before the programming is actually transformed. + We say a elementary refactoring fails if the conjunction of the set of + preconditions returns false; otherwise we say the elementary refactoring succeeds .
+ +Composite Refactoring. A composite refactoring is either an atomic composite +refactoring or a non-atomic composite refactoring.
+ + Atomic composite refactoring Given a sequence of elementary refactorings, R_1, ..., R_n(n>=1)
,
+ the atomic composition of R_1, ..., R_n
, creates a new refactoring consisting of
+ the sequential application of refactorings from R_1
to R_n
. If any R_i(1=<i=<n)
fails,
+ then the whole refactoring fails and the original program returns unchanged.
+ The composite refactoring succeeds if all R_i(1=<i=<n)
succeeds, and the result
+ program is the program returned after applying R_n
.
Non-atomic composite refactoring
+ Given a sequence of refactorings R_1, ..., Rn(n>=1)
, the non-atomic composition of R_1, ..., R_n
,
+ creates a new refactoring consisting of the sequential application of refactorings from
+ R_1 to R_n
. If refactoring R_i
fails, the execution of R_{i+1}
continues. A failed refactoring
+ does not change the status of the program. The program returned by applying R_n
is the final result
+of the application of the composite refactoring. As a convention, we say that a non-atomic
+composite refactoring always succeeds.
+Each primitive refactoring in Wrangler has been extended with a refactoring command generator. The +interface of a command generator is enriched in such a way that it accepts not only concrete values +as what a primitive refactoring does, but also structures that specify the constraints that a parameter +should meet or structures that specify how the value for a parameter should be generated.
+ +When applied to an Erlang program, a command generator searches the AST representation of the program +for refactoring candidates according to the constraints on arguments. A command generator can also be +instructed to run lazily or strictly; if applied strictly, it returns the complete list of primitive +refactoring commands that can be generated in one go; otherwise, it returns a single refactoring +command together with another command generator wrapped in a function closure, or an empty list +if no more commands can be generated. Lazy refactoring command generation is especially useful +when the primitive refactoring command refers some program entities by locations, or the +effect of a previous refactoring could affect the refactorings after.
+ +Each primitive refactoring command generated is represented as a tuple in the format of:
+ {refactoring, RefacName, Args}
, where RefacName
is the name of the refactoring command,
+ and Args
is the list representation of the arguments for that refactoring command.
+ A refactoring command generator is also syntactically represented as a three-element tuple,
+ but with a different tag, in the format of {refac_, RefacName, Args}
, where RefacName
is
+ the name of the refactoring, and Args
are the arguments that supplied to the command generator.
rename function
refactoring as an example, the type specification of the refactoring
+ command is:
+ -spec rename_fun(File::filename(), FunNameArity::{atom(), integer()}, + NewName::atom()) -> ok | {error, Reason::string()}.+ which should be clear enough to explain itself. + The type specification of the command generator is: +
-spec rename_fun(File::filename() | fun((filename()) -> boolean()), + FunNameArity::{atom(), integer()} + | fun(({atom(),integer()}) -> boolean()), + NewName::atom() + |{generator, fun(({filename(), {atom(), integer()}}) + -> atom())} + |{user_input,fun(({filename(), {atom(), integer()}}) + -> string())}, + Lazy :: boolean()) + -> [{refactoring, rename_fun, Args::[term()]}] | + {{refactoring, rename_fun, Args::[term()]}, function()}.
+As it shows, a command generator accepts not only actual values, but also function closures +that allow values to be generated by analyzing the code to be refactored . The first parameter +of the generator accepts either a file name, or a condition that a file should satisfy to be +refactored. In the latter case, Wrangler will search the whole program for files that meet +the condition specified, and only those files are further analyzed in order to generate values +for the remaining parameters. The second parameter accepts either a function name tupled with +its arity, or a condition that a function should meet in order to be refactored. In the latter +case, every function in an Erlang file will be checked, and those functions that do not meet +the condition are filtered out, and a primitive refactoring command is generated for each function +that meets the condition. The third argument specifies how the new function name should be generated. +It could be a fixed function name, a generator function that generates the new function based on the +previous parameter values, or a name that will be supplied by the user before the execution of the +refactoring, in which case the function closure is used to generate the prompt string that will be +shown to the user when prompting for input. Finally, the last parameter allows the user to choose +whether to generate the commands lazily or not.
+ + The following example illustrates the generation of refactoring commands that rename all functions + in a program whose name is incamelCase
format to camel _case
format.
+ {refac_, rename_fun, [fun(_File)-> true end, + fun({FunName, _Arity}) -> is_camelCase(FunName) end, + {generator, fun({_File,{FunName,_Arity}}) -> + camelCase_to_camel_case(FunName) + end}, false]}
+ As the condition for the first parameter always returns true, every file in the program should be checked.
+ The second argument checks if the function name is in camelCase
format using the utility function
+ is_camelCase
, and a refactoring command is generated for each function whose name is in camelCase
format.
+ The new function name is generated by applying the utility function camelCase_to_camel_case
to the old
+function name. In this example, we choose to generate the refactoring commands in a strict way.
For some command generators, it is also possible to specify the order in which the functions in an +Erlang file are visited. By default, functions are visited by their textual order in the file, but it +is also possible for them to be visited according to the function callgraph in either top-down or +bottom-up order.
+ +For the type specification of refactoring command generators, please see + wrangler command generators.
+ +To allow fine control over the generation of refactoring commands and the way a refactoring command
+ to be run, we have defined a small language for scripting composite refactorings. The DSL, as shown
+ below, is defined in Erlang syntax. In the definition, ER
denotes a primitive refactoring, and CR
+ denotes a composite refactoring. we explain the definition of CR
in more details now.
RefacName ::= rename_fun | rename_mod | rename_var | new_fun |gen_fun | ... + ER ::= {refactoring, RefacName, Args} + CR ::= ER + |{interactive, Qualifier, [ERs]} + |{repeat_interactive, Qualifier, [ERs]} + |{if_then, fun()-> Cond end, CR} + |{while, fun()-> Cond end, Qualifier, CR} + |{Qualifier, [CRs]} + ERs::= ER | ERs, ER + CRs ::= CR |CRs, CR + Qualifier ::= atomic | non_atomic + Args ::= ...A list of Erlang terms ... + Cond ::= ...An Erlang expression that evaluates to a `boolean' value ...+ +
The definition of CR
is explained in more details below.
+ A primitive refactorings is an atomic composite refactoring by definition.
+ {interactive, Qualifier, [ERs]}
represents a list of primitive refactorings that to be
+ executed in an interactive way, that is, before the execution of every primitive refactoring,
+ Wrangler asks the user for confirmation that he/she really wants that refactoring to be applied.
+ {repeat_interactive, Qualifier, [ERs]}
also represents a list of primitive refactorings to be
+ executed in an interactive way, but different from the previous one, it allows user to repeatedly
+ apply one refactoring, with different parameters supplied, multiple times.
+ {if_then, Cond, CR}
represents the conditional application of CR
, i.e. CR
is applied only
+ if Cond
, which is an Erlang expression, evaluates to true
.
+ {while, Cond, Qualifier, CR}
allows CR
, which should be generated dynamically, to be continually
+ applied until $Cond$ evaluates to false
. Qualifier
specifies the way in which
+ the refactoring between each loop should be composed.
+ {Qualifier, [CRs]}
represents the composition of a list of composite refactorings into a new composite refactoring.
+In practice, instead of writing tuples with tags in a composite refactoring script, we use macros. A suite of macros +have been defined for this purpose as follows.
+ +?interactive([ERs])
represents {interactive, atomic, [ERs]}
.
?interactive(Qualifier,[ERs])
represents {interactive, Qualifier, [ERs]}
.
?repeat_interactive([ERs])
represents {repeat_interactive, atomic, [ERs]}
.
?repeat_interactive(Qualifier,[ERs])
represents {repeat_interactive, Qualifier, [ERs]}
.
?if_then(Cond, CR)
represents {if_then, fun()-> Cond end, CR}
.
?while(Cond, CR)
represents {while, fun() -> Cond end, atomic, CR}
.
?while(Cond, Qualifier, CR)
represents {while, fun() -> Cond end, Qualifier, CR}
.
?try_refac([CRs])
represents {non_atomic, [CRs]}
.
?refac([CRs])
represents {atomic, [CRs]}
.
+ In a composite refactoring, it is possible that a refactoring needs to refer to a program entity that might have be
+ renamed by previous refactoring steps. Tracking the change of names statically is problematic given the dynamic nature
+ of a refactoring process.Wrangler allows users to refer to a program entity through its initial name, i.e. the name of
+ the entity before the refactoring process is started. For this purpose, we have defined a macro ?current
. An entity
+ name wrapped in a ?current
macro tells Wrangler that this entity might have been renamed, therefore Wrangler needs to
+search its record of renaming history, and replaces the macro application with the entity's latest name. If no renaming
+history can be found for that entity, its original name is used.
In the background, Wrangler monitors application of renaming
refactorings, and keeps a record of the mapping between
+ the old and new names. Currently, only module names and function names are tracked, as these are the entities that can
+ be referred by name and also can be renamed by the refactorings supported by Wrangler. Syntactically, a module name is
+ represented as an Erlang atom, and a function name is represented by a tuple consisting of the module name, function name
+ and arity. The data format returned by the application of the ?current
is the same as its input.
+ To invoke a user's own-defined gen_composite_refac
refactoring, select menu item Wrangler -> Refactor -> Apply Composite Refactoring,
+Wrangler will then prompt you to input the name of the callback module, and the values for parameters needed by the
+refactoring.
gen_composite_refac
refactoring to the My gen_composite_refac Refacs
menu, set the file buffer implementing the
+ refactoring as the current buffer, then select Wrangler -> Refactor -> Add to My gen_composite_refac Refacs.Generated by EDoc, Nov 12 2015, 19:13:23.
+ + diff --git a/docs/doc/gen_refac.html b/docs/doc/gen_refac.html new file mode 100644 index 00000000..0c8f0d91 --- /dev/null +++ b/docs/doc/gen_refac.html @@ -0,0 +1,135 @@ + + + + +gen_refac
behaviour.
+
+This module defines the gen_refac behaviour.
Required callback functions: input_par_prompts/0, select_focus/1, check_pre_cond/1, selective/0, transform/1.
Authors: Huiqing Li (H.Li@kent.ac.uk).
+ +This module defines the gen_refac
behaviour. It provides a
+high-level abstraction of the logic work-flow of a refactoring
+process. A user-interactive refactoring
+process in Emacs generally works in the following way : the user first
+selects the focus of interest by either pointing the cursor to a
+particular program entity or by highlighting, then invokes the
+refactoring command; in case that the refactoring needs certain
+initial inputs from the user, it will prompt the user to input
+the values from the mini-buffer. After all these interactions,
+the refactor engine starts the pre-condition checking to
+make sure that performing the refactoring initiated by the user
+will not change the behaviour of the program; the refactorer
+continues to carry out the program transformation if the pre-condition
+passes, otherwise aborts the refactoring process and returns the reason
+for failure.
The idea behind this module is that the user module provides functions
+ to handle different parts of the refactoring process that is particular
+ to that refactoring, while gen_refac
handles the parts that are common
+to all refactorings.
input_par_prompts() + ===> [string()]+
input_par_prompts
returns the list of prompt strings to be used when
+ the refactorer asks the user for input. There should be one
+ prompt string for each input.
+ select_focus(Args::#args{}) + ===> none|{ok, term()}|{error, Reason}+
select_pars
returns the focus of interest selected by the user.
+ This function should return none
if no focus selection is needed;
+ {error, Reason}
if the user didn't select the kind of entity
+ expected; or {ok, term()
when a valid focus of interest has been
+ selected.
+ check_pre_cond(Args::#args{}) + ===> ok | {error, Reason}+ This function checks whether the pre-conditions of the refactoring + hold, and returns
ok
if the pre-condition checking passes, otherwise
+ {error, Reason}
.
+ selective() + ===> true | false+ This function should returns
true
if the user is allowed to browse
+ through and select the changes to be made.
+ transform(Args::#args()) + ===> {ok, [{{filename(),filename()} syntaxTree()}] | {error, Reason}}
+ Function transform
carries out the transformation part of the
+ refactorings. If the refactoring succeeds, it returns the list of
+ file names together with their new AST (only files that have been
+ changed need to be returned); otherwise {error, Reason}
.
args
defines the data structure that is passed through, and also modified by, the different phases
+ of the refactoring.
+ -record(args,{current_file_name :: filename(), %% the file name of the current Erlang buffer. + cursor_pos :: pos(), %% the current cursor position. + highlight_range :: {pos(), pos()}, %% the start and end location of the highlighted code if there is any. + user_inputs :: [string()], %% the data inputted by the user. + focus_sel :: any(), %% the focus of interest selected by the user. + selective :: boolean(), %% selective refactoring or not. + search_paths ::[dir()|filename()], %% the list of directories or files which specify the scope of the project. + tabwidth =8 ::integer() %% the number of white spaces denoted by a tab key. + }).+ +
Some example refactorings implemented using the Wrangler API: +
+ To invoke a user's own-defined gen_refac
refactoring, select menu item Wrangler -> Refactor -> Apply Adhoc Refactoring,
+Wrangler will then prompt you to input the name of the callback module, and the values for parameters needed by the
+refactoring.
gen_refac
refactoring to the My gen_refac Refacs
menu, set the file buffer implementing the
+ refactoring as the current buffer, then select Wrangler -> Refactor -> Add to My gen_refac Refacs.
+
+run_refac/2 | The interface function for invoking a refactoring defined
+ in module ModName . |
run_refac(Module::module() | string() | tuple(), Args::[term()]) -> {ok, string()} | {change_set, [{string(), string()}], module(), #args{}} | {error, term()}
The interface function for invoking a refactoring defined
+ in module ModName
.
Generated by EDoc, Nov 5 2015, 16:30:22.
+ + diff --git a/docs/doc/how_to_use.htm b/docs/doc/how_to_use.htm index a714ceb0..8ad46c7b 100644 --- a/docs/doc/how_to_use.htm +++ b/docs/doc/how_to_use.htm @@ -1,7 +1,7 @@ - +Copyright © 2006-2011 Huiqing Li, Simon Thompson +
+ +Authors: Huiqing Li, Simon Thompson [web site: http://www.cs.kent.ac.uk/projects/wrangler].
+ +col() = integer()
+ + +dir() = string()
+ + +filename() = string()
+ + +functionarity() = integer()
+ + +functionname() = atom()
+ + +line() = integer()
+ + +modulename() = atom()
+ + +pos() = {integer(), integer()}
+ + +calls_to_fun/4 | Report the functions by which the function specified is called. |
cyclic_dependent_modules/3 | Report the cyclic module dependencies, if there is any, for a given list of + directories of Erlang source code. |
dependencies_of_a_module/2 | Report modules that depend on the module specified, as well as modules on which the + module specified in dependent. |
find_var_instances/3 | Find all the instances of a variable, including both defining and use instances. |
gen_function_callgraph/3 | Generate the function callgraph for a given Erlang file. |
gen_module_graph/3 | Generate the module graph for a given list of directories of Erlang source code. |
improper_inter_module_calls/2 | Report improper module dependencies, if there is any, for a given list of + directories of Erlang source code. |
large_modules/2 | Report all the modules that consist of more than a specified number of lines of code. |
long_functions/2 | Report all the functions that consist of more than specified number of lines of code. |
nested_exprs/3 | Find all the functions that contain certain type of expressions that are nested a + specified number of levels or more. |
non_tail_recursive_servers/1 | Report non tail-recursive server functions. |
not_flush_unknown_messages/1 | Report functions whose receive expression, if there is one, does not flush unknown messages. |
calls_to_fun(FileName::filename(), FunctionName::functionname(), Arity::integer(), SearchPaths::[dir()]) -> {error, string()} | ok
Report the functions by which the function specified is called. A function is reported + only if Wrangler is certain that it calls the function specified.
+ +cyclic_dependent_modules(OutputDotFileName::filename(), SearchPaths::[filename() | dir()], WithLabel::boolean()) -> true
Report the cyclic module dependencies, if there is any, for a given list of + directories of Erlang source code.
+ +dependencies_of_a_module(ModOrFileName::modulename() | filename(), SearchPaths::[filename() | dir()]) -> ok
Report modules that depend on the module specified, as well as modules on which the + module specified in dependent.
+ +find_var_instances(FileName::filename(), X2::{Line::integer(), Col::integer()}, TabWidth::integer()) -> {error, string()} | {ok, [{pos(), pos()}], [pos()]}
Find all the instances of a variable, including both defining and use instances.
+ +gen_function_callgraph(OutputDotFileName::filename(), FileName::filename(), SearchPaths::[filename() | dir()]) -> true
Generate the function callgraph for a given Erlang file.
+ +gen_module_graph(OutputDotFileName::filename(), SearchPaths::[filename() | dir()], WithLabel::boolean()) -> true
Generate the module graph for a given list of directories of Erlang source code.
+ +improper_inter_module_calls(OutputDotFileName::filename(), SearchPaths::[filename() | dir()]) -> true
Report improper module dependencies, if there is any, for a given list of + directories of Erlang source code.
+ +large_modules(SearchPaths::[dir()], Lines::integer()) -> {error, string()} | ok
Report all the modules that consist of more than a specified number of lines of code.
+ +long_functions(FileOrDirNames::[filename() | dir()], Lines::integer()) -> {error, string()} | ok
Report all the functions that consist of more than specified number of lines of code.
+ +nested_exprs(FileOrDirNames::[filename() | dir()], NestLevel::integer(), ExprType::'if' | 'case' | 'receive') -> {error, string()} | ok
Find all the functions that contain certain type of expressions that are nested a + specified number of levels or more.
+ +non_tail_recursive_servers(FileOrDirNames::[filename() | dir()]) -> ok
Report non tail-recursive server functions. +
+ The Erlang Programming Rules says: + All servers must be tail-recursive, otherwise the server will consume memory until the system runs out of it. + + Don't program like this: + +
loop() -> + receive + {msg1, Msg1} -> + ..., + loop(); + stop -> + true; + Other -> + error_logger:log({error, {process_got_other, self(), Other}}), + loop() + end, + io:format("Server going down"). + + The above is not tail-recusive. This is a correct solution: + + loop() -> + receive + {msg1, Msg1} -> + ..., + loop(); + stop -> + io:format("Server going down"); + Other -> + error_logger:log({error, {process_got_other, self(), Other}}), + loop() + end.+ + +
not_flush_unknown_messages(FileOrDirNames::[filename() | dir()]) -> ok
Report functions whose receive expression, if there is one, does not flush unknown messages. +
+ The Erlang Programming Rules says: + Every server should have an Other alternative in at least one receive statement. + This is to avoid filling up message queues. Example: + +
main_loop() -> + receive + {msg1, Msg1} -> + ..., + main_loop(); + {msg2, Msg2} -> + ..., + main_loop(); + Other -> % Flushes the message queue. + error_logger:error_msg( + "Error: Process ~w got unknown msg ~w~n.", + [self(), Other]), + main_loop() + end.+ +
Generated by EDoc, Nov 5 2015, 16:30:22.
+ + diff --git a/docs/doc/keysearch_keyfind.erl b/docs/doc/keysearch_keyfind.erl new file mode 100644 index 00000000..909bd039 --- /dev/null +++ b/docs/doc/keysearch_keyfind.erl @@ -0,0 +1,19 @@ +%%@hidden +%%@private +-module(keysearch_keyfind). + +-export([old_api_module_name/0]). + +-compile(export_all). + +old_api_module_name() -> + lists. + +keysearch(Key, N, TupleList) -> + case lists:keyfind(Key, N, TupleList) of + Tuple when is_tuple(Tuple)-> + {value, Tuple}; + false -> + false + end. + diff --git a/docs/doc/modules-frame.html b/docs/doc/modules-frame.html new file mode 100644 index 00000000..99de5c06 --- /dev/null +++ b/docs/doc/modules-frame.html @@ -0,0 +1,20 @@ + + + +api_interface |
api_refac |
api_wrangler |
gen_composite_refac |
gen_refac |
inspec_lib |
refac_api_migration |
wrangler_gen |
wrangler_refacs |
Copyright © 2006-2012 Huiqing Li, Simon Thompson
+Authors: Huiqing Li (H.Li@kent.ac.uk), Simon Thompson (s.j.thompson@kent.ac.uk) [web site: http://www.cs.kent.ac.uk/projects/wrangler].
+Wrangler is an Erlang refactoring tool that supports interactive +refactoring of Erlang programs.
+ +Refactoring is the process of improving the design of a program without +changing its external behaviour. While refactoring by hand is possible, tool +support for refactoring is invaluable as it is more reliable, and allows +refactoring to be done (or undone) easily. Wrangler is such a tool that +supports interactive refactoring of Erlang programs. Wrangler currently +supports a number of basic Erlang refactorings, such as renaming of +variable/function/module names, generalisation of a function definition, +function extraction, folding against a function definition, duplicated code +detection, etc.
+ +Wrangler also provides a set of process-based refactorings, including the
+ introduction of process naming, instead of providing access to a process
+only through a dynamically-generated process id Wrangler also contains
+a variety of refactorings which work with Erlang QuickCheck, introducing
+ and merging constructs such as ?LET
and ?FORALL
.
Transforming data types in Erlang can be difficult, as Erlang functions +can take values of any type, in principle. There are situations -- particularly +in implementing an Erlang behaviour , which can be thought of as an +interface for a set of callback functions -- where the types are more +constrained, and where data transformations are possible. In particular +we have implemented transformations for state data in various kinds +of generic state machine in both the OTP library and QuickCheck.
+ +In implementing Wrangler we have chosen to respect various features of +the language and related tools. Wrangler is able to process modules which +use macros, including the Erlang test frameworks that are in +regular use. Wrangler also respects the naming conventions in those +test frameworks.
+ +Wrangler provides a portfolio of decision support tools. The code inspector +highlights local code smells and a number of reports highlight issues in +the module structure of projects, including circular inclusions and other +potential faults. The code clone detection facilities can be +used on large multi-module projects to report on code clones and how they +can be removed; clone detection can be preformed incrementally on larger code +bases, for example as part of a continuous integration approach to software +construction.
+ + +Wrangler has recently been extended with a framework that allows users to define +for themselves refactorings and code inspection functions that suit their +needs. These are defined using a template- and rule-based +program transformation and analysis API. Wrangler also supports a +domain-specific language that allows users to script composite refactorings, +test them and apply them on the fly. +User-defined refactorings and scripts are not second-class citizens: like +the existing Wrangler refactorings, user-defined refactorings benefit +from features such as results preview, layout preservation, selective +refactoring, undo and so on.
+ + +Built on top of the functionalities provided by the Erlang syntax-tools +package, Wrangler is embedded in the Emacs/Xemacs editing environment, and +makes use of the functionalities provided by Distel, an Emacs-based user +interface toolkit for Erlang, to manage the communication between the +refactoring tool and Emacs. Wrangler is also integrated within +Eclipse, as a part of the ErlIDE plugin for Erlang.
+ +
+Below is a snapshot of Wrangler embedded in Emacs, which shows a particular
+refactoring scenario. The user has selected the expression
+io:format("Hello")
in the definition of repeat/1
, has
+chosen the Generalise Function Definition command from the
+Refactor sub-menu, and has just entered a new parameter name A in the
+mini-buffer.
+ +
The result of this refactoring is shown in the snapshot below.
+ ++ +
Preview of the changes to be made by a refactoring is supported, and the +user could choose to commit or abort the refactoring result after preview. +Wrangler's preview uses the Ediff package for Emacs.
+ +All the implemented refactorings are module-aware. In the case that a +refactoring affects more than one module in the program, a message telling +which files have been modified by the refactorer will be given after the +refactoring has been successfully done. The Customize Wrangler +command from the Refactor sub-menu allows the user to specify the +boundary of the program, i.e., the directories that will be searched and +analysed by the refactorer, as shown in the example snapshot below.
+ ++ +
Undo is supported by the refactorer. Applying undo once will revert +the program back to the status right before the last refactoring performed. +However, PLEASE NOTE that the refactorer undo is currently separate +from the Emacs undo, and undoing a refactoring will lose all the editing +activities after the refactoring.
+ ++Below is a snapshot of Wrangler embedded in Eclipse + Erlide.
+ ++ +
Wrangler makes use of functionalities provided by the epp_dodger
module
+from the Erlang syntax_tools
library to parse Erlang source code, and
+should be able to refactor Erlang modules containing preprocessor directives
+and macro applications, as long as the macro definitions are syntactically
+"well-behaved".
Wrangler accepts Erlang programs with syntax errors or macro definitions
+that cannot be parsed by epp_dodger
. In the case that the program under
+consideration has syntax errors or unparsable macros, functions/attributes
+to which these syntax errors belong are not affected by the refactoring
+process; however, warning messages asking for manual inspection of those
+parts of the program are given after the refactoring.
Wrangler is downloadable from Github: https://github.com/RefactoringTools, and also +from http://www.cs.kent.ac.uk/projects/wrangler
+ +Open an Erlang source file in the Emacs editor. You should now have a + menu called Erlang, if you have configured Emacs properly to +use the Erlang-mode (see the file INSTALL otherwise).
+ +To start Wrangler, type: M-x erlang-wrangler-on
, or
+ alternatively Ctrl-c Ctrl-r
. After that, new menu Wrangler should appear in the
+menu bar (see INSTALL otherwise).
To stop Wrangler, type M-x erlang-wrangler-off
, or
+ alternatively use Ctrl-c Ctrl-r
again. The Refactor and Inspector
+menus will disappear from the menu bar.
You can use Ctrl-c Ctrl-r
to toggle Wrangler on or off.
For most refactorings, the editor interface will pass the current +filename (should be the module name, as well), the refactoring command, +and the current cursor position. For some refactorings, you'll also +need to highlight an expression, or enter a new name.
+ +The Customize Wrangler menu in the Wrangler submenu allows you +to specify the boundary of the system by giving the list of directories +to search for Erlang source files/header files that could be affected +by a refactoring.
+ +For most refactorings, the editor interface will pass the current filename +(should be the module name, as well), the refactoring command, and the current +cursor position. For some refactorings, you'll also need to highlight an +expression, or enter a new name.
+ + How to use: +Generated by EDoc, Nov 5 2015, 16:30:22.
+ + diff --git a/docs/doc/refac_add_an_import_attribute.erl b/docs/doc/refac_add_an_import_attribute.erl new file mode 100644 index 00000000..82448db5 --- /dev/null +++ b/docs/doc/refac_add_an_import_attribute.erl @@ -0,0 +1,124 @@ +%% Copyright (c) 2013, Huiqing Li, Simon Thompson +%% All rights reserved. +%% +%% Redistribution and use in source and binary forms, with or without +%% modification, are permitted provided that the following conditions are met: +%% %% Redistributions of source code must retain the above copyright +%% notice, this list of conditions and the following disclaimer. +%% %% Redistributions in binary form must reproduce the above copyright +%% notice, this list of conditions and the following disclaimer in the +%% documentation and/or other materials provided with the distribution. +%% %% Neither the name of the copyright holders nor the +%% names of its contributors may be used to endorse or promote products +%% derived from this software without specific prior written permission. +%% +%% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS'' +%% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +%% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +%% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS +%% BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +%% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +%% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +%% BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +%% WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +%% OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +%% ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%%@author Huiqing LiAuthors: Huiqing Li and Simon Thompson (H.Li, S.J.Thompson@kent.ac.uk).
+ +Wrangler's support for API migration. +Most software evolves during its lifetime, and this will often change +the API of a library. A change of interface made to a library function could +potentially affect all client applications of the library. The API +transformations required tend to be done manually by the maintainers +of the client code, and this process can be both tedious and error-prone.
+ +Wrangler's support for API migration refactorings is based on the template-
+ and rule-based technique; however, unlike general refactorings, an API migration
+ refactoring only requires the author to define adapter functions that implement
+ the old
API functions using the new
API functions. Once the adapter module
+has been defined, Wrangler can then take this as input, and generate the refactoring
+code that implements the migration.
As a design principle, we try to limit the scope of changes as much as possible, so
+ that only the places where the old
API function is called are affected, and
+the remaining part of the code is unaffected.
To illustrate our approach, we take the migration from regexp:match/2
+ to re:run/3
as an example, which represents one of the most complex API changes
+we have seen in practice. Tthe change involves every aspect of the function interface,
+namely the module name, function name, arguments and values returned.
old
API
+ function using the new
API. The function shown below is the adapter function for
+ the migration from regexp:match/2
to re:run/3
.
+ match(String, RegExp) -> + case re:run(String, RegExp, [global]) of + {match, Match} -> + {Start0, Len}=lists:last(lists:ukeysort(2, Match)), + Start = Start0+1, + {match, Start, Len}; + nomatch -> nomatch + end.
+ A case
expression is needed by the definition of the adapter function if and only
+ if the value returned by the API function is affected by the migration, and the returned
+ value is of a union
type, i.e. a type consists of a number of alternatives. Within
+ the case
expression, each expression clause handles one possible alternative of the
+ return value, and the clause body defines how to derive the value that should be returned
+ by the old
API function from the value returned by the new
one.
keysearch(Key, N, TupleList) -> + case lists:find(Key, N, TupleList) of + Tuple when is_tuple(Tuple)-> + {value, Tuple}; + false -> + false + end.+ +
Obviously, for an API migration that does not affect the return value of the function,
+ a case
expression is not needed. For the case in which only the name of the API function
+ has been changed, the body of the adapter function could be just a function application
+ of the new
function.
old
function. case
expression, then the last expression of
+ every clause body of the case
expression should be a simple expression
+ that syntactically can be used as a pattern expression.
+ Apart from the adaptor functions, an adaptor module should also export a special function
+ old_api_module_name/0
which returns an atom representing the name of the module to
+which the old API functions belong. As a result, an adaptor module can only contain adaptor
+functions for API functions from the same module.
do_api_migration/5 | |
generate_rule_based_api_migration_mod/2 |
do_api_migration(FileOrDirs::[filename() | dir()], CallBackMod::module(), SearchPaths::[filename() | dir()], Editor::atom(), TabWidth::integer()) -> {error, string()} | {ok, [{filename(), filename(), string()}]}
generate_rule_based_api_migration_mod(FileName::filename(), NewModName::string() | atom()) -> {ok, filename()} | {error, term()}
Generated by EDoc, Nov 5 2015, 16:30:21.
+ + diff --git a/docs/doc/refac_apply_to_remote_call.erl b/docs/doc/refac_apply_to_remote_call.erl new file mode 100644 index 00000000..d13c27be --- /dev/null +++ b/docs/doc/refac_apply_to_remote_call.erl @@ -0,0 +1,88 @@ +%% Copyright (c) 2013, Huiqing Li, Simon Thompson +%% All rights reserved. +%% +%% Redistribution and use in source and binary forms, with or without +%% modification, are permitted provided that the following conditions are met: +%% %% Redistributions of source code must retain the above copyright +%% notice, this list of conditions and the following disclaimer. +%% %% Redistributions in binary form must reproduce the above copyright +%% notice, this list of conditions and the following disclaimer in the +%% documentation and/or other materials provided with the distribution. +%% %% Neither the name of the copyright holders nor the +%% names of its contributors may be used to endorse or promote products +%% derived from this software without specific prior written permission. +%% +%% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS'' +%% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +%% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +%% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS +%% BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +%% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +%% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +%% BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +%% WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +%% OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +%% ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%%@author Huiqing LiCopyright © (C) 2013, Gabriela Cunha Sampaio, Roberto S. M. de Barros Filho, Simon Thompson
+ +Authors: Gabriela Cunha Sampaio, Roberto Souto Maior de Barros Filho.
+ ++Arithmetic Calculations Core - Simplification of arithmetic operations involving integer literals or arbitrary expressions.
+ + The four basic arithmetic operators plus the operator rem are covered for integers, while only + and - are simplified for arbitrary expressions. + Some examples of simplifications are given below: +rules/2 | + Returns the list of arithmetics calculations rules. |
rules(X1::term(), X2::term()) -> [rule()]
+ Returns the list of arithmetics calculations rules. The rules are organised in the following order: +
Generated by EDoc, Nov 5 2015, 16:30:15.
+ + diff --git a/docs/doc/symbolic_evaluation/core/core_arit_simpl.html b/docs/doc/symbolic_evaluation/core/core_arit_simpl.html new file mode 100644 index 00000000..b3805c7f --- /dev/null +++ b/docs/doc/symbolic_evaluation/core/core_arit_simpl.html @@ -0,0 +1,56 @@ + + + + +Copyright © (C) 2013, Gabriela C. Sampaio, Roberto S. M. de Barros Filho, Simon Thompson
+ +Authors: Gabriela Cunha Sampaio, Roberto Souto Maior de Barros Filho.
+ +rules/2 | + Returns the list of arithmetic simplification rules. |
rules(X1::term(), X2::term()) -> [rule()]
+ Returns the list of arithmetic simplification rules. This list includes, in order, rules for the following possibilities: +
Generated by EDoc, Nov 5 2015, 16:30:15.
+ + diff --git a/docs/doc/symbolic_evaluation/core/core_arithmetics.html b/docs/doc/symbolic_evaluation/core/core_arithmetics.html new file mode 100644 index 00000000..4bb66e99 --- /dev/null +++ b/docs/doc/symbolic_evaluation/core/core_arithmetics.html @@ -0,0 +1,40 @@ + + + + +Copyright © (C) 2014, Gabriela C. Sampaio, Roberto S. M. de Barros Filho, Simon Thompson
+ +Authors: Gabriela Cunha Sampaio, Roberto Souto Maior de Barros Filho.
+ ++Arithmetic Operators Core - Covers arithmetic expressions.
+ + The simplifications performed are divided into two minor cores: Arithmetic Simplifications Core and Arithmetic Calculations Core. +rules/2 | + Returns the list of arithmetics rules. |
rules(A::term(), B::term()) -> [rule()]
+ Returns the list of arithmetics rules. The returned list of rules, contains the rules from Arithmetic Simplifications Core first and then the rules of Arithmetic Calculations Core.
+Generated by EDoc, Nov 5 2015, 16:30:15.
+ + diff --git a/docs/doc/symbolic_evaluation/core/core_boolean_operators.html b/docs/doc/symbolic_evaluation/core/core_boolean_operators.html new file mode 100644 index 00000000..d1f5d358 --- /dev/null +++ b/docs/doc/symbolic_evaluation/core/core_boolean_operators.html @@ -0,0 +1,91 @@ + + + + +Copyright © (C) 2014, Gabriela C. Sampaio, Roberto S. M. de Barros Filho, Simon Thompson
+ +Authors: Gabriela Cunha Sampaio, Roberto Souto Maior de Barros Filho.
+ +
+ The following list of boolean operators that receives parameters of any type was implemented:
+
+ >
,
+ <
,
+ >=
,
+ =<
,
+ /=
,
+ =/=
,
+ ==
,
+ =:=
,
+ is_atom/1, is_boolean/1, is_integer/1, is_float/1, is_function/1, is_function/2, is_list/1, is_number/1, is_tuple/1.
+
+
+ Furthermore, the following list of operators that only simplify boolean expressions was created: and, andalso, or, orelse, xor, not/1. +
+ Examples of usage: +rules/2 | + Returns the list of boolean operators rules. |
rules(X1::term(), X2::term()) -> [rule()]
+ Returns the list of boolean operators rules. The returned list of rules has the following order: +
Generated by EDoc, Nov 5 2015, 16:30:15.
+ + diff --git a/docs/doc/symbolic_evaluation/core/core_case.html b/docs/doc/symbolic_evaluation/core/core_case.html new file mode 100644 index 00000000..289ec5e1 --- /dev/null +++ b/docs/doc/symbolic_evaluation/core/core_case.html @@ -0,0 +1,78 @@ + + + + +Copyright © (C) 2014, Gabriela C. Sampaio, Roberto S. M. de Barros Filho, Simon Thompson
+ +Authors: Gabriela Cunha Sampaio, Roberto Souto Maior de Barros Filho.
+ ++Case Core - Where possible, simplifies case expressions by the result of their evaluation.
+ + Examples of usage: +rules/2 | + Returns a list with a single rule for the case simplification. |
rules(X1::{term(), VarsInfo::[{[{atom(), pos()}], syntaxTree()}], term()}, X2::term()) -> [rule()]
+ Returns a list with a single rule for the case simplification.
+Generated by EDoc, Nov 5 2015, 16:30:15.
+ + diff --git a/docs/doc/symbolic_evaluation/core/core_funApp.html b/docs/doc/symbolic_evaluation/core/core_funApp.html new file mode 100644 index 00000000..defcf854 --- /dev/null +++ b/docs/doc/symbolic_evaluation/core/core_funApp.html @@ -0,0 +1,88 @@ + + + + +Copyright © (C) 2013, Gabriela C. Sampaio, Roberto S. M. de Barros Filho, Simon Thompson
+ +Authors: Gabriela Cunha Sampaio, Roberto Souto Maior de Barros Filho.
+ +Unfold Function Application Core - Substitute function calls by its application.
+ + There are three types of transformations in this module: +anonymousCall_rule/0 | + Rule that substitutes parametrized anonymous calls. |
collect/1 | + Collects info from the exported functions in the file. |
functionCall_cond/6 | + Boolean condition to execute the function application transformations. |
functionCall_rule/4 | + Rule that substitutes external function calls. |
length_rule/0 | + Rule that substitutes call to length/1 from the standard. |
anonymousCall_rule() -> rule()
+ Rule that substitutes parametrized anonymous calls.
+ +collect(File::filename()) -> [{mfa(), syntaxTree(), [syntaxTree()], syntaxTree()}]
+ Collects info from the exported functions in the file.
+ +functionCall_cond(FunInfo::mfa() | unknown, FunDefInfo::mfa() | unknown, InfoList::[{mfa(), syntaxTree(), [syntaxTree()], syntaxTree()}] | [{list, [{modulename(), [{mfa(), syntaxTree(), [syntaxTree()], syntaxTree()}]}]}], Args::syntaxTree(), BoundVars::[{atom(), pos()}], BoundVarsThis::[{atom(), pos()}]) -> boolean()
+ Boolean condition to execute the function application transformations.
+ +functionCall_rule(InfoList::[{mfa(), syntaxTree(), [syntaxTree()], syntaxTree()}] | [{list, [{modulename(), [{mfa(), syntaxTree(), [syntaxTree()], syntaxTree()}]}]}], FunDefInfo::mfa() | unknown, IsRefactoring::boolean(), BoundVars::[{atom(), pos()}]) -> rule()
+ Rule that substitutes external function calls.
+ +length_rule() -> rule()
+ Rule that substitutes call to length/1 from the standard.
+Generated by EDoc, Nov 5 2015, 16:30:15.
+ + diff --git a/docs/doc/symbolic_evaluation/core/core_if.html b/docs/doc/symbolic_evaluation/core/core_if.html new file mode 100644 index 00000000..98edc6f4 --- /dev/null +++ b/docs/doc/symbolic_evaluation/core/core_if.html @@ -0,0 +1,78 @@ + + + + +Copyright © (C) 2014, Gabriela C. Sampaio, Roberto S. M. de Barros Filho, Simon Thompson
+ +Authors: Gabriela Cunha Sampaio, Roberto Souto Maior de Barros Filho.
+ ++If Core - Where possible, simplifies if expressions by the result of their evaluation.
+ + Examples of usage: +rules/2 | + Returns a list with a single rule for the if simplification. |
rules(X1::{term(), VarsInfo::[{[{atom(), pos()}], syntaxTree()}], term()}, X2::term()) -> [rule()]
+ Returns a list with a single rule for the if simplification.
+Generated by EDoc, Nov 5 2015, 16:30:15.
+ + diff --git a/docs/doc/symbolic_evaluation/core/core_lists_concat.html b/docs/doc/symbolic_evaluation/core/core_lists_concat.html new file mode 100644 index 00000000..0cf1082e --- /dev/null +++ b/docs/doc/symbolic_evaluation/core/core_lists_concat.html @@ -0,0 +1,46 @@ + + + + +Copyright © (C) 2014, Gabriela C. Sampaio, Roberto S. M. de Barros Filho, Simon Thompson
+ +Authors: Gabriela Cunha Sampaio, Roberto Souto Maior de Barros Filho.
+ +rules/2 | + Returns a list with a single rule for the lists concatenation simplification. |
rules(X1::term(), X2::term()) -> [rule()]
+ Returns a list with a single rule for the lists concatenation simplification.
+Generated by EDoc, Nov 5 2015, 16:30:15.
+ + diff --git a/docs/doc/symbolic_evaluation/core/core_unreferenced_assign.html b/docs/doc/symbolic_evaluation/core/core_unreferenced_assign.html new file mode 100644 index 00000000..b8cc5ef5 --- /dev/null +++ b/docs/doc/symbolic_evaluation/core/core_unreferenced_assign.html @@ -0,0 +1,105 @@ + + + + +Copyright © (C) 2014, Gabriela C. Sampaio, Roberto S. M. de Barros Filho, Simon Thompson
+ +Authors: Gabriela Cunha Sampaio, Roberto Souto Maior de Barros Filho.
+ ++Remove Unreferenced Assignments - Removes assignments when the variables are not used afterwards.
+ + For example, the expression:collector_var_expr_value/1 | + Collects all the assignments within Scope. |
collector_variable_occurrences/1 | + Collects all the variable occurrences within Scope. |
rules/2 | + List of rules to remove unreferenced assignments. |
variable_assignment_cond/2 | + Returns true if the variable is unused and false otherwise. |
variable_assignment_rule/1 | + Removes unreferenced assignments in a list of steps. |
variable_assignment_rule_begin/1 | + Removes unreferenced assignments in a list of steps within a begin/end block. |
collector_var_expr_value(Scope::syntaxTree()) -> [{[{atom(), pos()}], syntaxTree()}]
+ Collects all the assignments within Scope.
+ +collector_variable_occurrences(Scope::syntaxTree()) -> [{atom(), pos()}]
+ Collects all the variable occurrences within Scope.
+ ++ List of rules to remove unreferenced assignments. This list contains the following rules: +
variable_assignment_cond(Var@::syntaxTree(), Info::[{atom(), pos()}]) -> boolean()
+ Returns true if the variable is unused and false otherwise.
+ ++ Removes unreferenced assignments in a list of steps.
+ ++ Removes unreferenced assignments in a list of steps within a begin/end block.
+Generated by EDoc, Nov 5 2015, 16:30:15.
+ + diff --git a/docs/doc/symbolic_evaluation/core/erlang.png b/docs/doc/symbolic_evaluation/core/erlang.png new file mode 100644 index 00000000..987a618e Binary files /dev/null and b/docs/doc/symbolic_evaluation/core/erlang.png differ diff --git a/docs/doc/symbolic_evaluation/core/index.html b/docs/doc/symbolic_evaluation/core/index.html new file mode 100644 index 00000000..26e9203f --- /dev/null +++ b/docs/doc/symbolic_evaluation/core/index.html @@ -0,0 +1,18 @@ + + + +core_arit_calc |
core_arit_simpl |
core_arithmetics |
core_boolean_operators |
core_case |
core_funApp |
core_if |
core_lists_concat |
core_unreferenced_assign |
Copyright © (C) 2014, Gabriela C. Sampaio, Roberto S. M. de Barros Filho, Simon Thompson
+Authors: Gabriela Cunha Sampaio, Roberto Souto Maior de Barros Filho.
+ +The core files, use Wrangler, to propose a number of simplifications that perform symbolic evaluation in Erlang. More specifically, the following modules belong to these group: +Generated by EDoc, Nov 5 2015, 16:30:15.
+ + diff --git a/docs/doc/symbolic_evaluation/core/stylesheet.css b/docs/doc/symbolic_evaluation/core/stylesheet.css new file mode 100644 index 00000000..ab170c09 --- /dev/null +++ b/docs/doc/symbolic_evaluation/core/stylesheet.css @@ -0,0 +1,55 @@ +/* standard EDoc style sheet */ +body { + font-family: Verdana, Arial, Helvetica, sans-serif; + margin-left: .25in; + margin-right: .2in; + margin-top: 0.2in; + margin-bottom: 0.2in; + color: #000000; + background-color: #ffffff; +} +h1,h2 { + margin-left: -0.2in; +} +div.navbar { + background-color: #add8e6; + padding: 0.2em; +} +h2.indextitle { + padding: 0.4em; + background-color: #add8e6; +} +h3.function,h3.typedecl { + background-color: #add8e6; + padding-left: 1em; +} +div.spec { + margin-left: 2em; + background-color: #eeeeee; +} +a.module { + text-decoration:none +} +a.module:hover { + background-color: #eeeeee; +} +ul.definitions { + list-style-type: none; +} +ul.index { + list-style-type: none; + background-color: #eeeeee; +} + +/* + * Minor style tweaks + */ +ul { + list-style-type: square; +} +table { + border-collapse: collapse; +} +td { + padding: 3 +} diff --git a/docs/doc/symbolic_evaluation/evaluator/erlang.png b/docs/doc/symbolic_evaluation/evaluator/erlang.png new file mode 100644 index 00000000..987a618e Binary files /dev/null and b/docs/doc/symbolic_evaluation/evaluator/erlang.png differ diff --git a/docs/doc/symbolic_evaluation/evaluator/eval_inline_variable.html b/docs/doc/symbolic_evaluation/evaluator/eval_inline_variable.html new file mode 100644 index 00000000..7b574ffa --- /dev/null +++ b/docs/doc/symbolic_evaluation/evaluator/eval_inline_variable.html @@ -0,0 +1,46 @@ + + + + +Copyright © (C) 2014, Gabriela C. Sampaio, Roberto S. M. de Barros Filho, Simon Thompson
+ +Authors: Gabriela Sampaio, Roberto Souto Maior.
+ ++This modules substitutes variable occurrences by their value.
+ + Only variables defined via a match expression of the format: VarName = Expr can be inlined. Consider the code below:Generated by EDoc, Nov 5 2015, 16:30:16.
+ + diff --git a/docs/doc/symbolic_evaluation/evaluator/evaluator.html b/docs/doc/symbolic_evaluation/evaluator/evaluator.html new file mode 100644 index 00000000..19e88d7c --- /dev/null +++ b/docs/doc/symbolic_evaluation/evaluator/evaluator.html @@ -0,0 +1,53 @@ + + + + +Copyright © (C) 2014, Gabriela C. Sampaio, Simon Thompson
+ +Authors: Gabriela Sampaio.
+ +start/1 | + This function starts the evaluator. |
start/2 | + This function starts the evaluator. |
start(DefFilesInp) -> any()
+
+ This function starts the evaluator.
+ - DefFilesInp: list of atoms representing the names of the Erlang modules containing definitions. It is assumed, in this function,
+ that these files are in the current directory.
start(DefFilesInput, Options) -> any()
+
+ This function starts the evaluator.
+ - DefFilesInput: list of atoms representing the names of the Erlang modules containing definitions.
+ - Options: a list of tuples. One tuple should represent the search paths and the other the timeout. They can be defined in any order
+ and each tuple should contain an atom specifying if is search paths or timeout and the respective value. If a timeout is defined, the
+ evaluation will not stop before this time. The search paths allow the user to choose which directory(ies) contain the Erlang file(s).
+ A possible call would be:
+ evaluator:start([file1,file2,...,fileN],[{timeout, Timeout},{search_paths,[Search_Path1,Search_Path2,...,Search_PathN]}],
+ where file1,file2,...,fileN, timeout and search_paths are atoms, Timeout is an integer representing the
+ timeout and Search_Path1, Search_Path2,..., Search_PathN are strings representing the search paths.
Generated by EDoc, Nov 5 2015, 16:30:16.
+ + diff --git a/docs/doc/symbolic_evaluation/evaluator/index.html b/docs/doc/symbolic_evaluation/evaluator/index.html new file mode 100644 index 00000000..32bf8a84 --- /dev/null +++ b/docs/doc/symbolic_evaluation/evaluator/index.html @@ -0,0 +1,18 @@ + + + +eval_inline_variable |
evaluator |
Copyright © 2014 Gabriela Sampaio, Simon Thompson
+Authors: Gabriela Sampaio (gaby.sampaio@gmail.com), Simon Thompson (s.j.thompson@kent.ac.uk).
+The Erlang Teaching Tool for Symbolic Evaluation was created +with the aim of teaching how expressions are evaluated in Erlang.
+ +
+Symbolic evaluation is a form of static program execution in which symbolic expressions are used to represent arbitrary values of program variables and computations. This tool was created with the aim of teaching how expressions are evaluated in Erlang. The tool is able to evaluate not only arbitrary expressions, but also symbolic ones. The tool can be used by any Erlang programmer, but is more useful for beginners or teachers in the area. The idea is that the user can interact with the application by evaluating an expression step-by-step.
+Symbolic transformations were created using Wrangler API. Wrangler is the refactoring tool for Erlang and it is user-extensible, i.e., users can create their own refactorings. With this possibility, some simplifications were built and are used in this project.
These simplifications are always used together. Thus, if the user types an expression that can be simplified by more than one type of evaluator, they are both used and each one simplifies a part of the expression.
+ ++The tool is distributed with the Wrangler tool. The user needs to download Wrangler from the Github website https://github.com/RefactoringTools/Wrangler, and run the evaluator in the Erlang shell.
+ +
+To use the evaluator, the user needs to have Wrangler and Erlang installed. The application works in the Erlang shell. To start the evaluator, one of the functions start/1 and start/2 should be called. This function is described in the Evaluator module. After the evaluator is started, two inputs are needed:
+- An expression: the user should write Erlang files containing definitions (modules, functions) and ideally, this expression should use these definitions. The expression can be a function call, an arithmetic calculation, a lists concatenation, etc.
+- A number of steps: the user can choose a number of steps to be applied in the evaluation process. This number can be:
+ *A positive number: steps are applied "forward" in the evaluation process.
+ *A negative number: the respective number of steps are undone.
+ *"F" or "f" (for "full"): all steps are applied.
Generated by EDoc, Nov 5 2015, 16:30:16.
+ + diff --git a/docs/doc/symbolic_evaluation/evaluator/stylesheet.css b/docs/doc/symbolic_evaluation/evaluator/stylesheet.css new file mode 100644 index 00000000..ab170c09 --- /dev/null +++ b/docs/doc/symbolic_evaluation/evaluator/stylesheet.css @@ -0,0 +1,55 @@ +/* standard EDoc style sheet */ +body { + font-family: Verdana, Arial, Helvetica, sans-serif; + margin-left: .25in; + margin-right: .2in; + margin-top: 0.2in; + margin-bottom: 0.2in; + color: #000000; + background-color: #ffffff; +} +h1,h2 { + margin-left: -0.2in; +} +div.navbar { + background-color: #add8e6; + padding: 0.2em; +} +h2.indextitle { + padding: 0.4em; + background-color: #add8e6; +} +h3.function,h3.typedecl { + background-color: #add8e6; + padding-left: 1em; +} +div.spec { + margin-left: 2em; + background-color: #eeeeee; +} +a.module { + text-decoration:none +} +a.module:hover { + background-color: #eeeeee; +} +ul.definitions { + list-style-type: none; +} +ul.index { + list-style-type: none; + background-color: #eeeeee; +} + +/* + * Minor style tweaks + */ +ul { + list-style-type: square; +} +table { + border-collapse: collapse; +} +td { + padding: 3 +} diff --git a/docs/doc/symbolic_evaluation/refactorings/erlang.png b/docs/doc/symbolic_evaluation/refactorings/erlang.png new file mode 100644 index 00000000..987a618e Binary files /dev/null and b/docs/doc/symbolic_evaluation/refactorings/erlang.png differ diff --git a/docs/doc/symbolic_evaluation/refactorings/index.html b/docs/doc/symbolic_evaluation/refactorings/index.html new file mode 100644 index 00000000..342fb5c0 --- /dev/null +++ b/docs/doc/symbolic_evaluation/refactorings/index.html @@ -0,0 +1,18 @@ + + + +refac_all |
refac_arit_calc |
refac_arit_simpl |
refac_arithmetics |
refac_boolean_operators |
refac_case |
refac_funApp |
refac_if |
refac_inline_variable |
refac_lists_concat |
refac_unreferenced_assign |
Copyright © (C) 2014, Roberto S. M. de Barros Filho, Simon Thompson
+Authors: Roberto Souto Maior de Barros Filho.
+See also: gen_refac.
+ +This set of refactorings, uses Wrangler API, to propose a number of simplifications that perform symbolic evaluation in Erlang. More specifically, the following refactorings belong to these group: +Generated by EDoc, Nov 5 2015, 16:30:17.
+ + diff --git a/docs/doc/symbolic_evaluation/refactorings/refac_all.html b/docs/doc/symbolic_evaluation/refactorings/refac_all.html new file mode 100644 index 00000000..7ade3dd1 --- /dev/null +++ b/docs/doc/symbolic_evaluation/refactorings/refac_all.html @@ -0,0 +1,34 @@ + + + + +Copyright © (C) 2013, Roberto S. M. de Barros Filho, Simon Thompson
+ +Behaviours: gen_refac.
+Authors: Roberto Souto Maior de Barros Filho.
+ +Generated by EDoc, Nov 5 2015, 16:30:17.
+ + diff --git a/docs/doc/symbolic_evaluation/refactorings/refac_arit_calc.html b/docs/doc/symbolic_evaluation/refactorings/refac_arit_calc.html new file mode 100644 index 00000000..f6604099 --- /dev/null +++ b/docs/doc/symbolic_evaluation/refactorings/refac_arit_calc.html @@ -0,0 +1,31 @@ + + + + +Copyright © (C) 2013, Roberto S. M. de Barros Filho, Simon Thompson
+ +Behaviours: gen_refac.
+Authors: Roberto Souto Maior de Barros Filho.
+ ++ Unfortunately, there are some cases that are still not being covered. +
However, if the expression contains integers and variables but they are not mixed, as in "1 + 2 + 3 + X + 2*X + Y", the refactoring can be done and the expression would become "6 + 3 * X + Y" for this example.
Generated by EDoc, Nov 5 2015, 16:30:17.
+ + diff --git a/docs/doc/symbolic_evaluation/refactorings/refac_arit_simpl.html b/docs/doc/symbolic_evaluation/refactorings/refac_arit_simpl.html new file mode 100644 index 00000000..64266fdc --- /dev/null +++ b/docs/doc/symbolic_evaluation/refactorings/refac_arit_simpl.html @@ -0,0 +1,37 @@ + + + + +Copyright © (C) 2013, Roberto S. M. de Barros Filho, Simon Thompson
+ +Behaviours: gen_refac.
+Authors: Roberto Souto Maior de Barros Filho.
+ +We can include here the following cases: +
These refactorings can only by applied to integers, variables and expressions formed by these two types.
Generated by EDoc, Nov 5 2015, 16:30:17.
+ + diff --git a/docs/doc/symbolic_evaluation/refactorings/refac_arithmetics.html b/docs/doc/symbolic_evaluation/refactorings/refac_arithmetics.html new file mode 100644 index 00000000..8c35e4ae --- /dev/null +++ b/docs/doc/symbolic_evaluation/refactorings/refac_arithmetics.html @@ -0,0 +1,28 @@ + + + + +Copyright © (C) 2014, Roberto S. M. de Barros Filho, Simon Thompson
+ +Behaviours: gen_refac.
+Authors: Roberto Souto Maior de Barros Filho.
+ ++ Arithmetic Operators - Covers arithmetic expressions. This refactoring uses Wrangler API and can be found in Wrangler -> Refactor -> gen_refac Refacs -> Symbolic Evaluation -> Arithmetic Operators.
+ + For more details of the simplifications performed, please refer to Arithmetics Operators Core.Generated by EDoc, Nov 5 2015, 16:30:17.
+ + diff --git a/docs/doc/symbolic_evaluation/refactorings/refac_boolean_operators.html b/docs/doc/symbolic_evaluation/refactorings/refac_boolean_operators.html new file mode 100644 index 00000000..b480b191 --- /dev/null +++ b/docs/doc/symbolic_evaluation/refactorings/refac_boolean_operators.html @@ -0,0 +1,28 @@ + + + + +Copyright © (C) 2014, Roberto S. M. de Barros Filho, Simon Thompson
+ +Behaviours: gen_refac.
+Authors: Roberto Souto Maior de Barros Filho.
+ ++ Boolean Operators - Simplifies the defined boolean operators to true or false. This refactoring uses Wrangler API and can be found in Wrangler -> Refactor -> gen_refac Refacs -> Symbolic Evaluation -> Boolean Operators.
+ + For more details of the transformation, please see Boolean Operators Core.Generated by EDoc, Nov 5 2015, 16:30:17.
+ + diff --git a/docs/doc/symbolic_evaluation/refactorings/refac_case.html b/docs/doc/symbolic_evaluation/refactorings/refac_case.html new file mode 100644 index 00000000..dafaa5fb --- /dev/null +++ b/docs/doc/symbolic_evaluation/refactorings/refac_case.html @@ -0,0 +1,28 @@ + + + + +Copyright © (C) 2014, Roberto S. M. de Barros Filho, Simon Thompson
+ +Behaviours: gen_refac.
+Authors: Roberto Souto Maior de Barros Filho.
+ ++ Case - Where possible, simplifies case expressions by the result of their evaluation. This refactoring uses Wrangler API and can be found in Wrangler -> Refactor -> gen_refac Refacs -> Symbolic Evaluation -> Case.
+ + For more details on the alterations, please refer to Case Core.Generated by EDoc, Nov 5 2015, 16:30:17.
+ + diff --git a/docs/doc/symbolic_evaluation/refactorings/refac_funApp.html b/docs/doc/symbolic_evaluation/refactorings/refac_funApp.html new file mode 100644 index 00000000..a8fe4606 --- /dev/null +++ b/docs/doc/symbolic_evaluation/refactorings/refac_funApp.html @@ -0,0 +1,51 @@ + + + + +Copyright © (C) 2013, Roberto S. M. de Barros Filho, Simon Thompson
+ +Behaviours: gen_refac.
+Authors: Roberto Souto Maior de Barros Filho.
+ +Unfold Function Application - Substitute function calls by its application. This refactoring uses Wrangler API and can be found in Wrangler -> Refactor -> gen_refac Refacs -> Symbolic Evaluation -> Unfold Function Application.
+ +Most of the transformation in this module are from Unfold Function Application Core.
+ +Nevertheless, the following simplification is also done in this module:
+ + Internal calls - Function application for function calls from internal modules. To illustrate, consider the following definition of the function double/1:rules/2 | + Return the list of rules for the function application refactoring. |
rules(X1::{{InternalInfo::[{mfa(), syntaxTree(), [syntaxTree()], syntaxTree()}], ExternalInfo::[{mfa(), syntaxTree(), [syntaxTree()], syntaxTree()}] | [{list, [{modulename(), [{mfa(), syntaxTree(), [syntaxTree()], syntaxTree()}]}]}]}, term(), BoundVars::[{atom(), pos()}]}, FunDefInfo::mfa() | unknown) -> [rule()]
+ Return the list of rules for the function application refactoring. This is formed by: +
Generated by EDoc, Nov 5 2015, 16:30:17.
+ + diff --git a/docs/doc/symbolic_evaluation/refactorings/refac_if.html b/docs/doc/symbolic_evaluation/refactorings/refac_if.html new file mode 100644 index 00000000..afb1a932 --- /dev/null +++ b/docs/doc/symbolic_evaluation/refactorings/refac_if.html @@ -0,0 +1,28 @@ + + + + +Copyright © (C) 2014, Roberto S. M. de Barros Filho, Simon Thompson
+ +Behaviours: gen_refac.
+Authors: Roberto Souto Maior de Barros Filho.
+ ++ If - Where possible, simplifies if expressions by the result of their evaluation. This refactoring uses Wrangler API and can be found in Wrangler -> Refactor -> gen_refac Refacs -> Symbolic Evaluation -> If.
+ + For examples of simplifications, please refer to If Core.Generated by EDoc, Nov 5 2015, 16:30:17.
+ + diff --git a/docs/doc/symbolic_evaluation/refactorings/refac_inline_variable.html b/docs/doc/symbolic_evaluation/refactorings/refac_inline_variable.html new file mode 100644 index 00000000..bf25e437 --- /dev/null +++ b/docs/doc/symbolic_evaluation/refactorings/refac_inline_variable.html @@ -0,0 +1,33 @@ + + + + +Copyright © (C) 2014, Roberto S. M. de Barros Filho, Simon Thompson
+ +Behaviours: gen_refac.
+Authors: Roberto Souto Maior de Barros Filho.
+ ++ Inline Variable - Inline a variable definition. This refactoring uses Wrangler API and can be found in Wrangler -> Refactor -> gen_refac Refacs -> Inline Variable.
+ +To unfold instances of a variable, point the cursor to the variable assignment and the select + Inline Variable from the item gen_refacs in the Wrangler Refactor menu. + After that, Wrangler will search for the occurrences of the selected variable and let you choose which instance to unfold. + Only variables defined via a match expression of the format: VarName = Expr can be inlined.
+ + If the user chooses to inline all instances of a variable, the match expression is also removed.Generated by EDoc, Nov 5 2015, 16:30:17.
+ + diff --git a/docs/doc/symbolic_evaluation/refactorings/refac_lists_concat.html b/docs/doc/symbolic_evaluation/refactorings/refac_lists_concat.html new file mode 100644 index 00000000..2251eedb --- /dev/null +++ b/docs/doc/symbolic_evaluation/refactorings/refac_lists_concat.html @@ -0,0 +1,28 @@ + + + + +Copyright © (C) 2014, Roberto S. M. de Barros Filho, Simon Thompson
+ +Behaviours: gen_refac.
+Authors: Roberto Souto Maior de Barros Filho.
+ ++ Lists Concatenation - Simplifies lists concatenations. This refactoring uses Wrangler API and can be found in Wrangler -> Refactor -> gen_refac Refacs -> Symbolic Evaluation -> Lists Concatenation.
+ + For more details of the transformation, please refer to Lists Concatenation Core.Generated by EDoc, Nov 5 2015, 16:30:17.
+ + diff --git a/docs/doc/symbolic_evaluation/refactorings/refac_unreferenced_assign.html b/docs/doc/symbolic_evaluation/refactorings/refac_unreferenced_assign.html new file mode 100644 index 00000000..0ea65411 --- /dev/null +++ b/docs/doc/symbolic_evaluation/refactorings/refac_unreferenced_assign.html @@ -0,0 +1,65 @@ + + + + +Copyright © (C) 2014, Roberto S. M. de Barros Filho, Simon Thompson
+ +Behaviours: gen_refac.
+Authors: Roberto Souto Maior de Barros Filho.
+ ++ Remove Unreferenced Assignments - Removes assignments when the variables are not used afterwards. This refactoring uses Wrangler API and can be found in Wrangler -> Refactor -> gen_refac Refacs -> Symbolic Evaluation -> Remove Unreferenced Assignments.
+ + For example, the expression:rules/2 | + List of rules that remove unreferenced assignments for this refactoring. |
rules(CollectResult::{modulename(), {mfa() | unknown, [syntaxTree()], [[syntaxTree()]], [[{atom(), pos()}]], [syntaxTree()]}}, FunInfo::{function | project | file, mfa() | unknown}) -> [rule()]
+ List of rules that remove unreferenced assignments for this refactoring. The following rules exist: +
Generated by EDoc, Nov 5 2015, 16:30:17.
+ + diff --git a/docs/doc/symbolic_evaluation/refactorings/stylesheet.css b/docs/doc/symbolic_evaluation/refactorings/stylesheet.css new file mode 100644 index 00000000..ab170c09 --- /dev/null +++ b/docs/doc/symbolic_evaluation/refactorings/stylesheet.css @@ -0,0 +1,55 @@ +/* standard EDoc style sheet */ +body { + font-family: Verdana, Arial, Helvetica, sans-serif; + margin-left: .25in; + margin-right: .2in; + margin-top: 0.2in; + margin-bottom: 0.2in; + color: #000000; + background-color: #ffffff; +} +h1,h2 { + margin-left: -0.2in; +} +div.navbar { + background-color: #add8e6; + padding: 0.2em; +} +h2.indextitle { + padding: 0.4em; + background-color: #add8e6; +} +h3.function,h3.typedecl { + background-color: #add8e6; + padding-left: 1em; +} +div.spec { + margin-left: 2em; + background-color: #eeeeee; +} +a.module { + text-decoration:none +} +a.module:hover { + background-color: #eeeeee; +} +ul.definitions { + list-style-type: none; +} +ul.index { + list-style-type: none; + background-color: #eeeeee; +} + +/* + * Minor style tweaks + */ +ul { + list-style-type: square; +} +table { + border-collapse: collapse; +} +td { + padding: 3 +} diff --git a/docs/doc/wrangler_gen.html b/docs/doc/wrangler_gen.html new file mode 100644 index 00000000..5214dde5 --- /dev/null +++ b/docs/doc/wrangler_gen.html @@ -0,0 +1,119 @@ + + + + +fa() = fun(({FunName::atom(), Arity::integer()}) -> boolean()) | {atom(), integer()}
+ + +file_filter() = {file, fun((File::filename()) -> boolean())}
+ + +generator() = {lazy_gen, function()}
+ + +lazy_refac() = {elementary_refac(), generator()}
+ + +mod_or_file() = file_filter() | module_filter() | atom() | filename()
+ + +module_filter() = {module, fun((Mod::atom()) -> boolean())}
+ + +search_paths() = [filename() | dir()]
+ + +add_to_export/4 | Command generator for adding function names to the export list of a module. |
fold_expr/6 | Command generator for folding expressions against a function definition. |
gen_fun/7 | Command generator for function generalisation. |
move_fun/5 | Command generator for moving functions from one module to another. |
rename_fun/5 | Command generator for renaming function names. |
rename_mod/4 | Command generator for renaming module names. |
rename_var/6 | Command generator for renaming variable names. |
swap_args/6 | Command generator for for swapping function arguments. |
tuple_args/6 | Command generator for tupling function arguments. |
unfold_fun_app/5 | Command generator for unfolding a function application. |
add_to_export(ModOrFile::mod_or_file(), Fa::fa(), Lazy::boolean(), SearchPaths::search_paths()) -> [elementary_refac()] | lazy_refac()
Command generator for adding function names to the export list of a module.
+ +fold_expr(CurModOrFile::mod_or_file(), ModOrFile::mod_or_file(), FA::fa(), ClauseIndex::integer(), Lazy::boolean(), SearhPaths::search_paths()) -> [elementary_refac()] | lazy_refac()
Command generator for folding expressions against a function definition.
+ +gen_fun(ModOrFile::mod_or_file(), FA::fa(), ExprStr::string(), NewParName::{user_input, Prompt::fun(({M::atom(), FA::{atom(), integer()}, ExprStr::string()}) -> string())} | atom() | string(), Lazy::boolean(), SearchPaths::search_paths(), GenOrder::textual | bu | td) -> [elementary_refac()] | lazy_refac()
Command generator for function generalisation.
+ +move_fun(SrcModOrFile::mod_or_file(), Fa::fa(), TagertModOrFile::mod_or_file() | {user_input, Prompt::fun(({M::atom(), FA::{atom(), integer()}}) -> string())}, Lazy::boolean(), SearchPaths::search_paths()) -> [elementary_refac()] | lazy_refac()
Command generator for moving functions from one module to another.
+ +rename_fun(ModOrFile::mod_or_file(), Fa::fa(), NewFunName::{generator, fun(({M::atom(), FA::{atom(), integer()}}) -> atom())} | {user_input, Prompt::fun(({M::atom(), FA::{atom(), integer()}}) -> string())} | atom(), Lazy::boolean(), SearchPaths::search_paths()) -> [elementary_refac()] | lazy_refac()
Command generator for renaming function names.
+ +rename_mod(ModOrFile::mod_or_file(), NewModName::{generator, fun((M::atom() | filename()) -> string())} | {user_input, Prompt::fun((M::atom()) -> string())} | string(), Lazy::boolean(), SearchPaths::search_paths()) -> [elementary_refac()] | lazy_refac()
Command generator for renaming module names.
+ +rename_var(ModOrFile::mod_or_file(), FA::fa(), OldVarName::fun((VarName::atom()) -> boolean()) | atom(), NewVarName::{generator, fun(({M::atom(), FA::{atom(), integer()}, V::atom()}) -> atom())} | {user_input, Prompt::fun(({M::atom(), FA::{atom(), integer()}, V::atom()}) -> string())} | atom(), Lazy::boolean(), SearchPaths::search_paths()) -> [elementary_refac()] | lazy_refac()
Command generator for renaming variable names.
+ +swap_args(ModOrFile::mod_or_file(), FA::fa(), Index1::integer() | {user_input, Prompt::fun(({M::atom(), FA::{atom(), integer()}}) -> string())}, Index2::integer() | {user_input, Prompt::fun(({M::atom(), FA::{atom(), integer()}}) -> string())}, Lazy::boolean(), SearchPaths::search_paths()) -> [elementary_refac()] | lazy_refac()
Command generator for for swapping function arguments.
+ +tuple_args(ModOrFile::mod_or_file(), FA::fa(), Index1::integer() | {user_input, Prompt::fun(({M::atom(), FA::{atom(), integer()}}) -> string())}, Index2::integer() | {user_input, Prompt::fun(({M::atom(), FA::{atom(), integer()}}) -> string())}, Lazy::boolean(), SearchPaths::search_paths()) -> [elementary_refac()] | lazy_refac()
Command generator for tupling function arguments.
+ +unfold_fun_app(ModOrFile::mod_or_file(), FA::fa(), MFAorPos::fun((mfa()) -> boolean()) | mfa() | pos(), Lazy::boolean(), SearchPaths::search_paths()) -> [elementary_refac()] | lazy_refac()
Command generator for unfolding a function application.
+Generated by EDoc, Nov 5 2015, 16:30:21.
+ + diff --git a/docs/doc/wrangler_refacs.html b/docs/doc/wrangler_refacs.html new file mode 100644 index 00000000..286f34b9 --- /dev/null +++ b/docs/doc/wrangler_refacs.html @@ -0,0 +1,624 @@ + + + + +Copyright © 2006-2012 Huiqing Li, Simon Thompson +
+ +Authors: Huiqing Li, Simon Thompson [web site: http://www.cs.kent.ac.uk/projects/wrangler].
+ +context() = emacs | composite_emacs | command
+ + +add_a_tag/7 | Add a tag to all the messages received by a server process (Beta). |
add_callback/6 | + Adds a callback declaration for the function with the name + and arity specified. |
add_callbacks/5 | + Adds a callback declaration for the functions with the name + specified. |
apply_changes_eclipse/3 | gen_refac refactorings - delegate functions in order to achieve more clear API (especially for Eclipse). |
copy_mod/5 | Copy a module. |
eqc_fsm_to_record/4 | Turn a non-record representation of eqc_fsm state into a record representation. |
eqc_statem_to_record/4 | Turn a non-record representation of eqc_statem state into a record representation. |
fold_against_macro/6 | Fold expressions/patterns against a macro definition. |
fold_expr/1 | Fold expressions against a function definition. |
fun_extraction/6 | Introduce a new function to represent an expression or expression sequence. |
fun_to_process/7 | Turn a function into a server process (Beta). |
gen_fsm_to_record/4 | Turn a non-record representation of gen_fsm state into a record representation. |
generalise/7 | Generalise a function definition. |
get_user_refactorings/1 | get all user refactoring modules (gen_refac and gen_composite_refac). |
inline_var/6 | Inline a variable definition. |
intro_new_var/7 | Introduce a new variable to represent an expression selected. |
merge_forall/4 | Merge nested but undependent ?FORALLs into one ?FORALL. |
merge_let/4 | Merge nested but independent ?LETs into one ?LET. |
move_fun/7 | Move a function definition from its current module to another. |
new_let/7 | Introduce ?LET. |
new_macro/7 | Introduce a macro to represent a syntactically well-formed expression/pattern or a sequence of expressions/patterns. |
normalise_record_expr/7 | Reorder the record fields in a record expression to be consistent with the record definition. |
partition_exports/5 | Partition the exports of a module. |
register_pid/7 | Register a process (Beta). |
rename_fun/6 | Rename a function. |
rename_mod/5 | Rename a module. |
rename_process/7 | Rename a registered process (Beta). |
rename_var/7 | Rename a variable. |
similar_code_detection/6 | A similar code detector that searches for similar code across multiple Erlang modules. |
similar_code_detection_in_buffer/6 | A similar code detector that searches for similar code in the current Erlang buffer. |
similar_expression_search_in_buffer/6 | Search expression search in the current Erlang buffer. |
similar_expression_search_in_dirs/6 | Simiar expression search across multiple Erlang modules. |
tuple_funpar/6 | Group a consecutive sequence of parameters of a function into a tuple. |
unfold_fun_app/5 | Unfold a function application to an instance of the function's body. |
add_a_tag(FileName::filename(), Line::integer(), Col::integer(), Tag::string(), SearchPaths::[dir()], Context::context(), TabWidth::integer()) -> {error, string()} | {ok, [filename()]}
Add a tag to all the messages received by a server process (Beta). +
This refactoring should be initiated from the main receive function of a server process. + The current implementation is still in an experimental stage, and has a number of limitations: +
send ... receive
pattern, to other processes
+ spawn
+ or spawn_link
+ + Usage: to apply this refactoring, point the cursor to the function name, then select Add a + Tag to Messages from the Refactor menu, Wrangler will then prompt to + enter the tag. +
+ +add_callback(TargetFileName::string(), FunctionName::string(), Arity::string(), SearchPaths::[string()], Editor::wrangler_refacs:context(), TabWidth::integer()) -> {ok, UpdatedFiles::[string()]}
+ Adds a callback declaration for the function with the name + and arity specified.
+ +add_callbacks(TargetFileName::string(), FunctionName::string(), SearchPaths::[string()], Editor::wrangler_refacs:context(), TabWidth::integer()) -> {ok, UpdatedFiles::[string()]}
+ Adds a callback declaration for the functions with the name + specified.
+ +apply_changes_eclipse(Module::module(), Args::[term()], CandsNotToChange::[term()]) -> {ok, [{filename(), filename(), syntaxTree()}]} | {error, term()}
gen_refac refactorings - delegate functions in order to achieve more clear API (especially for Eclipse)
+ +copy_mod(FileName::filename(), NewName::string(), SearchPaths::[dir()], Context::context(), TabWidth::integer()) -> {error, string()} | {question, string()} | {warning, string()} | {ok, [filename()]}
Copy a module. +
This refactoring affects all those modules in which the module name is used. +
++ The following side-conditions apply to this refactoring: +
Usage: to apply this refactoring, point the cursor anywhere in the module to be copied, then select + Copy Module from the Refactor menu, after that, the refactorer will prompt to enter + the new module name in the mini-buffer. +
+ +eqc_fsm_to_record(FileName::filename(), SearchPaths::[dir()], Context::context(), TabWidth::integer()) -> {error, string()} | {ok, non_tuple, [{atom(), atom(), integer()}]} | {ok, {tuple, integer()}, [{atom(), atom(), integer()}]}
Turn a non-record representation of eqc_fsm state into a record representation. +
This refactoring introduce a record to represent the state used by eqc_fsm. + This refactoring is especially for QuickCheck users. +
+Usage: Select the refactoring command, and Wrangler will check the current type of the state machine, + and prompt you to input the record and field names if Wrangler is able to proceed the refactoring. +
+ +eqc_statem_to_record(FileName::filename(), SearchPaths::[dir()], Context::context(), TabWidth::integer()) -> {error, string()} | {ok, non_tuple, [{atom(), atom(), integer()}]} | {ok, {tuple, integer()}, [{atom(), atom(), integer()}]}
Turn a non-record representation of eqc_statem state into a record representation. +
This refactoring introduce a record to represent the state used by eqc_statem. + This refactoring is especially for QuickCheck users. +
+Usage: Select the refactoring command, and Wrangler will check the current type of the state machine, + and prompt you to input the record and field names if Wrangler is able to proceed the refactoring. +
+ +fold_against_macro(FileName::filename(), Line::integer(), Col::integer(), SearchPaths::[dir()], Context::context(), TabWidth::integer()) -> {error, string()} | {ok, [{integer(), integer(), integer(), integer(), syntaxTree(), syntaxTree()}], string()}
Fold expressions/patterns against a macro definition. +
+ This refactoring replaces instances of the right-hand side of a macro definition by the corresponding + left-hand side with necessary parameter substitutions. +
+Usage: to apply this refactoring, first point the cursor to the macro definition against which candidate + expressions/candidates will be folded; then select Fold Against Macro Definition from the + Refactor menu; after that, Wrangler will search the current module for expressions/patterns + which are instances of the right-hand side of the selected macro definition; and direct you through the + refactoring process. +
+ +fold_expr(X1) -> any()
+Fold expressions against a function definition. +
+ This refactoring replaces instances of the right-hand side of a function clause definition by + the corresponding left-hand side with necessary parameter substitutions. The function clause can + be defined in either the current module or another module. +
+In the case that a candidate expression/expression sequence needs to export some variables which + are used by the code following code, that expression/expression sequence will be replaced by a match + expression, whose left-hand side it the exported variable(s), and right-hand side is the function + application. +
+This refactoring does not support folding against function clauses with guard expressions, or + function clauses with complex formal parameters, such as tuples, lists, or records. +
+Usage: first point the cursor to the function clause against which expressions will be + folded if the function is defined in the current module, or leave the cursor anywhere if you would like to + fold against a function clause defined in another module; then select Fold Expression Against Function + from the Refactor menu; after that, Wrangler then asks to confirm that you want to fold against + the function clause pointed to by the cursor, if you answer 'no', Wrangler will prompt to provide the + module name, function name, arity of the function and the index of the function clause (starting from 1). After all these initial interaction, + Wrangler will search + the current module for expressions which are instances of the right-hand side of the selected function clause. +
+If no candidate expression has been found, a message will be given, and the refactoring + finishes; otherwise, Wrangler will go through the found candidate expressions one by one, and ask + the user whether she/he wants to replace the expression with an application of selected function. + If the user answers 'yes' to one instance, that instance will be replaced by function application, + otherwise it will remain unchanged. +
+ +fun_extraction(FileName::filename(), Start::[integer()], End::[integer()], FunName::string(), Context::context(), TabWidth::integer()) -> {error, string()} | {warning, string()} | {ok, [filename()]}
Introduce a new function to represent an expression or expression sequence. +
This refactoring allows the user to introduce a new function to represent a selected expression or expression + sequence, and replace the selected code with a call to the new function. Free variables + within the selected code become the formal parameters of the function definition. +
++ Usage: highlight the expression/expression sequence of interest, then selected the Function Extraction + from Refactor, Wrangler will then prompt for the new function name. +
+ +fun_to_process(FileName::filename(), Line::integer(), Col::integer(), ProcessName::string(), SearchPaths::[dir()], Context::context(), TabWidth::integer()) -> {ok, [filename()]} | {undecidables, string()} | {error, string()}
Turn a function into a server process (Beta). +
+ This refactoring turns a function into a server process. + Turning a function into a server process provides potential for memorisation of calculated values, adding states to the process, etc. +
+ The following example shows the application of this refactoring to the function f/2
on the
+ left-hand side, and the result is shown on the right-hand side.
+
f(add, X, Y) -> X + Y; f(add, X, Y) -> f_rpc(f, {add, X, Y}); + f(sub, X, Y) -> X - Y. f(sub, X, Y) -> f_rpc(f, {sub, X, Y}). + + g(X, Y) -> f() -> + f(add, X, Y)*f(sub, X, Y). receive + {From, {add, X, Y}} -> From ! {f, X + Y}, f(); + {From, {sub, X, Y}} -> From ! {f, X - Y}, f() + end. + + f_rpc(RegName, Request) -> + Sender = self(), + Fun = fun () -> + try + register(RegName, self()) + of + true -> Sender ! {started, self()}, f() + catch + error:_ -> + Sender ! {already_running, self()}, + already_running + end + end, + Pid = spawn(Fun), + receive {_, Pid} -> ok end, + RegName ! {self(), Request}, + receive {RegName, Response} -> Response end. + + g(X, Y) -> + f(add, X, Y) *f(sub, X, Y).+ + The following side-conditions apply to this refactoring: +
+
Pid
returned by self()
.
+ Wrangler generates the new function name and the rpc function name automatically, but the user could always rename it afterwards.
+ Suppose the original function is f/n
, then the new function name would be f/0
and the rpc
+ function name would be f_rpc/2
; if any conflicts occur, '_i'
will be attached to the end of the function
+ name where i
is a smallest number that makes the name fresh.
+
Usage: To apply this refactoring, point the cursor to the function of interest, then select + From Function to Process from Refactor, after that Wrangler will prompt + to enter the process registration name in the mini-buffer. +
+ +gen_fsm_to_record(FileName::filename(), SearchPaths::[dir()], Context::context(), TabWidth::integer()) -> {error, string()} | {ok, non_tuple, [{atom(), atom(), integer()}]} | {ok, {tuple, integer()}, [{atom(), atom(), integer()}]}
Turn a non-record representation of gen_fsm state into a record representation. +
This refactoring introduce a record to represent the state used by eqc_statem. +
+Usage: Select the refactoring command, and Wrangler will check the current type of the state machine, + and prompt you to input the record and field names if Wrangler is able to proceed the refactoring. +
+ +generalise(FileName::filename(), Start::[integer()], End::[integer()], ParName::string(), SearchPaths::[dir()], Context::context(), TabWidth::integer()) -> {ok, [filename()]} | {error, string()} | {multiple_instances, {atom(), atom(), integer(), pos(), syntaxTree(), boolean(), [{pos(), pos()}], string()}} | {unknown_side_effect, {atom(), atom(), integer(), pos(), syntaxTree(), integer(), [{pos(), pos()}], [{pos(), pos()}], string()}} | {more_than_one_clause, {atom(), atom(), integer(), pos(), syntaxTree(), boolean(), [{pos(), pos()}], [{pos(), pos()}], string()}}
Generalise a function definition. +
Generalise a function definition by selecting a sub-expression of its right-hand + side and making this the value of a new argument added to the definition of the function. + The sub-expression becomes the actual parameter at the call sites.
+ + Here is an example of generalisation, in which the function add_one
defined
+ on the left-hand side is generalised on the expression 1
, and the result is
+ shown on the right-hand side.
+
+
-module (test). -module (test). + -export([f/1]). -export([f/1]). + + add_one ([H|T]) -> add_one (N, [H|T]) -> + [H+1 | add_one(T)]; [H+N | add_one(N,T)]; + add_one ([]) -> []. add_one (N, []) -> []. + + f(X) -> add_one(X). f(X) -> add_one(1,X)+ + +
In the case that the selected expression has a side-effect, the refactorer will wrap this expression
+ in an function expression before passing it as the actual parameter to the call-sites. This is illustrated
+ in the following example, in which function repeat/1
is generalised on the expression
+ io:format("Hello\n")
.
+
+
-module (test). -module (test). + -export([f/0]). -export([f/0]). + + repeat(0) -> ok; repeat(A, 0) -> ok; + repeat(N) -> repeat(A, N) -> + io:format("Hello\n"), A( ), + repeat(N-1). repeat(A,N-1). + + f() -> repeat(5). f( ) -> + repeat (fun( )->io:format ("Hello\n") end, 5).+ + +
This refactoring only affects the module in which the refactoring is initialised. In the case that + the generalised function is exported by the module, an auxiliary function will be created + to wrap the generalised function up, so that the module's interface is not changed. +
+The following side-conditions apply to this refactoring: +
foo/n
, then foo/n+1
should not
+ be in scope before the generalisation;Usage: to apply this refactoring, highlight the expression first, then select + Generalise Function Definitio5n from the Refactor menu, after + that the refactorer will prompt to enter the parameter name in the mini-buffer.
+ + NOTE: in Erlang some literal expressions can not be replaced by variables. For example, the atomfields
+ in the expression record_info(fields, Record)
should not be replaced by a variable or other expressions.
+ This kind of checking is NOT supported by Wrangler yet.
+
+get_user_refactorings(Modules) -> any()
+get all user refactoring modules (gen_refac and gen_composite_refac)
+ +inline_var(FName::filename(), Line::integer(), Col::integer(), SearchPaths::[dir()], Context::context(), TabWidth::integer()) -> {error, string()} | {ok, string()} | {ok, [{pos(), pos()}], string()}
Inline a variable definition. +
To unfold a particular use instance of a variable, point the cursor to that instance, and then select + Inline Variable from the Refactor menu; to unfold some, or all, use instances of + a variable, point the cursor to the define occurrence of the variable, then select Inline Variable + from the Refactor menu, Wrangler will search for the use occurrences of the variable selected, and + let you choose which instances to unfold. Only variables defined via a match expression of the + format: VarName=Expr can be inlined. +
+ +intro_new_var(FileName::filename(), Start::[integer()], End::[integer()], NewVarName::string(), SearchPaths::[dir()], Context::context(), TabWidth::integer()) -> {error, string()} | {ok, string()}
Introduce a new variable to represent an expression selected. +
+ Usage: Highlight the expression of interest, then selected the Introduce New Variable + from Refactor, Wrangler will then prompt for the new variable name. +
+ +merge_forall(FileName::filename, SearchPaths::[dir()], Context::context(), TabWidth::integer()) -> {error, string()} | {not_found, string()} | {ok, [{integer(), integer(), integer(), integer(), string()}], string()}
Merge nested but undependent ?FORALLs into one ?FORALL. +
This refactoring combines multiple nested, but undependent, ?FORALLs into one; the latter representation has + better shrinking performance. This refactoring is especially for QuickCheck users. +
++ Usage: Select the refactoring command, and Wrangler will search for candidates to merge automatically, + guide you through the candidates found one by one, and ask you to decide whether to merge. +
+ +merge_let(FileName::filename, SearchPaths::[dir()], Context::context(), TabWidth::integer()) -> {error, string()} | {not_found, string()} | {ok, [{integer(), integer(), integer(), integer(), string()}], string()}
Merge nested but independent ?LETs into one ?LET. +
This refactoring combines multiple nested, but undependent, ?LETs into one; the latter representation has + better shrinking performance. This refactoring is especially for QuickCheck users. +
++ Usage: Select the refactoring command, and Wrangler will search for candidates to merge automatically, + guide you through the candidates found one by one, and ask you to decide whether to merge. +
+ +move_fun(FileName::filename(), Line::integer(), Col::integer(), TargetModName::string(), SearchPaths::[dir()], Context::context(), TabWidth::integer()) -> {ok, [filename()]} | {question, string()} | {error, string()}
Move a function definition from its current module to another. +
This refactoring has a global effect, i.e., it affects all the modules in which + the function is imported/used. +
+This refactoring assumes that an Erlang module name always matches its file name. +
+Suppose we move function foo/n from its current module M + to module N , then the following side-conditions apply to + this refactoring: +
Usage: to apply this refactoring, point the cursor at the function definition, then + select Move Definition to Another Module from the Refactor menu, + Wrangler will then prompt to enter the target module name in the mini-buffer. +
+ +new_let(FileName::filename(), Start::[integer()], End::[integer()], PatName::string(), SearchPaths::[dir()], Context::context(), TabWidth::integer()) -> {error, string()} | {ok, [filename()]} | {question, string(), list(), list(), string()}
Introduce ?LET. +
Bind the values generated by a generator to a variable, so that the values generated by + the generator can be referred by other generators. The refactoring helps to introduce dependency + between QuickCheck generators. This refactoring is especially for QuickCheck users. +
++ Usage: highlight the expression, which should be a QuickCheck generator, then select the + refactoring command, you will be prompted for the pattern variable name. +
+ +new_macro(FileName::filename(), Start::[integer()], End::[integer()], MacroName::string(), SearchPaths::[dir()], Context::context(), TabWidth::integer()) -> {error, string()} | {ok, string()}
Introduce a macro to represent a syntactically well-formed expression/pattern or a sequence of expressions/patterns. +
This refactoring allows the user to define a new macro to represent a expression/pattern or sequence + of expressions/patterns selected by the user, and replace the selected code with an application of the macro. + Free variables within the selected code become the formal parameters of the macro definition. +
++ Usage: Highlight the expression of interest, then selected the Introduce a Macro + from Refactor, Wrangler will then prompt for the new macro name. +
+ +normalise_record_expr(FileName::filename(), Line::integer(), Col::integer(), ShowDefault::boolean(), SearchPaths::[dir()], Context::context(), TabWidth::integer()) -> {error, string()} | {ok, [filename()]}
Reorder the record fields in a record expression to be consistent with the record definition. +
+ Usage: point cursor to the record expression interested, then select Normalise Record Expression from Refactor. +
+ +partition_exports(File::filename(), DistTreshold::string(), SearchPaths::[filename() | dir()], Context::context(), TabWidth::integer()) -> {error, string()} | {ok, [filename()]}
Partition the exports of a module.
+ +register_pid(FileName::filename(), Start::[integer()], End::[integer()], RegName::string(), SearchPaths::[dir()], Context::context(), TabWidth::integer()) -> {error, string()} | {ok, [filename()]}
Register a process (Beta). +
This refactoring registers a process id, Pid
say, with a name, regname say, and replaces
+ the uses of Pid ! Msg
with regname ! Msg
whenever it is possible.
+
+ The following side-conditions apply to this refactoring: +
+ Usage: First select a match expression whose left-hand side is a process identifier, and right-hand side is a spawn expression, + then select Register a Process command from the Refactor menu, after that, Wrangler will prompt for the + process name. +
+ +rename_fun(ModOrFileName, X2, NewFunName, SearchPaths, Editor, TabWidth) -> any()
+Rename a function. +
+ When renaming an exported function, this refactoring has a global effect, that is, + it affects all those modules in which this function is imported/used. +
+The following side-conditions (or pre-conditions} apply to this refactoring: +
Usage: to apply this refactoring, point the cursor to any occurrence of this + function name, then select Rename Function Name from the Refactor menu, + after that, Wrangler will prompt to enter the new function name in the mini-buffer. +
+ +rename_mod(FileName::filename(), NewName::string(), SearchPaths::[dir()], Context::context(), TabWidth::integer()) -> {error, string()} | {question, string()} | {warning, string()} | {ok, [filename()]}
Rename a module. +
This refactoring affects all those modules in which the module name is used. +
++ The following side-conditions apply to this refactoring: +
Usage: to apply this refactoring, point the cursor anywhere in the module to be renamed, then select + Rename Module Name from the Refactor menu, after that, the refactorer will prompt to enter + the new module name in the mini-buffer. +
+ +rename_process(FileName::filename(), Line::integer(), Col::integer(), NewName::string(), SearchPaths::[dir()], Context::context(), TabWidth::integer()) -> {error, string()} | {undecidables, string()} | {ok, [filename()]}
Rename a registered process (Beta). +
This refactoring has a global effect, i.e. it needs to check the whole program for places where the + original process name is used. +
+The following side-conditions apply to this refactoring: +
Usage: To apply this refactoring, point the cursor to the process name, then select + Rename a Process from the Refactor menu, after that, Wrangler will prompt + to enter the new process name in the mini-buffer. +
+ +rename_var(FileName::filename(), Line::integer(), Col::integer(), NewName::string(), SearchPaths::[dir()], Context::context(), TabWidth::integer()) -> {error, string()} | {ok, filename()}
Rename a variable. +
This refactoring has a local effect, i.e., it only affects the function clause in which the refactoring is initialized. +
+The following side-conditions (or pre-conditions) apply to this refactoring: +
Usage: to apply this refactoring, point the cursor to any occurrence of this variable, then select + Rename Variable Name from Refactor , after that, Wrangler will prompt + to enter the new variable name in the mini-buffer. +
+ +similar_code_detection(DirFileList::[filename() | dir()], MinLen::string(), MinFreq::string(), MinScore::string(), SearchPaths::[dir()], TabWidth::integer()) -> {ok, string()}
A similar code detector that searches for similar code across multiple Erlang modules. +
This function reports similar expression sequences found in the directories specified, but does not + remove those clones though. The algorithm is based on the notion of anti-unification, or the least common generalisation. + The user needs to provide three parameters to be used by the clone detector, and + they are: the minimum length of an expression sequence, the minimum number of duplication times, and + a similarity score which should be between 0.1 and 1.0. +
++ Usage: select Detect Similar Code in Dirs from Similar Code Detection, Wrangler will then prompt to + input the parameters needed. +
+ +similar_code_detection_in_buffer(FileName::filename(), MinLen::string(), MinFreq::string(), MinScore::string(), SearchPaths::[dir()], TabWidth::integer()) -> {ok, string()}
A similar code detector that searches for similar code in the current Erlang buffer. +
This function reports similar expression sequences found in the current Erlang buffer, but does not + remove those clones though. The user needs to provide three parameters to be used by the clone detector, and + they are: the minimum length of an expression sequence, the minimum number of duplication times, and + a similarity score which should be between 0.1 and 1.0. +
++ Usage: select Detect Similar Code in Buffer from Similar Code Detection, Wrangler will then prompt to + input the parameters needed. +
+ +similar_expression_search_in_buffer(FileName::filename(), Start::[integer()], End::[integer()], SimiScore::string(), SearchPaths::[dir()], TabWidth::integer()) -> {ok, [{filename(), {{integer(), integer()}, {integer(), integer()}}}]}
Search expression search in the current Erlang buffer. +
This functionality allows searching for expression sequence that are similar to the expression sequence selected. In this context, + two expressions, A and B say, are similar if there exists an anti-unifier, say C, of A and B, and C satisfies the similarity score specified + by the user (the calculation calculated of similarity score is going to be further explored). +
+ Usage: highlight the expression sequence of interest, then selected Similar Expression Search in Current Buffer + from Similar Code Detection . + +similar_expression_search_in_dirs(FileName::filename(), Start::[integer()], End::[integer()], SimiScore::string(), SearchPaths::[dir()], TabWidth::integer()) -> {ok, [{filename(), {{integer(), integer()}, {integer(), integer()}}}]}
Simiar expression search across multiple Erlang modules. +
This functionality allows searching for expression sequence that are similar to the expression sequence selected. In this context, + two expressions, A and B say, are similar if there exists an anti-unifier, say C, of A and B, and C satisfies the similarity score specified + by the user (the calculation calculated of similarity score is going to be further explored). +
+ Usage: highlight the expression sequence of interest, then selected Similar Expression Search in Dirs from Simiar Code Detection. + +tuple_funpar(FileName::filename(), StartLoc::[integer()], EndLoc::[integer()], SearchPaths::[dir()], Context::context(), TabWidth::integer()) -> {error, string()} | {ok, [filename()]}
Group a consecutive sequence of parameters of a function into a tuple. +
+ When the function under consideration is exported by the module where it is defined, this refactoring has a global effect. +
+ Suppose the new function after refactoring is f/n
, then the following side-conditions apply:
+
f/n
should not cause confliction with any of the functions which are in scope in the
+ current module;f/n
+ should not be already in scope (either defined or imported) in that module. Usage: to apply this refactoring, highlight the arguments to be grouped into a tuple from + the function definition, then select Tuple Function Arguments from Refactor. +
+ +unfold_fun_app(FileName::filename(), Pos::[integer()], SearchPaths::[dir()], Context::context(), TabWidth::integer) -> {error, string()} | {ok, [string()]}
Unfold a function application to an instance of the function's body. +
This refactoring replaces a function application with an instance of the function body. + With the current implementation, Wrangler unfolds a function application only if the function + is defined in the same module, and Wrangler could work out which function clause to use (in case + the function definition contains multiple function clauses). +
++ Usage: Point the cursor to the function name in the function application to unfold, then + select Unfold Function Application from Refactor. +
+Generated by EDoc, Nov 5 2015, 16:30:21.
+ +