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