changeset 709:ed7183a46dca

create a stub when the output is a different interface
author anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Mon, 24 Aug 2020 21:20:34 +0900
parents 4e80cdea307d
children 0d35a152b4e7
files src/parallel_execution/generate_stub.pl src/parallel_execution/lib/Gears/Interface.pm src/parallel_execution/lib/Gears/Util.pm
diffstat 3 files changed, 120 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/src/parallel_execution/generate_stub.pl	Mon Aug 24 14:51:25 2020 +0900
+++ b/src/parallel_execution/generate_stub.pl	Mon Aug 24 21:20:34 2020 +0900
@@ -11,7 +11,6 @@
 
 use Gears::Interface;
 use Gears::Util;
-use DDP {deparse => 1};
 
 # interface.h
 # typedef struct Worker {
@@ -67,12 +66,13 @@
 my %dataGearVarType;
 my %codeGear;
 my %call_interfaces;
-my $interfaceNameToHeaderPath = createInterfaceNameToHeaderPath($FindBin::Bin);
-my $searchCbCFromCodeGearAndFilename  = createSearchCbCFileFromCodeGearNameAndFilename($FindBin::Bin);
+my $headerNameToInfo = createHeaderNameToInfo($FindBin::Bin);
+my $searchCbCFromCodeGearNameWCurrentFrileName  = createSearchCbCFromCodeGearNameWCurrentFrileName($FindBin::Bin);
 my %filename2EachCodeGearArgs;
-my %specialyEmitStubCodeGears;
+my %stub;
 
 my $implInterfaceInfo = {isImpl => undef, implementation => undef, interface => undef};
+my $generateHaveOutputStub = { counter => {}, list => {} };
 
 
 # this for statement is main routine
@@ -141,13 +141,13 @@
                 $implInterfaceInfo->{isImpl} = 1;
                 $implInterfaceInfo->{interface} = $interfaceName;
                 $implInterfaceInfo->{implementation} = $3;
-                my $cbc_source_path = $searchCbCFromCodeGearAndFilename->($interfaceName, $filename);
+                my $cbc_source_path = $searchCbCFromCodeGearNameWCurrentFrileName->($interfaceName, $filename);
                 if ($cbc_source_path) {
                     &getDataGear($cbc_source_path);
                 }
             } elsif(/^(.*)par goto (\w+)\((.*)\)/) {
                 my $codeGearName = $2;
-                my $cbc_source_path = $searchCbCFromCodeGearAndFilename->($codeGearName, $filename);
+                my $cbc_source_path = $searchCbCFromCodeGearNameWCurrentFrileName->($codeGearName, $filename);
                 if ($cbc_source_path) {
                     &getCodeGear($cbc_source_path);
                 }
@@ -157,11 +157,17 @@
                 next if ($interfaceHeader =~ /context.h/);
                 $interfaceHeader =~ m|(\w+)\.\w+$|; #remove filename extention
                 my $interfaceName = $1;
-                includeInterface(\%call_interfaces, $filename, $interfaceName, $interfaceNameToHeaderPath);
+                includeInterface(\%call_interfaces, $filename, $interfaceName, $headerNameToInfo);
             } elsif (/^\_\_code (\w+)\((.*)\)(.*)/) {
                 my $codeGearName = $1;
+                if ($codeGearName =~ /_stub$/) {
+                  $stub{$codeGearName}->{static} = 1;
+                  $stub{$codeGearName}->{wrote} = 1;
+                  $currentCodeGear = undef;
+                  next;
+                }
                 my $args = $2;
-                my $cbc_source_path = $searchCbCFromCodeGearAndFilename->($codeGearName, $filename);
+                my $cbc_source_path = $searchCbCFromCodeGearNameWCurrentFrileName->($codeGearName, $filename);
                 if ($cbc_source_path) {
                     &getCodeGear($cbc_source_path);
                 }
@@ -197,17 +203,28 @@
                 }
                 unless (exists $call_interfaces{$filename}->{$typeName}) {
                   warn "[AUTOINCLUDE] Forget #interface '$typeName'  declaration in $filename";
-                  includeInterface(\%call_interfaces, $filename, $typeName, $interfaceNameToHeaderPath);
+                  includeInterface(\%call_interfaces, $filename, $typeName, $headerNameToInfo);
                 }
 
