#!/usr/bin/env perl
use v5.30.0; # implies strict
use warnings;
use feature 'state';
use FindBin qw/$Bin/;
use lib qq{$Bin/../lib};
use Sub::Genius ();
#
# Implements classic JAPH, perl hacker hackerman benchmark
# sequentially consistent, yet oblivious, way - that's right!
# This is a Sequential Consistency Oblivious Algorithm (in the
# same vein as 'cache oblivious' algorithms
#
# paradigm below is effective 'fork'/'join'
#
my $pre = q{
begin
(
J &
A &
P &
H
)
end
};
# Load PRE describing concurrent semantics
my $sq = Sub::Genius->new(preplan => $pre );
my $GLOBAL = {};
# 'compile' PRE
$sq->init_plan;
# run loop-ish
$sq->run_once(
verbose => $ARGV[0],
# 'scope' is passed as reference to all calls, effectively
# acts as shared memory, federated only among subroutine
# participating in the serialized excecution plan
scope => {
japh => [ qw/just Another perl/, q{Hacker,} ],
curr => 0,
contrib => [],
}
);
# Dump $GLOBAL that's now been changed
if ( $ARGV[0] ) {
print qq{\n... actual contributions of each sub ...\n};
foreach my $k ( keys %$GLOBAL ) {
printf( qq{ %s() => %s\n}, $k, $GLOBAL->{$k} );
}
}
# #
## S T A T E S U B S ##
# #
# noop
sub begin {
my $scope = shift;
state $persist = {}; # gives subroutine memory, also 'private'
my $private = {}; # reset after each call
return;
}
sub J {
my $scope = shift;
state $persist = { akctual => $scope->{japh}->[ $scope->{curr} ], }; # gives subroutine memory, also 'private'
# sub's killroy
$GLOBAL->{J} = $persist->{akctual};
++$scope->{curr};
my $private = {}; # reset after each call
push @{ $scope->{contrib} }, $persist->{akctual};
return;
}
sub A {
my $scope = shift;
state $persist = { akctual => $scope->{japh}->[ $scope->{curr} ], }; # gives subroutine memory, also 'private'
# sub's killroy
$GLOBAL->{A} = $persist->{akctual};
++$scope->{curr};
my $private = {}; # reset after each call
push @{ $scope->{contrib} }, $persist->{akctual};
return;
}
sub H {
my $scope = shift;
state $persist = { akctual => $scope->{japh}->[ $scope->{curr} ], }; # gives subroutine memory, also 'private'
# sub's killroy
$GLOBAL->{H} = $persist->{akctual};
++$scope->{curr};
my $private = {}; # reset after each call
push @{ $scope->{contrib} }, $persist->{akctual};
return;
}
sub P {
my $scope = shift;
state $persist = { akctual => $scope->{japh}->[ $scope->{curr} ], }; # gives subroutine memory, also 'private'
# sub's killroy
$GLOBAL->{P} = $persist->{akctual};
++$scope->{curr};
my $private = {}; # reset after each call
push @{ $scope->{contrib} }, $persist->{akctual};
return;
}
sub end {
my $scope = shift;
state $persist = {}; # gives subroutine memory, also 'private'
my $private = {}; # reset after each call
printf( "%s\n", join( q{ }, @{ $scope->{contrib} } ) );
return;
}
exit;
####
b 70
b 82
b 94
b 106
b 118
b 126
c
c
v
p $persist->{akctual}
v
c
p $persist->{akctual}
v
c
p $persist->{akctual}
v
c
p $persist->{akctual}
v
c
p @{$scope->{contrib}}
#save 4.seq.txt
##
##
$ perl -d 1.japh.pl jehosophat
Loading DB routines from perl5db.pl version 1.55
Editor support available.
Enter h or 'h h' for help, or 'man perldebug' for more help.
main::(1.japh.pl:20): my $pre = q{
main::(1.japh.pl:21): begin
main::(1.japh.pl:22): (
main::(1.japh.pl:23): J &
main::(1.japh.pl:24): A &
main::(1.japh.pl:25): P &
main::(1.japh.pl:26): H
main::(1.japh.pl:27): )
main::(1.japh.pl:28): end
DB<1> source 4.seq.txt
>> b 70
>> b 82
>> b 94
>> b 106
>> b 118
>> b 126
>> c
plan: "begin A H J P end" <<<
Execute:
main::begin(1.japh.pl:70): return;
>> c
main::A(1.japh.pl:94): return;
>> v
91: ++$scope->{curr};
92: my $private = {}; # reset after each call
93: push @{ $scope->{contrib} }, $persist->{akctual};
94==>b return;
95 }
96
97 sub H {
98: my $scope = shift;
99: state $persist = { akctual => $scope->{japh}->[ $scope->{curr} ], }; # gives subroutine memory, also 'private'
100 # sub's killroy
>> p $persist->{akctual}
just
>> v
98: my $scope = shift;
99: state $persist = { akctual => $scope->{japh}->[ $scope->{curr} ], }; # gives subroutine memory, also 'private'
100 # sub's killroy
101: $GLOBAL->{H} = $persist->{akctual};
102
103: ++$scope->{curr};
104: my $private = {}; # reset after each call
105: push @{ $scope->{contrib} }, $persist->{akctual};
106:b return;
107 }
>> c
main::H(1.japh.pl:106): return;
>> p $persist->{akctual}
Another
>> v
103: ++$scope->{curr};
104: my $private = {}; # reset after each call
105: push @{ $scope->{contrib} }, $persist->{akctual};
106==>b return;
107 }
108
109 sub P {
110: my $scope = shift;
111: state $persist = { akctual => $scope->{japh}->[ $scope->{curr} ], }; # gives subroutine memory, also 'private'
112 # sub's killroy
>> c
main::J(1.japh.pl:82): return;
>> p $persist->{akctual}
perl
>> v
79: ++$scope->{curr};
80: my $private = {}; # reset after each call
81: push @{ $scope->{contrib} }, $persist->{akctual};
82==>b return;
83 }
84
85 sub A {
86: my $scope = shift;
87: state $persist = { akctual => $scope->{japh}->[ $scope->{curr} ], }; # gives subroutine memory, also 'private'
88 # sub's killroy
>> c
main::P(1.japh.pl:118): return;
>> p $persist->{akctual}
Hacker,
>> v
115: ++$scope->{curr};
116: my $private = {}; # reset after each call
117: push @{ $scope->{contrib} }, $persist->{akctual};
118==>b return;
119 }
120
121 sub end {
122: my $scope = shift;
123: state $persist = {}; # gives subroutine memory, also 'private'
124: my $private = {}; # reset after each call
>> c
just Another perl Hacker,
main::end(1.japh.pl:126): return;
>> p @{$scope->{contrib}}
justAnotherperlHacker,
>> #save 4.seq.txt
DB<14> q
$
##
##
M
b 82
c
y
c
#save 3.2.txt
##
##
$ perl -d 1.japh.pl jesophat
...
DB<1> source 3.2.txt
1.japh.pl* 2.seq.txt 3.2.txt 4.seq.txt _Sub::Genius/
1.seq.txt 3.1.txt 3.seq.txt 5.seq.txt
DB<1> source 3.2.txt
>> M
'FLAT.pm' => '1.0.4 from /usr/local/share/perl/5.30.0/FLAT.pm'
'FLAT/DFA.pm' => '/usr/local/share/perl/5.30.0/FLAT/DFA.pm'
'FLAT/DFA/Minimal.pm' => '/usr/local/share/perl/5.30.0/FLAT/DFA/Minimal.pm'
'FLAT/FA.pm' => '/usr/local/share/perl/5.30.0/FLAT/FA.pm'
'FLAT/NFA.pm' => '/usr/local/share/perl/5.30.0/FLAT/NFA.pm'
'FLAT/PFA.pm' => '/usr/local/share/perl/5.30.0/FLAT/PFA.pm'
'FLAT/Regex.pm' => '/usr/local/share/perl/5.30.0/FLAT/Regex.pm'
'FLAT/Regex/Op.pm' => '/usr/local/share/perl/5.30.0/FLAT/Regex/Op.pm'
'FLAT/Regex/Parser.pm' => '/usr/local/share/perl/5.30.0/FLAT/Regex/Parser.pm'
'FLAT/Regex/WithExtraOps.pm' => '/usr/local/share/perl/5.30.0/FLAT/Regex/WithExtraOps.pm'
'FLAT/Symbol.pm' => '/usr/local/share/perl/5.30.0/FLAT/Symbol.pm'
'FLAT/Symbol/Regex.pm' => '/usr/local/share/perl/5.30.0/FLAT/Symbol/Regex.pm'
'FLAT/Transition.pm' => '/usr/local/share/perl/5.30.0/FLAT/Transition.pm'
'FLAT/Transition/Simple.pm' => '/usr/local/share/perl/5.30.0/FLAT/Transition/Simple.pm'
>> b 82
>> c
plan: "begin A P J H end" <<<
Execute:
main::J(1.japh.pl:82): return;
>> y
$GLOBAL = HASH(0x557b5132e420)
'A' => 'just'
'J' => 'perl'
'P' => 'Another'
$persist = HASH(0x557b5251d3b8)
'akctual' => 'perl'
$private = HASH(0x557b5251d298)
empty hash
$scope = HASH(0x557b524e0fd8)
'contrib' => ARRAY(0x557b5132e3d8)
0 'just'
1 'Another'
2 'perl'
'curr' => 3
'japh' => ARRAY(0x557b510bec80)
0 'just'
1 'Another'
2 'perl'
3 'Hacker,'
$sq = Sub::Genius=HASH(0x557b5214ad38)
'DFA' => FLAT::DFA=HASH(0x557b524d2410)
'ALPHA' => HASH(0x557b524e1a28)
'A' => 8
'H' => 8
'J' => 8
'P' => 8
'begin' => 1
'end' => 1
'preplan' => '[begin]([J]&[A]&[P]&[H])[end]'
'preprocess' => 1
>> c
just Another perl Hacker,
... actual contributions of each sub ...
H() => Hacker,
P() => Another
A() => just
J() => perl
Debugged program terminated. Use q to quit or R to restart,
##
##
$ perldoc /usr/local/share/perl/5.30.0/Sub/Genius.pm
$ perldoc /usr/local/share/perl/5.30.0/FLAT.pm
$ perldoc /usr/local/share/perl/5.30.0/FLAT/DFA.pm