root/trunk/ProjectFortress/src/com/sun/fortress/Shell.java @ 2405

Revision 2405, 22.1 KB (checked in by sukyoungryu, 16 months ago)

[tool] Fixed arrays and also do.

Line 
1/*******************************************************************************
2  Copyright 2008 Sun Microsystems, Inc.,
3  4150 Network Circle, Santa Clara, California 95054, U.S.A.
4  All rights reserved.
5
6  U.S. Government Rights - Commercial software.
7  Government users are subject to the Sun Microsystems, Inc. standard
8  license agreement and applicable provisions of the FAR and its supplements.
9
10  Use is subject to license terms.
11
12  This distribution may include materials developed by third parties.
13
14  Sun, Sun Microsystems, the Sun logo and Java are trademarks or registered
15  trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
16  ******************************************************************************/
17
18package com.sun.fortress;
19
20import com.sun.fortress.repository.CacheBasedRepository;
21import com.sun.fortress.repository.FortressRepository;
22import com.sun.fortress.repository.GraphRepository;
23import com.sun.fortress.repository.ProjectProperties;
24import java.io.*;
25import java.util.*;
26
27import edu.rice.cs.plt.tuple.Option;
28import edu.rice.cs.plt.tuple.OptionUnwrapException;
29import edu.rice.cs.plt.iter.IterUtil;
30
31import com.sun.fortress.compiler.*;
32import com.sun.fortress.exceptions.shell.UserError;
33import com.sun.fortress.exceptions.StaticError;
34import com.sun.fortress.exceptions.WrappedException;
35import com.sun.fortress.exceptions.ProgramError;
36import com.sun.fortress.exceptions.FortressException;
37import com.sun.fortress.exceptions.shell.RepositoryError;
38import com.sun.fortress.compiler.Parser;
39import com.sun.fortress.compiler.phases.PhaseOrder;
40import com.sun.fortress.nodes.Api;
41import com.sun.fortress.nodes.APIName;
42import com.sun.fortress.nodes.CompilationUnit;
43import com.sun.fortress.nodes.Component;
44import com.sun.fortress.nodes_util.NodeFactory;
45import com.sun.fortress.nodes_util.ASTIO;
46import com.sun.fortress.interpreter.Driver;
47import com.sun.fortress.syntax_abstractions.parser.PreParser;
48import com.sun.fortress.useful.Path;
49import com.sun.fortress.useful.Debug;
50import com.sun.fortress.useful.Useful;
51import com.sun.fortress.tools.FortressAstToConcrete;
52
53public final class Shell {
54    static boolean test;
55
56    /* set this statically if you only want to run up to a certain phase */
57    private static PhaseOrder finalPhase = PhaseOrder.CODEGEN;
58
59    private final FortressRepository _repository;
60    private static final CacheBasedRepository defaultRepository =
61        new CacheBasedRepository(ProjectProperties.ANALYZED_CACHE_DIR);
62    public static FortressRepository CURRENT_INTERPRETER_REPOSITORY = null;
63
64    public Shell(FortressRepository repository) { _repository = repository; }
65
66    public FortressRepository getRepository() {
67        return _repository;
68    }
69
70    private static void setPhase( PhaseOrder phase ){
71        finalPhase = phase;
72    }
73
74    /**
75     * This is used to communicate, clumsily, with parsers generated by syntax expansion.
76     * The interface should be improved.
77     */
78    public static void setCurrentInterpreterRepository( FortressRepository g ){
79        CURRENT_INTERPRETER_REPOSITORY = g;
80    }
81
82    private static GraphRepository specificRepository(Path p, CacheBasedRepository cache ){
83        GraphRepository fr = new GraphRepository( p, cache );
84        CURRENT_INTERPRETER_REPOSITORY = fr;
85        return fr;
86    }
87
88    public static GraphRepository specificRepository(Path p) {
89        return specificRepository( p, defaultRepository );
90    }
91
92    /* Helper method to print usage message.*/
93    private static void printUsageMessage() {
94        System.err.println("Usage:");
95        System.err.println(" compile [-out file] [-debug [type]* [#]] somefile.fs{s,i}");
96        System.err.println(" [run] [-test] [-debug [type]* [#]] somefile.fss arg...");
97        System.err.println(" parse [-out file] [-debug [type]* [#]] somefile.fs{s,i}");
98        System.err.println(" unparse [-out file] [-debug [type]* [#]] somefile.tf{s,i}");
99        System.err.println(" disambiguate [-out file] [-debug [type]* [#]] somefile.fs{s,i}");
100        System.err.println(" desugar [-out file] [-debug [type]* [#]] somefile.fs{s,i}");
101        System.err.println(" grammar [-out file] [-debug [type]* [#]] somefile.fs{s,i}");
102        System.err.println(" typecheck [-out file] [-debug [type]* [#]] somefile.fs{s,i}");
103        System.err.println(" help");
104    }
105
106    private static void printHelpMessage() {
107        System.err.println
108        ("Invoked as script: fortress args\n"+
109         "Invoked by java: java ... com.sun.fortress.Shell args\n"+
110         "\n"+
111         "fortress compile [-out file] [-debug [type]* [#]] somefile.fs{s,i}\n"+
112         "  Compile somefile. If compilation succeeds no message will be printed.\n"+
113         "\n"+
114         "fortress [run] [-test] [-debug [type]* [#]] somefile.fss arg ...\n"+
115         "  Runs somefile.fss through the Fortress interpreter, passing arg ... to the\n"+
116         "  run method of somefile.fss.\n"+
117         "\n"+
118         "fortress parse [-out file] [-debug [type]* [#]] somefile.fs{i,s}\n"+
119         "  Parses a file. If parsing succeeds the message \"Ok\" will be printed.\n"+
120         "  If -out file is given, a message about the file being written to will be printed.\n"+
121         "\n"+
122         "fortress unparse [-out file] [-debug [type]* [#]] somefile.tf{i,s}\n"+
123         "  Convert a parsed file back to Fortress source code. The output will be dumped to stdout if -out is not given.\n"+
124         "  If -out file is given, a message about the file being written to will be printed.\n"+
125         "\n"+
126         "fortress disambiguate [-out file] [-debug [type]* [#]] somefile.fs{i,s}\n"+
127         "  Disambiguates a file.\n"+
128         "  If -out file is given, a message about the file being written to will be printed.\n"+
129         "\n"+
130         "fortress desugar [-out file] [-debug [#]] somefile.fs{i,s}\n"+
131         "  Desugars a file.\n"+
132         "  If -out file is given, a message about the file being written to will be printed.\n"+
133         "\n"+
134         "fortress grammar [-out file] [-debug [#]] somefile.fs{i,s}\n"+
135         "  Rewrites syntax grammars in a file.\n"+
136         "  If -out file is given, a message about the file being written to will be printed.\n"+
137         "\n"+
138         "fortress typecheck [-out file] [-debug [#]] somefile.fs{i,s}\n"+
139         "  Typechecks a file. If type checking succeeds no message will be printed.\n"+
140         "\n"+
141         "More details on each flag:\n"+
142         "   -out file : dumps the processed abstract syntax tree to a file.\n"+
143         "   -test : first runs test functions associated with the program.\n"+
144         "   -debug : enables debugging to the maximum level (99) for all \n"+
145         "            debugging types and prints java stack traces.\n"+
146         "   -debug # : sets debugging to the specified level, where # is a number, \n"+
147         "            and sets all debugging types on.\n"+
148         "   -debug types : sets debugging types to the specified types with \n"+
149         "            the maximum debugging level. \n" +
150         "   -debug types # : sets debugging to the specified level, where # is a number, \n"+
151         "            and the debugging types to the specified types. \n" +
152         "   The acceptable debugging types are:\n"+
153         "            " + Debug.typeStrings() + "\n"+
154         "\n"
155        );
156    }
157
158    private static void turnOnTypeChecking(){
159        com.sun.fortress.compiler.StaticChecker.typecheck = true;
160    }
161
162    /* Main entry point for the fortress shell.*/
163    public static void main(String[] tokens) throws InterruptedException, Throwable {
164        if (tokens.length == 0) {
165            printUsageMessage();
166            System.exit(-1);
167        }
168
169        // Now match the assembled string.
170        try {
171            String what = tokens[0];
172            List<String> args = Arrays.asList(tokens).subList(1, tokens.length);
173            if (what.equals("compile")) {
174                compile(args, Option.<String>none());
175            } else if (what.equals("run")) {
176                run(args);
177            } else if ( what.equals("parse" ) ){
178                parse(args, Option.<String>none());
179            } else if ( what.equals("unparse" ) ){
180                unparse(args, Option.<String>none());
181            } else if ( what.equals( "disambiguate" ) ){
182                setPhase( PhaseOrder.DISAMBIGUATE );
183                compile(args, Option.<String>none());
184            } else if ( what.equals( "desugar" ) ){
185                setPhase( PhaseOrder.DESUGAR );
186                compile(args, Option.<String>none());
187            } else if ( what.equals( "grammar" ) ){
188                setPhase( PhaseOrder.GRAMMAR );
189                compile(args, Option.<String>none());
190            } else if (what.equals("typecheck")) {
191                /* TODO: remove the next line once type checking is permanently turned on */
192                turnOnTypeChecking();
193                setPhase( PhaseOrder.TYPECHECK );
194                compile(args, Option.<String>none());
195            } else if (what.contains(ProjectProperties.COMP_SOURCE_SUFFIX)
196                       || (what.startsWith("-") && tokens.length > 1)) {
197                // no "run" command.
198                run(Arrays.asList(tokens));
199            } else if (what.equals("help")) {
200                printHelpMessage();
201
202            } else { printUsageMessage(); }
203        }
204        catch (UserError error) {
205            System.err.println(error.getMessage());
206        }
207        catch (IOException error) {
208            System.err.println(error.getMessage());
209        }
210    }
211
212    /**
213     * Parse a file. If the file parses ok it will say "Ok".
214     * If you want a dump then give -out somefile.
215     */
216    private static void parse(List<String> args, Option<String> out)
217        throws UserError, InterruptedException, IOException {
218        if (args.size() == 0) {
219            throw new UserError("Need a file to parse");
220        }
221        String s = args.get(0);
222        List<String> rest = args.subList(1, args.size());
223
224        if (s.startsWith("-")) {
225            if (s.equals("-debug")){
226                rest = Debug.parseOptions(rest);
227            }
228            if (s.equals("-out") && ! rest.isEmpty() ){
229                out = Option.<String>some(rest.get(0));
230                rest = rest.subList( 1, rest.size() );
231            }
232            if (s.equals("-noPreparse")) ProjectProperties.noPreparse = true;
233
234            parse( rest, out );
235        } else {
236            parse( s, out );
237        }
238    }
239
240    /**
241     * UnParse a file.
242     * If you want a dump then give -out somefile.
243     */
244    private static void unparse(List<String> args, Option<String> out)
245        throws UserError, InterruptedException, IOException {
246        if (args.size() == 0) {
247            throw new UserError("Need a file to unparse");
248        }
249        String s = args.get(0);
250        List<String> rest = args.subList(1, args.size());
251
252        if (s.startsWith("-")) {
253            if (s.equals("-debug")){
254                rest = Debug.parseOptions(rest);
255            }
256            if (s.equals("-out") && ! rest.isEmpty() ){
257                out = Option.<String>some(rest.get(0));
258                rest = rest.subList( 1, rest.size() );
259            }
260            if (s.equals("-noPreparse")) ProjectProperties.noPreparse = true;
261
262            unparse( rest, out );
263        } else {
264            unparse( s, out );
265        }
266    }
267
268    private static void unparse( String file, Option<String> out ){
269        try{
270            String code = ASTIO.readJavaAst( file ).unwrap().accept( new FortressAstToConcrete() );
271            if ( out.isSome() ){
272                try{
273                    BufferedWriter writer = Useful.filenameToBufferedWriter(out.unwrap());
274                    writer.write(code);
275                    writer.close();
276                    System.out.println( "Dumped code to " + out.unwrap() );
277                } catch ( IOException e ){
278                    System.err.println( "Error while writing " + out.unwrap() );
279                }
280            } else {
281                System.out.println( code );
282            }
283        } catch ( IOException i ){
284            i.printStackTrace();
285        } catch ( OptionUnwrapException o ){
286            o.printStackTrace();
287        }
288    }
289
290    private static void parse( String file, Option<String> out){
291        try{
292            CompilationUnit unit = Parser.parseFile(cuName(file), new File(file));
293            System.out.println( "Ok" );
294            if ( out.isSome() ){
295                try{
296                    ASTIO.writeJavaAst(unit, out.unwrap());
297                    System.out.println( "Dumped parse tree to " + out.unwrap() );
298                } catch ( IOException e ){
299                    System.err.println( "Error while writing " + out.unwrap() );
300                }
301            }
302        } catch (ProgramError e) {
303            System.err.println(e.getMessage());
304            e.printInterpreterStackTrace(System.err);
305            if (Debug.isOnMax()) {
306                e.printStackTrace();
307            } else {
308                System.err.println("Turn on -debug for Java-level error dump.");
309            }
310            System.exit(1);
311        } catch ( FileNotFoundException f ){
312            System.err.println( file + " not found" );
313        } catch ( IOException ie ){
314            System.err.println( "Error while reading " + file );
315        } catch ( StaticError s ){
316            System.err.println(s);
317        }
318    }
319
320    private static boolean isApi(String file){
321        return file.endsWith(ProjectProperties.API_SOURCE_SUFFIX);
322    }
323
324    private static boolean isComponent(String file){
325        return file.endsWith(ProjectProperties.COMP_SOURCE_SUFFIX);
326    }
327
328    private static APIName cuName( String file ){
329        if ( file.endsWith( ProjectProperties.COMP_SOURCE_SUFFIX ) ||
330             file.endsWith( ProjectProperties.API_SOURCE_SUFFIX ) ){
331            return NodeFactory.makeAPIName(file.substring( 0, file.lastIndexOf(".") ));
332        }
333        return NodeFactory.makeAPIName(file);
334    }
335
336    public static boolean checkCompilationUnitName(String filename,
337                                                   String cuname) {
338        String file = filename.substring( 0, filename.lastIndexOf(".") );
339        file = file.replace('/','.');
340        file = file.replace('\\','.');
341        String regex = "(.*\\.)?" + cuname.replaceAll("\\.", "\\.") + "$";
342        Debug.debug( Debug.Type.REPOSITORY, 3, "Checking file name " + file + " vs cuname " + regex );
343        return file.matches( regex );
344    }
345
346    /**
347     * Compile a file.
348     * If you want a dump then give -out somefile.
349     */
350    private static void compile(List<String> args, Option<String> out)
351        throws UserError, InterruptedException, IOException {
352        if (args.size() == 0) {
353            throw new UserError("Need a file to compile");
354        }
355        String s = args.get(0);
356        List<String> rest = args.subList(1, args.size());
357
358        if (s.startsWith("-")) {
359            if (s.equals("-debug")){
360                rest = Debug.parseOptions(rest);
361            }
362            if (s.equals("-out") && ! rest.isEmpty() ){
363                out = Option.<String>some(rest.get(0));
364                rest = rest.subList( 1, rest.size() );
365            }
366            if (s.equals("-noPreparse")) ProjectProperties.noPreparse = true;
367            compile(rest, out);
368        } else {
369            try {
370                APIName name = trueApiName( s );
371                Path path = sourcePath( s, name );
372
373                Iterable<? extends StaticError> errors = compile(path, name.toString() + (s.endsWith(".fss") ? ".fss" : ".fsi"), out );
374                if ( errors.iterator().hasNext() ){
375                    for (StaticError error: errors) {
376                        System.err.println(error);
377                    }
378                }
379            } catch (RepositoryError error) {
380                System.err.println(error);
381            }
382        }
383    }
384
385    private static APIName trueApiName( String path ) throws IOException {
386        return PreParser.apiName( NodeFactory.makeAPIName(path), new File(path).getCanonicalFile() );
387    }
388
389    /**
390     * Compile a file.
391     */
392    public static Iterable<? extends StaticError> compile(Path path, String file) {
393        return compile(path, file, Option.<String>none());
394    }
395
396    private static Iterable<? extends StaticError> compile(Path path, String file, Option<String> out) {
397        GraphRepository bcr = specificRepository( path, defaultRepository );
398
399        Debug.debug( Debug.Type.FORTRESS, 2, "Compiling file ", file );
400        APIName name = cuName(file);
401        try {
402            if ( isApi(file) ) {
403                // FIXME: The following line is executed for its side effects
404                Api a = (Api) bcr.getApi(name).ast();
405                if ( out.isSome() )
406                    ASTIO.writeJavaAst(defaultRepository.getApi(name).ast(), out.unwrap());
407            } else if (isComponent(file)) {
408                // FIXME: The following line is executed for its side effects
409                Component c = (Component) bcr.getComponent(name).ast();
410                if ( out.isSome() )
411                    ASTIO.writeJavaAst(defaultRepository.getComponent(name).ast(), out.unwrap());
412            } else {
413                System.out.println( "Don't know what kind of file " + file +
414                                    " is. Append .fsi or .fss." );
415            }
416        } catch (ProgramError pe) {
417            Iterable<? extends StaticError> se = pe.getStaticErrors();
418            if (se == null) {
419                return IterUtil.singleton(new WrappedException(pe, Debug.isOnMax()));
420            }
421            else {
422                return se;
423            }
424        } catch (RepositoryError ex) {
425            throw ex;
426        } catch ( FileNotFoundException ex ){
427            throw new WrappedException(ex);
428        } catch ( IOException e ){
429            throw new WrappedException(e);
430        } catch (StaticError ex) {
431             return IterUtil.singleton(new WrappedException(ex, Debug.isOnMax()));
432        }
433
434        if (bcr.verbose())
435            System.err.println("Compiling done.");
436
437        return IterUtil.empty();
438    }
439
440    /**
441     * Run a file.
442     */
443    private static void run(List<String> args)
444        throws UserError, IOException, Throwable {
445        if (args.size() == 0) {
446            throw new UserError("Need a file to run");
447        }
448        String s = args.get(0);
449        List<String> rest = args.subList(1, args.size());
450
451        if (s.startsWith("-")) {
452            if (s.equals("-debug")){
453                rest = Debug.parseOptions(rest);
454            }
455            if (s.equals("-test")) {
456                test = true;
457            }
458            if (s.equals("-noPreparse")) ProjectProperties.noPreparse = true;
459
460            run(rest);
461        } else {
462            run(s, rest);
463        }
464    }
465
466    private static void run(String fileName, List<String> args)
467        throws UserError, Throwable {
468        try {
469            APIName name = trueApiName( fileName );
470            Path path = sourcePath(fileName, name);
471
472            GraphRepository bcr = specificRepository( path, defaultRepository );
473            Iterable<? extends StaticError> errors = IterUtil.empty();
474
475            try {
476                CompilationUnit cu = bcr.getLinkedComponent(name).ast();
477                Driver.runProgram(bcr, cu, test, args);
478            } catch (Throwable th) {
479                // TODO FIXME what is the proper treatment of errors/exceptions etc.?
480                if (th instanceof FortressException) {
481                    FortressException pe = (FortressException) th;
482                    if (pe.getStaticErrors() != null)
483                        errors = pe.getStaticErrors();
484                }
485                if (th instanceof RuntimeException)
486                    throw (RuntimeException) th;
487                if (th instanceof Error)
488                    throw (Error) th;
489                throw new WrappedException(th, Debug.isOnMax());
490            }
491
492            for (StaticError error: errors) {
493                System.err.println(error);
494            }
495            // If there are no errors,
496            // all components will have been written to disk
497            // by the CacheBasedRepository.
498        } catch ( StaticError e ){
499            System.err.println(e);
500            if ( Debug.isOnMax() ){
501                e.printStackTrace();
502            }
503        } catch (RepositoryError e) {
504            System.err.println(e.getMessage());
505        } catch (FortressException e) {
506            System.err.println(e.getMessage());
507            e.printInterpreterStackTrace(System.err);
508            if (Debug.isOnMax()) {
509                e.printStackTrace();
510            } else {
511                System.err.println("Turn on -debug for Java-level error dump.");
512            }
513            System.exit(1);
514        }
515    }
516
517    /* find the api name for a file and chop it off the source path.
518     * what remains from the source path is the directory that contains
519     * the file( including sub-directories )
520     */
521    private static Path sourcePath( String file, APIName name ) throws IOException {
522        Debug.debug( Debug.Type.REPOSITORY, 2, "True api name is " + name );
523        String fullPath = new File(file).getCanonicalPath();
524        Debug.debug( Debug.Type.REPOSITORY, 2, "Path is " + fullPath );
525        Path path = ProjectProperties.SOURCE_PATH;
526        /* the path to the file is /absolute/path/a/b/c/foo.fss and the apiname is
527         * a.b.c.foo, so we need to take off the apiname plus four more characters,
528         * ".fss" or ".fsi"
529         */
530        String source = fullPath.substring( 0, fullPath.length() - (name.toString().length() + 4) );
531        path = path.prepend( source );
532        Debug.debug( Debug.Type.REPOSITORY, 2, "Source path is " + source );
533        Debug.debug( Debug.Type.REPOSITORY, 2, "Lookup path is " + path );
534        return path;
535    }
536
537    /* run all the analysis available */
538    public static AnalyzeResult analyze(final FortressRepository repository,
539                                        final GlobalEnvironment env,
540                                        List<Api> apis,
541                                        List<Component> components,
542                                        final long lastModified) throws StaticError {           
543        AnalyzeResult result = finalPhase.makePhase(repository,env,apis,components,lastModified).run();
544        return result;
545    }
546
547
548}
Note: See TracBrowser for help on using the browser.