bs.java Source code

Java tutorial

Introduction

Here is the source code for bs.java

Source

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.apache.commons.io.FilenameUtils;

import com.bs.interpreter.stack.BsStack;
import com.bs.interpreter.stack.Stack;
import com.bs.lang.Bs;
import com.bs.lang.BsConst;
import com.bs.lang.BsObject;
import com.bs.lang.builtin.BsModule;
import com.bs.lang.builtin.BsString;
import com.bs.lang.lib.Loadable;
import com.bs.parser.StatementsParser;
import com.bs.parser.source.BsScanner;
import com.bs.parser.source.BsTokenizer;
import com.bs.parser.source.Scanner;
import com.bs.parser.source.Tokenizer;
import com.bs.parser.token.DefaultTokenFactory;
import com.bs.parser.tree.DefaultNodeFactory;
import com.bs.parser.tree.Node;
import com.bs.util.MessageHandler;
import com.bs.util.PrintStreamMessageListener;

public class bs {

    private static final String VERSION = "version";

    private static final String LOADABLE = "loadable";

    private static final String EVAL = "eval";

    private static final String HELP = "help";

    private static final String LOAD_PATH = "loadPath";

    private static final String VERSION_ID = "0.5";

    private static Option help = new Option("h", HELP, false, "Print this message");

    private static Option version = new Option("v", VERSION, false, "Show the version");

    // @formatter:off

    @SuppressWarnings("static-access")
    private static Option loadPath = OptionBuilder.withArgName(LOAD_PATH).isRequired(false).hasArg()
            .withDescription("Append <loadPath> to the load path").withLongOpt(LOAD_PATH).create('p');

    @SuppressWarnings("static-access")
    private static Option eval = OptionBuilder.withArgName(EVAL).isRequired(false).hasArg()
            .withDescription("Evaluate code and exit").withLongOpt(EVAL).create('e');

    @SuppressWarnings("static-access")
    private static Option loadable = OptionBuilder.withArgName(LOADABLE).isRequired(false).hasArg()
            .withDescription("Add all instances of 'Loadable' as loadable modules").withLongOpt(LOADABLE)
            .create('l');

    // @formatter:on

    public static void main(String[] args) throws FileNotFoundException {
        Options options = new Options();
        options.addOption(help);
        options.addOption(version);
        options.addOption(loadPath);
        options.addOption(loadable);
        options.addOption(eval);

        //       args = new String[] { "Reflection.bs" };

        try {
            Bs.init();

            CommandLineParser argParser = new PosixParser();
            CommandLine line = argParser.parse(options, args);

            if (line.hasOption(HELP)) {
                help(options);
            }

            if (line.hasOption(VERSION)) {
                version();
            }

            if (line.hasOption(LOAD_PATH)) {
                loadPath(line.getOptionValue(LOAD_PATH));
            }

            if (line.hasOption(EVAL)) {
                eval(line.getOptionValue(EVAL));
            }

            if (line.hasOption(LOADABLE)) {
                loadable(line.getOptionValue(LOADABLE));
            }

            List<?> rest = line.getArgList();

            if (rest.size() > 0) {
                eval(rest);
            } else {
                repl();
            }

        } catch (ParseException e) {
            help(options);
        }

    }

    private static void version() {
        System.out.println("bs (bullshit lang) " + VERSION_ID);
        System.out.println("Copyright (C) 2012+ Isak Karlsson");
        System.out.println("License BSD");
        System.exit(1);
    }

    private static void loadable(String filename) {
        File file = new File(filename);

        JarInputStream is;
        try {
            ClassLoader loader = URLClassLoader.newInstance(new URL[] { file.toURI().toURL() });
            is = new JarInputStream(new FileInputStream(file));
            JarEntry entry;
            while ((entry = is.getNextJarEntry()) != null) {
                if (entry.getName().endsWith(".class") && !entry.getName().contains("/")) {
                    Class<?> cls = Class.forName(FilenameUtils.removeExtension(entry.getName()), false, loader);
                    for (Class<?> i : cls.getInterfaces()) {
                        if (i.equals(Loadable.class)) {
                            Loadable l = (Loadable) cls.newInstance();
                            Bs.addModule(l);
                        }
                    }
                }
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }

    }

    /**
     * 
     */
    protected static void repl() {
        java.util.Scanner scanner = new java.util.Scanner(System.in);
        BsObject module = BsModule.create("<stdin>");
        Stack stack = BsStack.getDefault();
        stack.push(module);
        while (true) {
            String code = read(scanner, ">> ");
            BsObject obj = Bs.evalRepl(code, stack);
            if (obj == null) {
                continue;
            }
            if (obj.isError()) {
                Bs.breakError(obj, false);
            } else {
                System.out.println(obj);
            }
        }
    }

    /**
     * @param rest
     * @throws FileNotFoundException
     */
    protected static void eval(List<?> rest) throws FileNotFoundException {
        MessageHandler handler = new MessageHandler();
        handler.add(new PrintStreamMessageListener(System.out));

        String file = (String) rest.get(0);
        BsObject module = BsModule.create(file);
        Stack stack = BsStack.getDefault();
        stack.push(module);

        Scanner sc = new BsScanner(new FileReader(new File(file)));
        Tokenizer tz = new BsTokenizer(sc, new DefaultTokenFactory(), handler, '#');
        StatementsParser parser = new StatementsParser(tz, new DefaultNodeFactory(), handler);

        Node code = parser.parse();

        if (handler.errors() == 0) {
            BsObject value = Bs.eval(code, BsStack.getDefault());
            if (value == null) {
                System.out.println("Wtf!?");
            }
            if (value.isError()) {
                Bs.breakError(value);
            }
        }
    }

    /**
     * @param code
     */
    protected static void eval(String code) {
        BsObject obj = Bs.eval(code);
        if (obj.isError()) {
            Bs.breakError(obj);
        }

        System.exit(1);
    }

    /**
     * @param path
     */
    protected static void loadPath(String path) {
        List<BsObject> loadPath = BsConst.Module.getSlot(BsModule.LOAD_PATH).value();

        loadPath.add(BsString.clone(path));
    }

    /**
     * @param options
     */
    protected static void help(Options options) {
        HelpFormatter formatter = new HelpFormatter();
        formatter.printHelp("bs", options);
        System.exit(0);
    }

    private static String read(java.util.Scanner scanner, String promt) {
        System.out.print(promt);
        return scanner.nextLine();
    }
}