/** * Creates a new Build step based on this builder but with a subsequent producer inserted after * the original protocol producer. * * @param function creation of the protocol producer - will be lazy evaluated */ public <NextOutputT> BuildStep<OutputT, BuilderT, NextOutputT> seq( FrescoLambda<OutputT, BuilderT, NextOutputT> function) { BuildStep<OutputT, BuilderT, NextOutputT> localChild = new BuildStep<>(new BuildStepSingle<>(function, false)); this.next = localChild; return localChild; }
@Override public boolean hasNextProtocols() { next(); return !isDone; }
/** * Creates a looping Build step based on this builder but with a subsequent producer inserted * after the original protocol producer. This simulates the while functionality in java. * * @param test the predicate - as long as it evaluates to true, the function will be evaluated * @param function creation of the protocol producer for a single loop step - will be * evaluated for each iteration */ public BuildStep<OutputT, BuilderT, OutputT> whileLoop( Predicate<OutputT> test, FrescoLambda<OutputT, BuilderT, OutputT> function) { BuildStep<OutputT, BuilderT, OutputT> localChild = new BuildStep<>(new BuildStepLooping<>(test, function)); this.next = localChild; return localChild; }
@Override public DRes<BigInteger> buildComputation(ProtocolBuilderNumeric producer) { return producer.seq(inputApp).seq((seq, inputs) -> { DRes<SInt> sum = null; for (SInt input : inputs) { if (sum == null) { sum = input; } else { sum = seq.numeric().add(sum, input); } } return seq.numeric().open(sum); }); } }
@Override public void test() { // define functionality to be tested Application<List<Integer>, ProtocolBuilderNumeric> testApplication = root -> root .seq(seq -> { // initiate loop return new IterationState(0, new ArrayList<>()); }).whileLoop( // iterate (state) -> state.round < numIterations, (seq, state) -> { List<Integer> roundsSoFar = state.rounds; roundsSoFar.add(state.round); return new IterationState(state.round + 1, roundsSoFar); }).seq((seq, state) -> () -> state.rounds); List<Integer> actual = runApplication(testApplication); Assert.assertEquals(expected, actual); } };
/** * Creates a new Build step based on this builder but with a nested sequential protocol * producer inserted into the original protocol producer. * * @param function creation of the protocol producer - will be lazy evaluated */ public <R> BuildStep<Void, BuilderT, R> seq(Computation<R, BuilderT> function) { FrescoLambda<Void, BuilderT, R> innerBuilder = (inner, ignored) -> function.buildComputation(inner); BuildStep<Void, BuilderT, R> builder = new BuildStep<>(new BuildStepSingle<>(innerBuilder, false)); createAndAppend(new LazyProtocolProducerDecorator(() -> builder.createProducer(null, factory))); return builder; }
/** * Creates a new Build step based on this builder but with a nested parallel protocol * producer inserted into the original protocol producer. * * @param f of the protocol producer - will be lazy evaluated */ public <R> BuildStep<Void, BuilderT, R> par(ComputationParallel<R, BuilderT> f) { FrescoLambda<Void, BuilderT, R> innerBuilder = (inner, ignored) -> f.buildComputation(inner); BuildStep<Void, BuilderT, R> builder = new BuildStep<>(new BuildStepSingle<>(innerBuilder, true)); createAndAppend(new LazyProtocolProducerDecorator(() -> builder.createProducer(null, factory))); return builder; } }
@Test(expected = IllegalStateException.class) public void build() throws Exception { ProtocolBuilderImpl<BuilderTestClass> protocolBuilder = new BuilderTestClass(); protocolBuilder.append(null); protocolBuilder.build(); protocolBuilder.append(null); }
public Pair<ProtocolProducer, DRes<OutputT>> createNextStep( InputT input, BuilderFactory<BuilderT> factory, BuildStep<OutputT, BuilderT, ?> next) { BuilderT builder = createBuilder(factory); DRes<OutputT> output = function.buildComputation(builder, input); if (next != null) { List<ProtocolProducer> protocols = Arrays.asList( builder.build(), new LazyProtocolProducerDecorator(() -> { OutputT out = null; if (output != null) { out = output.out(); } return next.createProducer(out, factory); })); SequentialProtocolProducer protocolProducer = new SequentialProtocolProducer(protocols); return new Pair<>(protocolProducer, null); } else { return new Pair<>(builder.build(), output); } }
private void updateToNextProducer(InputT input) { if (doneWithOwn) { isDone = true; } else { if (predicate.test(input)) { BuilderT builder = factory.createSequential(); currentResult = function.buildComputation(builder, input); currentProducer = builder.build(); } else { doneWithOwn = true; if (next != null) { currentProducer = next.createProducer(input, factory); next = null; } } } }
/** * Creates a new Build step based on this builder but with a subsequent producer inserted after * the original protocol producer. The two producer will be evalueted in parallel, however each * of the two functions will be evaluated in sequence. * * @param firstFunction of the first protocol producer - will be lazy evaluated * @param secondFunction of the second protocol producer - will be lazy evaluated */ public <FirstOutputT, SecondOutputT> BuildStep<OutputT, BuilderT, Pair<FirstOutputT, SecondOutputT>> pairInPar( FrescoLambda<OutputT, BuilderT, FirstOutputT> firstFunction, FrescoLambda<OutputT, BuilderT, SecondOutputT> secondFunction) { BuildStep<OutputT, BuilderT, Pair<FirstOutputT, SecondOutputT>> localChild = new BuildStep<>( new BuildStepSingle<>( (BuilderT builder, OutputT output1) -> { DRes<FirstOutputT> firstOutput = builder.seq( seq -> firstFunction.buildComputation(seq, output1)); DRes<SecondOutputT> secondOutput = builder.seq( seq -> secondFunction.buildComputation(seq, output1)); return () -> new Pair<>(firstOutput.out(), secondOutput.out()); }, true) ); this.next = localChild; return localChild; }
@Test public void test_while_multiple_iterations() { runTest(new TestWhileLoop<>(10, Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)), new TestParameters()); } }
private void next() { while (!isDone && !currentProducer.hasNextProtocols()) { updateToNextProducer(out()); } }
LoopProtocolProducer( BuilderFactory<BuilderT> factory, InputT input, Predicate<InputT> predicate, FrescoLambda<InputT, BuilderT, InputT> function, BuildStep<InputT, BuilderT, ?> next) { this.factory = factory; this.predicate = predicate; this.function = function; this.next = next; isDone = false; doneWithOwn = false; currentProducer = null; currentResult = () -> input; updateToNextProducer(input); }
public Pair<ProtocolProducer, DRes<InputT>> createNextStep( InputT input, BuilderFactory<BuilderT> factory, BuildStep<InputT, BuilderT, ?> next) { LoopProtocolProducer<BuilderT, InputT> loopProtocolProducer = new LoopProtocolProducer<>(factory, input, predicate, function, next); return new Pair<>(loopProtocolProducer, loopProtocolProducer); }
/** * Appends a concrete, native protocol to the list of producers - useful for the native protocol * factories that needs to be builders. * * @param nativeProtocol the native protocol to add * @param <T> the result type of the native protocol * @return a computation that resolves to the result of the native protocol once evaluated */ public <T> DRes<T> append(NativeProtocol<T, ?> nativeProtocol) { SingleProtocolProducer<T> producer = new SingleProtocolProducer<>(nativeProtocol); createAndAppend(producer); return producer; }
ProtocolProducer createProducer( InputT input, BuilderFactory<BuilderT> factory) { Pair<ProtocolProducer, DRes<OutputT>> nextStep = stepBuilder.createNextStep(input, factory, next); stepBuilder = null; output = nextStep.getSecond(); return nextStep.getFirst(); } }
@Test public void test_while_no_iteration() { runTest(new TestWhileLoop<>(0, Collections.emptyList()), new TestParameters()); }
/** * Creates a new Build step based on this builder but with a subsequent parallel producer inserted * after the original protocol producer. * * @param function of the protocol producer - will be lazy evaluated */ public <NextOutputT> BuildStep<OutputT, BuilderT, NextOutputT> par( FrescoLambdaParallel<OutputT, BuilderT, NextOutputT> function) { BuildStep<OutputT, BuilderT, NextOutputT> localChild = new BuildStep<>(new BuildStepSingle<>(function, true)); this.next = localChild; return localChild; }
@Test public void test_while_single_iteration() { runTest(new TestWhileLoop<>(1, Collections.singletonList(0)), new TestParameters()); }