diff trans_impl.pl @ 1:9a4279c88aa7 default tip

copy from xv6 repository
author anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Fri, 06 Mar 2020 14:59:59 +0900
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trans_impl.pl	Fri Mar 06 14:59:59 2020 +0900
@@ -0,0 +1,244 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+
+use FindBin;
+use lib "$FindBin::Bin/lib";
+use Gears::Util;
+
+use Getopt::Std;
+use File::Spec;
+
+my %opt;
+getopts("wo:" => \%opt);
+
+my $impl_file = shift or die 'require impl file';
+my $impl_ir         = Gears::Util->parse_with_separate_code_data_gears(File::Spec->rel2abs($impl_file));
+my $interface_file  = Gears::Util->find_using_interface_header($impl_ir->{isa},"$FindBin::Bin/..");
+
+my $inter_ir        = Gears::Util->parse_with_separate_code_data_gears($interface_file);
+
+my $interface_var_name = shift @{$inter_ir->{data}};
+
+if ($interface_var_name =~ /union\s*Data\*\s*(\w+)/) {
+  $interface_var_name = $1;
+}
+
+my $impl_var_name  = decamelize($impl_ir->{name});
+
+my $interface = {ir => $inter_ir, var_name => $interface_var_name};
+my $impl = {ir => $impl_ir, var_name => $impl_var_name};
+
+my $output_file = $impl_file;
+$output_file =~ s/\.h/.cbc/;
+my $stdout    = *STDOUT;
+
+if ($opt{w}) {
+    if(-f $output_file) {
+      update_file($output_file, $interface, $impl, $impl_file);
+      exit 0;
+    }
+    open $stdout, '>', $output_file;
+} elsif ($opt{o}) {
+    if(-f $opt{o}) {
+      update_file($opt{o}, $interface, $impl, $impl_file);
+      exit 0;
+    }
+    open $stdout, '>', $opt{o};
+}
+
+emit_include_part($stdout, $inter_ir->{name});
+emit_impl_header_in_comment($stdout, $impl_file);
+emit_constracutor($stdout,$impl,$interface);
+emit_code_gears($stdout,$impl,$interface);
+close $stdout;
+
+sub emit_include_part {
+  my ($out, $interface) = @_;
+  print $out <<"EOF"
+#include "../context.h"
+#interface "$interface.h"
+
+EOF
+}
+
+sub emit_impl_header_in_comment {
+  my ($out, $impl_file) = @_;
+  my $line =  Gears::Util->slup($impl_file);
+  print $out "// ----\n";
+  map { print $out "// $_\n" } split /\n/, $line;
+  print $out "// ----\n\n";
+}
+
+
+sub emit_constracutor {
+  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* cbc_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";
+}
+
+
+sub emit_code_gears {
+  my ($out, $impl, $interface) = @_;
+
+  my $inter_ir = $interface->{ir};
+  my $impl_ir  = $impl->{ir};
+
+  my $impl_name = $impl_ir->{name};
+  my $interface_name = $inter_ir->{name};
+
+  my $impl_var_name = $impl->{var_name};
+  my $interface_var_name = $interface->{var_name};
+
+  my @inter_data = @{$inter_ir->{data}};
+
+  my $data_gear_types = {};
+
+  if (defined $impl_ir->{codes}) {
+    replace_code_gears($impl_ir,$impl_name,$interface_name,1,$out);
+  }
+  replace_code_gears($inter_ir,$impl_name,$interface_name,0,$out);
+}
+
+sub replace_code_gears {
+  my ($ir, $impl, $interface_name, $is_impl, $out) = @_;
+
+  my $replace_impl = $is_impl ? $impl : $interface_name;
+
+  for my $cg (@{$ir->{codes}}) {
+    next if ($cg->{name} eq 'next');
+    my $data_gears = $cg->{args};
+    while ($data_gears =~ /Type\*\s*(\w+),/g) {
+        $data_gears =~ s/Type\*/struct $replace_impl*/;
+    }
+
+    if ($is_impl) {
+      while ($data_gears =~ /Isa\*\s*(\w+),/g) {
+          $data_gears =~ s/Isa\*/struct $interface_name*/;
+      }
+    } else {
+      $data_gears =~ s/Impl/struct $impl/g;
+    }
+    print $out "__code $cg->{name}";
+    unless ($is_impl) {
+        print $out $impl;
+    }
+    print $out "(";
+    print $out "$data_gears) {\n\n";
+    _emit_cg($out,$data_gears);
+  }
+}
+
+
+sub _emit_cg {
+  my ($out, $data_gears) = @_;
+  my @cg = ();
+  while ($data_gears =~ /__code ([\w(\.)\*\s,]+?\)),?/g) {
+    push(@cg, $1);
+  }
+  if (@cg) {
+    if (@cg == 2) {
+      print $out "    if (:TODO:) {\n";
+      print $out "         goto ",shift(@cg),";\n";
+      print $out "    }\n";
+      print $out "    goto ",shift(@cg),";\n";
+    } else {
+      print $out "    goto ",shift(@cg),";\n";
+    }
+  }
+  print $out "}\n\n";
+}
+
+sub update_file {
+    my ($output_file, $interface, $impl, $impl_file) = @_;
+    my $under_code = collection_save_code_gears($output_file,$interface->{var_name});
+    open my $fh, '>', $output_file;
+    emit_include_part($fh, $interface->{ir}->{name});
+    emit_impl_header_in_comment($fh, $impl_file);
+    emit_constracutor($fh,$impl,$interface);
+    map { print $fh $_ } @{$under_code};
+    close $fh;
+}
+
+sub collection_save_code_gears {
+  my ($output_file,$interface_name) = @_;
+  open my $fh, '<', $output_file;
+  while (my $line = <$fh>) {
+    if ($line =~ /\s*return $interface_name;\s*/) {
+      $line = <$fh>; # } skip...
+      last;
+    }
+  }
+
+  my @res;
+  push(@res, <$fh>);
+  return \@res;
+}
+
+#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;
+}