[[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. A query always has the starting point {{{mods}}}. Moving on we select functions with {{{funs}}}. Here 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, that is, 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 can only be created using properties in filters. It is ''valid'' to write {{{ mods[name=A] }}} or {{{ mods.funs[A=arity] }}} but it is ''semantic error'' to write {{{ mods[A=not_a_property] }}} 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. The first {{{ = }}} or {{{ == }}} binds, the others compare. The general form of binding is the following: {{{ [property=Variable] }}} or {{{ [Variable=property] }}} Variables may bind to values of any type. They can hold atoms, integers, strings etc. == Occurences == === Filters === Variables can only 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. === 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 }}}