comparison 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
comparison
equal deleted inserted replaced
0:720e9c0936e0 1:9a4279c88aa7
1 #!/usr/bin/env perl
2 use strict;
3 use warnings;
4
5 use FindBin;
6 use lib "$FindBin::Bin/lib";
7 use Gears::Util;
8
9 use Getopt::Std;
10 use File::Spec;
11
12 my %opt;
13 getopts("wo:" => \%opt);
14
15 my $impl_file = shift or die 'require impl file';
16 my $impl_ir = Gears::Util->parse_with_separate_code_data_gears(File::Spec->rel2abs($impl_file));
17 my $interface_file = Gears::Util->find_using_interface_header($impl_ir->{isa},"$FindBin::Bin/..");
18
19 my $inter_ir = Gears::Util->parse_with_separate_code_data_gears($interface_file);
20
21 my $interface_var_name = shift @{$inter_ir->{data}};
22
23 if ($interface_var_name =~ /union\s*Data\*\s*(\w+)/) {
24 $interface_var_name = $1;
25 }
26
27 my $impl_var_name = decamelize($impl_ir->{name});
28
29 my $interface = {ir => $inter_ir, var_name => $interface_var_name};
30 my $impl = {ir => $impl_ir, var_name => $impl_var_name};
31
32 my $output_file = $impl_file;
33 $output_file =~ s/\.h/.cbc/;
34 my $stdout = *STDOUT;
35
36 if ($opt{w}) {
37 if(-f $output_file) {
38 update_file($output_file, $interface, $impl, $impl_file);
39 exit 0;
40 }
41 open $stdout, '>', $output_file;
42 } elsif ($opt{o}) {
43 if(-f $opt{o}) {
44 update_file($opt{o}, $interface, $impl, $impl_file);
45 exit 0;
46 }
47 open $stdout, '>', $opt{o};
48 }
49
50 emit_include_part($stdout, $inter_ir->{name});
51 emit_impl_header_in_comment($stdout, $impl_file);
52 emit_constracutor($stdout,$impl,$interface);
53 emit_code_gears($stdout,$impl,$interface);
54 close $stdout;
55
56 sub emit_include_part {
57 my ($out, $interface) = @_;
58 print $out <<"EOF"
59 #include "../context.h"
60 #interface "$interface.h"
61
62 EOF
63 }
64
65 sub emit_impl_header_in_comment {
66 my ($out, $impl_file) = @_;
67 my $line = Gears::Util->slup($impl_file);
68 print $out "// ----\n";
69 map { print $out "// $_\n" } split /\n/, $line;
70 print $out "// ----\n\n";
71 }
72
73
74 sub emit_constracutor {
75 my ($out, $impl, $interface) = @_;
76
77 my $impl_ir = $impl->{ir};
78 my $inter_ir = $interface->{ir};
79 my $impl_var_name = $impl->{var_name};
80 my $interface_var_name = $interface->{var_name};
81
82 my @inter_data = @{$inter_ir->{data}};
83 my @impl_data = @{$impl_ir->{data}};
84
85 print $out <<"EOF";
86 $impl_ir->{isa}* create$impl_ir->{name}(struct Context* cbc_context) {
87 struct $impl_ir->{isa}* $interface_var_name = new $impl_ir->{isa}();
88 struct $impl_ir->{name}* $impl_var_name = new $impl_ir->{name}();
89 $interface_var_name->$interface_var_name = (union Data*)$impl_var_name;
90 EOF
91
92 for my $datum (@impl_data) {
93 $datum =~ s|//[\s\w]+||;
94 if ($datum =~ /^\s+#/) {
95 next;
96 }
97
98 if ($datum =~ /\w+\s\w+\*\s(\w+)/) {
99 print $out " ${impl_var_name}->$1 = NULL;\n";
100 next;
101 }
102 if ($datum =~ /\w+\s\w+\s(\w+)/) {
103 print $out " ${impl_var_name}->$1 = 0;\n";
104 }
105
106 if ($datum =~ /\w+(\*)?\s(\w+)/) {
107 my $is_pointer = $1;
108 my $var_name = $2;
109 if ($1) {
110 print $out " ${impl_var_name}->$var_name = NULL;\n";
111 } else {
112 print $out " ${impl_var_name}->$var_name = 0;\n";
113 }
114 }
115 }
116
117
118 for my $code (@{$impl_ir->{codes}}) {
119 my $code_gear = $code->{name};
120 next if $code_gear eq 'next';
121 print $out " ${impl_var_name}->$code_gear = C_$code_gear;\n"
122 }
123
124 for my $code (@{$inter_ir->{codes}}) {
125 my $code_gear = $code->{name};
126 next if $code_gear eq 'next';
127 print $out " ${interface_var_name}->$code_gear = C_$code_gear$impl_ir->{name};\n"
128 }
129
130 print $out " return $interface_var_name;\n";
131 print $out "}\n";
132 }
133
134
135 sub emit_code_gears {
136 my ($out, $impl, $interface) = @_;
137
138 my $inter_ir = $interface->{ir};
139 my $impl_ir = $impl->{ir};
140
141 my $impl_name = $impl_ir->{name};
142 my $interface_name = $inter_ir->{name};
143
144 my $impl_var_name = $impl->{var_name};
145 my $interface_var_name = $interface->{var_name};
146
147 my @inter_data = @{$inter_ir->{data}};
148
149 my $data_gear_types = {};
150
151 if (defined $impl_ir->{codes}) {
152 replace_code_gears($impl_ir,$impl_name,$interface_name,1,$out);
153 }
154 replace_code_gears($inter_ir,$impl_name,$interface_name,0,$out);
155 }
156
157 sub replace_code_gears {
158 my ($ir, $impl, $interface_name, $is_impl, $out) = @_;
159
160 my $replace_impl = $is_impl ? $impl : $interface_name;
161
162 for my $cg (@{$ir->{codes}}) {
163 next if ($cg->{name} eq 'next');
164 my $data_gears = $cg->{args};
165 while ($data_gears =~ /Type\*\s*(\w+),/g) {
166 $data_gears =~ s/Type\*/struct $replace_impl*/;
167 }
168
169 if ($is_impl) {
170 while ($data_gears =~ /Isa\*\s*(\w+),/g) {
171 $data_gears =~ s/Isa\*/struct $interface_name*/;
172 }
173 } else {
174 $data_gears =~ s/Impl/struct $impl/g;
175 }
176 print $out "__code $cg->{name}";
177 unless ($is_impl) {
178 print $out $impl;
179 }
180 print $out "(";
181 print $out "$data_gears) {\n\n";
182 _emit_cg($out,$data_gears);
183 }
184 }
185
186
187 sub _emit_cg {
188 my ($out, $data_gears) = @_;
189 my @cg = ();
190 while ($data_gears =~ /__code ([\w(\.)\*\s,]+?\)),?/g) {
191 push(@cg, $1);
192 }
193 if (@cg) {
194 if (@cg == 2) {
195 print $out " if (:TODO:) {\n";
196 print $out " goto ",shift(@cg),";\n";
197 print $out " }\n";
198 print $out " goto ",shift(@cg),";\n";
199 } else {
200 print $out " goto ",shift(@cg),";\n";
201 }
202 }
203 print $out "}\n\n";
204 }
205
206 sub update_file {
207 my ($output_file, $interface, $impl, $impl_file) = @_;
208 my $under_code = collection_save_code_gears($output_file,$interface->{var_name});
209 open my $fh, '>', $output_file;
210 emit_include_part($fh, $interface->{ir}->{name});
211 emit_impl_header_in_comment($fh, $impl_file);
212 emit_constracutor($fh,$impl,$interface);
213 map { print $fh $_ } @{$under_code};
214 close $fh;
215 }
216
217 sub collection_save_code_gears {
218 my ($output_file,$interface_name) = @_;
219 open my $fh, '<', $output_file;
220 while (my $line = <$fh>) {
221 if ($line =~ /\s*return $interface_name;\s*/) {
222 $line = <$fh>; # } skip...
223 last;
224 }
225 }
226
227 my @res;
228 push(@res, <$fh>);
229 return \@res;
230 }
231
232 #https://metacpan.org/pod/String::CamelCase
233 sub decamelize
234 {
235 my $s = shift;
236 $s =~ s{([^a-zA-Z]?)([A-Z]*)([A-Z])([a-z]?)}{
237 my $fc = pos($s)==0;
238 my ($p0,$p1,$p2,$p3) = ($1,lc$2,lc$3,$4);
239 my $t = $p0 || $fc ? $p0 : '_';
240 $t .= $p3 ? $p1 ? "${p1}_$p2$p3" : "$p2$p3" : "$p1$p2";
241 $t;
242 }ge;
243 $s;
244 }