Home | History | Annotate | Download | only in perl
      1 #!/usr/bin/perl
      2 #
      3 # Copyright 2017 The TensorFlow Authors. All Rights Reserved.
      4 #
      5 # Licensed under the Apache License, Version 2.0 (the "License");
      6 # you may not use this file except in compliance with the License.
      7 # You may obtain a copy of the License at
      8 #
      9 #     http://www.apache.org/licenses/LICENSE-2.0
     10 #
     11 # Unless required by applicable law or agreed to in writing, software
     12 # distributed under the License is distributed on an "AS IS" BASIS,
     13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 # See the License for the specific language governing permissions and
     15 # limitations under the License.
     16 # =============================================================================
     17 
     18 use strict;
     19 
     20 my $copyright =
     21 '/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
     22 
     23 Licensed under the Apache License, Version 2.0 (the "License");
     24 you may not use this file except in compliance with the License.
     25 You may obtain a copy of the License at
     26 
     27     http://www.apache.org/licenses/LICENSE-2.0
     28 
     29 Unless required by applicable law or agreed to in writing, software
     30 distributed under the License is distributed on an "AS IS" BASIS,
     31 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     32 See the License for the specific language governing permissions and
     33 limitations under the License.
     34 ==============================================================================*/
     35 ';
     36 
     37 my $count;
     38 
     39 my $option = '-t', my $template;
     40 
     41 sub usage {
     42     print "Usage: tftypes [-ctdT] <type desc file> <tmpl file>\n\n"
     43          ."This script generates parts of various .java files that depend on which"
     44          ."TensorFlow types are supported by the Java API and how much. For each"
     45          ."such .java file, there is a .tmpl file in the same source directory in"
     46          ."which the strings \@TYPEINFO\@ and \@IMPORTS\@ are replaced with"
     47          ."appropriate Java code. Output code is sent to standard output.\n\n";
     48 
     49     print "Modulo putting in the correct directory names, it can be invoked as follows:\n";
     50     print "tftypes -c tftypes.csv Tensors.java.tmpl > Tensors.java\n";
     51     print "tftypes -t tftypes.csv <dir>                                   [outputs files to dir]\n";
     52 }
     53 
     54 if ($ARGV[0] =~ m/^-/) {
     55     $option = shift;
     56 }
     57 my $typedesc = shift;
     58 my $tmpl = shift;
     59 
     60 my $dirname;
     61 
     62 if ($option eq '-t') {
     63     $dirname = $tmpl;
     64 }
     65 
     66 open (TMPL, "<$tmpl") || die "Cannot open $tmpl for reading\n";
     67 
     68 my $text = do { local $/; <TMPL> };
     69 
     70 my %jtypecount;
     71 
     72 my $typeinfo, my $imports;
     73 
     74 open (TYPEDESC, $typedesc);
     75 
     76 my @info = ([]);
     77 
     78 sub trim {
     79     (my $ret) = @_;
     80     $ret =~ s/^\s*//g;
     81     $ret =~ s/\s*$//g;
     82     return $ret;
     83 }
     84 
     85 while (<TYPEDESC>) {
     86     chomp;
     87     my $line = $_;
     88     if ($line =~ m/^TF type/) { next }
     89     $line =~ s/\r$//;
     90     my @items = split /,/, $line, 6;
     91     for (my $i = 0; $i <= $#items; $i++) {
     92         $items[$i] = trim $items[$i];
     93     }
     94     my $jtype = $items[2];
     95     $jtypecount{$jtype}++;
     96     if ($jtypecount{$jtype} > 1) {
     97 # currently allowing Java types to stand for more than one TF type, but
     98 # may want to revisit this.
     99 #       print STDERR "Ambiguous Java type for $name : $jtype\n";
    100 #       exit 1
    101     }
    102 
    103     push @info, \@items;
    104 }
    105 
    106 sub article {
    107     (my $s) = @_;
    108     if (substr($s, 0, 1) =~ m/^[aeoiu8]$/i) {
    109         return "an $s"
    110     } else {
    111         return "a $s"
    112     }
    113 }
    114 
    115 for (my $i = 1; $i <= $#info; $i++) {
    116     (my $name, my $builtin, my $jtype, my $creat, my $default, my $desc) =
    117         @{$info[$i]};
    118     my $tfname = $name;
    119     my $ucname = uc $name;
    120 
    121     print STDERR "$name $desc\n";
    122 
    123     if ($option eq '-t') {
    124         if ($jtype eq '') { next }
    125         if ($builtin eq 'y') { next }
    126         # Generate class declarations
    127         # print STDERR "Creating $dirname/$tfname.java\n";
    128         open (CLASSFILE, ">$dirname/$tfname.java") || die "Can't open $tfname.java";
    129         print CLASSFILE $copyright, "\n";
    130         # print CLASSFILE "// GENERATED FILE. To update, edit tftypes.pl instead.\n\n";
    131 
    132         my $fulldesc = article($desc);
    133         print CLASSFILE  "package org.tensorflow.types;\n\n";
    134         print CLASSFILE  "/** Represents $fulldesc. */\n"
    135                         ."public class $tfname {\n"
    136                         ."  private $tfname() {\n"
    137                         ."  }\n"
    138                         ."}\n";
    139         close(CLASSFILE);
    140     } elsif ($option eq '-c') {
    141       # Generate creator declarations for Tensors.java
    142       if ($jtype ne '' && $creat eq 'y') {
    143         for (my $brackets = '', my $rank = 0; length $brackets <= 12; $brackets .= '[]', $rank++) {
    144             my $datainfo = "   *  \@param data An array containing the values to put into the new tensor.\n"
    145                           ."   *  The dimensions of the new tensor will match those of the array.\n";
    146             if ($rank == 0) {
    147                 $datainfo = "   *  \@param data The value to put into the new scalar tensor.\n"
    148             }
    149 
    150             my $trank = $rank;
    151             if ($tfname eq 'String') {
    152                 $trank = $rank-1;
    153                 next if $trank < 0;
    154 
    155                 $datainfo = "   *  \@param data An array containing the data to put into the new tensor.\n"
    156                            ."   *  String elements are sequences of bytes from the last array dimension.\n";
    157             }
    158 
    159 
    160             my $intro = ($trank > 0)
    161                 ?  "Creates a rank-$trank tensor of {\@code $jtype} elements."
    162                 :  "Creates a scalar tensor containing a single {\@code $jtype} element.";
    163             $typeinfo .=
    164              "  /**\n"
    165             ."   * $intro\n"
    166             ."   * \n"
    167             .$datainfo
    168             ."   */\n"
    169             ."  public static Tensor<$tfname> create($jtype$brackets data) {\n"
    170             ."    return Tensor.create(data, $tfname.class);\n"
    171             ."  }\n\n";
    172         }
    173       }
    174       if ($text =~ m/\b$tfname\b/ && $builtin eq 'n' && $creat eq 'y') {
    175             $imports .= "import org.tensorflow.types.$tfname;\n";
    176       }
    177     }
    178 }
    179 
    180 if ($option ne '-t') {
    181 # print "// GENERATED FILE. Edits to this file will be lost -- edit $tmpl instead.\n";
    182 
    183   $text =~ s/\@TYPEINFO\@/$typeinfo/;
    184   $text =~ s/\@IMPORTS\@/$imports/;
    185 
    186   print $text;
    187 }
    188