com.jsuper.compiler.cli.SuperCommand.java Source code

Java tutorial

Introduction

Here is the source code for com.jsuper.compiler.cli.SuperCommand.java

Source

/*
 * Copyright (C) 2013 Super Programming Language
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.jsuper.compiler.cli;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.Map;

import org.apache.commons.io.IOUtils;

import com.jsuper.compiler.CompilerConfiguration;
import com.jsuper.compiler.CompilerResult;
import com.jsuper.compiler.ErrorMessage;
import com.jsuper.compiler.SuperCompiler;

/**
 * This is the main command line class of the compiler.
 *
 * @author superlang
 *
 */
public class SuperCommand {

    /** Output stream of the command line. */
    private PrintStream outputStream;
    /** Error stream of the command line. */
    private PrintStream errorStream;

    /**
     * Default constructor.
     */
    public SuperCommand() {
        this.outputStream = System.out;
        this.errorStream = System.err;
    }

    /**
     * Run the command line with a specified list of arguments.
     *
     * @param args The command line arguments for the compiler.
     * @return The result to exit the operating system process.
     */
    private ProcessResult run(String[] args) {
        if (args.length == 0) {
            showUsage();
            return ProcessResult.SUCCESS;
        }

        CompilerConfiguration config = new CompilerConfiguration();

        int sourcesIndex = 0;
        for (int i = 0; i != args.length; ++i) {
            String argument = args[i];

            if (argument.startsWith("-")) {
                if (argument.equals("--version") || argument.equals("-v")) {
                    showVersion();

                } else if (argument.equals("--verbose")) {
                    // TODO
                    showVersion();

                } else if (argument.equals("--classpath")) {
                    // TODO
                    showVersion();

                } else if (argument.equals("--bootclasspath")) {
                    // TODO
                    showVersion();

                } else if (argument.equals("--help") || argument.equals("-h")) {
                    // TODO
                    showUsage();
                } else {
                    throw new SuperCommandException("Unknown option: " + argument);
                }

                sourcesIndex = i + 1;
            }
        }

        if (sourcesIndex == args.length) {
            outputStream.println("superc: No files to compile.");

            return ProcessResult.SUCCESS;
        }

        long startTime = System.nanoTime();

        SuperCompiler compiler = new SuperCompiler();
        CompilerResult results = compiler.compile(config);

        for (ErrorMessage message : results.getErrorHandler().getErrors()) {
            errorStream.println();
            String filename = message.getLocation().getFilePath();

            if (filename != null) {
                errorStream.println(new File(filename).getAbsolutePath());
            } else {
                errorStream.println("Unknown source");
            }

            if (message.getLocation().getLine() > 0) {
                errorStream.println(" (");
                errorStream.println(message.getLocation().getLine());
                if (message.getLocation().getColumn() > 0) {
                    errorStream.println(", ");
                    errorStream.println(message.getLocation().getColumn());
                }
                errorStream.println(")");
            }

            switch (message.getLevel()) {
            case ERROR:
                errorStream.println(" error ");
                break;
            case WARNING:
                errorStream.println(" warning ");
                break;
            default:
                throw new IllegalStateException();
            }

            errorStream.println(message.getErrorCode());
            errorStream.println(": ");
            errorStream.println(message.getMessage());
        }

        if (results.getErrorHandler().getErrors().isEmpty()) {
            try {
                for (Map.Entry<String, byte[]> e : results.getClassFiles().entrySet()) {
                    String fileName = e.getKey().replace('.', '/') + ".class";

                    File file = new File(config.getOutputDirectory(), fileName);
                    File dir = file.getParentFile();
                    if (!dir.exists()) {
                        dir.mkdirs();
                    }

                    OutputStream classFileOutput = null;
                    try {
                        classFileOutput = new FileOutputStream(file);
                        classFileOutput.write(e.getValue());
                    } catch (Exception ex) {
                        errorStream.println(String.format("Error writing file ''{0}''", fileName));

                        throw ex;
                    } finally {
                        IOUtils.closeQuietly(classFileOutput);
                    }
                }

                long endTime = System.nanoTime();

                String seconds = String.format("%.2f", (endTime - startTime) / 1e9);
                int totalFiles = results.getClassFiles().size();

                outputStream.println(
                        String.format("{0} class(es) successfully generated in {1}s", totalFiles, seconds));
            } catch (Exception ex) {
                errorStream.println("Error writting generated files.");

                ex.printStackTrace();
            }

            return ProcessResult.SUCCESS;
        } else {
            outputStream.println("Compilation failed.");

            return ProcessResult.FAILURE;
        }

    }

    public void showUsage() {
        outputStream.println("Usage: superc <options> <source-files>");
        outputStream.println("Options are:");

        String[][] options = { //
                { "--version, -v", "Show version information." }, //
                { "--verbose", "Show compiler progress information" }, //
                { "--classpath <path>", "Specify where to find class or jar files" }, //
                { "--bootclasspath <path>", "Specific where to find system class files" }, //
                { "--help, -h", "Show command line information." } //
        };

        int max = 0;
        for (String[] option : options) {
            max = Math.max(max, option[0].length() + 5);
        }

        for (String[] option : options) {
            outputStream.print(" " + option[0]);
            int rest = max - option[0].length();
            for (int i = 0; i != rest; ++i) {
                outputStream.print(" ");
            }
            outputStream.println(option[1]);
        }

        outputStream.println();
    }

    private void showVersion() {
        outputStream.println(String.format("superc: Version {0}", Version.VERSION));
    }

    /**
     * The compiler main function.
     *
     * @param args List of command line arguments invoking to the compiler
     */
    public static void main(String[] args) {
        SuperCommand compiler = new SuperCommand();

        try {
            ProcessResult result = compiler.run(args);

            System.exit(result.getValue());
        } catch (Throwable cause) {
            cause.printStackTrace(System.err);

            System.exit(ProcessResult.FAILURE.getValue());
        }
    }
}