john-liu / jaql

Automatically exported from code.google.com/p/jaql
0 stars 0 forks source link

Captures of global variables may produce wrong result when rewrite is disabled #61

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
This problem occurs only when rewriting is disabled, i.e., it does not
affect Jaql in the usual case. Take the following set of statements

z = randomLong();
e = [ 1, 2, 3 ] -> transform each z z+::z;
explain e;

With rewrites enabled, the final explain produces

( z__0 = randomLong(), [ 1, 2, 3 ] -> transform each z z+z__0 );

which is correct. With rewrites disabled, we obtain

( z = randomLong(), [ 1, 2, 3 ] -> transform each z z+z );

which is incorrect. The problem occurs because the RebindVars rewrite rule
is not executed.

Original issue reported on code.google.com by Rainer.G...@gmx.de on 1 Oct 2009 at 10:54

GoogleCodeExporter commented 9 years ago
A related problem also occurs when rewrites are enabled. The following code

fn(x) (y=x, fn(x) x+y);

evaluates to

fn(x) (fn(x) x+x)

which is incorrect.

Original comment by Rainer.G...@gmx.de on 2 Oct 2009 at 4:21

GoogleCodeExporter commented 9 years ago
A solution to this problem is to separate rewrite and variable renaming, with 
rewrite
being optional and renaming being mandatory. 

Original comment by Rainer.G...@gmx.de on 2 Oct 2009 at 4:23

GoogleCodeExporter commented 9 years ago
Special treatment has to be taken for parameters of functions, as those cannot 
be
renamed. Suppose that in

fn(x_1) (fn(x_2) x_1+x_2)

both variables x_1 and x_2 have name "x" (_1 and _2 are shown here to make the
references unambiguous; they are not part of the variable name). Since we cannot
rename function parameters, this should decompile to

fn(x) (y=x, fn(x) y+x)

i.e., the function argument should be renamed in the beginning of the function 
body.

Original comment by Rainer.G...@gmx.de on 2 Oct 2009 at 4:29

GoogleCodeExporter commented 9 years ago
After some discussion, we go for a different approach. The idea is enhance 
variables
so that they not only have a name, but also a "tag" used for disambiguation. 
The tag
can be any non-empty string and is specified using syntax name#tag. If no tag is
specified, the variable is resolved as before, i.e., ignoring tags. Thus

( x#1=1, x );

produces 1. If a tag is specified, search is done in the current scope first 
and then
upwards up to the global scope. Thus

( x#first = 1, x#second = 2, x = 3, [ x#first, x#second, x ] );

produces [1, 2, 3].

Tagging is automatically applied after parsing (or rewrite, when enabled). Only 
local
variables can have tags; globals are referred to using namespace syntax.

EXAMPLES

Query:
z = randomLong();
e = [ 1, 2, 3 ] -> transform each z z+::z;
explain e;

Result:
(
  z#0 = system::randomLong(),
  [ 1, 2, 3 ] -> transform each z z+z#0
)

Query:
fn(x) (y=x, fn(x) x+y)

Result:
fn(x#0) (fn(x) x+x#0)

Original comment by Rainer.G...@gmx.de on 9 Oct 2009 at 12:40

GoogleCodeExporter commented 9 years ago
Committed r380

Original comment by Rainer.G...@gmx.de on 9 Oct 2009 at 1:40