All Downloads are FREE. Search and download functionalities are using the official Maven repository.

lt.repl.REPL Maven / Gradle / Ivy

Go to download

The project is to build the latte-lang modules into one, and provide command line support.

The newest version!
/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2016 KuiGang Wang
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package lt.repl;

import lt.compiler.SyntaxException;
import lt.repl.scripting.Config;
import lt.repl.scripting.EvalEntry;
import lt.util.Utils;

import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * repl
 */
public class REPL {
        private static final String lineStarter = "lt> ";
        private static final String multipleLine = "  | ";
        private static StringBuilder replSourceRec = new StringBuilder();

        private REPL() {
        }

        public static void main(String[] args) throws Exception {
                if (args != null && args.length != 0) {
                        runCommands(args);
                } else {
                        System.out.println("Welcome to Latte lang");
                        System.out.println("Type in expressions and double Enter to have them evaluated.");
                        System.out.println("Type :help for more information.");
                        System.out.println("for syntax help, please visit https://github.com/wkgcass/Latte-lang/");
                        System.out.println();

                        handleCtrlC();

                        ClassPathLoader classPathLoader = new ClassPathLoader(Thread.currentThread().getContextClassLoader());

                        Evaluator evaluator = new Evaluator(classPathLoader);
                        LineReader reader;
                        if (System.console() == null) {
                                reader = new ScannerLineReader();
                        } else {
                                try {
                                        Class.forName("jline.console.ConsoleReader"); // check exists
                                        reader = (LineReader) Class.forName("lt.repl.JLineLineReader").newInstance();
                                } catch (ClassNotFoundException ignore) {
                                        reader = new ScannerLineReader();
                                }
                        }
                        System.out.println();
                        System.out.print(lineStarter);
                        while (true) {
                                String str = reader.readLine();
                                if (str.trim().startsWith(":")) {
                                        String cmd = str.trim();
                                        // some functions that controls the REPL
                                        if (cmd.equals(":help")) {
                                                System.out.println(":q                                         exit the REPL");
                                                System.out.println(":reset                                     reset the repl to its initial state, forgetting all session entries");
                                                System.out.println(":restart                                   restart the repl environment, drop all loaded jars");
                                                System.out.println(":                                          set current input to empty string");
                                                System.out.println(":cp                            load classes");
                                                System.out.println(":script                       compile a script");
                                                System.out.println("----------------------------------------------------------------");
                                                System.out.println(":scanner-indent                            use IndentScanner to scan input");
                                                System.out.println(":scanner-brace                             use BraceScanner to scan input");
                                                System.out.println("----------------------------------------------------------------");
                                                System.out.println("Compiler()                                 construct a new Compiler");
                                                System.out.println("compiler >> ''                  set compiler output directory");
                                                System.out.println("compiler compile filesInDirectory('')");
                                                System.out.println("                                           start compiling and generate class files");
                                                System.out.println("----------------------------------------------------------------");
                                                System.out.println("ScriptCompiler()                           construct a new ScriptCompiler");
                                                System.out.println("scriptCompiler << File('')                 add source code file");
                                                System.out.println("scriptCompiler compile File('script')      compile the script");
                                        } else if (cmd.equals(":q")) {
                                                break;
                                        } else if (cmd.equals(":reset")) {
                                                replSourceRec.delete(0, replSourceRec.length());
                                                evaluator = new Evaluator(classPathLoader);
                                        } else if (cmd.equals(":restart")) {
                                                replSourceRec.delete(0, replSourceRec.length());
                                                classPathLoader = new ClassPathLoader(Thread.currentThread().getContextClassLoader());
                                                evaluator = new Evaluator(classPathLoader);
                                        } else if (cmd.startsWith(":cp ")) {
                                                String cp = cmd.substring(":cp ".length()).trim();
                                                try {
                                                        URL url = new URL(new File(cp).toURI().toString());
                                                        classPathLoader.load(url);
                                                } catch (Throwable t) {
                                                        t.printStackTrace();
                                                        sleep(10);
                                                }
                                        } else if (cmd.startsWith(":script ")) {
                                                String run = cmd.substring(":script ".length()).trim();
                                                try {
                                                        ScriptCompiler scriptCompiler = new ScriptCompiler(classPathLoader);
                                                        ScriptCompiler.Script script = scriptCompiler.compile(new File(run));
                                                        evaluator.put("script", script);
                                                        System.out.println("script : " + script.getClass().getName() + " = " + script);
                                                } catch (Throwable t) {
                                                        t.printStackTrace();
                                                        sleep(10);
                                                }
                                        } else if (cmd.equals(":scanner-indent")) {
                                                evaluator.setScannerType(Config.SCANNER_TYPE_INDENT);
                                        } else if (cmd.equals(":scanner-brace")) {
                                                evaluator.setScannerType(Config.SCANNER_TYPE_BRACE);
                                        } else if (cmd.equals(":")) {
                                                replSourceRec.delete(0, replSourceRec.length());
                                        } else {
                                                System.err.println("unknown command " + cmd + ", Type :help for more more information");
                                                sleep(10);
                                        }
                                        System.out.print("\n" + lineStarter);
                                } else {
                                        if (str.trim().isEmpty()) {
                                                if (replSourceRec.length() != 0) {
                                                        // do repl
                                                        String stmt = replSourceRec.toString();
                                                        try {
                                                                EvalEntry entry = evaluator.eval(stmt);
                                                                String name = entry.name;
                                                                Object o = entry.result;
                                                                if (name == null) {
                                                                        showObjectStructure(o);
                                                                } else {
                                                                        System.out.println(name + " : " + entry.type.getName().replaceAll("\\.", "::") + " = " + o);
                                                                }
                                                                System.out.print("\n" + lineStarter);
                                                        } catch (Throwable t) {
                                                                if (t instanceof InvocationTargetException) {
                                                                        t.getCause().printStackTrace();
                                                                } else if (t instanceof SyntaxException) {
                                                                        int line = ((SyntaxException) t).lineCol.line - 1;
                                                                        int col = ((SyntaxException) t).lineCol.column - 1;

                                                                        if (line < 0) {
                                                                                System.err.println(t.getMessage());
                                                                        } else {

                                                                                String[] strs = stmt.split("\\n|\\r");
                                                                                String s = strs[line];
                                                                                System.err.println(s);
                                                                                for (int i = 0; i < col; ++i) {
                                                                                        System.err.print(" ");
                                                                                }
                                                                                System.err.print("^ ");
                                                                                System.err.println(t.getMessage());
                                                                        }
                                                                } else {
                                                                        t.printStackTrace();
                                                                }
                                                                sleep(10);
                                                                System.out.print(lineStarter);
                                                        }
                                                        replSourceRec.delete(0, replSourceRec.length());
                                                } else {
                                                        System.out.print(lineStarter);
                                                }
                                        } else {
                                                replSourceRec.append(str).append("\n");
                                                System.out.print(multipleLine);
                                        }
                                }

                        }
                }
        }

