basex icon indicating copy to clipboard operation
basex copied to clipboard

prof:variables(): Show all variables?

Open LeoWoerteler opened this issue 10 years ago • 7 comments

Query:

prof:variables(),
let $i := random:integer() return $i * $i

Expected:

No variable bindings, some random squared number.

Got:

Exception in thread "main" java.lang.NullPointerException
    at org.basex.query.var.QueryStack.dump(QueryStack.java:135)
    at org.basex.query.func.prof.ProfVariables.item(ProfVariables.java:20)
    at org.basex.query.expr.ParseExpr.iter(ParseExpr.java:43)
    at org.basex.query.QueryContext.iter(QueryContext.java:404)
    at org.basex.query.expr.List$1.next(List.java:120)
    at org.basex.query.MainModule$1.next(MainModule.java:118)

LeoWoerteler avatar Mar 26 '15 14:03 LeoWoerteler

I would propose that prof:variables() is expanded after parsing, e.g. introducing a map from the names of in-scope variables to a VarRef.

The following query currently only outputs bindings of $a, even though it is not even actually in scope:

declare function local:foo($x) {
  let $y := $x * $x
  return
    if($x gt 1) then (
      for $i in 1 to $y
      return $x
    ) else prof:variables()
};

for $a in 1 to 5
return local:foo($a)

This could be fixed by generating the following code after all variables are resolved but before optimizing:

declare function local:foo($x) {
  let $y := $x * $x
  return
    if($x gt 1) then (
      for $i in 1 to $y
      return $x
    ) else prof:dump(
      map {
        '$x': $x,
        '$y': $y
      },
      'Local Variables: '
    )
};

for $a in 1 to 5
return local:foo($a)

Even though the function disappears and $y is inlined into the map, the output contains exactly the variables that the programmer would expect.

LeoWoerteler avatar Mar 26 '15 14:03 LeoWoerteler

I didn't think of that.. Sounds like a good idea!

ChristianGruen avatar Mar 26 '15 14:03 ChristianGruen

One interesting case are closures, should all potentially reachable variables be referenced or only the actually captured ones? The first option seems preferable, but the closure would potentially become much bigger without the programmer knowing why...

LeoWoerteler avatar Mar 26 '15 14:03 LeoWoerteler

Good point. Option 2 sounds more attractive to me; I think the output of this function should be as intuitive as possible.

ChristianGruen avatar Mar 26 '15 15:03 ChristianGruen

How about this?

for $i in 1 to 5,
    $j in 1 to 5
let $f :=
  function($k) {
    prof:variables(),
    $i * $k
  }
return $f($j)

I would expect either $i and $j in the output or none of them. We could obviously have prof:variables([xs:boolean]) with an optional flag for all in-scope variables.

LeoWoerteler avatar Mar 26 '15 15:03 LeoWoerteler

A flag may indeed be the best choice. As prof:variables is not supposed to be used in productive code, we can change or extend the function signature without too much hassle.

ChristianGruen avatar Mar 26 '15 15:03 ChristianGruen

Do you know what's the most convenient way to access all potentially reachable variables? This is the current code... https://github.com/BaseXdb/basex/blob/master/basex-core/src/main/java/org/basex/query/var/QueryStack.java#L132-L141

ChristianGruen avatar May 06 '15 12:05 ChristianGruen