gf-core icon indicating copy to clipboard operation
gf-core copied to clipboard

Bug in implementation of variants

Open heatherleaf opened this issue 7 years ago • 1 comments

Here is a problem with how GF interprets variants -- I guess it's a bug somewhere.

Variants> l -all adjNPv2 good (mkNP king)
bonus rex
rex bonus

Variants> l -all adjNPv1 good (mkNP king)
bonus rex
rex bonus

Variants> l -all mkNP (adjCNv1 good king)
bonus rex
rex bonus

Variants> l -all mkNP (adjCNv2 good king)
bonus rex
bonus rex bonus
rex
rex bonus

The only difference between adjCNv1 and adjCNv2 is that in v2 the variants{...} is inlined in the function, but in v1 it is in the argument (ap.position) instead. The other two adjNPv1/2 don't show the same problem.

best, Peter

PS. Here is the grammar:

abstract Variants = {
flags startcat = NP;
cat NP; CN; AP;
fun
 king : CN;
 good : AP;
 mkNP : CN -> NP;
 adjCNv1, adjCNv2 : AP -> CN -> CN;
 adjNPv1, adjNPv2 : AP -> NP -> NP;
}

concrete VariantsCnc of Variants = {
lincat
 NP = {s : Str};
 CN = {s, before, after : Str};
 AP = {s : Str; position : Position};
param
 Position = Before | After ;
lin
 king = {s = "rex"; before = []; after = []};
 good = {s = "bonus"; position = variants{Before ; After}};

 mkNP cn = {s = cn.before ++ cn.s ++ cn.after};

 adjNPv1 ap np = 
   let pos = ap.position in
   {s = case pos of { Before => ap.s ++ np.s ;
                      After  => np.s ++ ap.s };
   };

 adjNPv2 ap np = 
   let pos = variants{Before ; After} in
   {s = case pos of { Before => ap.s ++ np.s ;
                      After  => np.s ++ ap.s };
   };

 adjCNv1 ap cn = 
   let pos = ap.position in
   {s = cn.s;
    before = case pos of { Before => ap.s ++ cn.before ; After => cn.after };
    after  = case pos of { Before => cn.before ; After => ap.s ++ cn.after };
   };

 -- this generates an error, because the two occurrences of pos will not be in sync:
 adjCNv2 ap cn = 
   let pos = variants{Before ; After} in
   {s = cn.s;
    before = case pos of { Before => ap.s ++ cn.before ; After => cn.after };
    after  = case pos of { Before => cn.before ; After => ap.s ++ cn.after };
   };

}

heatherleaf avatar Oct 26 '18 12:10 heatherleaf

And here's another example (by Krasimir from issue #37):

lin ... = ... let x = "a" | "b" in x ++ x 

results in {"aa", "ab", "ba", "bb"} while it should only return {"aa", "bb"}. This works correctly:

oper dup : Str -> Str = \x -> x ++ x;
lin ... = ... dup ("a" | "b")

heatherleaf avatar Mar 18 '19 14:03 heatherleaf