use v6;
sub find_first(@list, Matcher $matcher --> Int)
{
@fl = @list.grep($matcher);
if @fl.elems >= 0
{
for @list.kv -> $i, $v
{
return $i if $v eqv @fl[0];
}
}
return Int;
}
class Symbol
{
our @!strlist;
has Int $!index;
submethod BUILD(Str $data)
{
Int $ix = find_first(@!strlist, { $_.k eq $data });
if $ix.defined
{
@!strlist[ix].v++;
$!index = $ix;
}
else
{
$!index = @!strlist.elems;
@!strlist.push($data => 1);
}
}
multi method new(Str $data)
{
return self.bless(*, :$data);
}
submethod DESTROY()
{
@!strlist[$!index].v--;
if @!strlist[$!index].v == 0
{
@!strlist.splice($!index, 1);
}
}
multi method Str() is export
{
@!strlist[$!index].k;
}
}
multi sub infix:<cmp>(Symbol $x, Symbol $y) is deep
{
return $x.Str cmp $y.Str;
}
multi sub infix:<cmp>(Symbol $x, $y) is deep
{
return $x.Str cmp ~$y;
}
multi sub infix:<cmp>($y, Symbol $x) is deep
{
return ~$x. cmp $y.Str;
}
my $a = Symbol.new('lol');
my $b = Symbol.new('wut');
"$a {$a.WHERE}".say;
"$b {$b.WHERE}".say;
"----------------".say;
my $x = Symbol.new('lol');
my $y = Symbol.new('wut');
"$x {$x.WHERE}".say;
"$y {$y.WHERE}".say;
dXNlIHY2OwoKc3ViIGZpbmRfZmlyc3QoQGxpc3QsIE1hdGNoZXIgJG1hdGNoZXIgLS0+IEludCkKewogICAgQGZsID0gQGxpc3QuZ3JlcCgkbWF0Y2hlcik7CiAgICBpZiBAZmwuZWxlbXMgPj0gMAogICAgewogICAgICAgIGZvciBAbGlzdC5rdiAtPiAkaSwgJHYKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybiAkaSBpZiAkdiBlcXYgQGZsWzBdOwogICAgICAgIH0KICAgIH0KICAgIHJldHVybiBJbnQ7Cn0KCmNsYXNzIFN5bWJvbAp7CiAgICBvdXIgQCFzdHJsaXN0OwogICAgaGFzIEludCAkIWluZGV4OwogICAgCiAgICBzdWJtZXRob2QgQlVJTEQoU3RyICRkYXRhKQogICAgewogICAgICAgIEludCAkaXggPSBmaW5kX2ZpcnN0KEAhc3RybGlzdCwgeyAkXy5rIGVxICRkYXRhIH0pOwogICAgICAgIGlmICRpeC5kZWZpbmVkCiAgICAgICAgewogICAgICAgICAgICBAIXN0cmxpc3RbaXhdLnYrKzsKICAgICAgICAgICAgJCFpbmRleCA9ICRpeDsKICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgIHsKICAgICAgICAgICAgJCFpbmRleCA9IEAhc3RybGlzdC5lbGVtczsKICAgICAgICAgICAgQCFzdHJsaXN0LnB1c2goJGRhdGEgPT4gMSk7CiAgICAgICAgfQogICAgfQogICAgCiAgICBtdWx0aSBtZXRob2QgbmV3KFN0ciAkZGF0YSkKICAgIHsKICAgICAgICByZXR1cm4gc2VsZi5ibGVzcygqLCA6JGRhdGEpOwogICAgfQoKICAgIHN1Ym1ldGhvZCBERVNUUk9ZKCkKICAgIHsKICAgICAgICBAIXN0cmxpc3RbJCFpbmRleF0udi0tOwogICAgICAgIGlmIEAhc3RybGlzdFskIWluZGV4XS52ID09IDAKICAgICAgICB7CiAgICAgICAgICAgIEAhc3RybGlzdC5zcGxpY2UoJCFpbmRleCwgMSk7CiAgICAgICAgfQogICAgfQoKICAgIG11bHRpIG1ldGhvZCBTdHIoKSBpcyBleHBvcnQKICAgIHsKICAgICAgICBAIXN0cmxpc3RbJCFpbmRleF0uazsKICAgIH0KfQoKbXVsdGkgc3ViIGluZml4OjxjbXA+KFN5bWJvbCAkeCwgU3ltYm9sICR5KSBpcyBkZWVwCnsKICAgIHJldHVybiAkeC5TdHIgY21wICR5LlN0cjsKfQoKbXVsdGkgc3ViIGluZml4OjxjbXA+KFN5bWJvbCAkeCwgJHkpIGlzIGRlZXAKewogICAgcmV0dXJuICR4LlN0ciBjbXAgfiR5Owp9CgptdWx0aSBzdWIgaW5maXg6PGNtcD4oJHksIFN5bWJvbCAkeCkgaXMgZGVlcAp7CiAgICByZXR1cm4gfiR4LiBjbXAgJHkuU3RyOwp9CgpteSAkYSA9IFN5bWJvbC5uZXcoJ2xvbCcpOwpteSAkYiA9IFN5bWJvbC5uZXcoJ3d1dCcpOwoiJGEgeyRhLldIRVJFfSIuc2F5OwoiJGIgeyRiLldIRVJFfSIuc2F5OwoiLS0tLS0tLS0tLS0tLS0tLSIuc2F5OwpteSAkeCA9IFN5bWJvbC5uZXcoJ2xvbCcpOwpteSAkeSA9IFN5bWJvbC5uZXcoJ3d1dCcpOwoiJHggeyR4LldIRVJFfSIuc2F5OwoiJHkgeyR5LldIRVJFfSIuc2F5Ow==