use of mb.statix.solver.IConstraint in project spoofax-pie by metaborg.
the class ExpandQueryStrategy method applyDataWF.
/**
* Applies the dataWF to the specified datum.
*
* applyDataWF :: DataWF * Data -> Unifier?
*
* @param dataWF the data WF predicate
* @param d the datum
* @param state the current state
* @param unifier the unifier of the context
* @param completeness the completeness of the context
* @param spec the Statix specification
* @return either a {@link SolverResult} with the result of applying the {@code dataWF} to the given datum;
* otherwise, nothing if the {@code dataWF} could not be applied
*/
private static Optional<SolverResult> applyDataWF(Rule dataWF, ITerm d, IState.Immutable state, IUniDisunifier.Immutable unifier, ICompleteness.Immutable completeness, Spec spec) {
// Apply the 'dataWF' to the specified 'd'
final ApplyResult applyResult;
if ((applyResult = RuleUtil.apply(unifier, dataWF, Collections.singletonList(d), null, ApplyMode.RELAXED, ApplyMode.Safety.SAFE).orElse(null)) == null) {
return Optional.empty();
}
final IState.Immutable applyState = state;
final IConstraint applyConstraint = applyResult.body();
// Update completeness for new state and constraint
final ICompleteness.Transient _completeness = completeness.melt();
_completeness.add(applyConstraint, spec, applyState.unifier());
final IConstraint constraint = applyResult.body();
// TODO: Reutrn a PreSolveResult or find another way to merge the SolverResult and PreSolveResult
// final Optional<Solver.PreSolveResult> solverResult = trySolveFast(constraint, state, _completeness, spec);
// if (!solverResult.isPresent()) return Optional.empty();
// final Solver.PreSolveResult result = solverResult.get();
// final IState.Immutable newState = result.state;
final Optional<SolverResult> solverResult = trySolveSlow(constraint, state, _completeness, spec);
if (!solverResult.isPresent())
return Optional.empty();
final SolverResult result = solverResult.get();
final IState.Immutable newState = result.state();
// NOTE: This part is almost a duplicate of ResolveDataWF::wf and should be kept in sync
// NOTE: The retain operation is important because it may change
// representatives, which can be local to newUnifier.
final IUniDisunifier.Immutable newUnifier = newState.unifier().retainAll(state.vars()).unifier();
// Check that all (remaining) disequalities are implied (i.e., not unifiable) in the original unifier
// @formatter:off
final List<ITermVar> disunifiedVars = newUnifier.disequalities().stream().filter(diseq -> diseq.toTuple().apply(unifier::disunify).map(r -> r.result().isPresent()).orElse(true)).flatMap(diseq -> diseq.domainSet().stream()).collect(Collectors.toList());
// @formatter:on
if (!disunifiedVars.isEmpty())
return Optional.empty();
// Applying dataWF succeeded.
return Optional.of(result);
}
use of mb.statix.solver.IConstraint in project spoofax-pie by metaborg.
the class ExpandQueryStrategy method updateSolverStateOld.
/**
* Creates a new solver state for the given matches.
*
* @param spec the spec
* @param query the query
* @param state the input state
* @param optMatches the accepted optional matches
* @param optRejects the rejected optional matches
* @param reqMatches the required matches
* @param reqRejects the required rejects
* @return the new solver state
*/
private static SolverState updateSolverStateOld(Spec spec, CResolveQuery query, SolverState state, Collection<Match<Scope, ITerm, ITerm, CEqual>> optMatches, Collection<Match<Scope, ITerm, ITerm, CEqual>> optRejects, Collection<Match<Scope, ITerm, ITerm, CEqual>> reqMatches, Collection<Match<Scope, ITerm, ITerm, CEqual>> reqRejects) {
// Build a new environment with all the matches and rejects.
final mb.statix.generator.scopegraph.Env.Builder<Scope, ITerm, ITerm, CEqual> subEnvBuilder = mb.statix.generator.scopegraph.Env.builder();
optMatches.forEach(subEnvBuilder::match);
reqMatches.forEach(subEnvBuilder::match);
optRejects.forEach(subEnvBuilder::reject);
reqRejects.forEach(subEnvBuilder::reject);
final mb.statix.generator.scopegraph.Env<Scope, ITerm, ITerm, CEqual> subEnv = subEnvBuilder.build();
// Build the list of constraints to add
final ImmutableList.Builder<IConstraint> addConstraints = ImmutableList.builder();
// The explicated match path must match the query result term
final List<ITerm> pathTerms = subEnv.matches.stream().map(m -> StatixTerms.pathToTerm(m.path, spec.dataLabels())).collect(ImmutableList.toImmutableList());
addConstraints.add(new CEqual(B.newList(pathTerms), query.resultTerm(), query));
subEnv.matches.stream().flatMap(m -> Optionals.stream(m.condition)).forEach(addConstraints::add);
subEnv.rejects.stream().flatMap(m -> Optionals.stream(m.condition)).forEach(condition -> addConstraints.add(new CInequal(ImmutableSet.of(), condition.term1(), condition.term2(), condition.cause().orElse(null), condition.message().orElse(null))));
// Build the list of constraints to remove
final Iterable<IConstraint> remConstraints = Iterables2.singleton(query);
// Update the given state with the added and removed constraints
return state.withUpdatedConstraints(addConstraints.build(), remConstraints).withMeta(state.getMeta().withExpandedQueriesIncremented());
}
use of mb.statix.solver.IConstraint in project spoofax-pie by metaborg.
the class MessageUtils method addMessage.
// //////////////////////////////////////////////
// Helper methods for creating error messages //
// //////////////////////////////////////////////
public static void addMessage(final IMessage message, final IConstraint constraint, final IUniDisunifier unifier, IStatixProjectConfig config, final Collection<ITerm> errors, final Collection<ITerm> warnings, final Collection<ITerm> notes) {
Tuple2<Iterable<String>, ITerm> message_origin = formatMessage(message, constraint, unifier, config);
final String messageText = Streams.stream(message_origin._1()).filter(s -> !s.isEmpty()).map(s -> cleanupString(s)).collect(Collectors.joining("<br>\n> ", "", "<br>\n"));
final ITerm messageTerm = B.newTuple(message_origin._2(), B.newString(messageText));
switch(message.kind()) {
case ERROR:
errors.add(messageTerm);
break;
case WARNING:
warnings.add(messageTerm);
break;
case NOTE:
notes.add(messageTerm);
break;
case IGNORE:
break;
}
}
use of mb.statix.solver.IConstraint in project spoofax-pie by metaborg.
the class MessageUtils method formatMessage.
public static Tuple2<Iterable<String>, ITerm> formatMessage(final IMessage message, final IConstraint constraint, final IUniDisunifier unifier, IStatixProjectConfig config) {
final TermFormatter formatter = Solver.shallowTermFormatter(unifier, config.messageTermDepth(config.messageTermDepth(IStatixProjectConfig.DEFAULT_MESSAGE_TERM_DEPTH)));
final int maxTraceLength = config.messageTraceLength(config.messageTraceLength(IStatixProjectConfig.DEFAULT_MESSAGE_TRACE_LENGTH));
ITerm originTerm = message.origin().flatMap(t -> getOriginTerm(t, unifier)).orElse(null);
final Deque<String> trace = new LinkedList<>();
IConstraint current = constraint;
int traceCount = 0;
while (current != null) {
if (originTerm == null) {
originTerm = findOriginArgument(current, unifier).orElse(null);
}
if (maxTraceLength < 0 || ++traceCount <= maxTraceLength) {
trace.addLast(current.toString(formatter));
}
current = current.cause().orElse(null);
}
if (maxTraceLength > 0 && traceCount > maxTraceLength) {
trace.addLast("... trace truncated ...");
}
// add constraint message
trace.addFirst(message.toString(formatter, () -> constraint.toString(formatter), completeness -> {
final ISubstitution.Transient subst = PersistentSubstitution.Transient.of();
completeness.vars().forEach(var -> {
ITerm sub = unifier.findRecursive(var);
if (!sub.equals(var)) {
subst.put(var, sub);
}
});
return completeness.apply(subst.freeze()).entrySet().stream().flatMap(e -> {
String scope = e.getKey().toString();
return e.getValue().elementSet().stream().map(edge -> scope + "-" + edge.toString());
}).collect(Collectors.joining(", "));
}));
// use empty origin if none was found
if (originTerm == null) {
originTerm = B.newTuple();
}
return Tuple2.of(trace, originTerm);
}
use of mb.statix.solver.IConstraint in project spoofax-pie by metaborg.
the class SmlPartialSolveProject method exec.
@Override
public Result<SolverResult, MultiLangAnalysisException> exec(ExecContext context, Input input) {
return context.require(instantiateGlobalScope.createTask(input.logLevel)).mapErr(MultiLangAnalysisException::wrapIfNeeded).flatMap(globalResult -> {
Set<ITerm> scopeArgs = Collections.singleton(globalResult.globalScope());
return languageMetadataManager.get().getLanguageMetadataResult(input.languageId).flatMap(lmd -> {
String qualifiedFileConstraintName = String.format("%s:%s", input.languageId.getId(), lmd.projectConstraint());
IConstraint projectConstraint = new CUser(qualifiedFileConstraintName, scopeArgs);
IDebugContext debug = SolverUtils.createDebugContext(input.logLevel);
return context.require(buildSpec.createSupplier(new SmlBuildSpec.Input(input.languageId))).mapErr(MultiLangAnalysisException::wrapIfNeeded).flatMap(spec -> {
try {
IState.Immutable initialState = State.of().add(globalResult.result().state()).withResource(input.languageId.getId());
SolverResult res = SolverUtils.partialSolve(spec, initialState, projectConstraint, debug, new NullCancel(), new NullProgress());
return Result.ofOk(res);
} catch (InterruptedException e) {
return Result.ofErr(new MultiLangAnalysisException(e));
}
});
});
});
}
Aggregations