001package org.clafer.javascript;
002
003import java.util.ArrayList;
004import java.util.HashMap;
005import java.util.List;
006import java.util.Map;
007import java.util.Map.Entry;
008import org.clafer.ast.AstClafer;
009import org.clafer.ast.AstModel;
010import org.clafer.ast.AstSetExpr;
011import org.clafer.ast.Asts;
012import org.clafer.objective.Objective;
013import org.clafer.scope.Scope;
014import org.mozilla.javascript.NativeJavaObject;
015import org.mozilla.javascript.Scriptable;
016
017/**
018 *
019 * @author jimmy
020 */
021public class JavascriptContext {
022
023    private final Map<String, Integer> scope = new HashMap<>();
024    private final List<Objective> objectives = new ArrayList<>(0);
025    private int defaultScope = 1;
026    private int intLow = -16;
027    private int intHigh = 16;
028    private final AstModel model = Asts.newModel();
029
030    public void setScope(Map<String, Number> scope) {
031        for (Entry<String, Number> entry : scope.entrySet()) {
032            // Javascript integers are doubles.
033            this.scope.put(entry.getKey(), entry.getValue().intValue());
034        }
035    }
036
037    public void setDefaultScope(int defaultScope) {
038        if (defaultScope < 1) {
039            throw new IllegalArgumentException();
040        }
041        this.defaultScope = defaultScope;
042    }
043
044    public void setIntRange(int intLow, int intHigh) {
045        if (intLow > intHigh) {
046            throw new IllegalArgumentException();
047        }
048        this.intLow = intLow;
049        this.intHigh = intHigh;
050    }
051
052    public Scope getScope(Scriptable engine) {
053        Map<AstClafer, Integer> resolvedScope = new HashMap<>();
054        for (Entry<String, Integer> entry : scope.entrySet()) {
055            String key = entry.getKey();
056            Object value = engine.get(key, engine);
057            if (!(value instanceof NativeJavaObject)) {
058                throw new IllegalStateException(key + " is not a Clafer, found " + value);
059            }
060            NativeJavaObject object = (NativeJavaObject) value;
061            if (!(object.unwrap() instanceof AstClafer)) {
062                throw new IllegalStateException(key + " is not a Clafer, found " + object.unwrap());
063            }
064            AstClafer clafer = (AstClafer) object.unwrap();
065            if (clafer == null) {
066                throw new IllegalStateException("Cannot set scope for unknown Clafer \"" + key + "\", "
067                        + ".");
068            }
069            resolvedScope.put(clafer, entry.getValue());
070        }
071        return new Scope(resolvedScope, defaultScope, intLow, intHigh);
072    }
073
074    public void addMaximizeObjective(AstSetExpr expr) {
075        objectives.add(Objective.maximize(expr));
076    }
077
078    public void addMinimizeObjective(AstSetExpr expr) {
079        objectives.add(Objective.minimize(expr));
080    }
081
082    public Objective[] getObjectives() {
083        return objectives.toArray(new Objective[objectives.size()]);
084    }
085
086    public AstModel getModel() {
087        return model;
088    }
089}