changeset 716:284fa7d7326e

automatic generation of constructors at stub creation
author anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Tue, 01 Sep 2020 15:56:55 +0900
parents fd9b9fa4ec98
children 1595fc808041
files src/parallel_execution/generate_stub.pl src/parallel_execution/lib/Gears/Interface.pm src/parallel_execution/lib/Gears/Stub.pm src/parallel_execution/lib/Gears/Stub/GenerateConstructor.pm src/parallel_execution/lib/Gears/Stub/GenerateDataGear.pm src/parallel_execution/perlTests/Interface.t src/parallel_execution/tools/trans_impl.pl
diffstat 7 files changed, 149 insertions(+), 115 deletions(-) [+]
line wrap: on
line diff
--- a/src/parallel_execution/generate_stub.pl	Fri Aug 28 16:43:39 2020 +0900
+++ b/src/parallel_execution/generate_stub.pl	Tue Sep 01 15:56:55 2020 +0900
@@ -11,6 +11,7 @@
 
 use Gears::Interface;
 use Gears::Util;
+use Gears::Stub;
 
 # interface.h
 # typedef struct Worker {
@@ -161,22 +162,27 @@
                 $interfaceHeader =~ m|(\w+)\.\w+$|; #remove filename extention
                 my $interfaceName = $1;
                 includeInterface(\%call_interfaces, $filename, $interfaceName, $headerNameToInfo);
-            } elsif(/^#impl "(.*)"/) {
+                # #impl "Stack.h" for "SingleLinkedStack.h"
+            } elsif(/^#impl "(.*?)"(?:\s+for\s+"(.*)")?/) {
                 # use interface
                 my $interfaceHeader = $1;
+                my $implName = $2;
+
                 $interfaceHeader =~ m|(\w+)\.\w+$|; #remove filename extention
                 my $interfaceName = $1;
                 includeInterface(\%call_interfaces, $filename, $interfaceName, $headerNameToInfo);
                 my $interfacePATH = $headerNameToInfo->{$interfaceName}->{path};
 
-                my $implName = basename $filename;
-                $implName =~ s/\.cbc$//;
+                unless ($implName) {
+                  $implName = basename $filename;
+                }
+                $implName =~ s/(\w+)\.\w+$/$1/;
 
                 $implInterfaceInfo->{isImpl} = 1;
                 $implInterfaceInfo->{interface} = $interfaceName;
                 $implInterfaceInfo->{implementation} = $implName;
                 $implInterfaceInfo->{genConstructor} = 1;
-                $implInterfaceInfo->{parsedInterfaceInfo} = Gears::Interface->separate_code_and_data_gear_after_parse($interfacePATH);
+                $implInterfaceInfo->{parsedInterfaceInfo} = Gears::Interface->detailed_parse($interfacePATH);
 
             } elsif (/^\_\_code (\w+)\((.*)\)(.*)/) {
                 my $codeGearName = $1;
@@ -511,7 +517,7 @@
       return undef;
     }
 
