Coverage Summary for Class: ForEach (it.unibo.tuprolog.argumentation.core.primitives.utils)

Class Class, % Method, % Branch, % Line, % Instruction, %
ForEach 100% (1/1) 100% (2/2) 66.7% (4/6) 91.7% (11/12) 90.2% (83/92)


 package it.unibo.tuprolog.argumentation.core.primitives.utils
 
 import it.unibo.tuprolog.argumentation.core.runtime.Arg2pUnificator
 import it.unibo.tuprolog.core.List
 import it.unibo.tuprolog.core.Tuple
 import it.unibo.tuprolog.solve.ExecutionContext
 import it.unibo.tuprolog.solve.Signature
 import it.unibo.tuprolog.solve.exception.error.TypeError
 import it.unibo.tuprolog.solve.primitive.Primitive
 import it.unibo.tuprolog.solve.primitive.Solve
 
 /**
  * forEach(?Element, +List, +Goal): Goal (all its solutions) for each element of List, as
  * findall(_, (member(Element, List), Goal), _), but without List in the goals of the iterations: with variable
  * tracking, every resolution step visits the terms of the goal it belongs to, so the list would make every step
  * as costly as it is long. Goal runs in this module: other modules are called through ::.
  */
 internal object ForEach : Primitive {
     val signature: Signature = Signature("forEach", 3)
 
     override fun solve(request: Solve.Request<ExecutionContext>): Sequence<Solve.Response> {
         val list = request.arguments[1]
         if (list !is List) {
             throw TypeError.forGoal(request.context, request.signature, TypeError.Expected.LIST, list)
         }
         // the iterations are solved one after the other, by the same solver
         val solver = request.subSolver()
         list.toList().forEach { item ->
             val iteration = Tuple.of(request.arguments[0], request.arguments[2]).freshCopy()
             val unifier = Arg2pUnificator.mgu(iteration[0], item)
             if (unifier.isSuccess) {
                 solver.solve(iteration[1].apply(unifier).castToStruct()).forEach { if (it.isHalt) throw it.exception!! }
             }
         }
         return sequenceOf(request.replyWith(true))
     }
 }