        /**
         * run the program with arguments
         *
         * @param args arguments
         */
        private static void runCommands(String[] args) throws Exception {
                String command = args[0];
                if (command.equals("help") || command.equals("-help") || command.equals("--help") || command.equals("-h") || command.equals("/h") || command.equals("/help")) {// help
                        System.out.println("" +
                                "usage: -s  [arguments [,...]]\n" +
                                "       -c  [-r] [-o ] [-cp ]\n" +
                                "       ClassName [-cp ]\n" +
                                "       -gb \n" +
                                "       -repl\n" +
                                "       -v | -version\n" +
                                "       -e \n" +
                                "\n" +
                                "-s       Specify the script location and run the script\n" +
                                "-c       Specify the source file directory and compile *.lt files\n" +
                                "-r       [option] Add sub directory files to compiling list.\n" +
                                "-o       [option] Specify the output directory. (the source-directory/target/classes/ as default)\n" +
                                "-cp      [option] The classpath. use ':' to separate the class-paths\n" +
                                "-repl    Start the repl (or run the program with 0 arguments)\n" +
                                "-gb      Generate build.lts and run.lts in the given directory\n" +
                                "-e       Evaluate the given statement and print the result\n" +
                                "-version Show current version\n");

                } else if (command.equals("-v") || command.equals("-version")) {
                        System.out.println("Latte-lang " + VersionRetriever.version());

                } else if (command.equals("-s")) {// run scripts
                        // -s ?
                        if (args.length < 2) {
                                System.err.println("invalid command -s. the script file location should be specified\n" +
                                        "see --help");
                                return;
                        }
                        String path = args[1];
                        File f = new File(path);
                        ScriptCompiler s = new ScriptCompiler(ClassLoader.getSystemClassLoader());
                        try {
                                ScriptCompiler.Script script = s.compile(f);
                                String[] scriptArgs = new String[args.length - 2];
                                System.arraycopy(args, 2, scriptArgs, 0, args.length - 2);
                                script.run(scriptArgs);
                        } catch (Throwable e) {
                                if (e instanceof SyntaxException) {
                                        System.err.println("[ERROR] " + e.getMessage());
                                } else {
                                        e.printStackTrace();
                                }
                        }

                } else if (command.equals("-c")) {// compile
                        // -c ?
                        if (args.length < 2) {
                                System.err.println("invalid command -c. the source directory should be specified\n" +
                                        "see --help");
                                return;
                        }
                        String sourceDir = args[1].trim();
                        if (sourceDir.endsWith(File.separator)) {
                                sourceDir = sourceDir.substring(0, sourceDir.length() - File.separator.length());
                        }

                        boolean recursive = false;
                        String outputDir = sourceDir + File.separator + "target" + File.separator + "classes";
                        List classPaths = new ArrayList();

                        for (int i = 2; i < args.length; ++i) {
                                String cmd = args[i];
                                if (cmd.equals("-r")) {
                                        recursive = true;

                                } else if (cmd.equals("-o")) {
                                        if (args.length - 1 == i) {
                                                System.err.println("invalid option -o. the output directory should be specified");
                                                System.err.println("see --help");
                                                return;
                                        }
                                        outputDir = args[++i];

                                } else if (cmd.equals("-cp")) {
                                        if (args.length - 1 == i) {
                                                System.err.println("invalid option -cp. the class-path should be specified");
                                                System.err.println("see --help");
                                                return;
                                        }
                                        String[] class_paths = args[++i].split(":");
                                        for (String class_path : class_paths) {
                                                try {
                                                        classPaths.add(new URL(new File(class_path).toURI().toString()));
                                                } catch (MalformedURLException e) {
                                                        System.err.println("[ERROR] " + e.getMessage());
                                                        return;
                                                }
                                        }


                                } else {
                                        System.err.println("unknown option " + cmd);
                                        System.err.println("see --help");
                                        return;
                                }
                        }

                        Compiler compiler = new Compiler();
                        File outputDirFile = new File(outputDir);
                        if (!outputDirFile.exists()) //noinspection ResultOfMethodCallIgnored
                                outputDirFile.mkdirs();
                        compiler.config.result.outputDir = outputDirFile;
                        compiler.config.classpath = classPaths;

                        try {
                                compiler.compile(Utils.filesInDirectory(sourceDir, ".*\\.(lt|latte)", recursive));
                        } catch (Exception e) {
                                if (e instanceof SyntaxException) {
                                        System.err.println("[ERROR] " + e.getMessage());
                                } else {
                                        e.printStackTrace();
                                }
                        }

                } else if (command.equals("-gb")) {
                        final List theFilesToBeGenerated = Arrays.asList("build.lts", "run.lts");

                        if (args.length != 2) {
                                System.err.println("invalid command -gb.");
                                System.err.println("see --help");
                                return;
                        }
                        String projectDir = args[1].trim();
                        if (projectDir.endsWith(File.separator)) {
                                projectDir = projectDir.substring(0, projectDir.length() - File.separator.length());
                        }

                        String core = String.valueOf(Runtime.getRuntime().availableProcessors());
                        String separator = File.separator;

                        for (String theFile : theFilesToBeGenerated) {
                                String filePath = projectDir + File.separator + theFile;
                                File file = new File(filePath);
                                if (file.exists()) {
                                        System.out.println("[INFO] " + filePath + " exists");
                                } else {
                                        try {
                                                //noinspection ResultOfMethodCallIgnored
                                                file.createNewFile();
                                        } catch (IOException e) {
                                                e.printStackTrace();
                                        }
                                }

                                try {
                                        FileWriter fw = new FileWriter(file);
                                        BufferedReader br = new BufferedReader(new InputStreamReader(REPL.class.getClassLoader().getResourceAsStream(theFile + ".template")));

                                        String ss;
                                        while ((ss = br.readLine()) != null) {
                                                ss = ss.replace("${core}", core)
                                                        .replace("${dir}", projectDir.replace("\\", "\\\\"))
                                                        .replace("${separator}", separator) + "\n";
                                                fw.write(ss.toCharArray());
                                        }
                                        fw.flush();
                                        fw.close();
                                } catch (IOException e) {
                                        e.printStackTrace();
                                }
                        }

                } else if (command.equals("-repl")) {// repl
                        main(new String[0]);
                } else if (command.equals("-e")) {// eval
                        if (args.length == 1 || args[1] == null || args[1].trim().isEmpty()) {
                                System.err.println("missing statements to eval");
                                return;
                        }
                        String statements = args[1].trim();
                        Evaluator e = new Evaluator(new ClassPathLoader(Thread.currentThread().getContextClassLoader()));
                        EvalEntry entry = e.eval(statements);
                        System.out.println(entry.result);

                } else {// run
                        List urls = new ArrayList();
                        try {
                                String url = new File("").toURI().toString();
                                urls.add(new URL(url));
                        } catch (MalformedURLException e) {
                                System.err.println("[ERROR] " + e.getMessage());
                                return;
                        }
                        String[] runArgs = new String[0];
                        for (int i = 1; i < args.length; ++i) {
                                String cmd = args[i];
                                if (cmd.equals("-cp")) {
                                        if (i == args.length - 1) {
                                                System.err.println("invalid option -cp. the class-path should be specified");
                                                System.err.println("see --help");
                                                return;
                                        }
                                        String cps = args[++i];
                                        for (String cp : cps.split(":")) {
                                                try {
                                                        urls.add(new URL(new File(cp).toURI().toString()));
                                                } catch (MalformedURLException e) {
                                                        System.err.println("[ERROR] " + e.getMessage());
                                                        return;
                                                }
                                        }

                                } else if (cmd.equals("-args")) {
                                        runArgs = new String[args.length - 1 - i];
                                        System.arraycopy(args, i + 1, runArgs, 0, runArgs.length);
                                        break;
                                } else {
                                        System.err.println("unknown option " + cmd);
                                        System.err.println("see --help");
                                        return;
                                }
                        }

                        try {
                                // run the class
                                Run run = new Run(urls, command);
                                run.exec(runArgs);
                        } catch (Throwable t) {
                                t.printStackTrace();
                        }
                }
        }

