use of mb.nabl2.constraints.IConstraint in project spoofax by metaborg.
the class ConstraintSingleFileAnalyzer method analyzeAll.
@Override
protected ISpoofaxAnalyzeResults analyzeAll(Map<String, ISpoofaxParseUnit> changed, Set<String> removed, ISingleFileScopeGraphContext context, HybridInterpreter runtime, String strategy, IProgress progress, ICancel cancel) throws AnalysisException {
final NaBL2DebugConfig debugConfig = context.config().debug();
for (String input : removed) {
context.removeUnit(input);
}
final int n = changed.size();
progress.setWorkRemaining(n + 1);
if (debugConfig.analysis() || debugConfig.files()) {
logger.info("Analyzing {} files in {}.", n, context.location());
}
final Collection<ISpoofaxAnalyzeUnit> results = Lists.newArrayList();
try {
for (Map.Entry<String, ISpoofaxParseUnit> input : changed.entrySet()) {
final String source = input.getKey();
final ISpoofaxParseUnit parseUnit = input.getValue();
final ITerm ast = strategoTerms.fromStratego(parseUnit.ast());
if (debugConfig.files()) {
logger.info("Analyzing {}.", source);
}
final ISingleFileScopeGraphUnit unit = context.unit(source);
unit.clear();
try {
// initial
InitialResult initialResult;
final Optional<ITerm> customInitial;
{
if (debugConfig.collection()) {
logger.info("Collecting initial constraints of {}.", source);
}
ITerm initialResultTerm = doAction(strategy, Actions.analyzeInitial(source, ast), context, runtime).orElseThrow(() -> new AnalysisException(context, "No initial result."));
initialResult = InitialResult.matcher().match(initialResultTerm).orElseThrow(() -> new MetaborgException("Invalid initial results."));
customInitial = doCustomAction(strategy, Actions.customInitial(source, ast), context, runtime);
initialResult = initialResult.withCustomResult(customInitial);
if (debugConfig.collection()) {
logger.info("Collected {} initial constraints of {}.", initialResult.getConstraints().size(), source);
}
}
// unit
UnitResult unitResult;
final Optional<ITerm> customUnit;
{
if (debugConfig.collection()) {
logger.info("Collecting constraints of {}.", source);
}
final ITerm unitResultTerm = doAction(strategy, Actions.analyzeUnit(source, ast, initialResult.getArgs()), context, runtime).orElseThrow(() -> new AnalysisException(context, "No unit result."));
unitResult = UnitResult.matcher().match(unitResultTerm).orElseThrow(() -> new MetaborgException("Invalid unit results."));
final ITerm desugaredAST = unitResult.getAST();
customUnit = doCustomAction(strategy, Actions.customUnit(source, desugaredAST, customInitial.orElse(B.EMPTY_TUPLE)), context, runtime);
unitResult = unitResult.withCustomResult(customUnit);
unit.setUnitResult(unitResult);
if (debugConfig.collection()) {
logger.info("Collected {} constraints of {}.", unitResult.getConstraints().size(), source);
}
}
// solve
ISolution solution;
{
Set<IConstraint> constraints = Sets.union(initialResult.getConstraints(), unitResult.getConstraints());
if (debugConfig.resolution()) {
logger.info("Solving {} constraints of {}.", constraints.size(), source);
}
Function1<String, String> fresh = base -> context.unit(source).fresh().fresh(base);
final IProgress subprogress = progress.subProgress(1);
final SingleFileSolver solver = new SingleFileSolver(context.config().debug(), callExternal(runtime));
GraphSolution preSolution = solver.solveGraph(ImmutableBaseSolution.of(initialResult.getConfig(), constraints, PersistentUnifier.Immutable.of()), fresh, cancel, subprogress);
preSolution = solver.reportUnsolvedGraphConstraints(preSolution);
solution = solver.solve(preSolution, fresh, cancel, subprogress);
solution = solver.reportUnsolvedConstraints(solution);
if (!solution.flowSpecSolution().controlFlowGraph().isEmpty()) {
logger.debug("CFG is not empty: calling FlowSpec dataflow solver");
solution = new FixedPoint().entryPoint(solution, getFlowSpecTransferFunctions(context.language()));
}
unit.setSolution(solution);
if (debugConfig.resolution()) {
logger.info("Solved constraints of {}.", source);
}
}
// final
FinalResult finalResult;
final Optional<ITerm> customFinal;
{
if (debugConfig.files()) {
logger.info("Finalizing analysis of {}.", source);
}
ITerm finalResultTerm = doAction(strategy, Actions.analyzeFinal(source), context, runtime).orElseThrow(() -> new AnalysisException(context, "No final result."));
finalResult = FinalResult.matcher().match(finalResultTerm).orElseThrow(() -> new MetaborgException("Invalid final results."));
customFinal = doCustomAction(strategy, Actions.customFinal(source, customInitial.orElse(B.EMPTY_TUPLE), customUnit.map(cu -> Collections.singletonList(cu)).orElse(Collections.emptyList())), context, runtime);
finalResult = finalResult.withCustomResult(customFinal);
unit.setFinalResult(finalResult);
if (debugConfig.files()) {
logger.info("Finalized analysis of {}.", source);
}
}
final IStrategoTerm analyzedAST = strategoTerms.toStratego(unitResult.getAST());
Optional<CustomSolution> customSolution = customFinal.flatMap(CustomSolution.matcher()::match);
customSolution.ifPresent(cs -> unit.setCustomSolution(cs));
// errors
final boolean success;
{
if (debugConfig.files()) {
logger.info("Processing messages of {}.", source);
}
Messages.Transient messageBuilder = Messages.Transient.of();
messageBuilder.addAll(Messages.unsolvedErrors(solution.constraints()));
messageBuilder.addAll(solution.messages().getAll());
customSolution.map(CustomSolution::getMessages).map(IMessages::getAll).ifPresent(messageBuilder::addAll);
IMessages messages = messageBuilder.freeze();
success = messages.getErrors().isEmpty();
Iterable<IMessage> fileMessages = Iterables.concat(analysisCommon.ambiguityMessages(parseUnit.source(), parseUnit.ast()), messages(messages.getAll(), solution.unifier(), context, context.location()));
// result
results.add(unitService.analyzeUnit(parseUnit, new AnalyzeContrib(true, success, true, analyzedAST, fileMessages, -1), context));
if (debugConfig.analysis() || debugConfig.files()) {
logger.info("Analyzed {}: {} errors, {} warnings, {} notes.", source, messages.getErrors().size(), messages.getWarnings().size(), messages.getNotes().size());
}
}
} catch (MetaborgException | SolverException e) {
logger.warn("Analysis of " + source + " failed.", e);
Iterable<IMessage> messages = Iterables2.singleton(MessageFactory.newAnalysisErrorAtTop(parseUnit.source(), "File analysis failed.", e));
results.add(unitService.analyzeUnit(parseUnit, new AnalyzeContrib(false, false, true, parseUnit.ast(), messages, -1), context));
}
}
} catch (InterruptedException e) {
logger.debug("Analysis was interrupted.");
}
if (debugConfig.analysis()) {
logger.info("Analyzed {} files.", n);
}
return new SpoofaxAnalyzeResults(results, Collections.emptyList(), context);
}
use of mb.nabl2.constraints.IConstraint in project nabl by metaborg.
the class PolymorphismComponent method solve.
private Optional<SolveResult> solve(CInstantiate inst) {
final ITerm declTerm = unifier().findRecursive(inst.getDeclaration());
if (!declTerm.isGround()) {
return Optional.empty();
}
final Occurrence decl = Occurrence.matcher().match(declTerm, unifier()).orElseThrow(() -> new TypeException("Expected an occurrence as first argument to " + inst));
if (!isInstSafe.test(decl)) {
return Optional.empty();
}
final Optional<ITerm> schemeTerm = getDeclProp.apply(decl, DeclProperties.TYPE_KEY);
if (!schemeTerm.isPresent()) {
return Optional.empty();
}
final Optional<Forall> forall = Forall.matcher().match(schemeTerm.get(), unifier());
final ITerm type;
// linked map to preserve key order
final Map<TypeVar, ITermVar> subst = Maps.newLinkedHashMap();
if (forall.isPresent()) {
final Forall scheme = forall.get();
scheme.getTypeVars().stream().forEach(v -> {
subst.put(v, B.newVar("", fresh(v.getName())));
});
type = subst(scheme.getType(), subst);
} else {
type = schemeTerm.get();
}
final IConstraint constraint = // @formatter:off
ImmutableCExists.of(subst.values(), ImmutableCConj.of(ImmutableCEqual.of(inst.getType(), type, inst.getMessageInfo()), ImmutableCEqual.of(inst.getInstVars(), B.newList(subst.keySet()), inst.getMessageInfo()), MessageInfo.empty()), inst.getMessageInfo());
// @formatter:on
SolveResult result = SolveResult.constraints(constraint);
return Optional.of(result);
}
use of mb.nabl2.constraints.IConstraint in project nabl by metaborg.
the class FixedPointSolver method solve.
public SolveResult solve(Iterable<? extends IConstraint> initialConstraints) throws InterruptedException {
propertiesAddAll(initialConstraints);
final IMessages.Transient messages = Messages.Transient.of();
final Multimap<String, String> dependencies = HashMultimap.create();
final Set<IConstraint> constraints = Sets.newHashSet(initialConstraints);
boolean progress;
do {
progress = false;
final Set<IConstraint> newConstraints = Sets.newHashSet();
final Iterator<IConstraint> it = constraints.iterator();
while (it.hasNext()) {
cancel.throwIfCancelled();
final IConstraint constraint = it.next();
final SolveResult result;
// property only on other constraints
propertiesRemove(constraint);
if ((result = component.apply(constraint).orElse(null)) != null) {
messages.addAll(result.messages());
dependencies.putAll(result.dependencies());
propertiesAddAll(result.constraints());
newConstraints.addAll(result.constraints());
updateVars(result.unifierDiff().varSet());
it.remove();
stepSubject.onNext(result);
this.progress.work(1);
progress |= true;
} else {
propertiesAdd(constraint);
}
}
constraints.addAll(newConstraints);
} while (progress);
return ImmutableSolveResult.builder().messages(messages.freeze()).dependencies(dependencies).constraints(constraints).build();
}
use of mb.nabl2.constraints.IConstraint in project nabl by metaborg.
the class SemiIncrementalMultiFileSolver method solveInter.
public ISolution solveInter(ISolution initial, Iterable<? extends ISolution> unitSolutions, IMessageInfo message, Function1<String, String> fresh, ICancel cancel, IProgress progress) throws SolverException, InterruptedException {
final SolverConfig config = initial.config();
// shared
final Ref<IUnifier.Immutable> unifier = new Ref<>(initial.unifier());
final IEsopScopeGraph.Transient<Scope, Label, Occurrence, ITerm> scopeGraph = initial.scopeGraph().melt();
final IEsopNameResolution<Scope, Label, Occurrence> nameResolution = EsopNameResolution.of(config.getResolutionParams(), scopeGraph, (s, l) -> true);
// constraint set properties
final ActiveVars activeVars = new ActiveVars(unifier);
final ActiveDeclTypes activeDeclTypes = new ActiveDeclTypes(unifier);
final HasRelationBuildConstraints hasRelationBuildConstraints = new HasRelationBuildConstraints();
// guards
final Predicate1<String> isRelationComplete = r -> !hasRelationBuildConstraints.contains(r);
// solver components
final SolverCore core = new SolverCore(config, unifier, fresh, callExternal);
final AstComponent astSolver = new AstComponent(core, initial.astProperties().melt());
final BaseComponent baseSolver = new BaseComponent(core);
final EqualityComponent equalitySolver = new EqualityComponent(core, unifier);
final NameResolutionComponent nameResolutionSolver = new NameResolutionComponent(core, scopeGraph, nameResolution, initial.declProperties().melt());
final NameSetsComponent nameSetSolver = new NameSetsComponent(core, scopeGraph, nameResolution);
final RelationComponent relationSolver = new RelationComponent(core, isRelationComplete, config.getFunctions(), VariantRelations.melt(initial.relations()));
final SetComponent setSolver = new SetComponent(core, nameSetSolver.nameSets());
final SymbolicComponent symSolver = new SymbolicComponent(core, initial.symbolic());
final ControlFlowComponent cfgSolver = new ControlFlowComponent(core, ImmutableFlowSpecSolution.of());
final PolySafe polySafe = new PolySafe(activeVars, activeDeclTypes, nameResolutionSolver);
final PolymorphismComponent polySolver = new PolymorphismComponent(core, polySafe::isGenSafe, polySafe::isInstSafe, nameResolutionSolver::getProperty);
final ISolver component = c -> c.matchOrThrow(IConstraint.CheckedCases.<Optional<SolveResult>, InterruptedException>builder().onBase(baseSolver::solve).onEquality(equalitySolver::solve).onNameResolution(nameResolutionSolver::solve).onPoly(polySolver::solve).onRelation(relationSolver::solve).onSet(setSolver::solve).onSym(symSolver::solve).onControlflow(cfgSolver::solve).otherwise(ISolver.deny("Not allowed in this phase")));
final FixedPointSolver solver = new FixedPointSolver(cancel, progress, component, Iterables2.from(activeVars, hasRelationBuildConstraints));
solver.step().subscribe(r -> {
if (!r.unifierDiff().isEmpty()) {
try {
nameResolutionSolver.update();
} catch (InterruptedException ex) {
// ignore here
}
}
});
try {
// seed unit solutions
final java.util.Set<IConstraint> constraints = Sets.newHashSet(initial.constraints());
final IMessages.Transient messages = initial.messages().melt();
for (ISolution unitSolution : unitSolutions) {
seed(astSolver.seed(unitSolution.astProperties(), message), messages, constraints);
seed(equalitySolver.seed(unitSolution.unifier(), message), messages, constraints);
final NameResolutionResult nameResult = ImmutableNameResolutionResult.of(unitSolution.scopeGraph(), unitSolution.declProperties()).withResolutionCache(unitSolution.nameResolutionCache());
seed(nameResolutionSolver.seed(nameResult, message), messages, constraints);
seed(relationSolver.seed(unitSolution.relations(), message), messages, constraints);
seed(symSolver.seed(unitSolution.symbolic(), message), messages, constraints);
seed(cfgSolver.seed(unitSolution.flowSpecSolution(), message), messages, constraints);
constraints.addAll(unitSolution.constraints());
messages.addAll(unitSolution.messages());
}
// solve constraints
nameResolutionSolver.update();
SolveResult solveResult = solver.solve(constraints);
messages.addAll(solveResult.messages());
// build result
IProperties.Immutable<TermIndex, ITerm, ITerm> astResult = astSolver.finish();
NameResolutionResult nameResolutionResult = nameResolutionSolver.finish();
IUnifier.Immutable unifierResult = equalitySolver.finish();
Map<String, IVariantRelation.Immutable<ITerm>> relationResult = relationSolver.finish();
ISymbolicConstraints symbolicConstraints = symSolver.finish();
IFlowSpecSolution<CFGNode> fsSolution = cfgSolver.finish();
return ImmutableSolution.of(config, astResult, nameResolutionResult.scopeGraph(), nameResolutionResult.declProperties(), relationResult, unifierResult, symbolicConstraints, fsSolution, messages.freeze(), solveResult.constraints()).withNameResolutionCache(nameResolutionResult.resolutionCache());
} catch (RuntimeException ex) {
throw new SolverException("Internal solver error.", ex);
}
}
use of mb.nabl2.constraints.IConstraint in project nabl by metaborg.
the class ActiveVars method add.
// ---------------------------------------------
@Override
public boolean add(IConstraint constraint) {
final Multiset<ITermVar> vars = findActiveVars(constraint);
boolean change = false;
for (ITermVar var : vars) {
change |= add(var);
}
return change;
}
Aggregations