/** UnParse a file. If you want a dump then give -out somefile. */ private static void unparse( List<String> args, Option<String> out, boolean _unqualified, boolean _unmangle) throws UserError, InterruptedException, IOException { if (args.size() == 0) { throw new UserError("The unparse command needs a file to unparse."); } String s = args.get(0); List<String> rest = args.subList(1, args.size()); boolean unqualified = _unqualified; boolean unmangle = _unmangle; if (s.startsWith("-")) { if (s.equals("-unqualified")) { unqualified = true; } else if (s.equals("-unmangle")) { unmangle = true; } else if (s.equals("-debug")) { rest = Debug.parseOptions(rest); } else if (s.equals("-out") && !rest.isEmpty()) { out = Option.<String>some(rest.get(0)); rest = rest.subList(1, rest.size()); } else invalidFlag(s, "unparse"); unparse(rest, out, unqualified, unmangle); } else { unparse(s, out, unqualified, unmangle); } }
/** Compile a file. If you want a dump then give -out somefile. */ public static int compilerPhases(List<String> args, Option<String> out, String phase) throws UserError, InterruptedException, IOException, RepositoryError { int return_code = 0; if (args.size() == 0) { throw new UserError("The " + phase + " command must be given a file."); } String s = args.get(0); List<String> rest = args.subList(1, args.size()); if (s.startsWith("-")) { if (s.equals("-debug")) { rest = Debug.parseOptions(rest); } else if (s.equals("-out") && !rest.isEmpty()) { out = Option.<String>some(rest.get(0)); rest = rest.subList(1, rest.size()); } else if (s.equals("-compiler-lib")) { WellKnownNames.useCompilerLibraries(); Types.useCompilerLibraries(); } else if (s.equals("-typecheck-java")) { setScala(false); } else if (s.equals("-coercion")) { setTestCoercion(true); } else invalidFlag(s, phase); return_code = compilerPhases(rest, out, phase); } else { return_code = compileWithErrorHandling(s, out, false); } return return_code; }
private static void walkTests(List<String> args, boolean verbose) throws UserError, IOException, Throwable { boolean _verbose = verbose; if (args.size() == 0) { throw new UserError("Need a file to run through the Fortress interpreter."); } String s = args.get(0); List<String> rest = args.subList(1, args.size()); if (s.startsWith("-")) { if (s.equals("-debug")) { rest = Debug.parseOptions(rest); } else if (s.equals("-verbose")) { _verbose = true; } else invalidFlag(s, "test"); walkTests(rest, _verbose); } else { for (String file : args) { try { Iterable<? extends StaticError> errors = IterUtil.empty(); try { if (!isComponent(file)) throw new UserError(file + " is not a component file."); APIName name = NodeUtil.apiName(file); Path path = sourcePath(file, name); GraphRepository bcr = specificInterpreterRepository(path); ComponentIndex cu = bcr.getLinkedComponent(name); Driver.runTests(bcr, cu, _verbose); } catch (Throwable th) { // TODO FIXME what is the proper treatment of errors/exceptions etc.? if (th instanceof FortressException) { FortressException pe = (FortressException) th; if (pe.getStaticErrors() != null) errors = pe.getStaticErrors(); } if (th instanceof RuntimeException) throw (RuntimeException) th; if (th instanceof Error) throw (Error) th; throw new WrappedException(th, Debug.stackTraceOn()); } for (StaticError error : errors) { System.err.println(error); } // If there are no errors, // all components will have been written to disk // by the CacheBasedRepository. } catch (StaticError e) { System.err.println(e); if (Debug.stackTraceOn()) { e.printStackTrace(); } } catch (RepositoryError e) { System.err.println(e.getMessage()); } catch (FortressException e) { failureBoilerplate(e); System.exit(1); } } } }
private static Iterable<? extends StaticError> compilerPhases( Path path, String file, Option<String> out, boolean link) throws UserError { GraphRepository bcr = null; Debug.debug(Debug.Type.FORTRESS, 2, "Compiling file ", file); APIName name = null; try { bcr = specificRepository(path); name = cuName(file); if (isApi(file)) { Api a = (Api) bcr.getApi(name).ast(); if (out.isSome()) ASTIO.writeJavaAst( a, // defaultRepository.getApi(name).ast(), out.unwrap()); } else if (isComponent(file)) { Component c; if (link) c = (Component) bcr.getLinkedComponent(name).ast(); else c = (Component) bcr.getComponent(name).ast(); if (out.isSome()) { ASTIO.writeJavaAst( c, // defaultRepository.getComponent(name).ast(), out.unwrap()); bcr.deleteComponent(name, true); } } else { throw new UserError( "What kind of file is " + file + "? Name should end with .fsi or .fss."); } } catch (ProgramError pe) { Iterable<? extends StaticError> se = pe.getStaticErrors(); if (se == null) return IterUtil.singleton(new WrappedException(pe, Debug.stackTraceOn())); else return flattenErrors(se); } catch (RepositoryError ex) { throw ex; } catch (FileNotFoundException ex) { throw new WrappedException(ex); } catch (IOException e) { throw new WrappedException(e); } catch (StaticError ex) { return flattenErrors(ex); } catch (CompilerBug e) { return IterUtil.singleton(new WrappedException(e, Debug.stackTraceOn())); } catch (InterpreterBug e) { return IterUtil.singleton(new WrappedException(e, Debug.stackTraceOn())); } catch (FortressException e) { failureBoilerplate(e); System.exit(1); } finally { if (bcr != null && name != null) bcr.deleteComponent(name, false); } if (bcr != null && bcr.verbose()) System.err.println("Compiling done."); return IterUtil.empty(); }
/* find the api name for a file and chop it off the source path. * what remains from the source path is the directory that contains * the file( including sub-directories ) */ public static Path sourcePath(String file, APIName name) throws IOException { Debug.debug(Debug.Type.REPOSITORY, 2, "True api name is ", name); String fullPath = new File(file).getCanonicalPath(); Debug.debug(Debug.Type.REPOSITORY, 2, "Path is ", fullPath); Path path = ProjectProperties.SOURCE_PATH; /* the path to the file is /absolute/path/a/b/c/foo.fss and the apiname is * a.b.c.foo, so we need to take off the apiname plus four more characters, * ".fss" or ".fsi" */ String source = fullPath.substring(0, fullPath.length() - (name.toString().length() + 4)); path = path.prepend(source); Debug.debug(Debug.Type.REPOSITORY, 2, "Source path is ", source); Debug.debug(Debug.Type.REPOSITORY, 2, "Lookup path is ", path); return path; }
/** * @param out * @param path * @param file_name * @param doLink * @return * @throws UserError * @throws IOException */ private static int compileWithErrorHandling(String s, Option<String> out, boolean doLink) throws UserError, IOException { int return_code = 0; try { APIName name = NodeUtil.apiName(s); Path path = sourcePath(s, name); String file_name = name.toString() + (s.endsWith(".fss") ? ".fss" : ".fsi"); List<StaticError> errors = new ArrayList<StaticError>(); for (StaticError error : IterUtil.sort(compilerPhases(path, file_name, out, doLink), StaticError.comparator)) { if (!error.toString().equals("")) errors.add(error); } return_code = reportErrors(errors, file_name); } catch (StaticError e) { return_code = reportErrors(flattenErrors(e), new File(s).getName()); } catch (ProgramError e) { System.err.println(e.getMessage()); e.printInterpreterStackTrace(System.err); if (Debug.stackTraceOn()) { e.printStackTrace(); } else { System.err.println(turnOnDebugMessage); } return_code = 1; } return return_code; }
private static List<? extends StaticError> flattenErrors(StaticError ex) { List<StaticError> result = new LinkedList<StaticError>(); if (ex instanceof MultipleStaticError) { for (StaticError err : (MultipleStaticError) ex) result.addAll(flattenErrors(err)); } else result.add(new WrappedException(ex, Debug.stackTraceOn())); return result; }
public static boolean checkCompilationUnitName(String filename, String cuname) { String rootName = filename.substring(0, filename.lastIndexOf(".")); rootName = rootName.replace('/', '.'); rootName = rootName.replace('\\', '.'); String regex = "(.*\\.)?" + cuname.replace(".", "\\.") + "$"; Debug.debug(Debug.Type.REPOSITORY, 3, "Checking file name ", rootName, " vs cuname ", regex); return rootName.matches(regex); }
private static void walk(String fileName, List<String> args) throws UserError, Throwable { try { Iterable<? extends StaticError> errors = IterUtil.empty(); try { eval(fileName, args, false); } catch (Throwable th) { // TODO FIXME what is the proper treatment of errors/exceptions etc.? if (th instanceof FortressException) { FortressException pe = (FortressException) th; if (pe.getStaticErrors() != null) errors = pe.getStaticErrors(); } if (th instanceof RuntimeException) throw (RuntimeException) th; if (th instanceof Error) throw (Error) th; throw new WrappedException(th, Debug.stackTraceOn()); } if (!IterUtil.isEmpty(errors)) { for (StaticError error : errors) { System.err.println(error); } System.exit(-1); } // If there are no errors, // all components will have been written to disk // by the CacheBasedRepository. } catch (StaticError e) { System.err.println(e); if (Debug.stackTraceOn()) { e.printStackTrace(); } System.exit(-1); } catch (RepositoryError e) { throw e; } catch (LabelException e) { System.err.println(e.getMessage()); if (Debug.stackTraceOn()) { e.printStackTrace(); } else { System.err.println(turnOnDebugMessage); } System.exit(1); } catch (FortressException e) { failureBoilerplate(e); System.exit(1); } }
/** @param e */ private static void failureBoilerplate(FortressException e) { System.err.println(e.getMessage()); e.printInterpreterStackTrace(System.err); if (Debug.stackTraceOn()) { e.printStackTrace(); } else { System.err.println(turnOnDebugMessage); } (new Throwable()).printStackTrace(); }
/* run all the analysis available */ public static AnalyzeResult analyze( final FortressRepository repository, final GlobalEnvironment env, Iterable<Api> apis, Iterable<Component> components, final long lastModified) throws StaticError { Phase ph = PhaseOrder.makePhaseOrder(finalPhaseOrder, repository, env, apis, components, lastModified); AnalyzeResult result = ph.run(); Debug.debug(Debug.Type.FORTRESS, 1, "All phases done"); return result; }
/** Link compiled components implementing APIs imported by the given component. */ private static int junit(List<String> args) throws UserError, IOException { if (args.size() == 0) { throw new UserError("Need a file to run junit tests."); } String s = args.get(0); List<String> rest = args.subList(1, args.size()); if (s.startsWith("-")) { if (s.equals("-debug")) { rest = Debug.parseOptions(rest); } else invalidFlag(s, "junit"); return junit(rest); } junit.textui.TestRunner.run(FileTests.suiteFromListOfFiles(args, "", "", "", false, false)); return 0; }
/** Compare results of two components. */ private static void compare(List<String> args) throws UserError, InterruptedException, IOException, Throwable { if (args.size() == 0) { throw new UserError("Need files to compare the results."); } String s = args.get(0); List<String> rest = args.subList(1, args.size()); if (s.startsWith("-")) { if (s.equals("-debug")) { rest = Debug.parseOptions(rest); } else invalidFlag(s, "compare"); compare(rest); } else { if (args.size() == 1) throw new UserError("Need one more file to compare the results."); compare(s, args.get(1)); } }
/** Run a file through the Fortress interpreter. */ private static void walk(List<String> args) throws UserError, IOException, Throwable { if (args.size() == 0) { throw new UserError("Need a file to run through the Fortress interpreter."); } String s = args.get(0); List<String> rest = args.subList(1, args.size()); if (s.startsWith("-")) { if (s.equals("-debug")) { rest = Debug.parseOptions(rest); } else if (s.equals("-compiler-lib")) { WellKnownNames.useCompilerLibraries(); Types.useCompilerLibraries(); } else invalidFlag(s, "walk"); walk(rest); } else { walk(s, rest); } }
/** Link compiled components implementing APIs imported by the given component. */ private static int link(List<String> args) throws UserError, IOException { if (args.size() == 0) { throw new UserError("Need a file to link."); } String s = args.get(0); List<String> rest = args.subList(1, args.size()); if (s.startsWith("-")) { if (s.equals("-debug")) { rest = Debug.parseOptions(rest); } else invalidFlag(s, "link"); return link(rest); } else { if (!s.endsWith(".fss")) { s = s + ".fss"; } return compileWithErrorHandling(s, Option.<String>none(), true); } }
/** * Parse a file. If the file parses ok it will say "Ok". If you want a dump then give -out * somefile. */ private static int parse(List<String> args, Option<String> out) throws UserError, InterruptedException, IOException { if (args.size() == 0) { throw new UserError("Need a file to parse"); } String s = args.get(0); List<String> rest = args.subList(1, args.size()); if (s.startsWith("-")) { if (s.equals("-debug")) { rest = Debug.parseOptions(rest); } else if (s.equals("-out") && !rest.isEmpty()) { out = Option.<String>some(rest.get(0)); rest = rest.subList(1, rest.size()); } else invalidFlag(s, "parse"); return parse(rest, out); } else { return parse(s, out); } }
private static int parse(String file, Option<String> out) throws UserError, IOException { int return_code = 0; try { CompilationUnit unit = Parser.parseFileConvertExn(new File(file)); System.out.println("Ok"); if (out.isSome()) { try { ASTIO.writeJavaAst(unit, out.unwrap()); System.out.println("Dumped parse tree to " + out.unwrap()); } catch (IOException e) { throw new IOException("IOException " + e + "while writing " + out.unwrap()); } } } catch (ParserError e) { if (Debug.stackTraceOn()) { System.err.println(e.getMessage()); e.printStackTrace(); } else { System.err.println(turnOnDebugMessage); } return_code = 1; } catch (ProgramError e) { failureBoilerplate(e); return_code = 1; } catch (CompilerBug e) { failureBoilerplate(e); return_code = 1; } catch (InterpreterBug e) { failureBoilerplate(e); return_code = 1; } catch (FileNotFoundException f) { throw new UserError(file + " not found"); } finally { try { Files.rm(ProjectProperties.preparserErrorLog(file)); } catch (IOException e) { } } return return_code; }
/** Automatically generate an API from a component. */ private static void api(List<String> args, Option<String> out, Option<String> prepend) throws UserError, InterruptedException, IOException { if (args.size() == 0) { throw new UserError("Need a file to generate an API."); } String s = args.get(0); List<String> rest = args.subList(1, args.size()); if (s.startsWith("-")) { if (s.equals("-debug")) { rest = Debug.parseOptions(rest); } else if (s.equals("-out") && !rest.isEmpty()) { out = Option.<String>some(rest.get(0)); rest = rest.subList(1, rest.size()); } else if (s.equals("-prepend") && !rest.isEmpty()) { prepend = Option.<String>some(rest.get(0)); rest = rest.subList(1, rest.size()); } else invalidFlag(s, "api"); api(rest, out, prepend); } else { api(s, out, prepend); } }
private static void printHelpMessage() { System.err.println( "Invoked as script: fortress args\n" + "Invoked by java: java ... com.sun.fortress.Shell args\n" + "\n" + "fortress parse [-out file] [-debug [type]* [#]] somefile.fs{i,s}\n" + " Parses a file. If parsing succeeds the message \"Ok\" will be printed.\n" + " If -out file is given, a message about the file being written to will be printed.\n" + "\n" + "fortress disambiguate [-compiler-lib] [-out file] [-debug [type]* [#]] somefile.fs{i,s}\n" + " Disambiguates a file.\n" + " If -out file is given, a message about the file being written to will be printed.\n" + "\n" + "fortress desugar [-compiler-lib] [-out file] [-debug [#]] somefile.fs{i,s}\n" + " Desugars a file.\n" + " If -out file is given, a message about the file being written to will be printed.\n" + "\n" + "fortress grammar [-compiler-lib] [-out file] [-debug [#]] somefile.fs{i,s}\n" + " Rewrites syntax grammars in a file.\n" + " If -out file is given, a message about the file being written to will be printed.\n" + "\n" + "fortress typecheck [-compiler-lib] [-out file] [-debug [#]] somefile.fs{i,s}\n" + " Typechecks a file. If type checking succeeds no message will be printed.\n" + "\n" + "fortress compile [-out file] [-debug [type]* [#]] somefile.fs{s,i}\n" + " Compiles somefile. If compilation succeeds no message will be printed.\n" + "\n" + "fortress link [-debug [type]* [#]] somecomponent[.fss]\n" + " Links compiled components implementing APIs imported by somecomponent.\n" + "\n" + "fortress build [-debug [type]* [#]] somecomponent[.fss]\n" + " Builds and links components implementing APIs imported by somecomponent.\n" + "\n" + "fortress run somecomponent\n" + " Runs the compiler-generated bytecode for somecomponent.\n" + "\n" + "fortress [walk] [-compiler-lib] [-debug [type]* [#]] somefile.fss arg ...\n" + " Runs somefile.fss through the Fortress interpreter, passing arg ... to the\n" + " run method of somefile.fss.\n" + "\n" + "fortress test [-verbose] [-debug [type]* [#]] somefile.fss ...\n" + " Runs the functions with the test modifier in the specified components \n" + " If -verbose is set, the name of each test function is printed before and after running the function\n" + "\n" + "fortress junit [-debug [type]* [#]] somefile1.test ...\n" + " Runs the system test file(s) somefile1.test (etc) in a junit textui harness.\n" + "\n" + "\n" + "fortress api [-out file] [-prepend prependFile] [-debug [type]* [#]] somefile.fss\n" + " Automatically generate an API from a component.\n" + " If -out file is given, a message about the file being written to will be printed.\n" + " If -prepend prependFile is given, the prependFile is prepended to the generated API.\n" + "\n" + "fortress compare [-debug [type]* [#]] somefile.fss anotherfile.fss\n" + " Compare results of two components.\n" + "\n" + "fortress unparse [-unqualified] [-unmangle] [-out file] [-debug [type]* [#]] somefile.tf{i,s}\n" + " Convert a parsed file back to Fortress source code. The output will be dumped to stdout if -out is not given.\n" + " If -unqualified is given, identifiers are dumped without their API prefixes.\n" + " If -unmangle is given, internally mangled identifiers are unmangled.\n" + " If -out file is given, a message about the file being written to will be printed.\n" + "\n" + "fortress expand property\n" + " Prints the contents of the given property name from the local Fortress repository.\n" + "\n" + "\n" + "More details on each flag:\n" + " -out file : dumps the processed abstract syntax tree to a file.\n" + " -debug : enables debugging to the maximum level (99) for all \n" + " debugging types and prints java stack traces.\n" + " -debug # : sets debugging to the specified level, where # is a number, \n" + " and sets all debugging types on.\n" + " -debug types : sets debugging types to the specified types with \n" + " the maximum debugging level. \n" + " -debug types # : sets debugging to the specified level, where # is a number, \n" + " and the debugging types to the specified types. \n" + " The acceptable debugging types are:\n" + " " + Debug.typeStrings() + "\n" + "\n"); }
/** * @param tokens * @return * @throws InterruptedException * @throws Throwable */ public static int subMain(String[] tokens) throws InterruptedException, Throwable { int return_code = 0; // Now match the assembled string. try { String what = tokens[0]; List<String> args = Arrays.asList(tokens).subList(1, tokens.length); if (what.equals("compile")) { useCompilerLibraries(); setTypeChecking(true); setPhaseOrder(PhaseOrder.compilerPhaseOrder); return_code = compilerPhases(args, Option.<String>none(), what); } else if (what.equals("junit")) { return_code = junit(args); } else if (what.equals("link")) { useCompilerLibraries(); setTypeChecking(true); setPhaseOrder(PhaseOrder.compilerPhaseOrder); return_code = link(args); } else if (what.equals("build")) { useCompilerLibraries(); setTypeChecking(true); setPhaseOrder(PhaseOrder.compilerPhaseOrder); return_code = link(args); } else if (what.equals("walk")) { useInterpreterLibraries(); setScala(false); setPhaseOrder(PhaseOrder.interpreterPhaseOrder); walk(args); } else if (what.equals("api")) { useCompilerLibraries(); api(args, Option.<String>none(), Option.<String>none()); } else if (what.equals("compare")) { useCompilerLibraries(); compare(args); } else if (what.equals("parse")) { useCompilerLibraries(); return_code = parse(args, Option.<String>none()); } else if (what.equals("unparse")) { useCompilerLibraries(); unparse(args, Option.<String>none(), false, false); } else if (what.equals("disambiguate")) { useCompilerLibraries(); setPhaseOrder(PhaseOrder.disambiguatePhaseOrder); return_code = compilerPhases(args, Option.<String>none(), what); } else if (what.equals("desugar")) { useCompilerLibraries(); setTypeChecking(true); setObjExprDesugaring(true); setPhaseOrder(PhaseOrder.desugarPhaseOrder); return_code = compilerPhases(args, Option.<String>none(), what); } else if (what.equals("grammar")) { useCompilerLibraries(); setPhaseOrder(PhaseOrder.grammarPhaseOrder); return_code = compilerPhases(args, Option.<String>none(), what); } else if (what.equals("typecheck")) { useCompilerLibraries(); setTypeChecking(true); setPhaseOrder(PhaseOrder.typecheckPhaseOrder); return_code = compilerPhases(args, Option.<String>none(), what); } else if (what.equals("test-coercion")) { useCompilerLibraries(); setTypeChecking(true); setPhaseOrder(PhaseOrder.typecheckPhaseOrder); return_code = compilerPhases(args, Option.<String>none(), what); } else if (what.equals("typecheck-old")) { useInterpreterLibraries(); setScala(false); /* TODO: remove the next line once type checking is permanently turned on */ setTypeChecking(true); setPhaseOrder(PhaseOrder.typecheckPhaseOrder); return_code = compilerPhases(args, Option.<String>none(), what); } else if (what.equals("test")) { useInterpreterLibraries(); setScala(false); setPhaseOrder(PhaseOrder.interpreterPhaseOrder); walkTests(args, false); } else if (what.contains(ProjectProperties.COMP_SOURCE_SUFFIX) || (what.startsWith("-") && tokens.length > 1)) { useInterpreterLibraries(); setScala(false); setPhaseOrder(PhaseOrder.interpreterPhaseOrder); walk(Arrays.asList(tokens)); } else if (what.equals("help")) { useCompilerLibraries(); printHelpMessage(); } else if (what.equals("expand") && tokens.length == 2) { System.out.println(ProjectProperties.get(tokens[1], "")); } else { useCompilerLibraries(); printUsageMessage(); } } catch (StaticError e) { System.err.println(e); if (Debug.stackTraceOn()) { e.printStackTrace(); } return_code = -1; } catch (UserError error) { System.err.println(error.getMessage()); return_code = -1; } catch (IOException error) { System.err.println(error.getMessage()); return_code = -2; } catch (CompilerBug error) { System.err.println(error.getMessage()); if (Debug.stackTraceOn()) { error.printStackTrace(); } return_code = -3; } Init.allowForLeakChecks(); return return_code; }