Search in sources :

Example 21 with IStrategoTerm

use of org.spoofax.interpreter.terms.IStrategoTerm in project spoofax by metaborg.

the class AbstractConstraintAnalyzer method getFlowSpecTransferFunctions.

protected Optional<TFFileInfo> getFlowSpecTransferFunctions(ILanguageComponent component) {
    TFFileInfo transferFunctions = flowSpecTransferFunctionCache.get(component);
    if (transferFunctions != null) {
        return Optional.of(transferFunctions);
    }
    FileObject tfs = resourceService.resolve(component.location(), TRANSFER_FUNCTIONS_FILE);
    try {
        IStrategoTerm sTerm = termFactory.parseFromString(IOUtils.toString(tfs.getContent().getInputStream(), StandardCharsets.UTF_8));
        ITerm term = strategoTerms.fromStratego(sTerm);
        transferFunctions = TFFileInfo.match().match(term, PersistentUnifier.Immutable.of()).orElseThrow(() -> new ParseException("Parse error on reading the transfer function file"));
    } catch (ParseError | ParseException | IOException e) {
        logger.error("Could not read transfer functions file for {}", component);
        return Optional.empty();
    }
    logger.debug("Caching flowspec transfer functions for language {}", component);
    flowSpecTransferFunctionCache.put(component, transferFunctions);
    return Optional.of(transferFunctions);
}
Also used : TFFileInfo(mb.flowspec.runtime.solver.TFFileInfo) IStrategoTerm(org.spoofax.interpreter.terms.IStrategoTerm) ITerm(mb.nabl2.terms.ITerm) ParseError(org.spoofax.terms.ParseError) FileObject(org.apache.commons.vfs2.FileObject) ParseException(mb.flowspec.runtime.solver.ParseException) IOException(java.io.IOException)

Example 22 with IStrategoTerm

use of org.spoofax.interpreter.terms.IStrategoTerm in project spoofax by metaborg.

the class ConstraintMultiFileAnalyzer method analyzeSemiIncremental.