-                my $res = findExistsOutputDataGear($typeName, $method);
-                if ($res) {
-                  my @parsedArgs = split /,/ , $tmpArgs;
+                my $nextOutPutArgs = findExistsOutputDataGear($typeName, $method);
+                my $outputStubElem = { modifyEnumCode => $currentCodeGear, createStubName => $tmpArgs };
+
+                if ($nextOutPutArgs) {
+                  my $tmpArgHash = {};
+                  map { $tmpArgHash->{$_} = $typeName } @$nextOutPutArgs;
+
+                  $outputStubElem->{args} = $tmpArgHash;
+
+                  #We're assuming that $tmpArgs only contains the name of the next CodeGear.
+                  #Eventually we need to parse the contents of the argument. (eg. @parsedArgs)
+                  my @parsedArgs = split /,/ , $tmpArgs; #
                   if (scalar(@parsedArgs) != 1) {
                     warn '[WARN] TBD';
                   }
-                  #p $res;
-                   $specialyEmitStubCodeGears{$currentCodeGear} = $res;
+
+                  $generateHaveOutputStub->{counter}->{$tmpArgs}++;
+                  $outputStubElem->{counter} = $generateHaveOutputStub->{counter}->{$tmpArgs};
+                  $generateHaveOutputStub->{list}->{$currentCodeGear} = $outputStubElem;
                 }
             } elsif (/^}$/) {
               $currentCodeGear = undef;
@@ -253,9 +270,9 @@
 }
 
 sub includeInterface {
-    my ($call_interfaces, $filename, $interfaceName, $interfaceNameToHeaderPath) = @_;
+    my ($call_interfaces, $filename, $interfaceName, $headerNameToInfo) = @_;
     $call_interfaces->{$filename}->{$interfaceName} = 1;
-    my $interface_path = $interfaceNameToHeaderPath->{$interfaceName};
+    my $interface_path = $headerNameToInfo->{$interfaceName}->{path};
     if ($interface_path) {
         getDataGear($interface_path);
         getCodeGear($interface_path);
@@ -451,7 +468,7 @@
 sub findExistsOutputDataGear {
     my ($interfaceName, $method) = @_;
 
-    my $interfacePATH = $interfaceNameToHeaderPath->{$interfaceName};
+    my $interfacePATH = $headerNameToInfo->{$interfaceName}->{path};
     unless ($interfacePATH) {
       return undef;
     }
@@ -503,7 +520,6 @@
     my $hasParGoto = 0;
     my $inMain = 0 ;
     my $inCode = 0 ;
-    my %stub;
     my $codeGearName;
     my %localVarType;
 
@@ -525,7 +541,7 @@
                 }
 
                 # This process assumes that there are no header files of the same name
-                my $path = $interfaceNameToHeaderPath->{$headerName};
+                my $path = $headerNameToInfo->{$headerName}->{path};
                 unless ($path) {
                   print $fd $_;
                   next;
@@ -544,17 +560,18 @@
                 if ($codeGearName =~ /_stub$/) {
                     # don't touch already existing stub
                     $inStub = 1;
-                    $stub{$codeGearName} = 1;
+                    $stub{$codeGearName}->{static} = 1;
+                    $stub{$codeGearName}->{wrote} = 1;
                     print $fd $_;
                     next;
                 }
                 if (defined $prevCodeGearName) {
                     # stub is generated just before next CodeGear
-                    if (defined $stub{$prevCodeGearName."_stub"}) {
+                    if (defined $stub{$prevCodeGearName."_stub"}->{wrote}) {
                         undef $prevCodeGearName;
                     } else {
                         &generateStub($fd,$prevCodeGearName,$dataGearName{$prevCodeGearName});
-                        $stub{$prevCodeGearName."_stub"} = 1;
+                        $stub{$prevCodeGearName."_stub"}->{wrote} = 1;
                     }
                 }
                 # analyzing CodeGear argument
@@ -686,20 +703,39 @@
                         if ($arg =~ /(\w+)\(.*\)/) {
                             print $fd "${indent}Gearef(${context_name}, $ntype)->$pName = $1;\n";
                         } else {
-                            my $argOrLocalVar = undef;
+                            my $hasGotoArgOrLocalVar = undef;
+                            my $outputStubElem = $generateHaveOutputStub->{list}->{$codeGearName};
+
+                            if ($outputStubElem && !$stub{$outputStubElem->{createStubName}."_stub"}->{static}) {
+                              my $pick_next = "$outputStubElem->{createStubName}_$outputStubElem->{counter}";
+                              print $fd "${indent}Gearef(${context_name}, $ntype)->$pName = C_$pick_next;\n";
+                              $i++;
+                              next;
+                            }
+
+                            # find __code of argument or local variable
                             for my $localVarType (qw/arg localVar/) {
                               my $foundVarType = $currentCodeGearInfo->{$localVarType}->{$arg};
                               if ($foundVarType && $foundVarType eq '__code') {
-                                $argOrLocalVar = 1;
+                                $hasGotoArgOrLocalVar = 1;
                               }
                             }
 
-                            if ($argOrLocalVar) {
+                            # inteface case
+
+                            if ($arg =~ /->/) {
                               print $fd "${indent}Gearef(${context_name}, $ntype)->$pName = $arg;\n"; #Gearef->()->next = next;
                               $i++;
                               next;
                             }
 
+                            if ($hasGotoArgOrLocalVar) {
+                              print $fd "${indent}Gearef(${context_name}, $ntype)->$pName = $arg;\n"; #Gearef->()->next = next;
+                              $i++;
+                              next;
+                            }
+
+                            #TODO: goto to special stub
                             print $fd "${indent}Gearef(${context_name}, $ntype)->$pName = C_$arg;\n";
                             $i++;
                             next;
@@ -853,14 +889,39 @@
         print $fd $_;
     }
     if (defined $prevCodeGearName) {
-        if (!defined $stub{$prevCodeGearName."_stub"}) {
+        if (!defined $stub{$prevCodeGearName."_stub"}->{wrote}) {
             $stub{$prevCodeGearName."_stub"} = &generateStub($fd,$prevCodeGearName,$dataGearName{$codeGearName});
         }
     }
 
+
+    #Create a stub when the output is a different interface
+    for my $modifyEnumCodeCodeGear (keys %{$generateHaveOutputStub->{list}})  {
+      my $outputStubElem = $generateHaveOutputStub->{list}->{$modifyEnumCodeCodeGear};
+      my $targetStubName = $outputStubElem->{createStubName};
+      my $createStubName = "$outputStubElem->{createStubName}_$outputStubElem->{counter}";
+      my $replaceArgs    = $outputStubElem->{args};
+
+      my $replaceStubContents = $dataGearName{$targetStubName};
+
+      #If the stub was handwritten, skip
+      if ($stub{"${targetStubName}_stub"}->{static}) {
+        next;
+      }
+
+      for my $arg (keys %$replaceArgs) {
+        my $interface = $replaceArgs->{$arg};
+        print "replace $arg $interface\n";
+        $replaceStubContents =~ s/,(.*)\)->$arg/,$interface)->$arg/;
+      }
+
+      generateStub($fd,$createStubName,$replaceStubContents);
+
+    }
+
 }
 
-sub createInterfaceNameToHeaderPath {
+sub createHeaderNameToInfo {
     my $search_root = shift;
     my $files = Gears::Util->find_headers_from_path($search_root);
     my $interface_name2headerpath = {};
@@ -869,7 +930,8 @@
     for my $file (@{$files}) {
       if ($file =~ m|/(\w+)\.\w+$|) {
         my $file_name = $1;
-        $interface_name2headerpath->{$file_name} = $file;
+        my $isInterface = Gears::Interface->isThisFileInterface($file);
+        $interface_name2headerpath->{$file_name} = { path => $file, isInterface => $isInterface };
       }
     }
 
@@ -900,7 +962,10 @@
   return $cbc_name2_source_path;
 }
 
-sub createSearchCbCFileFromCodeGearNameAndFilename {
+sub createSearchCbCFromCodeGearNameWCurrentFrileName {
+  #Find the cbc file that contains CodeGear.
+  #If there are more than one cbc file, the one whose namespace is the same as the filename has priority.
+
   my $search_root = shift;
   my $cbc_name2_source_path = create_cbc_name_to_source_path($search_root);
 
@@ -917,7 +982,6 @@
       return $cbc_files->[0];     # return "/Users/anatofuz/src/firefly/hg/Gears/Gears/src/parallel_execution/SingleLinkedQueue.cbc"
     }
 
-
     my $cbc_dir_name = dirname $filename;
 
     for my $cbc_file (@{$cbc_files}) {
--- a/src/parallel_execution/lib/Gears/Interface.pm	Mon Aug 24 14:51:25 2020 +0900
+++ b/src/parallel_execution/lib/Gears/Interface.pm	Mon Aug 24 21:20:34 2020 +0900
@@ -149,4 +149,25 @@
 }
 
 
+sub isThisFileInterface {
+  my ($class, $filename) = @_;
+  open my $fh, '<', $filename;
+  my $line = <$fh>;
+  unless ($line =~ /typedef struct \w+\s?<.*>([\s\w{]+)/) {
+    return 0;
+  }
+  my $annotation = $1;
+  return 0 if ($annotation =~ /impl/);
+
+  return 1;
+}
+
+
+sub collect_interfaces_from_all_headers {
+  my ($class, $find_path) = @_;
+  my $header_files = Gears::Util->find_headers_from_path($find_path);
+  my @result = sort grep { Gears::Interface->isThisFileInterface($_) } @$header_files;
+  return \@result;
+}
+
 1;
--- a/src/parallel_execution/lib/Gears/Util.pm	Mon Aug 24 14:51:25 2020 +0900
+++ b/src/parallel_execution/lib/Gears/Util.pm	Mon Aug 24 21:20:34 2020 +0900
@@ -5,7 +5,7 @@
 use File::Find qw/find/;
 
 my $cbc_files;
-my $headers_files;
+my $header_files;
 my $cbc_files_analyzed_code_gear;
 
 sub uniq {
@@ -47,15 +47,16 @@
 sub find_headers_from_path {
   my ($class, $find_path) = @_;
   $find_path //= ".";
-  return $headers_files if $headers_files;
+  return $header_files if $header_files;
 
   my @files;
   find( { wanted => sub { push @files, $_ if /\.(?:h|dg)/ }, no_chdir => 1 }, $find_path);
 
-  $headers_files = \@files;
-  return $headers_files;
+  $header_files = \@files;
+  return $header_files;
 }
 
+
 sub collect_codegears_from_all_cbc_sources {
   my ($class, $find_path) = @_;
   $find_path //= ".";