/** * Converts the given value to the given NativeObject (optionally following the prototype chains). * * @param nativeObject target NativeObject * @param value Value to convert * @param prototype use the prototype chain? */ public static Value toNativeObject( HostObject nativeObject, Value value, boolean prototype, Solver.SolverInterface solverInterface) { State state = solverInterface.getState(); boolean bad = false; Set<ObjectLabel> matches = Collections.newSet(); if (prototype) { // Make lookup using prototype chains Set<ObjectLabel> objectLabels = Collections.newSet(value.getObjectLabels()); Set<ObjectLabel> visited = Collections.newSet(); while (!objectLabels.isEmpty()) { Set<ObjectLabel> temp = Collections.newSet(); for (ObjectLabel objectLabel : objectLabels) { if (!visited.contains(objectLabel)) { visited.add(objectLabel); Value prototypeValue = state.readInternalPrototype(java.util.Collections.singleton(objectLabel)); prototypeValue = UnknownValueResolver.getRealValue(prototypeValue, state); // FIXME: Needs code review. Looks fishy to compare objects with toString(). String nativeObjectPrototype = nativeObject.toString(); String objectLabelPrototype = ""; if (objectLabel.getHostObject() != null) { objectLabelPrototype = objectLabel.getHostObject().toString(); } if (nativeObject == objectLabel.getHostObject() || nativeObjectPrototype.equals(objectLabelPrototype)) { matches.add(objectLabel); } else if (prototypeValue.getObjectLabels().isEmpty()) { bad = true; } else { temp.addAll(prototypeValue.getObjectLabels()); } } } objectLabels = temp; } } else { // Make lookup ignoring prototype chains // TODO: Verify this for (ObjectLabel objectLabel : value.getObjectLabels()) { if (objectLabel.getHostObject() == nativeObject || (objectLabel.getHostObject() != null && objectLabel.getHostObject().toString().equals(nativeObject + ".prototype"))) { matches.add(objectLabel); } else { bad = true; } } } // Message.Status status; // if (good && bad) { // status = Message.Status.MAYBE; // } else if (!good && bad) { // status = Message.Status.CERTAIN; // } else if (good && !bad) { // status = Message.Status.NONE; // } else if (!good && !bad) { // equivalent to Value of Undef / a null argument // // Considered a certain type error. // status = Message.Status.CERTAIN; // } else { // throw new AnalysisException("toNativeObject: fell through cases - should not // happen."); // } if (bad) { String message = "TypeError, argument is not of expected type: " + nativeObject; solverInterface .getMonitoring() .addMessage(solverInterface.getNode(), Message.Severity.HIGH, message); } return Value.makeObject(matches); }
public NormalForm(String normal_form, Map<String, Integer> mapping, Collection<String> args) { super(); this.normal_form = normal_form; this.mapping = Collections.newMap(mapping); this.arguments_in_use = Collections.newSet(args); }