private ISpoofaxAnalyzeResults analyzeSemiIncremental(Map<String, ISpoofaxParseUnit> changed, java.util.Set<String> removed, IMultiFileScopeGraphContext context, HybridInterpreter runtime, String strategy, IProgress progress, ICancel cancel) throws AnalysisException {
    final NaBL2DebugConfig debugConfig = context.config().debug();
    final Timer totalTimer = new Timer(true);
    final AggregateTimer collectionTimer = new AggregateTimer();
    final AggregateTimer solverTimer = new AggregateTimer();
    final AggregateTimer finalizeTimer = new AggregateTimer();
    final String globalSource = "";
    final Function1<String, String> globalFresh = base -> context.unit(globalSource).fresh().fresh(base);
    for (String input : removed) {
        context.removeUnit(input);
    }
    final int n = changed.size();
    final int w = context.units().size() / 2;
    progress.setWorkRemaining(n + w + 1);
    if (debugConfig.analysis() || debugConfig.files()) {
        logger.info("Analyzing {} files in {}.", n, context.location());
    }
    final Collection<ISpoofaxAnalyzeUnit> results = Lists.newArrayList();
    final Collection<ISpoofaxAnalyzeUnitUpdate> updateResults = Lists.newArrayList();
    try {
        // initial
        InitialResult initialResult;
        final Optional<ITerm> customInitial;
        {
            if (debugConfig.collection()) {
                logger.info("Collecting initial constraints.");
            }
            if (context.initialResult().isPresent()) {
                initialResult = context.initialResult().get();
                customInitial = context.initialResult().flatMap(r -> r.getCustomResult());
            } else {
                collectionTimer.start();
                try {
                    final ITerm globalAST = Actions.sourceTerm(globalSource, B.EMPTY_TUPLE);
                    ITerm initialResultTerm = doAction(strategy, Actions.analyzeInitial(globalSource, globalAST), context, runtime).orElseThrow(() -> new AnalysisException(context, "No initial result."));
                    initialResult = InitialResult.matcher().match(initialResultTerm).orElseThrow(() -> new AnalysisException(context, "Invalid initial results."));
                    customInitial = doCustomAction(strategy, Actions.customInitial(globalSource, globalAST), context, runtime);
                    initialResult = initialResult.withCustomResult(customInitial);
                    context.setInitialResult(initialResult);
                } finally {
                    collectionTimer.stop();
                }
            }
            if (debugConfig.collection()) {
                logger.info("Initial constraints collected.");
            }
        }
        // global parameters, that form the interface for a single unit
        final java.util.Set<ITermVar> intfVars = Sets.newHashSet();
        {
            initialResult.getArgs().getParams().stream().forEach(param -> intfVars.addAll(param.getVars()));
            initialResult.getArgs().getType().ifPresent(type -> intfVars.addAll(type.getVars()));
        }
        final SemiIncrementalMultiFileSolver solver = new SemiIncrementalMultiFileSolver(context.config().debug(), callExternal(runtime));
        // global
        ISolution initialSolution;
        {
            if (context.initialSolution().isPresent()) {
                initialSolution = context.initialSolution().get();
            } else {
                try {
                    solverTimer.start();
                    final IProgress subprogress = progress.subProgress(1);
                    GraphSolution preSolution = solver.solveGraph(ImmutableBaseSolution.of(initialResult.getConfig(), initialResult.getConstraints(), PersistentUnifier.Immutable.of()), globalFresh, cancel, subprogress);
                    preSolution = solver.reportUnsolvedGraphConstraints(preSolution);
                    initialSolution = solver.solveIntra(preSolution, intfVars, null, globalFresh, cancel, subprogress);
                    if (debugConfig.resolution()) {
                        logger.info("Reduced file constraints to {}.", initialSolution.constraints().size());
                    }
                } catch (SolverException e) {
                    throw new AnalysisException(context, e);
                } finally {
                    solverTimer.stop();
                }
                context.setInitialSolution(initialSolution);
            }
        }
        final java.util.Set<Scope> intfScopes = Sets.newHashSet();
        {
            initialResult.getArgs().getParams().stream().forEach(param -> Scope.matcher().match(param, initialSolution.unifier()).ifPresent(intfScopes::add));
        }
        // units
        final Map<String, IStrategoTerm> astsByFile = Maps.newHashMap();
        final Map<String, IMessage> failures = Maps.newHashMap();
        final Multimap<String, IMessage> ambiguitiesByFile = HashMultimap.create();
        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 IMultiFileScopeGraphUnit unit = context.unit(source);
            unit.clear();
            try {
                UnitResult unitResult;
                final Optional<ITerm> customUnit;
                {
                    if (debugConfig.collection()) {
                        logger.info("Collecting constraints of {}.", source);
                    }
                    try {
                        collectionTimer.start();
                        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);
                        final IStrategoTerm analyzedAST = strategoTerms.toStratego(desugaredAST);
                        astsByFile.put(source, analyzedAST);
                        ambiguitiesByFile.putAll(source, analysisCommon.ambiguityMessages(parseUnit.source(), parseUnit.ast()));
                        unit.setUnitResult(unitResult);
                    } finally {
                        collectionTimer.stop();
                    }
                    if (debugConfig.collection()) {
                        logger.info("Collected {} constraints of {}.", unitResult.getConstraints().size(), source);
                    }
                }
                {
                    final ISolution unitSolution;
                    if (debugConfig.resolution()) {
                        logger.info("Reducing {} constraints of {}.", unitResult.getConstraints().size(), source);
                    }
                    try {
                        solverTimer.start();
                        final Function1<String, String> fresh = base -> context.unit(source).fresh().fresh(base);
                        final IProgress subprogress = progress.subProgress(1);
                        GraphSolution preSolution = solver.solveGraph(ImmutableBaseSolution.of(initialResult.getConfig(), unitResult.getConstraints(), initialSolution.unifier()), fresh, cancel, subprogress);
                        preSolution = solver.reportUnsolvedGraphConstraints(preSolution);
                        unitSolution = solver.solveIntra(preSolution, intfVars, intfScopes, fresh, cancel, subprogress);
                        if (debugConfig.resolution()) {
                            logger.info("Reduced file constraints to {}.", unitSolution.constraints().size());
                        }
                    } catch (SolverException e) {
                        throw new AnalysisException(context, e);
                    } finally {
                        solverTimer.stop();
                    }
                    unit.setPartialSolution(unitSolution);
                    if (debugConfig.files() || debugConfig.resolution()) {
                        logger.info("Analyzed {}: {} errors, {} warnings, {} notes, {} unsolved constraints.", source, unitSolution.messages().getErrors().size(), unitSolution.messages().getWarnings().size(), unitSolution.messages().getNotes().size(), unitSolution.constraints().size());
                    }
                }
            } catch (MetaborgException e) {
                logger.warn("Analysis of " + source + " failed.", e);
                failures.put(source, MessageFactory.newAnalysisErrorAtTop(parseUnit.source(), "File analysis failed.", e));
            }
        }
        // solve
        final ISolution solution;
        final List<Optional<ITerm>> customUnits = Lists.newArrayList();
        {
            final List<ISolution> partialSolutions = Lists.newArrayList();
            for (IMultiFileScopeGraphUnit unit : context.units()) {
                unit.partialSolution().ifPresent(partialSolutions::add);
                unit.unitResult().map(UnitResult::getCustomResult).ifPresent(customUnits::add);
            }
            if (debugConfig.resolution()) {
                logger.info("Solving {} partial solutions.", partialSolutions.size());
            }
            ISolution sol;
            try {
                solverTimer.start();
                Function1<String, String> fresh = base -> context.unit(globalSource).fresh().fresh(base);
                IMessageInfo message = ImmutableMessageInfo.of(MessageKind.ERROR, MessageContent.of(), Actions.sourceTerm(globalSource));
                sol = solver.solveInter(initialSolution, partialSolutions, message, fresh, cancel, progress.subProgress(w));
                sol = solver.reportUnsolvedConstraints(sol);
            } catch (SolverException e) {
                throw new AnalysisException(context, e);
            } finally {
                solverTimer.stop();
            }
            if (!sol.flowSpecSolution().controlFlowGraph().isEmpty()) {
                logger.debug("CFG is not empty: calling FlowSpec dataflow solver");
                sol = new FixedPoint().entryPoint(sol, getFlowSpecTransferFunctions(context.language()));
            }
            solution = sol;
            context.setSolution(solution);
            if (debugConfig.resolution()) {
                logger.info("Project constraints solved.");
            }
        }
        // final
        FinalResult finalResult;
        final Optional<ITerm> customFinal;
        final Optional<CustomSolution> customSolution;
        {
            if (debugConfig.analysis()) {
                logger.info("Finalizing project analysis.");
            }
            finalizeTimer.start();
            try {
                ITerm finalResultTerm = doAction(strategy, Actions.analyzeFinal(globalSource), context, runtime).orElseThrow(() -> new AnalysisException(context, "No final result."));
                finalResult = FinalResult.matcher().match(finalResultTerm, solution.unifier()).orElseThrow(() -> new AnalysisException(context, "Invalid final results."));
                customFinal = doCustomAction(strategy, Actions.customFinal(globalSource, customInitial.orElse(B.EMPTY_TUPLE), Optionals.filter(customUnits)), context, runtime);
                finalResult = finalResult.withCustomResult(customFinal);
                context.setFinalResult(finalResult);
                customSolution = customFinal.flatMap(cs -> CustomSolution.matcher().match(cs, solution.unifier()));
                customSolution.ifPresent(cs -> context.setCustomSolution(cs));
            } finally {
                finalizeTimer.stop();
            }
            if (debugConfig.analysis()) {
                logger.info("Project analysis finalized.");
            }
        }
        // errors
        {
            if (debugConfig.analysis()) {
                logger.info("Processing project messages.");
            }
            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();
            IRelation3.Transient<String, MessageSeverity, IMessage> messagesByFile = HashTrieRelation3.Transient.of();
            messagesByFile(failures.values(), messagesByFile, context);
            messagesByFile(messages(messages.getAll(), solution.unifier(), context, context.location()), messagesByFile, context);
            // precondition: the messagesByFile should not contain any files that do not have corresponding units
            for (IMultiFileScopeGraphUnit unit : context.units()) {
                final String source = unit.resource();
                final java.util.Set<IMessage> fileMessages = messagesByFile.get(source).stream().map(Map.Entry::getValue).collect(Collectors2.toHashSet());
                if (changed.containsKey(source)) {
                    fileMessages.addAll(ambiguitiesByFile.get(source));
                    final boolean valid = !failures.containsKey(source);
                    final boolean success = valid && messagesByFile.get(source, MessageSeverity.ERROR).isEmpty();
                    final IStrategoTerm analyzedAST = astsByFile.get(source);
                    results.add(unitService.analyzeUnit(changed.get(source), new AnalyzeContrib(valid, success, analyzedAST != null, analyzedAST, fileMessages, -1), context));
                } else {
                    try {
                        final FileObject file = context.location().resolveFile(source);
                        updateResults.add(unitService.analyzeUnitUpdate(file, new AnalyzeUpdateData(fileMessages), context));
                    } catch (IOException ex) {
                        logger.error("Could not resolve {} to update messages", source);
                    }
                }
                messagesByFile.remove(source);
            }
            if (!messagesByFile.keySet().isEmpty()) {
                logger.error("Found messages for unanalyzed files {}", messagesByFile.keySet());
            }
            if (debugConfig.analysis() || debugConfig.files() || debugConfig.resolution()) {
                logger.info("Analyzed {} files: {} errors, {} warnings, {} notes.", n, messages.getErrors().size(), messages.getWarnings().size(), messages.getNotes().size());
            }
        }
    } catch (InterruptedException e) {
        logger.debug("Analysis was interrupted.");
    } finally {
        totalTimer.stop();
    }
    final ConstraintDebugData debugData = new ConstraintDebugData(totalTimer.stop(), collectionTimer.total(), solverTimer.total(), finalizeTimer.total());
    if (debugConfig.analysis()) {
        logger.info("{}", debugData);
    }
    return new SpoofaxAnalyzeResults(results, updateResults, context, debugData);
}
Also used : UnitResult(mb.nabl2.spoofax.analysis.UnitResult) ITerm(mb.nabl2.terms.ITerm) ISpoofaxAnalyzeUnit(org.metaborg.spoofax.core.unit.ISpoofaxAnalyzeUnit) IProgress(org.metaborg.util.task.IProgress) Inject(com.google.inject.Inject) IRelation3(mb.nabl2.util.collections.IRelation3) MetaborgException(org.metaborg.core.MetaborgException) HashMultimap(com.google.common.collect.HashMultimap) ICancel(org.metaborg.util.task.ICancel) Map(java.util.Map) ITermVar(mb.nabl2.terms.ITermVar) SolverException(mb.nabl2.solver.SolverException) ISolution(mb.nabl2.solver.ISolution) IStrategoTerm(org.spoofax.interpreter.terms.IStrategoTerm) B(mb.nabl2.terms.build.TermBuild.B) GraphSolution(mb.nabl2.solver.solvers.BaseSolver.GraphSolution) ISpoofaxAnalyzer(org.metaborg.spoofax.core.analysis.ISpoofaxAnalyzer) ISpoofaxParseUnit(org.metaborg.spoofax.core.unit.ISpoofaxParseUnit) Collection(java.util.Collection) ISpoofaxTracingService(org.metaborg.spoofax.core.tracing.ISpoofaxTracingService) IMessageInfo(mb.nabl2.constraints.messages.IMessageInfo) SemiIncrementalMultiFileSolver(mb.nabl2.solver.solvers.SemiIncrementalMultiFileSolver) AnalyzeUpdateData(org.metaborg.spoofax.core.unit.AnalyzeUpdateData) Sets(com.google.common.collect.Sets) FinalResult(mb.nabl2.spoofax.analysis.FinalResult) List(java.util.List) Optionals(org.metaborg.util.optionals.Optionals) Optional(java.util.Optional) LoggerUtils(org.metaborg.util.log.LoggerUtils) Timer(org.metaborg.util.time.Timer) ImmutableBaseSolution(mb.nabl2.solver.solvers.ImmutableBaseSolution) IMultiFileScopeGraphContext(org.metaborg.spoofax.core.context.scopegraph.IMultiFileScopeGraphContext) ITermFactoryService(org.metaborg.spoofax.core.terms.ITermFactoryService) AggregateTimer(org.metaborg.util.time.AggregateTimer) Function1(org.metaborg.util.functions.Function1) AnalysisCommon(org.metaborg.spoofax.core.analysis.AnalysisCommon) ISpoofaxAnalyzeResults(org.metaborg.spoofax.core.analysis.ISpoofaxAnalyzeResults) Multimap(com.google.common.collect.Multimap) Actions(mb.nabl2.spoofax.analysis.Actions) Lists(com.google.common.collect.Lists) ISpoofaxAnalyzeUnitUpdate(org.metaborg.spoofax.core.unit.ISpoofaxAnalyzeUnitUpdate) IMultiFileScopeGraphUnit(org.metaborg.spoofax.core.context.scopegraph.IMultiFileScopeGraphUnit) ISpoofaxUnitService(org.metaborg.spoofax.core.unit.ISpoofaxUnitService) HybridInterpreter(org.strategoxt.HybridInterpreter) PersistentUnifier(mb.nabl2.terms.unification.PersistentUnifier) ILogger(org.metaborg.util.log.ILogger) ImmutableMessageInfo(mb.nabl2.constraints.messages.ImmutableMessageInfo) HashTrieRelation3(mb.nabl2.util.collections.HashTrieRelation3) Messages(mb.nabl2.solver.messages.Messages) IOException(java.io.IOException) MessageKind(mb.nabl2.constraints.messages.MessageKind) Scope(mb.nabl2.scopegraph.terms.Scope) CustomSolution(mb.nabl2.spoofax.analysis.CustomSolution) IMessage(org.metaborg.core.messages.IMessage) FileObject(org.apache.commons.vfs2.FileObject) Maps(com.google.common.collect.Maps) NaBL2DebugConfig(mb.nabl2.config.NaBL2DebugConfig) MessageContent(mb.nabl2.constraints.messages.MessageContent) AnalyzeContrib(org.metaborg.spoofax.core.unit.AnalyzeContrib) IMessages(mb.nabl2.solver.messages.IMessages) SpoofaxAnalyzeResults(org.metaborg.spoofax.core.analysis.SpoofaxAnalyzeResults) Collectors2(org.metaborg.util.stream.Collectors2) FixedPoint(mb.flowspec.runtime.solver.FixedPoint) IResourceService(org.metaborg.core.resource.IResourceService) IStrategoCommon(org.metaborg.spoofax.core.stratego.IStrategoCommon) InitialResult(mb.nabl2.spoofax.analysis.InitialResult) MessageSeverity(org.metaborg.core.messages.MessageSeverity) AnalysisException(org.metaborg.core.analysis.AnalysisException) IStrategoRuntimeService(org.metaborg.spoofax.core.stratego.IStrategoRuntimeService) MessageFactory(org.metaborg.core.messages.MessageFactory) ISpoofaxAnalyzeResults(org.metaborg.spoofax.core.analysis.ISpoofaxAnalyzeResults) SpoofaxAnalyzeResults(org.metaborg.spoofax.core.analysis.SpoofaxAnalyzeResults) ITermVar(mb.nabl2.terms.ITermVar) GraphSolution(mb.nabl2.solver.solvers.BaseSolver.GraphSolution) List(java.util.List) FileObject(org.apache.commons.vfs2.FileObject) InitialResult(mb.nabl2.spoofax.analysis.InitialResult) IProgress(org.metaborg.util.task.IProgress) Optional(java.util.Optional) AnalyzeUpdateData(org.metaborg.spoofax.core.unit.AnalyzeUpdateData) FinalResult(mb.nabl2.spoofax.analysis.FinalResult) IMessage(org.metaborg.core.messages.IMessage) Function1(org.metaborg.util.functions.Function1) ISolution(mb.nabl2.solver.ISolution) IMultiFileScopeGraphUnit(org.metaborg.spoofax.core.context.scopegraph.IMultiFileScopeGraphUnit) CustomSolution(mb.nabl2.spoofax.analysis.CustomSolution) NaBL2DebugConfig(mb.nabl2.config.NaBL2DebugConfig) Map(java.util.Map) IStrategoTerm(org.spoofax.interpreter.terms.IStrategoTerm) ISpoofaxAnalyzeUnitUpdate(org.metaborg.spoofax.core.unit.ISpoofaxAnalyzeUnitUpdate) SemiIncrementalMultiFileSolver(mb.nabl2.solver.solvers.SemiIncrementalMultiFileSolver) MetaborgException(org.metaborg.core.MetaborgException) UnitResult(mb.nabl2.spoofax.analysis.UnitResult) AggregateTimer(org.metaborg.util.time.AggregateTimer) IMessageInfo(mb.nabl2.constraints.messages.IMessageInfo) AnalyzeContrib(org.metaborg.spoofax.core.unit.AnalyzeContrib) FixedPoint(mb.flowspec.runtime.solver.FixedPoint) ISpoofaxAnalyzeUnit(org.metaborg.spoofax.core.unit.ISpoofaxAnalyzeUnit) ISpoofaxParseUnit(org.metaborg.spoofax.core.unit.ISpoofaxParseUnit) IMessages(mb.nabl2.solver.messages.IMessages) IOException(java.io.IOException) FixedPoint(mb.flowspec.runtime.solver.FixedPoint) Timer(org.metaborg.util.time.Timer) AggregateTimer(org.metaborg.util.time.AggregateTimer) Scope(mb.nabl2.scopegraph.terms.Scope) AnalysisException(org.metaborg.core.analysis.AnalysisException) ITerm(mb.nabl2.terms.ITerm) SolverException(mb.nabl2.solver.SolverException)

