001package org.clafer.javascript;
002
003import java.io.File;
004import java.io.FileReader;
005import java.io.IOException;
006import java.io.InputStreamReader;
007import java.io.Reader;
008import org.clafer.ast.AstModel;
009import org.clafer.collection.Triple;
010import org.clafer.objective.Objective;
011import org.clafer.scope.Scope;
012import org.mozilla.javascript.Context;
013import org.mozilla.javascript.ImporterTopLevel;
014import org.mozilla.javascript.Scriptable;
015
016/**
017 * This class provides various methods of loading models and scopes via the
018 * Javascript API.
019 *
020 * @author jimmy
021 */
022public class Javascript {
023
024    private Javascript() {
025    }
026
027    /**
028     * @return a new Javascript engine.
029     */
030    public static Scriptable newEngine() {
031        Context cxt = Context.enter();
032        cxt.setOptimizationLevel(-1);
033        try {
034            return new ImporterTopLevel(cxt);
035        } finally {
036            Context.exit();
037        }
038    }
039
040    public static Triple<AstModel, Scope, Objective[]> readModel(String in) throws IOException {
041        return readModel("<unknown>", in, newEngine());
042    }
043
044    public static Triple<AstModel, Scope, Objective[]> readModel(File in) throws IOException {
045        return readModel(in, newEngine());
046    }
047
048    public static Triple<AstModel, Scope, Objective[]> readModel(Reader in) throws IOException {
049        return readModel("<unknown>", in, newEngine());
050    }
051
052    public static Triple<AstModel, Scope, Objective[]> readModel(File in, Scriptable engine) throws IOException {
053        return readModel(in.getName(), in, engine);
054    }
055
056    public static Triple<AstModel, Scope, Objective[]> readModel(String name, String in, Scriptable engine) throws IOException {
057        JavascriptContext context = new JavascriptContext();
058        Context cxt = Context.enter();
059        cxt.setOptimizationLevel(-1);
060        try {
061            engine.put("rc", engine, context);
062            cxt.evaluateReader(engine,
063                    new InputStreamReader(Javascript.class.getResourceAsStream("header.js")),
064                    "header.js", 1, null);
065            cxt.evaluateString(engine, in, name, 1, null);
066            return new Triple<>(
067                    context.getModel(),
068                    context.getScope(engine),
069                    context.getObjectives());
070        } finally {
071            Context.exit();
072        }
073    }
074
075    public static Triple<AstModel, Scope, Objective[]> readModel(String name, File in, Scriptable engine) throws IOException {
076        return readModel(name, new FileReader(in), engine);
077    }
078
079    public static Triple<AstModel, Scope, Objective[]> readModel(String name, Reader in, Scriptable engine) throws IOException {
080        JavascriptContext context = new JavascriptContext();
081        Context cxt = Context.enter();
082        cxt.setOptimizationLevel(-1);
083        try {
084            engine.put("rc", engine, context);
085            cxt.evaluateReader(engine,
086                    new InputStreamReader(Javascript.class.getResourceAsStream("header.js")),
087                    "header.js", 1, null);
088            cxt.evaluateReader(engine, in, name, 1, null);
089            return new Triple<>(
090                    context.getModel(),
091                    context.getScope(engine),
092                    context.getObjectives());
093        } finally {
094            Context.exit();
095        }
096    }
097}