[[PageOutline]] = Using variables in semantic queries = While writing semantic queries sometimes we need to refer back to a property of an entity at some earlier point. To make it clear suppose we want to write such query: we would like to know about functions with the same name as the module it resides in, like {{{mymod:mymod/1}}}. Lets start with all the functions of all modules: {{{ mods.funs }}} This query has starting point {{{mods}}}. Moving on we select functions with {{{funs}}}. At this point we need to filter all the functions based on its module. Here come the variables in: The problem can easily solved by the following query: {{{ mods[name=A].funs[name==A] }}} Here for each module the variable {{{A}}} binds the module's name. Unlike in Erlang, the value of {{{A}}} changes. In the following sections we show how to make variable bindings and present some examples of using variables in semantic queries. == Binding == Variables may only be defined using properties in filters or selectors. === Properties === It is ''valid'' to write {{{ mods[name=A] }}} or {{{ mods.funs[A=arity] }}} but it is ''semantic error'' to write {{{ mods[A=this_is_not_a_property_of_modules] }}} or {{{ mods[A=2].funs[arity==A] }}} As you may noticed, the binding operator {{{ = }}} is commutative. Also, one may interchangeably use {{{ = }}} and {{{ == }}} to bind and compare. In case of variables the first {{{ = }}} or {{{ == }}} binds, the others test equality. The general form of binding to a property is the following: {{{ [property=Variable] }}} or {{{ [Variable=property] }}} Variables may bind to values of any type. They can hold atoms, integers, strings etc. === Selectors === It is also possible to bind a variable to a selector. In this case the variable holds a database node. {{{ mods->M }}} Variable {{{M}}} can function as a selector in the rest of a query. Its semantics is to set the state of current entities to the bound entity. {{{ mods->M.funs[name=foo].M.path }}} is equivalent to {{{ mods[.funs[name=foo]].path }}} Variables bound this way can be used to filter entities. It comes handy when we would like to know all the recursive functions: {{{ mods.funs->A.calls?A }}} Of course one cannot mix variables bound to properties and selectors. The following query will make the type checker complain: {{{ mods[name=M].funs?M }}} == Occurences == === Filters === Variables may occur in filters. In its simplest form a semantic query is sequence of selectors and filters. When a variable binding takes place the variable can be used in any following filter. In other words, the ''scope'' of a variable is right from its binding. {{{ mods.funs[name=A].calls[name==A] }}} yields all function that called by a function with the same name. Example output would be: {{{ module_a:f/0 module_b:f/1 module_b:g/2 module_c:g/1 }}} means in the program code {{{f/0}}} calls {{{f/1}}}. In comparisons it is allowed to use every operator that standard semantic query language allows. This means {{{==, /=, >, >=, <, <=}}} and {{{ ~ }}}. A variable can be compared to property, variable and literal. {{{ mods.funs[arity=A, A>2] mods.funs[exported=A, dirty/=A, A==true] mods[name=A].funs[name=B, A==B] }}} ==== Conversion ==== It is important to note that any form of ''conversion'' between types is ''not supported''. When you use a value of a variable in a comparison, you have to make sure that both operands have the same type. {{{ mods.funs[name=A].vars[name==A] }}} yields type error, because {{{vars.name}}} has type of string. === At the end of a query === Ending a query with a variable make RefactorErl show the set of values of that variable. {{{ mods[name=M].M }}} Results in {{{ Mymod1 M = Mymod1 Mymod2 M = Mymod2 }}} === Iterations === Writing such query as {{{ mods.funs.{calls[name=A]}2.name }}} is exactly the same as writing {{{ mods.funs.calls[name=A].calls[name=A].name }}} It sheds light on that binding always happens in the first iteration. One may use previously bound variable or use variable bound inside the iteration later: {{{ mods.funs[name=A].{calls[name==A]}3 mods.funs.{calls[name=A]}2.mod[name==A] }}} === Closures === Similarly to iterations, variables can be used in transitive closures. Here are some examples: {{{ mods.funs.(calls[name=A)+ mods.funs[name=A].(calls[name=A])2.name }}} The first means all possible call chains that consist of functions with the same name from the second chain link onwards. Example output would be: {{{ module_a:f/0 module_a:g/0 module_a:g/1 module_a:g/0 module_a:g/1 }}}