Example 23 with IStrategoTerm

use of org.spoofax.interpreter.terms.IStrategoTerm 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);
}
Also used : UnitResult(mb.nabl2.spoofax.analysis.UnitResult) ITerm(mb.nabl2.terms.ITerm) ISpoofaxAnalyzeUnit(org.metaborg.spoofax.core.unit.ISpoofaxAnalyzeUnit) IProgress(org.metaborg.util.task.IProgress) Inject(com.google.inject.Inject) IConstraint(mb.nabl2.constraints.IConstraint) MetaborgException(org.metaborg.core.MetaborgException) ICancel(org.metaborg.util.task.ICancel) Map(java.util.Map) SolverException(mb.nabl2.solver.SolverException) ISolution(mb.nabl2.solver.ISolution) IStrategoTerm(org.spoofax.interpreter.terms.IStrategoTerm) B(mb.nabl2.terms.build.TermBuild.B) GraphSolution(mb.nabl2.solver.solvers.BaseSolver.GraphSolution) ISpoofaxAnalyzer(org.metaborg.spoofax.core.analysis.ISpoofaxAnalyzer) ISpoofaxParseUnit(org.metaborg.spoofax.core.unit.ISpoofaxParseUnit) Collection(java.util.Collection) ISpoofaxTracingService(org.metaborg.spoofax.core.tracing.ISpoofaxTracingService) Set(java.util.Set) Sets(com.google.common.collect.Sets) Iterables2(org.metaborg.util.iterators.Iterables2) FinalResult(mb.nabl2.spoofax.analysis.FinalResult) Optional(java.util.Optional) LoggerUtils(org.metaborg.util.log.LoggerUtils) ImmutableBaseSolution(mb.nabl2.solver.solvers.ImmutableBaseSolution) ITermFactoryService(org.metaborg.spoofax.core.terms.ITermFactoryService) Iterables(com.google.common.collect.Iterables) Function1(org.metaborg.util.functions.Function1) AnalysisCommon(org.metaborg.spoofax.core.analysis.AnalysisCommon) ISpoofaxAnalyzeResults(org.metaborg.spoofax.core.analysis.ISpoofaxAnalyzeResults) ISingleFileScopeGraphContext(org.metaborg.spoofax.core.context.scopegraph.ISingleFileScopeGraphContext) Actions(mb.nabl2.spoofax.analysis.Actions) Lists(com.google.common.collect.Lists) ISpoofaxUnitService(org.metaborg.spoofax.core.unit.ISpoofaxUnitService) HybridInterpreter(org.strategoxt.HybridInterpreter) SingleFileSolver(mb.nabl2.solver.solvers.SingleFileSolver) PersistentUnifier(mb.nabl2.terms.unification.PersistentUnifier) ILogger(org.metaborg.util.log.ILogger) Messages(mb.nabl2.solver.messages.Messages) ISingleFileScopeGraphUnit(org.metaborg.spoofax.core.context.scopegraph.ISingleFileScopeGraphUnit) CustomSolution(mb.nabl2.spoofax.analysis.CustomSolution) IMessage(org.metaborg.core.messages.IMessage) NaBL2DebugConfig(mb.nabl2.config.NaBL2DebugConfig) AnalyzeContrib(org.metaborg.spoofax.core.unit.AnalyzeContrib) IMessages(mb.nabl2.solver.messages.IMessages) SpoofaxAnalyzeResults(org.metaborg.spoofax.core.analysis.SpoofaxAnalyzeResults) FixedPoint(mb.flowspec.runtime.solver.FixedPoint) IResourceService(org.metaborg.core.resource.IResourceService) IStrategoCommon(org.metaborg.spoofax.core.stratego.IStrategoCommon) InitialResult(mb.nabl2.spoofax.analysis.InitialResult) Collections(java.util.Collections) AnalysisException(org.metaborg.core.analysis.AnalysisException) IStrategoRuntimeService(org.metaborg.spoofax.core.stratego.IStrategoRuntimeService) MessageFactory(org.metaborg.core.messages.MessageFactory) ISpoofaxAnalyzeResults(org.metaborg.spoofax.core.analysis.ISpoofaxAnalyzeResults) SpoofaxAnalyzeResults(org.metaborg.spoofax.core.analysis.SpoofaxAnalyzeResults) ISingleFileScopeGraphUnit(org.metaborg.spoofax.core.context.scopegraph.ISingleFileScopeGraphUnit) Set(java.util.Set) IStrategoTerm(org.spoofax.interpreter.terms.IStrategoTerm) MetaborgException(org.metaborg.core.MetaborgException) UnitResult(mb.nabl2.spoofax.analysis.UnitResult) AnalyzeContrib(org.metaborg.spoofax.core.unit.AnalyzeContrib) SingleFileSolver(mb.nabl2.solver.solvers.SingleFileSolver) FixedPoint(mb.flowspec.runtime.solver.FixedPoint) GraphSolution(mb.nabl2.solver.solvers.BaseSolver.GraphSolution) InitialResult(mb.nabl2.spoofax.analysis.InitialResult) ISpoofaxAnalyzeUnit(org.metaborg.spoofax.core.unit.ISpoofaxAnalyzeUnit) ISpoofaxParseUnit(org.metaborg.spoofax.core.unit.ISpoofaxParseUnit) IProgress(org.metaborg.util.task.IProgress) FinalResult(mb.nabl2.spoofax.analysis.FinalResult) IMessages(mb.nabl2.solver.messages.IMessages) Function1(org.metaborg.util.functions.Function1) ISolution(mb.nabl2.solver.ISolution) IConstraint(mb.nabl2.constraints.IConstraint) FixedPoint(mb.flowspec.runtime.solver.FixedPoint) CustomSolution(mb.nabl2.spoofax.analysis.CustomSolution) NaBL2DebugConfig(mb.nabl2.config.NaBL2DebugConfig) AnalysisException(org.metaborg.core.analysis.AnalysisException) ITerm(mb.nabl2.terms.ITerm) SolverException(mb.nabl2.solver.SolverException) Map(java.util.Map)

Example 24 with IStrategoTerm

use of org.spoofax.interpreter.terms.IStrategoTerm in project spoofax by metaborg.

the class StrategoAnalyzer method result.

private ISpoofaxAnalyzeUnit result(IStrategoTerm result, ISpoofaxParseUnit input, IContext context, long duration) {
    final IStrategoTerm ast = result.getSubterm(0);
    final FileObject source = input.source();
    final Collection<IMessage> errors = analysisCommon.messages(source, MessageSeverity.ERROR, result.getSubterm(1));
    final Collection<IMessage> warnings = analysisCommon.messages(source, MessageSeverity.WARNING, result.getSubterm(2));
    final Collection<IMessage> notes = analysisCommon.messages(source, MessageSeverity.NOTE, result.getSubterm(3));
    final Collection<IMessage> ambiguities = analysisCommon.ambiguityMessages(source, ast);
    final Collection<IMessage> messages = Lists.newArrayListWithCapacity(errors.size() + warnings.size() + notes.size() + ambiguities.size());
    messages.addAll(errors);
    messages.addAll(warnings);
    messages.addAll(notes);
    messages.addAll(ambiguities);
    return unitService.analyzeUnit(input, new AnalyzeContrib(true, errors.isEmpty(), true, ast, messages, duration), context);
}
Also used : IStrategoTerm(org.spoofax.interpreter.terms.IStrategoTerm) IMessage(org.metaborg.core.messages.IMessage) FileObject(org.apache.commons.vfs2.FileObject) AnalyzeContrib(org.metaborg.spoofax.core.unit.AnalyzeContrib)

Example 25 with IStrategoTerm

use of org.spoofax.interpreter.terms.IStrategoTerm in project spoofax by metaborg.

the class TaskEngineAnalyzer method result.

@Nullable
private ISpoofaxAnalyzeUnit result(IStrategoTerm result, Map<String, ISpoofaxParseUnit> inputsPerSource, IContext context, long duration) {
    final String sourceString = Tools.asJavaString(result.getSubterm(0));
    final FileObject source;
    try {
        source = resourceService.resolve(sourceString);
    } catch (MetaborgRuntimeException e) {
        logger.error("Cannot find original source for {}, skipping result", e, sourceString);
        return null;
    }
    final ISpoofaxParseUnit input = inputsPerSource.get(sourceString);
    if (input == null) {
        logger.error("Cannot find input parse result for {}, skipping result", sourceString);
        return null;
    }
    final IStrategoTerm ast = result.getSubterm(2);
    final Collection<IMessage> errors = analysisCommon.messages(source, MessageSeverity.ERROR, result.getSubterm(3));
    final Collection<IMessage> warnings = analysisCommon.messages(source, MessageSeverity.WARNING, result.getSubterm(4));
    final Collection<IMessage> notes = analysisCommon.messages(source, MessageSeverity.NOTE, result.getSubterm(5));
    final Collection<IMessage> ambiguities = analysisCommon.ambiguityMessages(source, ast);
    final Collection<IMessage> messages = Lists.newArrayListWithCapacity(errors.size() + warnings.size() + notes.size() + ambiguities.size());
    messages.addAll(errors);
    messages.addAll(warnings);
    messages.addAll(notes);
    messages.addAll(ambiguities);
    return unitService.analyzeUnit(input, new AnalyzeContrib(true, errors.isEmpty(), true, ast, messages, duration), context);
}
Also used : ISpoofaxParseUnit(org.metaborg.spoofax.core.unit.ISpoofaxParseUnit) MetaborgRuntimeException(org.metaborg.core.MetaborgRuntimeException) IStrategoTerm(org.spoofax.interpreter.terms.IStrategoTerm) IMessage(org.metaborg.core.messages.IMessage) IStrategoString(org.spoofax.interpreter.terms.IStrategoString) FileObject(org.apache.commons.vfs2.FileObject) AnalyzeContrib(org.metaborg.spoofax.core.unit.AnalyzeContrib) Nullable(javax.annotation.Nullable)

Aggregations

IStrategoTerm (org.spoofax.interpreter.terms.IStrategoTerm)82 IStrategoString (org.spoofax.interpreter.terms.IStrategoString)31 FileObject (org.apache.commons.vfs2.FileObject)27 IStrategoAppl (org.spoofax.interpreter.terms.IStrategoAppl)25 MetaborgException (org.metaborg.core.MetaborgException)19 ITermFactory (org.spoofax.interpreter.terms.ITermFactory)17 HybridInterpreter (org.strategoxt.HybridInterpreter)17 IStrategoList (org.spoofax.interpreter.terms.IStrategoList)16 ILanguageImpl (org.metaborg.core.language.ILanguageImpl)15 Nullable (javax.annotation.Nullable)14 ISourceRegion (org.metaborg.core.source.ISourceRegion)12 ICompletion (org.metaborg.core.completion.ICompletion)11 IStrategoTuple (org.spoofax.interpreter.terms.IStrategoTuple)10 IOException (java.io.IOException)9 IProject (org.metaborg.core.project.IProject)9 IMessage (org.metaborg.core.messages.IMessage)8 IToken (org.spoofax.jsglr.client.imploder.IToken)8 IContext (org.metaborg.core.context.IContext)7 ILanguageComponent (org.metaborg.core.language.ILanguageComponent)7 ListImploderAttachment (org.spoofax.jsglr.client.imploder.ListImploderAttachment)7