# Do not edit this file - Generated by Perlito5 9.025

{
    package main;
    package Perlito5::Grammar::Use;
    use Perlito5::Grammar::Precedence ;
    use Perlito5::Grammar ;
    use strict ;
    our @Perlito_internal_lib_directory = ("Perlito5X", '');
    our %Perlito_internal_module;
    sub Perlito5::Grammar::Use::use_decl {
        my $str = $_[0];
        my $pos = $_[1];
        my $MATCH = {"str" => $str, "from" => $pos, "to" => $pos, };
        my $tmp = ((do {
            my $tmp102 = $MATCH->{"to"};
            ((("u" eq $str->[($MATCH->{"to"}) + 0]) && ("s" eq $str->[($MATCH->{"to"}) + 1]) && ("e" eq $str->[($MATCH->{"to"}) + 2]) && ($MATCH->{"to"} += 3))) || ($MATCH->{"to"} = $tmp102, (("n" eq $str->[($MATCH->{"to"}) + 0]) && ("o" eq $str->[($MATCH->{"to"}) + 1]) && ($MATCH->{"to"} += 2)))
        }));
        $tmp ? $MATCH : undef
    }
    sub Perlito5::Grammar::Use::version_string {
        my $str = $_[0];
        my $pos = $_[1];
        my $MATCH = {"str" => $str, "from" => $pos, "to" => $pos, };
        my $tmp = ((do {
            my $tmp108 = $MATCH->{"to"};
            (((do {
                my $m2 = Perlito5::Grammar::Number::val_version($str, $MATCH->{"to"});
                if ($m2) {
                    $MATCH->{"to"} = $m2->{"to"};
                    $MATCH->{"Perlito5::Grammar::Number::val_version"} = $m2;
                    1
                }
                else {;
                    0
                }
            }) && (do {
                $MATCH->{"capture"} = $MATCH->{"Perlito5::Grammar::Number::val_version"}->{"capture"};
                1
            }))) || ($MATCH->{"to"} = $tmp108, ((do {
                my $m2 = Perlito5::Grammar::Number::term_digit($str, $MATCH->{"to"});
                if ($m2) {
                    $MATCH->{"to"} = $m2->{"to"};
                    $MATCH->{"Perlito5::Grammar::Number::term_digit"} = $m2;
                    1
                }
                else {;
                    0
                }
            }) && (do {
                my $version = $MATCH->{"Perlito5::Grammar::Number::term_digit"}->{"capture"}->[1]->{"buf"} || $MATCH->{"Perlito5::Grammar::Number::term_digit"}->{"capture"}->[1]->{"int"} || $MATCH->{"Perlito5::Grammar::Number::term_digit"}->{"capture"}->[1]->{"num"};
                $MATCH->{"capture"} = Perlito5::AST::Buf::->new("buf", $version);
                1
            })))
        }));
        $tmp ? $MATCH : undef
    }
    sub Perlito5::Grammar::Use::term_require {
        my $str = $_[0];
        my $pos = $_[1];
        my $MATCH = {"str" => $str, "from" => $pos, "to" => $pos, };
        my $tmp = (((("r" eq $str->[($MATCH->{"to"}) + 0]) && ("e" eq $str->[($MATCH->{"to"}) + 1]) && ("q" eq $str->[($MATCH->{"to"}) + 2]) && ("u" eq $str->[($MATCH->{"to"}) + 3]) && ("i" eq $str->[($MATCH->{"to"}) + 4]) && ("r" eq $str->[($MATCH->{"to"}) + 5]) && ("e" eq $str->[($MATCH->{"to"}) + 6]) && ($MATCH->{"to"} += 7)) && (do {
            my $m2 = Perlito5::Grammar::Space::ws($str, $MATCH->{"to"});
            if ($m2) {
                $MATCH->{"to"} = $m2->{"to"};
                1
            }
            else {;
                0
            }
        }) && (do {
            my $tmp117 = $MATCH->{"to"};
            (((do {
                my $m2 = Perlito5::Grammar::Use::version_string($str, $MATCH->{"to"});
                if ($m2) {
                    $MATCH->{"to"} = $m2->{"to"};
                    $MATCH->{"version_string"} = $m2;
                    1
                }
                else {;
                    0
                }
            }) && (do {
                my $version = $MATCH->{"version_string"}->{"capture"};
                $version->{"is_version_string"} = 1;
                $MATCH->{"capture"} = ["term", Perlito5::AST::Apply::->new("code", "require", "namespace", '', "arguments", [$version])];
                1
            }))) || ($MATCH->{"to"} = $tmp117, ((do {
                my $m2 = Perlito5::Grammar::full_ident($str, $MATCH->{"to"});
                if ($m2) {
                    $MATCH->{"to"} = $m2->{"to"};
                    $MATCH->{"Perlito5::Grammar::full_ident"} = $m2;
                    1
                }
                else {;
                    0
                }
            }) && (do {
                my $module_name = Perlito5::Match::flat($MATCH->{"Perlito5::Grammar::full_ident"});
                $Perlito5::PACKAGES->{$module_name} = 1;
                my $filename = Perlito5::Grammar::Use::modulename_to_filename($module_name);
                $MATCH->{"capture"} = ["term", Perlito5::AST::Apply::->new("code", "require", "namespace", '', "arguments", [Perlito5::AST::Buf::->new("buf", $filename)])];
                1
            })))
        })));
        $tmp ? $MATCH : undef
    }
    sub Perlito5::Grammar::Use::stmt_use {
        my $str = $_[0];
        my $pos = $_[1];
        my $MATCH = {"str" => $str, "from" => $pos, "to" => $pos, };
        my $tmp = (((do {
            my $m2 = Perlito5::Grammar::Use::use_decl($str, $MATCH->{"to"});
            if ($m2) {
                $MATCH->{"to"} = $m2->{"to"};
                $MATCH->{"use_decl"} = $m2;
                1
            }
            else {;
                0
            }
        }) && (do {
            my $m2 = Perlito5::Grammar::Space::ws($str, $MATCH->{"to"});
            if ($m2) {
                $MATCH->{"to"} = $m2->{"to"};
                1
            }
            else {;
                0
            }
        }) && (do {
            my $tmp129 = $MATCH->{"to"};
            (((do {
                my $m2 = Perlito5::Grammar::Use::version_string($str, $MATCH->{"to"});
                if ($m2) {
                    $MATCH->{"to"} = $m2->{"to"};
                    $MATCH->{"version_string"} = $m2;
                    1
                }
                else {;
                    0
                }
            }) && (do {
                my $version = $MATCH->{"version_string"}->{"capture"}->{"buf"};
                Perlito5::test_perl_version($version);
                $MATCH->{"capture"} = Perlito5::Grammar::Block::ast_nop();
                1
            }))) || ($MATCH->{"to"} = $tmp129, ((do {
                my $m2 = Perlito5::Grammar::full_ident($str, $MATCH->{"to"});
                if ($m2) {
                    $MATCH->{"to"} = $m2->{"to"};
                    $MATCH->{"Perlito5::Grammar::full_ident"} = $m2;
                    1
                }
                else {;
                    0
                }
            }) && (do {
                my $m = $MATCH;
                if (!((("-" eq $str->[($MATCH->{"to"}) + 0]) && ($MATCH->{"to"} += 1)) && (do {
                    my $m2 = Perlito5::Grammar::ident($str, $MATCH->{"to"});
                    if ($m2) {
                        $MATCH->{"to"} = $m2->{"to"};
                        if (exists($MATCH->{"Perlito5::Grammar::ident"})) {;
                            push(@{$MATCH->{"Perlito5::Grammar::ident"}}, $m2)
                        }
                        else {;
                            $MATCH->{"Perlito5::Grammar::ident"} = [$m2]
                        }
                        1
                    }
                    else {;
                        0
                    }
                }))) {;
                    $MATCH = $m
                }
                1
            }) && (do {
                my $m = $MATCH;
                if (!((do {
                    my $m2 = Perlito5::Grammar::Space::ws($str, $MATCH->{"to"});
                    if ($m2) {
                        $MATCH->{"to"} = $m2->{"to"};
                        1
                    }
                    else {;
                        0
                    }
                }) && (do {
                    my $m2 = Perlito5::Grammar::Use::version_string($str, $MATCH->{"to"});
                    if ($m2) {
                        $MATCH->{"to"} = $m2->{"to"};
                        if (exists($MATCH->{"version_string"})) {;
                            push(@{$MATCH->{"version_string"}}, $m2)
                        }
                        else {;
                            $MATCH->{"version_string"} = [$m2]
                        }
                        1
                    }
                    else {;
                        0
                    }
                }) && (do {
                    my $m2 = Perlito5::Grammar::Space::opt_ws($str, $MATCH->{"to"});
                    if ($m2) {
                        $MATCH->{"to"} = $m2->{"to"};
                        1
                    }
                    else {;
                        0
                    }
                }) && (do {
                    my $tmp = $MATCH;
                    $MATCH = {"from" => $tmp->{"to"}, "to" => $tmp->{"to"}, };
                    my $res = (("," eq $str->[($MATCH->{"to"}) + 0]) && ($MATCH->{"to"} += 1));
                    $MATCH = $tmp;
                    $res ? 0 : 1
                }))) {;
                    $MATCH = $m
                }
                1
            }) && (do {
                my $tmp130 = $MATCH->{"to"};
                ((do {
                    my $m2 = Perlito5::Grammar::Expression::exp_parse($str, $MATCH->{"to"});
                    if ($m2) {
                        $MATCH->{"to"} = $m2->{"to"};
                        $MATCH->{"Perlito5::Grammar::Expression::exp_parse"} = $m2;
                        1
                    }
                    else {;
                        0
                    }
                })) || ($MATCH->{"to"} = $tmp130, (do {
                    my $m2 = Perlito5::Grammar::Space::opt_ws($str, $MATCH->{"to"});
                    if ($m2) {
                        $MATCH->{"to"} = $m2->{"to"};
                        1
                    }
                    else {;
                        0
                    }
                }))
            }) && (do {
                my $version = $MATCH->{"version_string"}->[0]->{"capture"}->{"buf"};
                my $list = Perlito5::Match::flat($MATCH->{"Perlito5::Grammar::Expression::exp_parse"});
                if (ref($list) eq "Perlito5::AST::Buf") {;
                    $list = [$list->{"buf"}]
                }
                elsif ($list) {
                    Perlito5::Grammar::Scope::check_variable_declarations();
                    my $ast = Perlito5::AST::Block::->new("stmts", [Perlito5::AST::Apply::->new("code", "circumfix:<[ ]>", "arguments", [$list])]);
                    $list = Perlito5::Grammar::Block::eval_begin_block($ast)
                }
                else {;
                    $list = undef
                }
                my $full_ident = Perlito5::Match::flat($MATCH->{"Perlito5::Grammar::full_ident"});
                $Perlito5::PACKAGES->{$full_ident} = 1;
                my $use_decl = Perlito5::Match::flat($MATCH->{"use_decl"});
                if ($use_decl eq "use" && $full_ident eq "vars" && $list) {
                    for my $name (@{$list}) {;
                        $Perlito5::VARS{substr($name, 0, 1) . $Perlito5::PKG_NAME . "::" . substr($name, 1)} = 1
                    }
                    $MATCH->{"capture"} = Perlito5::Grammar::Block::ast_nop()
                }
                elsif ($use_decl eq "use" && $full_ident eq "subs" && $list) {
                    for my $name (@{$list}) {
                        my $glob = $Perlito5::PKG_NAME . "::" . $name;
                        if (!exists($Perlito5::PROTO->{$glob})) {;
                            $Perlito5::PROTO->{$glob} = undef
                        }
                    }
                    $MATCH->{"capture"} = Perlito5::Grammar::Block::ast_nop()
                }
                elsif ($use_decl eq "use" && $full_ident eq "constant") {
                    my @ast;
                    if ($list) {
                        my $name = shift(@{$list});
                        if (ref($name) eq "HASH") {;
                            for my $key (sort {;
                                $a cmp $b
                            } keys(%{$name})) {
                                my $code = "sub " . $key . " () { " . Perlito5::Dumper::_dumper($name->{$key}) . " }";
                                my $m = Perlito5::Grammar::Statement::statement_parse([split('', $code)], 0);
                                !$m && Perlito5::Compiler::error("not a valid constant: " . join(${"\""}, @{$list}));
                                push(@ast, $m->{"capture"})
                            }
                        }
                        else {
                            my $code = "sub " . $name . " () { (" . join(", ", map {;
                                Perlito5::Dumper::_dumper($_)
                            } @{$list}) . ") }";
                            my $m = Perlito5::Grammar::Statement::statement_parse([split('', $code)], 0);
                            !$m && Perlito5::Compiler::error("not a valid constant: " . join(${"\""}, @{$list}));
                            push(@ast, $m->{"capture"})
                        }
                    }
                    $MATCH->{"capture"} = Perlito5::AST::Block::->new("stmts", \@ast)
                }
                elsif ($Perlito5::EMIT_USE) {;
                    $MATCH->{"capture"} = Perlito5::AST::Apply::->new("code", "use", "special_arg", Perlito5::AST::Apply::->new("code", $full_ident, "bareword", 1, "arguments", []), "arguments", $list)
                }
                else {;
                    $MATCH->{"capture"} = Perlito5::Grammar::Use::parse_time_eval({"mod" => $full_ident, "code" => $use_decl, "arguments" => $list, })
                }
                1
            }))) || ($MATCH->{"to"} = $tmp129, (do {
                Perlito5::Compiler::error("Syntax error");
                1
            }))
        })));
        $tmp ? $MATCH : undef
    }
    sub Perlito5::Grammar::Use::parse_time_eval {
        my $ast = shift;
        my $module_name = $ast->{"mod"};
        my $use_or_not = $ast->{"code"};
        my $arguments = $ast->{"arguments"};
        my $skip_import = defined($arguments) && @{$arguments} == 0;
        defined($arguments) || ($arguments = []);
        if ($Perlito5::EXPAND_USE) {
            my $caller = [$Perlito5::PKG_NAME, $Perlito5::FILE_NAME, $Perlito5::LINE_NUMBER], my $filename = Perlito5::Grammar::Use::modulename_to_filename($module_name);
            unshift(@Perlito5::CALLER, [$module_name]);
            Perlito5::Grammar::Use::require($filename);
            shift(@Perlito5::CALLER);
            if (!$skip_import) {
                if ($use_or_not eq "use") {
                    my $code = $module_name->can("import");
                    if (defined($code)) {
                        unshift(@Perlito5::CALLER, $caller);
                        eval {
                            $module_name->import(@{$arguments});
                            1
                        } or Perlito5::Compiler::error(${"\@"});
                        shift(@Perlito5::CALLER)
                    }
                }
                elsif ($use_or_not eq "no") {
                    my $code = $module_name->can("unimport");
                    if (defined($code)) {
                        unshift(@Perlito5::CALLER, $caller);
                        eval {
                            $module_name->unimport(@{$arguments});
                            1
                        } or Perlito5::Compiler::error(${"\@"});
                        shift(@Perlito5::CALLER)
                    }
                }
            }
        }
        else {
            Perlito5::Grammar::Use::bootstrapping_use($ast);
            Perlito5::Grammar::Use::emit_time_eval($ast)
        }
        return Perlito5::Grammar::Block::ast_nop()
    }
    sub Perlito5::Grammar::Use::emit_time_eval {
        my $ast = shift;
        if ($ast->{"mod"} eq "strict") {
            if ($ast->{"code"} eq "use") {;
                strict::->import()
            }
            elsif ($ast->{"code"} eq "no") {;
                strict::->unimport()
            }
        }
    }
    sub Perlito5::Grammar::Use::modulename_to_filename {
        my $s = shift;
        exists($Perlito_internal_module{$s}) && ($s = $Perlito_internal_module{$s});
        $s =~ s!::!/!g;
        return $s . ".pm"
    }
    sub Perlito5::Grammar::Use::filename_lookup {
        my $filename = shift;
        if (exists($INC{$filename})) {
            $INC{$filename} && return "done";
            Perlito5::Compiler::error("Compilation failed in require")
        }
        if (substr($filename, 0, 2) eq "./") {;
            if (-f $filename) {
                $INC{$filename} = $filename;
                return "todo"
            }
        }
        for my $prefix (@INC) {;
            for my $internal (@Perlito_internal_lib_directory) {
                my $realfilename = join("/", $prefix, ($internal ? $internal : ()), $filename);
                if (-f $realfilename) {
                    $INC{$filename} = $realfilename;
                    return "todo"
                }
            }
        }
        Perlito5::Compiler::error("Can't locate " . $filename . " in \@INC " . "(\@INC contains " . join(" ", @INC) . ").")
    }
    sub Perlito5::Grammar::Use::bootstrapping_use {
        my $stmt = shift;
        my $module_name = $stmt->{"mod"};
        my $filename = Perlito5::Grammar::Use::modulename_to_filename($module_name);
        Perlito5::Grammar::Use::filename_lookup($filename) eq "done" && return;
        local $Perlito5::FILE_NAME = $filename;
        local $Perlito5::LINE_NUMBER = 1;
        my $realfilename = $INC{$filename};
        open(FILE, "<", $realfilename) or Perlito5::Compiler::error("Cannot read " . $realfilename . ": " . ${"!"} . "
");
        local $/ = undef;
        my $source = <FILE>;
        close(FILE);
        local @Perlito5::BASE_SCOPE = (Perlito5::Grammar::Scope::->new_base_scope());
        local $Perlito5::CLOSURE_SCOPE = 0;
        local @Perlito5::SCOPE_STMT = ();
        local ${^H} = 0;
        local %{^H} = ();
        my $m = Perlito5::Grammar::exp_stmts($source, 0);
        $m->{"to"} != length($source) && Perlito5::Compiler::error("Syntax Error near ", $m->{"to"});
        if ($m->{"to"} != length($source)) {
            my $pos = ($m->{"to"}) - 10;
            $pos < 0 && ($pos = 0);
            print("* near: ", substr($source, $pos, 20), "
");
            print("* filename: " . $realfilename . "
");
            Perlito5::Compiler::error("Syntax Error")
        }
        push(@Perlito5::COMP_UNIT, Perlito5::AST::CompUnit::->new("name", "main", "body", Perlito5::Match::flat($m)));
        return
    }
    sub Perlito5::Grammar::Use::require {
        my $filename = shift;
        my $m2 = Perlito5::Grammar::Use::version_string([split('', $filename)], 0);
        if ($m2) {
            my $version = $m2->{"version_string"}->{"capture"}->{"buf"};
            Perlito5::test_perl_version($version);
            return 1
        }
        if (length($filename) > 3 && substr($filename, -3) eq ".pm") {
            my $module_name = substr($filename, 0, -3);
            $module_name =~ s!/!::!g;
            if (exists($Perlito_internal_module{$module_name})) {
                my $s = $Perlito_internal_module{$module_name};
                $s =~ s!::!/!g;
                $filename = $s . ".pm"
            }
        }
        Perlito5::Grammar::Use::filename_lookup($filename) eq "done" && return;
        my $source = Perlito5::Grammar::Use::slurp_file($filename);
        local $Perlito5::FILE_NAME = $filename;
        Perlito5::Grammar::Scope::check_variable_declarations();
        local @Perlito5::BASE_SCOPE = (Perlito5::Grammar::Scope::->new_base_scope());
        local $Perlito5::CLOSURE_SCOPE = 0;
        local @Perlito5::SCOPE_STMT = ();
        local ${^H} = 0;
        local %{^H} = ();
        my $m = Perlito5::Grammar::exp_stmts($source, 0);
        my $ast = Perlito5::AST::Block::->new("stmts", Perlito5::Match::flat($m));
        my $result = Perlito5::Grammar::Block::eval_begin_block($ast);
        if (${"\@"}) {
            $INC{$filename} = undef;
            Perlito5::Compiler::error(${"\@"})
        }
        elsif (!$result) {
            delete($INC{$filename});
            ${"\@"} && warn(${"\@"});
            Perlito5::Compiler::error($filename . " did not return true value")
        }
        else {;
            return $result
        }
    }
    sub Perlito5::Grammar::Use::slurp_file {
        my $filename = shift;
        eval {
            Perlito5::Grammar::Use::filename_lookup($filename);
            1
        } or do {
            $INC{$filename} = undef;
            ${"\@"} = '';
            ${"!"} = "No such file or directory";
            return "undef"
        };
        my $realfilename = $INC{$filename};
        Perlito5::Grammar::Use::slurp_source_file($realfilename)
    }
    sub Perlito5::Grammar::Use::slurp_source_file {
        my $realfilename = shift;
        open(FILE, "<", $realfilename) or Perlito5::Compiler::error("Cannot read " . $realfilename . ": " . ${"!"} . "
");
        binmode(FILE);
        local $/ = undef;
        my $source = <FILE>;
        close(FILE);
        my $charset = '';
        eval {
            my $c0 = substr($source, 0, 1);
            my $c1 = substr($source, 1, 1);
            my $c2 = substr($source, 2, 1);
            my $c3 = substr($source, 3, 1);
            if ($c0 eq "\x{ef}" && $c1 eq "\x{bb}" && $c2 eq "\x{bf}") {
                $charset = "UTF-8";
                $source = substr($source, 3)
            }
            elsif ($c0 eq "\x{fe}" && $c1 eq "\x{ff}") {
                $charset = "UTF-16BE";
                $source = substr($source, 2)
            }
            elsif ($c0 eq "\x{ff}" && $c1 eq "\x{fe}") {
                $charset = "UTF-16LE";
                $source = substr($source, 2)
            }
            elsif ($c0 eq "\x{0}" && $c1 ne "\x{0}" && $c2 eq "\x{0}" && $c3 ne "\x{0}") {;
                $charset = "UTF-16BE"
            }
            elsif ($c0 ne "\x{0}" && $c1 eq "\x{0}" && $c2 ne "\x{0}" && $c3 eq "\x{0}") {;
                $charset = "UTF-16LE"
            }
            $charset && ($source = Encode::decode($charset, $source));
            1
        } or warn("Source code charset '" . $charset . "' decoding failed: " . ${"\@"});
        return $source
    }
    Perlito5::Grammar::Statement::add_statement("no", \&stmt_use);
    Perlito5::Grammar::Statement::add_statement("use", \&stmt_use);
    Perlito5::Grammar::Precedence::add_term("require", \&term_require);
    1
}
;1
