source: to-imperative/trunk/compiler/rfpc.rf @ 1819

Last change on this file since 1819 was 1819, checked in by orlov, 15 years ago
  • Merged converters to C++ and Java. Not properly working yet.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.7 KB
Line 
1//
2// Copyright (C) 1999, 2000 Refal+ Development Group
3//
4// Refal+ is free software; you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation; either version 2 of the License, or
7// (at your option) any later version.
8//
9// Refal+ is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Refal+; if not, write to the Free Software
16// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17//
18// $Source$
19// $Revision: 1819 $
20// $Date: 2005-12-27 11:48:51 +0000 (Tue, 27 Dec 2005) $
21
22// rfpc.rfi
23$use "rfp_src"; // rfp_src.rfi
24$use "rfp_err"; // rfp_err.rfi
25$use "rfp_lex"; // rfp_lex.rfi
26$use "rfp_parse"; // rfp_parse.rfi
27$use "rfp_debug"; // rfp_debug.rfi
28$use "rfp_compile"; // rfp_compile.rfi
29$use "rfp_asail_cpp"; //rfp_asail_cpp.rfi
30$use "rfp_asail_java"; //rfp_asail_java.rfi
31$use "rfp_as2as";
32$use "rfp_check";
33$use "rfp_helper";
34$use "rfp_format";
35$use "rfp_asail_optim"; //rfp_asail_optim.rfi
36
37$use StdIO;
38$use Box;
39$use Dos;
40$use Arithm;
41$use Table;
42$use Convert;
43$use Class;
44$use Access;
45$use Compare;
46$use CppMangle;
47
48$const RevDate = ('$Revision: 1819 $') ('$Date: 2005-12-27 11:48:51 +0000 (Tue, 27 Dec 2005) $');
49$func Version = e.version;
50
51// information about available compiler options
52$box Options;
53
54// put information about compiler options in the &Options box
55$func Init-Options = ;
56
57// display help screen
58$func Display-Help = ;
59
60$func RFP-Parse-Args (e.files) (e.prevarg) s.index = e.files;
61$func RFP-Set-Path = ;
62
63// initialize tables
64$func Get-Ready-To-Work e.Items = ;
65
66$func CPP-Pretty-Print s.inner-call? s.channel (e.indent) e.expr = ;
67
68// print information about compilation stages when -verbose option was
69// supplied on command line
70$func Verbose e.string = ;
71
72$func Open-Channel e.name (e.ext) = s.channel s.need-close?;
73
74$func Find-Includes = e.includes;
75
76
77Main =
78  <Init-Options>,
79  <RFP-Parse-Args () () 1> :: e.files,
80  <RFP-Set-Path>,
81  <Store &Error-Counter 0>,
82  <Store &Warning-Counter 0>,
83//  <PrintLN e.files>,
84  e.files : {
85    /*empty*/ =
86      {
87        <In-Table? &RFP-Options HELP>;
88        <PrintLN 'Refal+ compiler ' <Version>>,
89          'Usage: rfpc' :: e.start,
90          <Length e.start> :: s.st-len,
91          <Print e.start>,
92          <Box> :: s.len,
93          <Store s.len s.st-len>,
94          {
95            <? &Options> : e (((e.next) e) t e.descr) e,
96              <"<=" (<Length e.next>) (3)>,
97              {
98                e.descr : (e.arg) e = ' [-' e.next ' <' e.arg '>]';
99                ' [-' e.next ']';
100              } :: e.next,
101              <Length e.next> :: s.n-len,
102              <"+" <To-Int <? s.len>> s.n-len> :: s.new,
103              {
104                <">" (s.new) (64)> =
105                  <Store s.len <"+" s.st-len s.n-len>>,
106                  <PrintLN>,
107                  <Print <Repeat s.st-len ' '>>;
108                <Store s.len s.new>;
109              },
110              <Print e.next>,
111              $fail;
112            <PrintLN ' file ...'>;
113          },
114          <PrintLN>,
115          <PrintLN! &StdErr 'No input files specified'>;
116      };
117    e01 (e.file) e02,
118      {
119        e.file : $r e.basename '.' e.ext = e.basename (' .' e.ext);
120        e.file ();
121      } :: e.in-basename (e.ext),
122      {
123        e01 : /*empty*/, <Lookup &RFP-Options NAME>;
124        e.in-basename;
125      } :: e.basename,
126      {
127        e.basename : $r e.dirname &RFP-Dir-Separator e.filename =
128          (e.dirname) e.filename;
129        () e.basename;
130      } :: (e.dirname) e.filename,
131      {
132        <Channel? e.basename> = e.in-basename;
133        e.basename;
134      } :: e.headname,
135      <Subst (&RFP-Dir-Separator) (('_')) e.headname> :: e.headname,
136      <Rfp2Cpp <To-Word e.headname>> :: e.headname,
137      {
138        e.ext : \{ ' .rf'; ' .rfi'; } =
139          <Verbose "parsing started" >,
140          <RFP-Lexer e.file> :: e.tokens,
141          <Store &RFP-Token-Stack e.tokens>,
142          <RFP-Parser> :: t.as,
143          <Verbose "parsing finished">,
144          AS-REFAL t.as;
145        e.ext : ' .asr' =
146          <Channel> :: s.channel,
147          <Open-File s.channel e.file R>,
148          AS-REFAL <Read! s.channel>;
149        e.ext : ' .ast' =
150          <Channel> :: s.channel,
151          <Open-File s.channel e.file R>,
152          AS-TRANSFORMED <Read! s.channel>;
153        e.ext : ' .asi' =
154          <Channel> :: s.channel,
155          <Open-File s.channel e.file R>,
156          AS-AIL (AS-AIL AS-AIL <Read! s.channel> <Read! s.channel>);
157        <PrintLN! &StdErr "Error: unknown extension" e.ext " in " e.file> = $fail;
158      } : s.type (s.tag t.ModuleName e.Items),
159      {
160        s.type : AS-AIL;
161        <Get-Ready-To-Work e.Items>;
162      },
163      s.type e.Items $iter s.type : {
164        AS-REFAL =
165          {
166            <In-Table? &RFP-Options AS-REFAL> =
167              <Open-Channel e.basename ('.asr')> :: s.channel s.need-close?,
168              <RFP-Pretty-Print s.channel () (s.tag t.ModuleName e.Items)>,
169              { s.need-close? : 1 = <Close-Channel s.channel>;; };;
170          },
171          <? &Error-Counter> : 0,
172          {
173            <In-Table? &RFP-Options NO-CHECK>;
174            <Verbose "syntax check started">,
175              <RFP-Check e.Items>,
176              <Verbose "syntax check finished"> =
177              <? &Error-Counter> : 0;
178          },
179          \{
180            <In-Table? &RFP-Options CC>;
181            <In-Table? &RFP-Options HH>;
182            <In-Table? &RFP-Options JAVA>;
183            <In-Table? &RFP-Options AS-AIL>;
184            <In-Table? &RFP-Options AS-TRANSFORMED>;
185          },
186          {
187            <In-Table? &RFP-Options DBG> =
188              <Verbose "debug-text generation started">,
189              <RFP-Debug e.Items> :: e.Items,
190              <Verbose "debug-text generation finished">,
191              e.Items;
192            e.Items;
193          } :: e.Items,   
194          {
195            <In-Table? &RFP-Options NO-TRANSFORM> = e.Items;
196            <Verbose "as-to-as transformation started">,
197              <RFP-As2As-Transform e.Items> :: e.Items,
198              <Verbose "as-to-as transformation finished">,
199              e.Items;
200          } :: e.Items,
201          AS-TRANSFORMED e.Items;
202        AS-TRANSFORMED =
203          {
204            <In-Table? &RFP-Options AS-TRANSFORMED> =
205              <Open-Channel e.basename ('.ast')> :: s.channel s.need-close?,
206              <RFP-Pretty-Print s.channel () (s.tag t.ModuleName e.Items)>,
207              { s.need-close? : 1 = <Close-Channel s.channel>;; };;
208          },
209          \{
210            <In-Table? &RFP-Options CC>;
211            <In-Table? &RFP-Options HH>;
212            <In-Table? &RFP-Options JAVA>;
213            <In-Table? &RFP-Options AS-AIL>;
214          },
215          <Verbose "compilation to abstract imperative language started">,
216          <RFP-Compile e.Items> : (INTERFACE e.interf) (MODULE e.module),
217          <Verbose "compilation to abstract imperative language finished">,
218          AS-AIL
219          (INTERFACE t.ModuleName e.interf) (MODULE t.ModuleName e.module);
220        AS-AIL =
221          {
222            <In-Table? &RFP-Options AS-AIL> =
223              <Open-Channel e.basename ('.asi')> :: s.channel s.need-close?,
224              {
225                e.Items : e t.item e,
226                  <RFP-Pretty-Print s.channel () t.item>,
227                  $fail;;
228              },
229              { s.need-close? : 1 = <Close-Channel s.channel>;; };;
230          },
231          \{
232            <In-Table? &RFP-Options HH>,
233              e.Items : (INTERFACE t.asail-mod-name v.headers) e,
234              <Verbose "headers generation started">,
235              <RFP-ASAIL-To-CPP t.asail-mod-name v.headers> :: e.headers,
236              <Verbose "headers generation finished">,
237              <Open-Channel e.basename ('.hh')> :: s.channel s.need-close?,
238              <PrintLN! s.channel '#ifndef __' e.headname '_hh__'>,
239              <PrintLN! s.channel '#define __' e.headname '_hh__'>,
240              <PrintLN! s.channel '\n#include <rf_core.hh>'>,
241              <CPP-Pretty-Print 0 s.channel () e.headers>,
242              <PrintLN! s.channel '\n#endif // __' e.headname '_hh__'>,
243              { s.need-close? : 1 = <Close-Channel s.channel>;; },
244              {
245                <In-Table? &RFP-Options CASE-INSENSITIVE>,
246                  # <Channel? e.basename>,
247                  <To-Lower e.filename> :: e.lowname,
248                  # \{ e.filename : e.lowname; } =
249                  e.basename : e.dir e.filename,
250                  e.dir e.lowname :: e.lowbase,
251                  <Open-Channel e.lowbase ('.hh')> :: s.channel s.need-close?,
252                  <Subst (&RFP-Dir-Separator) (('_')) e.lowbase> :: e.headname,
253                  <Rfp2Cpp <To-Word e.headname>> :: e.headname,
254                  <PrintLN! s.channel '#ifndef __' e.headname '_hh__'>,
255                  <PrintLN! s.channel '#define __' e.headname '_hh__'>,
256                  <PrintLN! s.channel '\n#include <' e.basename '.hh>'>,
257                  <PrintLN! s.channel '\nnamespace refal\n{'>,
258                  <PrintLN! s.channel '\nnamespace ' e.lowname
259                            ' = ' e.filename ';'>,
260                  <PrintLN! s.channel '\n}'>,
261                  <PrintLN! s.channel '\n#endif // __' e.headname '_hh__'>,
262                  { s.need-close? : 1 = <Close-Channel s.channel>;; };;
263              },
264              $fail;
265            <In-Table? &RFP-Options CC>,
266              e.Items : e (MODULE t.asail-mod-name v.module),
267              {
268                <In-Table? &RFP-Options NO-OPTIM> = v.module;
269                <Verbose "as-ail optimization started">,
270                  <ASAIL-Optim v.module> :: e.module,
271                  <Verbose "as-ail optimization finished"> =
272                  e.module;
273              } :: e.module ,
274              <Verbose "compilation from as-ail to c++ started">,
275              <RFP-ASAIL-To-CPP t.asail-mod-name e.module> :: e.module,
276              <Verbose "compilation from as-ail to c++ finished">,
277              <Open-Channel e.basename ('.cc')> :: s.channel s.need-close?,
278              <PrintLN! s.channel '#include <rf_core.hh>'>,
279              {
280                <Find-Includes> : e (e.include) e,
281                  <PrintLN! s.channel '#include ' e.include>,
282                  $fail;;
283              },
284              <CPP-Pretty-Print 0 s.channel () e.module>,
285              { s.need-close? : 1 = <Close-Channel s.channel>;; },
286              $fail;
287            <In-Table? &RFP-Options JAVA>,
288              e.Items : (INTERFACE t.asail-mod-name e.headers) (MODULE t e.module),
289              {
290                <In-Table? &RFP-Options NO-OPTIM> = e.module;
291                <Verbose "as-ail optimization started">,
292                  <ASAIL-Optim e.module> :: e.module,
293                  <Verbose "as-ail optimization finished"> =
294                  e.module;
295              } :: e.module,
296              <Verbose "compilation from as-ail to java started">,
297              {
298                e.headers (/*e.exports*/) $iter {
299                  e.headers : (s.decl t.name) e.rest =
300                    e.rest (e.exports t.name);
301                } :: e.headers (e.exports),
302                  e.headers : /*empty*/ =
303                  e.exports;
304              } :: e.exports,
305              <RFP-ASAIL-To-Java t.asail-mod-name (e.exports) e.module> :: e.module,
306              <Verbose "compilation from as-ail to java finished">,
307              <Open-Channel e.basename ('.java')> :: s.channel s.need-close?,
308              {
309                e.dirname : v =
310                  <PrintLN! s.channel
311                  'package '<Subst (&RFP-Dir-Separator) (('.')) e.dirname>';'>;;
312              },
313              <PrintLN! s.channel 'import org.refal.plus.*;'>,
314              <CPP-Pretty-Print 0 s.channel () e.module>,
315              { s.need-close? : 1 = <Close-Channel s.channel>;; },
316              $fail;
317          };
318      } :: s.type e.Items,
319      $fail;
320    e.all-files-have-gone;
321  };
322
323Init-Options = <Store &Options
324  ((('I') ('ipath')) IPATH
325    ("dir") "add <dir> to the list of directories to be searched" "for .rfi files")
326  ((('ne') ('no-elaborate')) (BIND NO-ELABORATE))
327  ((('nc') ('no-check')) (BIND NO-CHECK)
328    "don't perform syntax check")
329  ((('nt') ('no-transform')) (BIND NO-TRANSFORM)
330    "don't perform AS-to-AS transformations")
331  ((('c') ('check')) (BIND CHECK)
332    "check only, causes no file creation in the absence"
333    "of other output control options")
334  ((('no') ('no-optim')) (BIND NO-OPTIM) "don't perform ASAIL-optimization")
335  ((('ci') ('comp-item')) COMP-ITEM
336    ("item") "compile <item> only, not the whole source" "(may be used several times)")
337  ((('h') ('help')) HELP /*"display this help screen"*/)
338  ((('v') ('verbose')) (BIND VERBOSE)
339    "display information about the stages of compilation")
340  ((('u')) (BIND CASE-INSENSITIVE)
341    "convert all symbol-words without surrounding quotes" "to upper case")
342  ((('o')) NAME
343    ("name| - ") "place outputs for file1 into files <name>.* or send" "them to stdout")
344  ((('cc')) (BIND CC)
345    "output C++ code")
346  ((('hh')) (BIND HH)
347    "generate header files")
348  ((('j') ('java')) (BIND JAVA)
349    "output Java code")
350  ((('asr') ('as-refal')) (BIND AS-REFAL)
351    "output Refal Abstract Syntax")
352  ((('ast') ('as-transformed')) (BIND AS-TRANSFORMED)
353    "output Refal Abstract Syntax after AS-to-AS" "transformations")
354  ((('asi') ('as-ail')) (BIND AS-AIL)
355    "output Abstract Syntax of Abstract Imperative" "Language")
356  ((('int')) INT ("class_name") "class to use for literal integers")
357  ((('replace-module')) REPLACE-MODULE ("m1" "m2") "use module <m2> instead of <m1>")
358  ((('d') ('debug')) (BIND DEBUG))
359  ((('dbg')) (BIND DBG) "generate text for debugger")
360>;
361
362Display-Help =
363  <Box> :: s.line,
364  ' ' :: e.start1,
365  29 :: s.2nd-col,
366  <Repeat s.2nd-col ' '> :: e.start2,
367  <PrintLN "Refal+ compiler " <Version>>,
368  <PrintLN "Copyright blah-blah-blah">,
369  <PrintLN>,
370  <PrintLN "Usage: rfpc [options] file1 [file2 ...]">,
371  <PrintLN "Options:">,
372  {
373    <? &Options> : e (((e.op) e.opts) t e.descr) e,
374      <Store s.line e.start1 '-' e.op>,
375      {
376        e.opts : e (e.next) e,
377          <Put s.line ', -' e.next>,
378          $fail;;
379      },
380      {
381        e.descr : (e.params) e.rest =
382          {
383            e.params : e s.par e,
384              <Put s.line ' <' <To-Chars s.par> '>'>,
385              $fail;
386            e.rest;
387          };
388        e.descr;
389      } : \{
390        s.phrase e,
391          <PrintLN
392            <? s.line>
393            <Repeat <"-" s.2nd-col <Length <? s.line>>> ' '>
394            s.phrase
395          >,
396          $fail;
397        e s s.phrase e,
398          <PrintLN e.start2 s.phrase>,
399          $fail;
400      };;
401  };
402
403RFP-Parse-Args (e.files) (e.prevarg) s.index =
404{
405  <Arg s.index> : v.arg, <"+" s.index 1> :: s.index =
406    {
407      e.prevarg : v, e.prevarg :
408        {
409          IPATH =
410            <Store &RFP-Include-Path <? &RFP-Include-Path> (v.arg)>,
411            {
412              $iter
413                # \{
414                  <? &RFP-Include-Path> : e1 (e2 &RFP-Dir-Separator),
415                    <Store &RFP-Include-Path e1 (e2)>;
416                };
417            };
418          COMP-ITEM =
419            {
420              <Lookup &RFP-Options ITEMS>;
421              /*empty*/;
422            } :: e.items,
423            <Bind &RFP-Options (ITEMS) (e.items <Make-Name v.arg>)>;
424          NAME =
425            {
426              v.arg : '-' = &StdOut;
427              v.arg;
428            } :: v.arg,
429            <Bind &RFP-Options (NAME) (v.arg)>;
430          INT =
431            <Bind &RFP-Options (INT) (v.arg)>;
432          REPLACE-MODULE = REPLACE-MODULE-2 v.arg;
433          REPLACE-MODULE-2 e.mod1 =
434            <Bind &RFP-Module-Subst (e.mod1) (v.arg)>;
435        } :: e.prevarg,
436        <RFP-Parse-Args (e.files) (e.prevarg) s.index>;
437      v.arg : '-' e.opt =
438        {
439          \{
440            <? &Options> : e ((e (e.opt) e) t.action e) e = t.action;
441            e.opt : '-' e.o,
442              <? &Options> : e ((e (e.o) e) t.action e) e = t.action;
443          } : {
444            (BIND s.option) = <Bind &RFP-Options (s.option) ()>;
445            HELP = <Bind &RFP-Options (HELP) ()>, <Display-Help>;
446            s.other = s.other;
447          } :: e.prevarg,
448            <RFP-Parse-Args (e.files) (e.prevarg) s.index>;
449          <PrintLN! &StdErr "Unknown option \"-" e.opt "\"">,
450            <RFP-Parse-Args (e.files) () s.index>;
451        };
452      <RFP-Parse-Args (e.files (v.arg)) () s.index>;
453    };
454  {
455    \{
456      <In-Table? &RFP-Options CC>;
457      <In-Table? &RFP-Options HH>;
458      <In-Table? &RFP-Options JAVA>;
459      <In-Table? &RFP-Options AS-REFAL>;
460      <In-Table? &RFP-Options AS-TRANSFORMED>;
461      <In-Table? &RFP-Options AS-AIL>;
462      <In-Table? &RFP-Options CHECK>;
463    };
464    <Bind &RFP-Options (CC) ()> <Bind &RFP-Options (HH) ()>;
465  },
466    e.files;
467};
468
469RFP-Set-Path =
470  <Store &RFP-Include-Path <? &RFP-Include-Path> &RFP-Default-Include-Path>;
471
472Get-Ready-To-Work e.Items =
473  <RFP-Clear-Table &Fun>,
474  <RFP-Clear-Table &Fun?>,
475  <RFP-Clear-Table &Const>,
476  <RFP-Clear-Table &Object>,
477  {
478    e.Items : e t.Item e,
479      t.Item : (s.Linkage s.ItemType t.Pragma t.ItemName e.ItemBody),
480      s.ItemType : {
481        FUNC =
482          <Left 0 2 e.ItemBody> : (e.in) (e.out),
483          &Fun (<Format-Exp e.in>) (<Format-Exp e.out>);
484        FUNC? =
485          <Left 0 2 e.ItemBody> : (e.in) (e.out),
486          &Fun? (<Format-Exp e.in>) (<Format-Exp e.out>);
487        CONST = &Const e.ItemBody;
488        s = &Object e.ItemBody;
489      } :: s.tab e.ItemDef,
490      <Bind s.tab (t.ItemName) (s.Linkage s.ItemType t.Pragma e.ItemDef)>,
491      $fail;;
492  };
493
494RFP-Pretty-Print s.channel (e.indent) e.expr = e.expr :
495  {
496    e0 (e1) e2 =
497      <Write! s.channel e0>,
498      { e.indent : v = <PrintLN! s.channel>;; },
499      <Print! s.channel e.indent '('>,
500      <RFP-Pretty-Print s.channel (e.indent '  ') e1>,
501      {
502        e1 : e (e) e =
503          <PrintLN! s.channel>,
504          <Print! s.channel e.indent ')'>;
505        <Print! s.channel ')'>;
506      },
507      {
508        e2 : (e) e = ;
509        e2 : , e.indent : v = ;
510        <PrintLN! s.channel>, <Print! s.channel e.indent>;
511      },
512      <RFP-Pretty-Print s.channel (e.indent) e2>;
513    v1 =
514      <Write! s.channel v1>;
515    =;
516  };
517
518$const Tab = '  ';
519
520CPP-Pretty-Print s.inner-call? s.channel (e.indent) e.expr, e.expr : {
521  e0 (e1) e2 =
522    { s.inner-call? : 0 = <PrintLN! s.channel>;; },
523    {
524      e0 : /*empty*/, {
525        e1 : LABEL e.label =
526          e.indent : e.ind &Tab,
527          <PrintLN! s.channel e.ind e.label>;
528        <CPP-Pretty-Print 1 s.channel (e.indent) e1>;
529      };
530      <PrintLN! s.channel e.indent e0>,
531        <CPP-Pretty-Print 1 s.channel (e.indent &Tab) (e1)>;
532    },
533    <CPP-Pretty-Print s.inner-call? s.channel (e.indent) e2>;
534  v1 = <PrintLN! s.channel e.indent v1>;
535  /*empty*/ = /*empty*/;
536};
537
538Verbose e.string, {
539  <In-Table? &RFP-Options VERBOSE> =
540    <PrintLN <Time> ": " e.string>;;
541};
542
543Open-Channel {
544  symbol (e), <Channel? symbol> = symbol 0;
545  e.name (e.ext) =
546    <Channel> :: s.channel,
547    {
548      <Open-File s.channel e.name e.ext W> =
549        s.channel 0; // When we need to close channel ???
550      <PrintLN! &StdErr "Error: cannot open file " e.name e.ext " for writing">,
551        <Exit 1>, $fail;
552    };
553};
554
555Find-Includes =
556  <Box> :: s.includes,
557  {
558    <Domain &RFP-Sources> : e (s.idx) e,
559      <Lookup &RFP-Sources s.idx> : e.full-name '.rfi',
560      {
561        <? &RFP-Include-Path> : e (e.path) e,
562          e.full-name : e.path &RFP-Dir-Separator e.name =
563          <Put s.includes ('<refal/' e.name '.hh>')>;
564        <RFP-Dir-Name <RFP-Source-File-Name 1>> : e.path,
565          e.full-name : e.path &RFP-Dir-Separator e.name =
566          <Put s.includes ('"' e.name '.hh"')>;
567        <Put s.includes ('"' e.full-name '.hh"')>;
568      },
569      $fail;;
570  },
571  <? s.includes>;
572
573Version = {
574  &RevDate : (e ' ' v.rev ' ' e) (e ' ' v.date ' ' e) = '2.0-beta-' v.rev ', ' v.date;
575  '2.0-unknown-beta';
576};
577
Note: See TracBrowser for help on using the repository browser.