-    my $parsedInterface = Gears::Interface->separate_code_and_data_gear_after_parse($interfacePATH);
+    my $parsedInterface = Gears::Interface->detailed_parse($interfacePATH);
 
     unless ($parsedInterface) {
       return undef;
@@ -568,6 +574,22 @@
             } elsif (/^int main\((.*)\) \{/) {
                 $inMain = 1;
             } elsif(/^#impl "(.*)"/) {
+              next unless ($implInterfaceInfo->{genConstructor});
+
+              my $constructInterface = {
+                                         name => $implInterfaceInfo->{interface},
+                                         path => $headerNameToInfo->{$implInterfaceInfo->{interface}}->{path}
+                                       };
+
+              my $constructImpl      = {
+                                        name => $implInterfaceInfo->{implementation},
+                                         path => $headerNameToInfo->{$implInterfaceInfo->{implementation}}->{path}
+                                       };
+
+              unless ($constructImpl->{path}) {
+                warn "[WARN] Not found $constructImpl->{name}.h";
+              }
+              print $fd Gears::Stub->generate_constructor($constructInterface, $constructImpl);
               next;
             } elsif(/^#interface "(.*)"/) {
                 my $interfaceHeader = $1;
--- a/src/parallel_execution/lib/Gears/Interface.pm	Fri Aug 28 16:43:39 2020 +0900
+++ b/src/parallel_execution/lib/Gears/Interface.pm	Tue Sep 01 15:56:55 2020 +0900
@@ -103,7 +103,8 @@
   return $ir;
 }
 
-sub separate_code_and_data_gear_after_parse {
+# separate_code_and_data_gear_after_parse
+sub detailed_parse {
   my ($class, $file)  = @_;
   my $ir = Gears::Interface->parse($file);
 
--- a/src/parallel_execution/lib/Gears/Stub.pm	Fri Aug 28 16:43:39 2020 +0900
+++ b/src/parallel_execution/lib/Gears/Stub.pm	Tue Sep 01 15:56:55 2020 +0900
@@ -1,39 +1,107 @@
 package Gears::Stub;
 use strict;
 use warnings;
+
 use Carp qw/croak/;
-use File::Find;
-use Gears::Util;
+
+use Gears::Interface;
+
+sub generate_constructor {
+  my ($class, $interface_info, $impl_info) = @_;
 
-use DDP {deparse => 1};
+  my $interface_name = $interface_info->{name};
+  my $impl_name      = $impl_info->{name};
+
+  my $interface_ir = Gears::Interface->detailed_parse($interface_info->{path});
+  my $impl_ir  = Gears::Interface->detailed_parse($impl_info->{path});
+
+  my $interface_var_name = shift @{$interface_ir->{data}};
 
-sub new {
-  my ($class, %args) = @_;
+  if ($interface_var_name =~ /union\s*Data\*\s*(\w+)/) {
+    $interface_var_name = $1;
+  }
+
+  my $impl_var_name  = _decamelize($impl_ir->{name});
+
+
+  my @interface_data = @{$interface_ir->{data}};
+  my @impl_data      = @{$impl_ir->{data}};
 
-  my $self = {};
-  $self->{file_name} = $args{file_name} || croak 'invalid file_name!'; 
+  my $constructor;
 
-  return bless $self, $class;
-}
+  $constructor .=  <<"EOF";
+$impl_ir->{isa}* create$impl_ir->{name}(struct Context* context) {
+    struct $impl_ir->{isa}* $interface_name  = new $impl_ir->{isa}();
+    struct $impl_ir->{name}* $impl_name = new $impl_ir->{name}();
+    $interface_name->$interface_name = (union Data*)$impl_name;
+EOF
+
+  $constructor .= _generate_variable_initialization($interface_ir->{data}, $interface_var_name);
+  $constructor .= _generate_variable_initialization($impl_ir->{data},      $impl_var_name);
 
 
 
-sub findInterfacewImpl {
-  my $self     = shift;
-  my $cbc_file = shift // $self->{file_name};
-  my $findInterfaces = Gears::Util->extraction_dg_compile_sources([$cbc_file]);
-  my $edgcs = Gears::Util->extraction_dg_compile_sources([$cbc_file]);
-  my $findInterfaces = {};
+  for my $code (@{$impl_ir->{codes}}) {
+      my $code_gear = $code->{name};
+      next if $code_gear eq 'next';
+      $constructor .= "    ${impl_name}->$code_gear = C_$code_gear;\n"
+  }
 
-  my %ifs = ();
-  map { $ifs{$_}++ } keys %{$edgcs->{interfaces}};
-  delete $ifs{Meta};
-  delete $ifs{TaskManager};
+  for my $code (@{$interface_ir->{codes}}) {
+      my $code_gear = $code->{name};
+      next if $code_gear eq 'next';
+      $constructor .= "    ${interface_name}->$code_gear = C_${code_gear}$impl_ir->{name};\n"
+  }
 
-  push(@{$findInterfaces->{interfaces}}, keys %ifs);
-  push(@{$findInterfaces->{impls}}, keys %{$edgcs->{impl}});
+  $constructor .= "    return $interface_name;\n";
+  $constructor .= "}\n";
 
-  return $findInterfaces;
+  return $constructor;
 }
 
+sub _generate_variable_initialization {
+  my ($data, $varTypeName) = @_;
+  my @generate_lines;
+  for my $datum (@$data) {
+        $datum =~ s|//[\s\w]+||;
+        if ($datum =~ /^\s+#/) {
+          next;
+        }
+
+        if ($datum =~ /\w+\s\w+\*\s(\w+)/) {
+           push(@generate_lines, "    ${varTypeName}->$1 = NULL;\n");
+            next;
+        }
+        if ($datum =~ /\w+\s\w+\s(\w+)/) {
+            push(@generate_lines, "    ${varTypeName}->$1 = 0;\n");
+        }
+
+        if ($datum =~ /\w+(\*)?\s(\w+)/) {
+            my $is_pointer = $1;
+            my $name = $2;
+            if ($is_pointer) {
+                push(@generate_lines, "    ${varTypeName}->$name = NULL;\n");
+            } else {
+                push(@generate_lines, "    ${varTypeName}->$name  = 0;\n");
+            }
+        }
+  }
+
+  return join '', @generate_lines;
+}
+
+#https://metacpan.org/pod/String::CamelCase
+sub _decamelize {
+  my $s = shift;
+  $s =~ s{([^a-zA-Z]?)([A-Z]*)([A-Z])([a-z]?)}{
+          my $fc = pos($s)==0;
+          my ($p0,$p1,$p2,$p3) = ($1,lc$2,lc$3,$4);
+          my $t = $p0 || $fc ? $p0 : '_';
+          $t .= $p3 ? $p1 ? "${p1}_$p2$p3" : "$p2$p3" : "$p1$p2";
+          $t;
+  }ge;
+  $s;
+}
+
+
 1;
--- a/src/parallel_execution/lib/Gears/Stub/GenerateConstructor.pm	Fri Aug 28 16:43:39 2020 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-package Gears::Stub::GenerateConstructor;
-
-use strict;
-use warnings;
-
-use Gears::Util;
-
-sub generate {
-  my ($out, $impl, $interface) = @_;
-
-  my $impl_ir = $impl->{ir};
-  my $inter_ir = $interface->{ir};
-  my $impl_var_name = $impl->{var_name};
-  my $interface_var_name = $interface->{var_name};
-
-  my @inter_data     = @{$inter_ir->{data}};
-  my @impl_data      = @{$impl_ir->{data}};
-
-  print $out <<"EOF";
-$impl_ir->{isa}* create$impl_ir->{name}(struct Context* context) {
-    struct $impl_ir->{isa}* $interface_var_name  = new $impl_ir->{isa}();
-    struct $impl_ir->{name}* $impl_var_name = new $impl_ir->{name}();
-    $interface_var_name->$interface_var_name = (union Data*)$impl_var_name;
-EOF
-
-  for my $datum (@impl_data) {
-        $datum =~ s|//[\s\w]+||;
-        if ($datum =~ /^\s+#/) {
-          next;
-        }
-
-        if ($datum =~ /\w+\s\w+\*\s(\w+)/) {
-            print $out "    ${impl_var_name}->$1 = NULL;\n";
-            next;
-        }
-        if ($datum =~ /\w+\s\w+\s(\w+)/) {
-            print $out "    ${impl_var_name}->$1 = 0;\n";
-        }
-
-        if ($datum =~ /\w+(\*)?\s(\w+)/) {
-            my $is_pointer = $1;
-            my $var_name = $2;
-            if ($1) {
-                print $out "    ${impl_var_name}->$var_name = NULL;\n";
-            } else {
-                print $out "    ${impl_var_name}->$var_name  = 0;\n";
-            }
-        }
-  }
-
-
-  for my $code (@{$impl_ir->{codes}}) {
-      my $code_gear = $code->{name};
-      next if $code_gear eq 'next';
-      print $out "    ${impl_var_name}->$code_gear = C_$code_gear;\n"
-  }
-
-  for my $code (@{$inter_ir->{codes}}) {
-      my $code_gear = $code->{name};
-      next if $code_gear eq 'next';
-      print $out "    ${interface_var_name}->$code_gear = C_${code_gear}_$impl_ir->{name};\n"
-  }
-
-print $out "    return $interface_var_name;\n";
-print $out "}\n";
-}
-
-1;
--- a/src/parallel_execution/lib/Gears/Stub/GenerateDataGear.pm	Fri Aug 28 16:43:39 2020 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-package Gears::Stub::GenerateDataGear;
-use strict;
-use warnings;
-
-
-sub new {
-  my ($class, %args) = @_;
-  my $self = {};
-
-  return bless $self, $class;
-}
-
-
-1;
--- a/src/parallel_execution/perlTests/Interface.t	Fri Aug 28 16:43:39 2020 +0900
+++ b/src/parallel_execution/perlTests/Interface.t	Tue Sep 01 15:56:55 2020 +0900
@@ -46,7 +46,7 @@
 };
 
 
-subtest 'separate_code_and_data_gear_after_parse' => sub {
+subtest 'detailed_parse' => sub {
   subtest 'Queue' => sub {
     plan tests => 1;
 
@@ -102,7 +102,7 @@
                                }
           };
 
-          my $have = Gears::Interface->separate_code_and_data_gear_after_parse($queue_header);
+          my $have = Gears::Interface->detailed_parse($queue_header);
 
           is_deeply ($have, $want, "parsing Queue.h")  || diag explain $have;
       };
@@ -189,7 +189,7 @@
                     ],
           'name' => 'Stack'
         };
-            my $have = Gears::Interface->separate_code_and_data_gear_after_parse($stack_header);
+            my $have = Gears::Interface->detailed_parse($stack_header);
 
             is_deeply ($have, $want, "parsing Stack.h")  || diag explain $have;
     };
--- a/src/parallel_execution/tools/trans_impl.pl	Fri Aug 28 16:43:39 2020 +0900
+++ b/src/parallel_execution/tools/trans_impl.pl	Tue Sep 01 15:56:55 2020 +0900
@@ -19,10 +19,10 @@
     die "require header file";
 }
 
-my $impl_ir         = Gears::Interface->separate_code_and_data_gear_after_parse(File::Spec->rel2abs($impl_file));
+my $impl_ir         = Gears::Interface->detailed_parse(File::Spec->rel2abs($impl_file));
 my $interface_file  = find_using_interface_header($impl_ir->{isa},"$FindBin::Bin/..");
 
-my $inter_ir        = Gears::Interface->separate_code_and_data_gear_after_parse($interface_file);
+my $inter_ir        = Gears::Interface->detailed_parse($interface_file);
 
 my $interface_var_name = shift @{$inter_ir->{data}};
 
@@ -127,6 +127,31 @@
   }
 
 
+  for my $datum (@inter_data) {
+        $datum =~ s|//[\s\w]+||;
+        if ($datum =~ /^\s+#/) {
+          next;
+        }
+
+        if ($datum =~ /\w+\s\w+\*\s(\w+)/) {
+            print $out "    ${interface_var_name}->$1 = NULL;\n";
+            next;
+        }
+        if ($datum =~ /\w+\s\w+\s(\w+)/) {
+            print $out "    ${interface_var_name}->$1 = 0;\n";
+        }
+
+        if ($datum =~ /\w+(\*)?\s(\w+)/) {
+            my $is_pointer = $1;
+            my $var_name = $2;
+            if ($1) {
+                print $out "    ${interface_var_name}->$var_name = NULL;\n";
+            } else {
+                print $out "    ${interface_var_name}->$var_name  = 0;\n";
+            }
+        }
+  }
+
   for my $code (@{$impl_ir->{codes}}) {
       my $code_gear = $code->{name};
       next if $code_gear eq 'next';