From a748f4ec7c67e38cefeef8b6fc95f43d7c9afdb8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mika=C3=ABl=20Mayer?= <a-mikmay@microsoft.com>
Date: Thu, 23 Jul 2015 17:33:56 +0200
Subject: [PATCH] Added more comments for some synthesis functions.

---
 src/main/scala/leon/purescala/Common.scala     |  8 ++++++++
 src/main/scala/leon/synthesis/Algebra.scala    | 18 ++++++++++++++++--
 .../scala/leon/synthesis/ExampleBank.scala     |  2 +-
 src/main/scala/leon/synthesis/Problem.scala    | 11 +++++++++--
 src/main/scala/leon/synthesis/Rules.scala      |  7 ++++++-
 .../leon/synthesis/rules/DetupleInput.scala    | 11 +++++++++++
 6 files changed, 51 insertions(+), 6 deletions(-)

diff --git a/src/main/scala/leon/purescala/Common.scala b/src/main/scala/leon/purescala/Common.scala
index 2d592e006..27818fd39 100644
--- a/src/main/scala/leon/purescala/Common.scala
+++ b/src/main/scala/leon/purescala/Common.scala
@@ -76,9 +76,17 @@ object Common {
   }
 
   object FreshIdentifier {
+    /** Builds a fresh identifier
+      * @param name The name of the identifier
+      * @param tpe The type of the identifier
+      * @param alwaysShowUniqueID If the unique ID should always be shown */
     def apply(name: String, tpe: TypeTree = Untyped, alwaysShowUniqueID: Boolean = false) : Identifier = 
       new Identifier(name, UniqueCounter.nextGlobal, UniqueCounter.next(name), tpe: TypeTree, alwaysShowUniqueID)
 
+    /** Builds a fresh identifier, whose ID is always shown
+      * @param name The name of the identifier
+      * @param forceId The forced ID of the identifier
+      * @param tpe The type of the identifier */
     def apply(name: String, forceId: Int, tpe: TypeTree): Identifier = 
       new Identifier(name, UniqueCounter.nextGlobal, forceId, tpe, true)
 
diff --git a/src/main/scala/leon/synthesis/Algebra.scala b/src/main/scala/leon/synthesis/Algebra.scala
index 6730cabb2..92ee346e0 100644
--- a/src/main/scala/leon/synthesis/Algebra.scala
+++ b/src/main/scala/leon/synthesis/Algebra.scala
@@ -11,20 +11,23 @@ package leon.synthesis
  */
 
 object Algebra {
-
+  /** Returns the remainder of the euclidian division between x an y (always positive) */
   def remainder(x: Int, y: Int) = ((x % y) + y.abs) % y.abs
 
+  /** Returns the quotient of the euclidian division between a and b.*/
   def divide(a: Int, b: Int): (Int, Int) = {
     val r = remainder(a, b)
     ((a - r)/b, r)
   }
 
+  /** Returns the remainder of the euclidian division between the big integers x an y (always positive) */
   def remainder(x: BigInt, y: BigInt) = ((x % y) + y.abs) % y.abs
+  /** Returns the quotient of the euclidian division between the big integers x an y */
   def divide(a: BigInt, b: BigInt): (BigInt, BigInt) = {
     val r = remainder(a, b)
     ((a - r)/b, r)
   }
-
+  /** Returns the gcd of two integers */
   def gcd(a: Int, b: Int): Int = {
     val (na, nb) = (a.abs, b.abs)
     def gcd0(a: Int, b: Int): Int = {
@@ -34,6 +37,7 @@ object Algebra {
     if(na > nb) gcd0(na, nb) else gcd0(nb, na)
   }
 
+  /** Returns the gcd of three or more integers */
   def gcd(a1: Int, a2: Int, a3: Int, as: Int*): Int = {
     var tmp = gcd(a1, a2)
     tmp = gcd(tmp, a3)
@@ -45,6 +49,7 @@ object Algebra {
     tmp
   }
 
+  /** Returns the gcd of a non-empty sequence of integers */
   def gcd(as: Seq[Int]): Int = {
     require(as.length >= 1)
     if(as.length == 1)
@@ -60,6 +65,7 @@ object Algebra {
     }
   }
 
+  /** Returns the gcd of two big integers */
   def gcd(a: BigInt, b: BigInt): BigInt = {
     val (na, nb) = (a.abs, b.abs)
     def gcd0(a: BigInt, b: BigInt): BigInt = {
@@ -69,6 +75,7 @@ object Algebra {
     if(na > nb) gcd0(na, nb) else gcd0(nb, na)
   }
 
+  /** Returns the gcd of three or more big integers  */
   def gcd(a1: BigInt, a2: BigInt, a3: BigInt, as: BigInt*): BigInt = {
     var tmp = gcd(a1, a2)
     tmp = gcd(tmp, a3)
@@ -80,6 +87,7 @@ object Algebra {
     tmp
   }
 
+  /** Returns the gcd of a non-empty sequence of big integers */
   def gcd(as: Seq[BigInt]): BigInt = {
     require(as.length >= 1)
     if(as.length == 1)
@@ -95,11 +103,13 @@ object Algebra {
     }
   }
 
+  /** Returns the lcm of two integers */
   def lcm(a: Int, b: Int): Int = {
     val (na, nb) = (a.abs, b.abs)
     na*nb/gcd(a, b)
   }
 
+  /** Returns the lcm of three or more integers */
   def lcm(a1: Int, a2: Int, a3: Int, as: Int*): Int = {
     var tmp = lcm(a1, a2)
     tmp = lcm(tmp, a3)
@@ -111,6 +121,7 @@ object Algebra {
     tmp
   }
 
+  /** Returns the lcm of a sequence of integers */
   def lcm(as: Seq[Int]): Int = {
     require(as.length >= 1)
     if(as.length == 1)
@@ -126,11 +137,13 @@ object Algebra {
     }
   }
 
+  /** Returns the lcm of two big integers */
   def lcm(a: BigInt, b: BigInt): BigInt = {
     val (na, nb) = (a.abs, b.abs)
     na*nb/gcd(a, b)
   }
 
+  /** Returns the lcm of three or more big integers */
   def lcm(a1: BigInt, a2: BigInt, a3: BigInt, as: BigInt*): BigInt = {
     var tmp = lcm(a1, a2)
     tmp = lcm(tmp, a3)
@@ -142,6 +155,7 @@ object Algebra {
     tmp
   }
 
+  /** Returns the lcm of a sequence of big integers */
   def lcm(as: Seq[BigInt]): BigInt = {
     require(as.length >= 1)
     if(as.length == 1)
diff --git a/src/main/scala/leon/synthesis/ExampleBank.scala b/src/main/scala/leon/synthesis/ExampleBank.scala
index 29c82015b..23fa9039e 100644
--- a/src/main/scala/leon/synthesis/ExampleBank.scala
+++ b/src/main/scala/leon/synthesis/ExampleBank.scala
@@ -9,7 +9,7 @@ import purescala.Common._
 import repair._
 import leon.utils.ASCIIHelpers._
 
-
+/** Sets of valid and invalid examples */
 case class ExampleBank(valids: Seq[Example], invalids: Seq[Example]) {
   def examples = valids ++ invalids
 
diff --git a/src/main/scala/leon/synthesis/Problem.scala b/src/main/scala/leon/synthesis/Problem.scala
index 99b1d699d..4ae607f81 100644
--- a/src/main/scala/leon/synthesis/Problem.scala
+++ b/src/main/scala/leon/synthesis/Problem.scala
@@ -11,8 +11,15 @@ import leon.purescala.Constructors._
 import leon.purescala.Extractors._
 import Witnesses._
 
-// Defines a synthesis triple of the form:
-// ⟦ as ⟨ ws && pc | phi ⟩ xs ⟧
+/** Defines a synthesis triple of the form:
+  * ⟦ as ⟨ ws && pc | phi ⟩ xs ⟧
+  * 
+  * @param as The list of input identifiers so far
+  * @param ws The axioms and other already proven theorems
+  * @param pc The path condition so far
+  * @param phi The formula on `as` and `xs` to satisfy
+  * @param xs The list of output identifiers for which we want to compute a function
+  */
 case class Problem(as: List[Identifier], ws: Expr, pc: Expr, phi: Expr, xs: List[Identifier], eb: ExampleBank = ExampleBank.empty) {
 
   def inType  = tupleTypeWrap(as.map(_.getType))
diff --git a/src/main/scala/leon/synthesis/Rules.scala b/src/main/scala/leon/synthesis/Rules.scala
index 2195cb126..908b753d9 100644
--- a/src/main/scala/leon/synthesis/Rules.scala
+++ b/src/main/scala/leon/synthesis/Rules.scala
@@ -10,6 +10,7 @@ import purescala.ExprOps._
 import purescala.Constructors.and
 import rules._
 
+/** A Rule can be applied on a synthesis problem */
 abstract class Rule(val name: String) extends RuleDSL {
   def instantiateOn(implicit hctx: SearchContext, problem: Problem): Traversable[RuleInstantiation]
 
@@ -30,7 +31,9 @@ abstract class PreprocessingRule(name: String) extends Rule(name) {
   override val priority = RulePriorityPreprocessing
 }
 
+/** Contains the list of all available rules for synthesis */
 object Rules {
+  /** Returns the list of all available rules for synthesis */
   def all = List[Rule](
     Unification.DecompTrivialClash,
     Unification.OccursCheck, // probably useless
@@ -142,12 +145,14 @@ case object RulePriorityDefault       extends RulePriority(20)
  */
 trait RuleDSL {
   this: Rule =>
-
+  /** Replaces all first elements of `what` by their second element in the expression `ìn`*/
   def subst(what: (Identifier, Expr), in: Expr): Expr = replaceFromIDs(Map(what), in)
+  /** Replaces all keys of `what` by their key in the expression `ìn`*/
   def substAll(what: Map[Identifier, Expr], in: Expr): Expr = replaceFromIDs(what, in)
 
   val forward: List[Solution] => Option[Solution] = { ss => ss.headOption }
   
+  /** Returns a function that transforms the precondition and term of the first Solution of a list using `f`.  */
   def forwardMap(f : Expr => Expr) : List[Solution] => Option[Solution] = { 
     _.headOption map { s =>
       Solution(f(s.pre), s.defs, f(s.term), s.isTrusted)
diff --git a/src/main/scala/leon/synthesis/rules/DetupleInput.scala b/src/main/scala/leon/synthesis/rules/DetupleInput.scala
index ed25fc4b3..bb0f1b4ba 100644
--- a/src/main/scala/leon/synthesis/rules/DetupleInput.scala
+++ b/src/main/scala/leon/synthesis/rules/DetupleInput.scala
@@ -10,15 +10,26 @@ import purescala.Types._
 import purescala.ExprOps._
 import purescala.Constructors._
 
+/** Rule for detupling input variables, to be able to use their sub-expressions. For example, the input variable:
+  * {{{d: Cons(head: Int, tail: List)}}}
+  * will create the following input variables
+  * {{{head42: Int, tail57: List}}}
+  * Recomposition is available.
+  */
 case object DetupleInput extends NormalizingRule("Detuple In") {
 
   def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = {
+    /** Returns true if this identifier is a tuple or a case class */
     def isDecomposable(id: Identifier) = id.getType match {
       case CaseClassType(t, _) if !t.isAbstract => true
       case TupleType(ts) => true
       case _ => false
     }
 
+    /* Decomposes a decomposable input identifier (eg of type Tuple or case class)
+     * into a list of fresh typed identifiers, the tuple of these new identifiers,
+     * and the mapping of those identifiers to their respective expressions.
+     */
     def decompose(id: Identifier): (List[Identifier], Expr, Map[Identifier, Expr]) = id.getType match {
       case cct @ CaseClassType(ccd, _) if !ccd.isAbstract =>
         val newIds = cct.fields.map{ vd => FreshIdentifier(vd.id.name, vd.getType, true) }
-- 
GitLab