use of mb.statix.generator.nodes.SearchNode in project nabl by metaborg.
the class StatixGenerate method logTrace.
@SuppressWarnings("unused")
private static void logTrace(ILogger log, Level lvl, SearchElement node, int maxDepth, Function1<SearchState, String> pp) {
if (node instanceof SearchNodes) {
SearchNodes<?> nodes = (SearchNodes<?>) node;
log.log(lvl, " * {}", nodes.desc());
logTrace(log, lvl, nodes.parent(), maxDepth, pp);
} else {
SearchNode<?> traceNode = (SearchNode<?>) node;
int depth = 0;
do {
log.log(lvl, " * [{}] {}", traceNode.id(), traceNode.desc());
if ((depth++ == 0 || (TRACE && depth <= maxDepth)) && traceNode.output() instanceof SearchState) {
SearchState state = (SearchState) ((SearchNode<?>) traceNode).output();
state.print(ln -> log.log(lvl, " {}", ln), (t, u) -> u.toString(t));
}
} while ((traceNode = traceNode.parent()) != null);
log.log(lvl, " # depth {}", depth);
}
}
use of mb.statix.generator.nodes.SearchNode in project nabl by metaborg.
the class StatixGenerate method run.
public void run(String file) throws MetaborgException, InterruptedException {
final FileObject resource = STX.S.resolve(file);
TermFormatter tf = ITerm::toString;
try {
final ILanguageImpl lang = STX.cli.loadLanguage(STX.project.location());
final IContext context = STX.S.contextService.get(resource, STX.project, lang);
tf = StatixGenerator.pretty(STX.S, context, "pp-generated");
} catch (MetaborgException e) {
// ignore
}
final TermFormatter _tf = tf;
final Function1<SearchState, String> pretty = (s) -> _tf.format(project(VAR, s));
final DescriptiveStatistics hitStats = new DescriptiveStatistics();
final DescriptiveStatistics missStats = new DescriptiveStatistics();
final StreamProgressPrinter progress = new StreamProgressPrinter(System.err, 80, out -> {
long hits = hitStats.getN();
long all = hits + missStats.getN();
out.println(" " + hits + "/" + all + " " + summary(hitStats));
});
final SearchLogger<SearchState, SearchState> searchLog = new SearchLogger<SearchState, SearchState>() {
@Override
public void init(long seed, SearchStrategy<SearchState, SearchState> strategy, Iterable<IConstraint> constraints) {
log.info("seed {}", seed);
log.info("strategy {}", strategy);
log.info("constraints {}", constraints);
}
@Override
public void success(SearchNode<SearchState> n) {
progress.step('+');
addSize(n.output(), hitStats);
logSuccess(log, Level.Debug, n, pretty);
}
@Override
public void failure(SearchNodes<?> nodes) {
progress.step('.');
SearchNode<?> parentNode = nodes.parent();
if (parentNode != null && parentNode.output() instanceof SearchState) {
addSize((SearchState) parentNode.output(), missStats);
}
logFailure(log, Level.Debug, nodes, pretty);
}
private void addSize(SearchState s, DescriptiveStatistics stats) {
s.state().unifier().size(project(VAR, s)).ifFinite(size -> {
stats.addValue(size.doubleValue());
});
}
};
final StatixGenerator statixGen = new StatixGenerator(STX.S, STX.context, resource);
// Paret.addFragments(statixGen.spec());
final Spec spec = statixGen.spec();
final RandomTermGenerator rtg = new RandomTermGenerator(spec, statixGen.constraint(), new Paret(spec).search(), searchLog);
final Stream<SearchState> resultStream = rtg.apply().nodes().map(sn -> {
searchLog.success(sn);
return sn.output();
});
log.info("Generating random terms.");
final List<SearchState> results = Lists.newArrayList(resultStream.limit(COUNT).iterator());
progress.done();
results.forEach(s -> {
System.out.println(pretty.apply(s));
});
log.info("Generated {} random terms.", results.size());
logStatsInfo("hits", hitStats);
logStatsInfo("misses", missStats);
}
use of mb.statix.generator.nodes.SearchNode in project nabl by metaborg.
the class Fix method doApply.
@Override
protected SearchNodes<SearchState> doApply(SearchContext ctx, SearchNode<SearchState> node) {
final AtomicInteger failureCount = new AtomicInteger();
final Deque<Iterator<SearchNode<SearchState>>> stack = new LinkedList<>();
final Action1<SearchNodes<SearchState>> push = ns -> {
Iterator<SearchNode<SearchState>> it = ns.nodes().iterator();
if (it.hasNext()) {
stack.push(it);
failureCount.set(0);
} else {
ctx.failure(ns);
failureCount.incrementAndGet();
}
};
final SearchNodes<SearchState> initNodes = infer.apply(ctx, node);
push.apply(initNodes);
final Stream<SearchNode<SearchState>> fixNodes = StreamUtil.generate(() -> {
while (!stack.isEmpty()) {
final Iterator<SearchNode<SearchState>> nodes = stack.peek();
if (!nodes.hasNext()) {
stack.pop();
continue;
}
final SearchNode<SearchState> next = nodes.next();
if (Streams.stream(next.output().constraintsAndDelays()).allMatch(c -> (c instanceof CUser && done.test((CUser) c)))) {
return Optional.of(next);
}
final SearchNodes<SearchState> nextNodes = searchAndInfer.apply(ctx, next);
push.apply(nextNodes);
if (maxConsecutiveFailures >= 0 && failureCount.get() >= maxConsecutiveFailures) {
// we're done here
stack.clear();
}
}
return Optional.empty();
});
return SearchNodes.of(node, () -> "fix(???)", fixNodes);
}
use of mb.statix.generator.nodes.SearchNode in project nabl by metaborg.
the class Seq method doApply.
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public SearchNodes<O> doApply(SearchContext ctx, SearchNode<I> node) {
Stream<SearchNode> nodes = Stream.of(node);
Deque<Function0<String>> descs = Queues.newArrayDeque();
for (SearchStrategy s : ss) {
nodes = flatMap(nodes, n -> {
final SearchNodes<?> sn = s.apply(ctx, n);
descs.push(sn::desc);
return sn.nodes();
});
}
final Function0<String> desc = () -> descs.stream().map(Function0::apply).collect(Collectors.joining(" . ", "(", ")"));
return SearchNodes.of(node, desc, (Stream) nodes);
}
use of mb.statix.generator.nodes.SearchNode in project nabl by metaborg.
the class CanResolve method doApply.
@Override
protected SearchNodes<FocusedSearchState<CResolveQuery>> doApply(SearchContext ctx, SearchNode<FocusedSearchState<CResolveQuery>> node) {
FocusedSearchState<CResolveQuery> input = node.output();
final IState.Immutable state = input.state();
final IUniDisunifier unifier = state.unifier();
final CResolveQuery query = input.focus();
final Scope scope = Scope.matcher().match(query.scopeTerm(), unifier).orElse(null);
if (scope == null) {
return SearchNodes.failure(node, this.toString() + "[no scope]");
}
final Boolean isAlways;
try {
isAlways = query.min().getDataEquiv().isAlways().orElse(null);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (isAlways == null) {
return SearchNodes.failure(node, this.toString() + "[cannot decide data equivalence]");
}
final ICompleteness.Immutable completeness = input.completeness();
final LabelWF<ITerm> labelWF = RegExpLabelWF.of(query.filter().getLabelWF());
final LabelOrder<ITerm> labelOrd = new RelationLabelOrder<>(query.min().getLabelOrder());
final DataWF<ITerm, CEqual> dataWF = new ResolveDataWF(state, completeness, query.filter().getDataWF(), query);
final Predicate2<Scope, EdgeOrData<ITerm>> isComplete = (s, l) -> completeness.isComplete(s, l, state.unifier());
// @formatter:off
final NameResolution<Scope, ITerm, ITerm, CEqual> nameResolution = new NameResolution<>(ctx.spec(), state.scopeGraph(), ctx.spec().allLabels(), labelWF, labelOrd, dataWF, isAlways, isComplete);
try {
nameResolution.resolve(scope, () -> false);
} catch (ResolutionException e) {
return SearchNodes.failure(node, this.toString() + "[cannot resolve]");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return SearchNodes.of(node, this::toString, node);
}
Aggregations