<commit_before>my $concrete := Perl6::Metamodel::ConcreteRoleHOW;
class Perl6::Metamodel::ParametricRoleHOW
    does Perl6::Metamodel::Naming
    does Perl6::Metamodel::Documenting
    does Perl6::Metamodel::Versioning
    does Perl6::Metamodel::MethodContainer
    does Perl6::Metamodel::PrivateMethodContainer
    does Perl6::Metamodel::MultiMethodContainer
    does Perl6::Metamodel::AttributeContainer
    does Perl6::Metamodel::RoleContainer
    does Perl6::Metamodel::MultipleInheritance
    does Perl6::Metamodel::Stashing
    does Perl6::Metamodel::TypePretence
    does Perl6::Metamodel::RolePunning
{
    has $!composed;
    has $!body_block;
    has @!role_typecheck_list;

    my $archetypes := Perl6::Metamodel::Archetypes.new( :nominal(1), :composable(1), :inheritalizable(1), :parametric(1) );
    method archetypes() {
        $archetypes
    }

    method new_type(:$name = '<anon>', :$ver, :$auth, :$repr) {
        my $metarole := self.new(:name($name), :ver($ver), :auth($auth));
        self.add_stash(pir::repr_type_object_for__PPS($metarole, 'Uninstantiable'));
    }
    
    method set_body_block($obj, $block) {
        $!body_block := $block
    }
    
    method body_block($obj) {
        $!body_block
    }
    
    method compose($obj) {
        my @rtl;
        for self.roles_to_compose($obj) {
            @rtl.push($_);
            for $_.HOW.role_typecheck_list($_) {
                @rtl.push($_);
            }
        }
        @!role_typecheck_list := @rtl;
        $!composed := 1;
        $obj
    }
    
    method is_composed($obj) {
        $!composed
    }
    
    method roles($obj, :$transitive) {
        if $transitive {
            my @result;
            for self.roles_to_compose($obj) {
                @result.push($_);
                for $_.HOW.roles($_, :transitive(1)) {
                    @result.push($_)
                }
            }
            @result
        }
        else {
            self.roles_to_compose($obj)
        }
    }
    
    method role_typecheck_list($obj) {
        @!role_typecheck_list
    }
    
    method type_check($obj, $checkee) {
        my $decont := pir::perl6_decontainerize__PP($checkee);
        if $decont =:= $obj.WHAT {
            return 1;
        }
        for self.prentending_to_be() {
            if $decont =:= pir::perl6_decontainerize__PP($_) {
                return 1;
            }
        }
        for self.roles_to_compose($obj) {
            if pir::type_check__IPP($checkee, $_) {
                return 1;
            }
        }
        0
    }
    
    method specialize($obj, *@pos_args, *%named_args) {
        # Run the body block to get the type environment.
        my $type_env;
        my $error;
        try {
            $type_env := $!body_block(|@pos_args, |%named_args);
            CATCH {
                $error := $!
            }
        }
        if $error {
            pir::die("Could not instantiate role '" ~ self.name($obj) ~ "':\n$error")
        }
        
        # Create a concrete role.
        my $conc := $concrete.new_type(:roles([$obj]), :name(self.name($obj)));
        
        # Go through attributes, reifying as needed and adding to
        # the concrete role.
        for self.attributes($obj, :local(1)) {
            $conc.HOW.add_attribute($conc,
                $_.is_generic ?? $_.instantiate_generic($type_env) !! $_);
        }
        
        # Go through methods and instantiate them; we always do this
        # unconditionally, since we need the clone anyway.
        for self.methods($obj, :local(1)) {
            $conc.HOW.add_method($conc, $_.name, $_.instantiate_generic($type_env))
        }
        for self.private_method_table($obj) {
            $conc.HOW.add_private_method($conc, $_.key, $_.value.instantiate_generic($type_env));
        }
        for self.multi_methods_to_incorporate($obj) {
            $conc.HOW.add_multi_method($conc, $_.name, $_.code.instantiate_generic($type_env))
        }
        
        # Roles down by this role need fully specializing also; all
        # they'll be missing is the target class (e.g. our first arg).
        for self.roles_to_compose($obj) {
            $conc.HOW.add_role($conc, $_.HOW.specialize($_, @pos_args[0]));
        }<commit_msg>Tiny refactor in preparation for implementing multiple roles with the same shortname.<commit_after>my $concrete := Perl6::Metamodel::ConcreteRoleHOW;
class Perl6::Metamodel::ParametricRoleHOW
    does Perl6::Metamodel::Naming
    does Perl6::Metamodel::Documenting
    does Perl6::Metamodel::Versioning
    does Perl6::Metamodel::MethodContainer
    does Perl6::Metamodel::PrivateMethodContainer
    does Perl6::Metamodel::MultiMethodContainer
    does Perl6::Metamodel::AttributeContainer
    does Perl6::Metamodel::RoleContainer
    does Perl6::Metamodel::MultipleInheritance
    does Perl6::Metamodel::Stashing
    does Perl6::Metamodel::TypePretence
    does Perl6::Metamodel::RolePunning
{
    has $!composed;
    has $!body_block;
    has @!role_typecheck_list;

    my $archetypes := Perl6::Metamodel::Archetypes.new( :nominal(1), :composable(1), :inheritalizable(1), :parametric(1) );
    method archetypes() {
        $archetypes
    }

    method new_type(:$name = '<anon>', :$ver, :$auth, :$repr) {
        my $metarole := self.new(:name($name), :ver($ver), :auth($auth));
        self.add_stash(pir::repr_type_object_for__PPS($metarole, 'Uninstantiable'));
    }
    
    method set_body_block($obj, $block) {
        $!body_block := $block
    }
    
    method body_block($obj) {
        $!body_block
    }
    
    method compose($obj) {
        my @rtl;
        for self.roles_to_compose($obj) {
            @rtl.push($_);
            for $_.HOW.role_typecheck_list($_) {
                @rtl.push($_);
            }
        }
        @!role_typecheck_list := @rtl;
        $!composed := 1;
        $obj
    }
    
    method is_composed($obj) {
        $!composed
    }
    
    method roles($obj, :$transitive) {
        if $transitive {
            my @result;
            for self.roles_to_compose($obj) {
                @result.push($_);
                for $_.HOW.roles($_, :transitive(1)) {
                    @result.push($_)
                }
            }
            @result
        }
        else {
            self.roles_to_compose($obj)
        }
    }
    
    method role_typecheck_list($obj) {
        @!role_typecheck_list
    }
    
    method type_check($obj, $checkee) {
        my $decont := pir::perl6_decontainerize__PP($checkee);
        if $decont =:= $obj.WHAT {
            return 1;
        }
        for self.prentending_to_be() {
            if $decont =:= pir::perl6_decontainerize__PP($_) {
                return 1;
            }
        }
        for self.roles_to_compose($obj) {
            if pir::type_check__IPP($checkee, $_) {
                return 1;
            }
        }
        0
    }
    
    method specialize($obj, *@pos_args, *%named_args) {
        # Run the body block to get the type environment.
        my $type_env;
        my $error;
        try {
            $type_env := $!body_block(|@pos_args, |%named_args);
            CATCH {
                $error := $!
            }
        }
        if $error {
            pir::die("Could not instantiate role '" ~ self.name($obj) ~ "':\n$error")
        }
        
        # Use it to build concrete role.
        self.specialize_with($obj, $type_env, @pos_args)
    }
    
    method specialize_with($obj, $type_env, @pos_args) {
        # Create a concrete role.
        my $conc := $concrete.new_type(:roles([$obj]), :name(self.name($obj)));
        
        # Go through attributes, reifying as needed and adding to
        # the concrete role.
        for self.attributes($obj, :local(1)) {
            $conc.HOW.add_attribute($conc,
                $_.is_generic ?? $_.instantiate_generic($type_env) !! $_);
        }
        
        # Go through methods and instantiate them; we always do this
        # unconditionally, since we need the clone anyway.
        for self.methods($obj, :local(1)) {
            $conc.HOW.add_method($conc, $_.name, $_.instantiate_generic($type_env))
        }
        for self.private_method_table($obj) {
            $conc.HOW.add_private_method($conc, $_.key, $_.value.instantiate_generic($type_env));
        }
        for self.multi_methods_to_incorporate($obj) {
            $conc.HOW.add_multi_method($conc, $_.name, $_.code.instantiate_generic($type_env))
        }
        
        # Roles done by this role need fully specializing also; all
        # they'll be missing is the target class (e.g. our first arg).
        for self.roles_to_compose($obj) {
            $conc.HOW.add_role($conc, $_.HOW.specialize($_, @pos_args[0]));
        }
{'fraction_non_alphanumeric': 0.13160291438979962, 'fraction_numerical': 0.006830601092896175, 'mean_word_length': 2.0355908776779543, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2259639', 'n_tokens_mistral': 2922, 'n_tokens_neox': 2782, 'n_words': 514}