        private static void showObjectStructure(Object o) throws IllegalAccessException {
                Class cls = o.getClass();
                String className = cls.getName();
                System.out.println("class " + className);
                for (Field f : cls.getDeclaredFields()) {
                        f.setAccessible(true);
                        Object value = f.get(o);
                        System.out.println("    " + f.getName() + " : " + f.getType().getName().replaceAll("\\.", "::") + " = " + value);
                }
                for (Method m : cls.getDeclaredMethods()) {
                        System.out.print("    " + m.getName() + "(");
                        boolean isFirst = true;
                        for (Class paramT : m.getParameterTypes()) {
                                if (isFirst) {
                                        isFirst = false;
                                } else {
                                        System.out.print(", ");
                                }
                                System.out.print(paramT);
                        }
                        System.out.println(") : " + m.getReturnType().getName().replaceAll("\\.", "::"));
                }
        }

        private static void sleep(long millis) {
                try {
                        Thread.sleep(millis);
                } catch (InterruptedException e) {
                        e.printStackTrace();
                }
        }

        private static void handleCtrlC() {
                // listen ctrl-c
                Class signalHandlerClass;
                try {
                        signalHandlerClass = Class.forName("lt.repl.CtrlCSignalHandler");
                } catch (Throwable ignore) {
                        // Signal api not correct or found
                        return;
                }
                CtrlCHandler ctrlCHandler;
                try {
                        ctrlCHandler = (CtrlCHandler) signalHandlerClass.newInstance();
                } catch (Throwable ignore) {
                        // unknown error
                        return;
                }
                ctrlCHandler.handle();
                ctrlCHandler.onAlert(new Runnable() {
                        @Override
                        public void run() {
                                System.out.print(lineStarter);
                                replSourceRec = new StringBuilder();
                        }
                });
        }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy