Skip to content

Commit

Permalink
Only insert results of actual dependencies, not dependencies that are…
Browse files Browse the repository at this point in the history
… used to disable the task.

When cyclic insertion occurs, insert a CYCLIC_INSERTION(task-id) term instead of silently failing.
Fix fixpoint evaluation not handling task without results.
  • Loading branch information
Gohla committed Dec 12, 2013
1 parent f0cea93 commit 2f1e0a5
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 38 deletions.
Expand Up @@ -35,17 +35,25 @@ public final class TaskInsertion {
public static P2<? extends Iterable<IStrategoTerm>, Boolean> taskCombinations(ITermFactory factory,
ITaskEngine taskEngine, IContext context, Strategy collect, Strategy insert, IStrategoTerm taskID, Task task) {
final IStrategoTerm instruction = task.instruction;
final boolean isCombinator = task.isCombinator;
final Iterable<IStrategoTerm> resultIDs = taskEngine.getDependencies(taskID);
final Iterable<IStrategoTerm> actualDependencies = getResultIDs(context, collect, instruction);
final Iterable<IStrategoTerm> allDependencies = taskEngine.getDependencies(taskID);

if(Iterables.isEmpty(resultIDs)) {
if(Iterables.isEmpty(allDependencies)) {
return P.p(new SingletonIterable<IStrategoTerm>(instruction), false);
} else if(!isCombinator) {
return insertResultCombinations(taskEngine, context, collect, insert, instruction, resultIDs);
} else if(!task.isCombinator) {
for(IStrategoTerm dependencyID : allDependencies) {
final Task dependency = taskEngine.getTask(dependencyID);
if(dependency.failed() || !dependency.hasResults()) {
return null; // If a dependency does not have any results, the task cannot be executed.
}
}

return insertResultCombinations(taskEngine, context, collect, insert, instruction, actualDependencies,
new SingletonIterable<IStrategoTerm>(taskID));
} else {
return P.p(
new SingletonIterable<IStrategoTerm>(insertResultLists(factory, taskEngine, context, insert,
instruction, resultIDs)), false);
instruction, actualDependencies)), false);
}
}

Expand All @@ -68,8 +76,9 @@ public static P2<? extends Iterable<IStrategoTerm>, Boolean> taskCombinations(IT
* it contains task IDs of dynamic task dependencies.
*/
public static P2<? extends Iterable<IStrategoTerm>, Boolean> insertResultCombinations(ITaskEngine taskEngine,
IContext context, Strategy collect, Strategy insert, IStrategoTerm term, Iterable<IStrategoTerm> dependencies) {
final Set<IStrategoTerm> seen = Sets.newHashSet();
IContext context, Strategy collect, Strategy insert, IStrategoTerm term, Iterable<IStrategoTerm> dependencies,
Iterable<IStrategoTerm> initialSeen) {
final Set<IStrategoTerm> seen = Sets.newHashSet(initialSeen);
final Either<Multimap<IStrategoTerm, IStrategoTerm>, ? extends Iterable<IStrategoTerm>> result =
createResultMapping(taskEngine, context, collect, insert, dependencies, seen);

Expand All @@ -82,6 +91,35 @@ public static P2<? extends Iterable<IStrategoTerm>, Boolean> insertResultCombina
}
}

private static Either<Multimap<IStrategoTerm, IStrategoTerm>, ? extends Iterable<IStrategoTerm>>
createResultMapping(ITaskEngine taskEngine, IContext context, Strategy collect, Strategy insert,
Iterable<IStrategoTerm> resultIDs, Set<IStrategoTerm> seen) {
final Multimap<IStrategoTerm, IStrategoTerm> resultsMap = ArrayListMultimap.create();
final Collection<IStrategoTerm> dynamicDependencies = Lists.newLinkedList();

for(final IStrategoTerm resultID : resultIDs) {
if(seen.contains(resultID)) {
resultsMap.put(resultID, createCycleTerm(context.getFactory(), resultID));
continue;
}

final Either<Collection<IStrategoTerm>, ? extends Iterable<IStrategoTerm>> results =
getResultsOf(taskEngine, context, collect, insert, resultID, Sets.newHashSet(seen));

if(results == null) {
return null;
} else if(results.isRight()) {
Iterables.addAll(dynamicDependencies, results.right().value());
} else {
resultsMap.putAll(resultID, results.left().value());
}
}

if(dynamicDependencies.isEmpty())
return Either.left(resultsMap);
else
return Either.right(dynamicDependencies);
}

private static Either<Collection<IStrategoTerm>, ? extends Iterable<IStrategoTerm>> getResultsOf(
ITaskEngine taskEngine, IContext context, Strategy collect, Strategy insert, IStrategoTerm taskID,
Expand Down Expand Up @@ -124,33 +162,6 @@ public static P2<? extends Iterable<IStrategoTerm>, Boolean> insertResultCombina
return Either.right(dynamicDependencies);
}

private static Either<Multimap<IStrategoTerm, IStrategoTerm>, ? extends Iterable<IStrategoTerm>>
createResultMapping(ITaskEngine taskEngine, IContext context, Strategy collect, Strategy insert,
Iterable<IStrategoTerm> resultIDs, Set<IStrategoTerm> seen) {
final Multimap<IStrategoTerm, IStrategoTerm> resultsMap = ArrayListMultimap.create();
final Collection<IStrategoTerm> dynamicDependencies = Lists.newLinkedList();

for(final IStrategoTerm resultID : resultIDs) {
if(seen.contains(resultID))
continue;
final Either<Collection<IStrategoTerm>, ? extends Iterable<IStrategoTerm>> results =
getResultsOf(taskEngine, context, collect, insert, resultID, Sets.newHashSet(seen));

if(results == null) {
return null;
} else if(results.isRight()) {
Iterables.addAll(dynamicDependencies, results.right().value());
} else {
resultsMap.putAll(resultID, results.left().value());
}
}

if(dynamicDependencies.isEmpty())
return Either.left(resultsMap);
else
return Either.right(dynamicDependencies);
}

private static Collection<IStrategoTerm> insertCarthesianProduct(IContext context, Strategy insert,
IStrategoTerm term, Multimap<IStrategoTerm, IStrategoTerm> resultMapping) {
final Collection<StrategoHashMap> resultCombinations = cartesianProduct(resultMapping);
Expand Down Expand Up @@ -215,4 +226,8 @@ private static IStrategoTerm insertResults(IContext context, Strategy insertResu
private static IStrategoAppl createHashtableTerm(ITermFactory factory, StrategoHashMap hashMap) {
return factory.makeAppl(factory.makeConstructor("Hashtable", 1), hashMap);
}

private static IStrategoAppl createCycleTerm(ITermFactory factory, IStrategoTerm taskID) {
return factory.makeAppl(factory.makeConstructor("CYCLIC_INSERTION", 1), taskID);
}
}
Expand Up @@ -205,13 +205,13 @@ public IStrategoTuple evaluate(Set<IStrategoTerm> scheduled, IContext context, S

// TODO: this assumes that no results and failure means the same, is that correct?
if(values.get(taskID).isEmpty()) {
if(task.failed()) {
if(task.failed() || !task.hasResults()) {
continue;
} else {
done = false;
break;
}
} else if(task.failed()) {
} else if(task.failed() || !task.hasResults()) {
done = false;
break;
}
Expand Down
Expand Up @@ -3,6 +3,7 @@
import org.metaborg.runtime.task.ITaskEngine;
import org.metaborg.runtime.task.TaskInsertion;
import org.metaborg.runtime.task.TaskManager;
import org.metaborg.runtime.task.util.EmptyIterable;
import org.metaborg.runtime.task.util.InvokeStrategy;
import org.metaborg.runtime.task.util.TermTools;
import org.spoofax.interpreter.core.IContext;
Expand Down Expand Up @@ -32,7 +33,8 @@ public boolean call(IContext env, Strategy[] svars, IStrategoTerm[] tvars) throw

final IStrategoTerm resultIDs = InvokeStrategy.invoke(env, collect, term);
final P2<? extends Iterable<IStrategoTerm>, Boolean> result =
TaskInsertion.insertResultCombinations(taskEngine, env, collect, insert, term, resultIDs);
TaskInsertion.insertResultCombinations(taskEngine, env, collect, insert, term, resultIDs,
new EmptyIterable<IStrategoTerm>());
if(result == null || result._1() == null)
return false; // No combinations could be constructed because a dependency failed or had no results.
final IStrategoList resultList = TermTools.makeList(factory, result._1());
Expand Down

0 comments on commit 2f1e0a5

Please sign in to comment.