gf-core
gf-core copied to clipboard
Bug in implementation of variants
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 };
};
}
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")