diff --git a/doc/userdoc.org b/doc/userdoc.org
index cec01a86d2a07b30bcdd53d4bb7c3b8299004576..95a577c9ba9284ef92356bcb6fc83edc88118367 100644
--- a/doc/userdoc.org
+++ b/doc/userdoc.org
@@ -1742,7 +1742,7 @@ section [[functions]], functions can return compound values, thus compound
 affectations (or definitions) are needed to get returned values in
 that case.
 
-*** TODO Tuple types<<tuples>>
+*** Tuple types<<tuples>>
 
 The last special type construction is the ability to deal with tuples
 in the ~pugs~ language. The tuples we are describing here are lists of
@@ -1786,21 +1786,105 @@ one of them. This is not something that should ever change. Tuples are
 not arrays! The ~pugs~ language is not meant to allow low-level
 instructions.
 
- The use case of tuples is to provide lists of data to the ~C++~
+The use case of tuples is to provide lists of data to the ~C++~
 underlying methods. A classical example is to provide a set of
 boundary conditions to a method.
 
-** TODO Statements
+** Statements
+
+The ~pugs~ language supports classical statements to control the data
+flow. For simplicity, these statements syntax follows their ~C++~
+counterpart. The only statement that is not implemented in ~pugs~ is the
+~switch...case~. This may change but in one hand, up to it was never
+necessary (we did not use chained ~if...else~ statements), and on the
+other hand, keeping the language as simple as possible remains the
+policy in ~pugs~ development.
+
+*** ~if...else~ statement
+
+The simplest statement is the conditional statement ~if...else~.  If a
+condition is satisfied, the ~truestatement~ (a single instruction or
+block of instructions) is executed. In the other case, if the /optional/
+~else~ keyword is used, the ~falsestatement~ (a single instruction or
+block of instructions) is executed.
+#+BEGIN_SRC pugs :exports code
+  if (condition) truestatement
+  if (condition) truestatement else falsestatement
+#+END_SRC
+
+The condition itself *must be* a boolean value (of type ~B~).
+
+#+NAME: if-instruction
+#+BEGIN_SRC pugs :exports both :results output
+  if (2>1) cout << "yes: 2 > 1\n";
+  if (not (2>1)) cout << "hmm... 2 <= 1 ?\n";
+#+END_SRC
+generates the following expected output. The second output is
+hopefully not executed.
+#+results: if-instruction
+
+It is probably better to use the ~else~ keyword to obtain the same
+result
+#+NAME: if-else-instruction
+#+BEGIN_SRC pugs :exports both :results output
+  if (2<=1)
+    cout << "hmm... 2 <= 1 ?\n";
+  else
+    cout << "ok: 2 > 1\n";
+#+END_SRC
+#+results: if-else-instruction
+
+However, it is recommended even in the case of single instructions in
+the conditional statements to use instruction blocks:
+#+NAME: if-else-block-of-one
+#+BEGIN_SRC pugs :exports both :results output
+  import math;
+  let sin100_positive:B;
 
-*** if/else
+  if (sin(100) > 0){
+     sin100_positive = true;
+  } else {
+     sin100_positive = false;
+  }
+
+  cout << "sin(100)>0: " << sin100_positive << "\n";
+#+END_SRC
+#+results: if-else-block-of-one
+Obviously in this simple case, it would be better to write
+#+BEGIN_SRC pugs :exports both :results output
+  import math;
+  let sin100_positive:B, sin100_positive = (sin(100) > 0);
+  // parenthesis are useless but ease reading
+
+  cout << "sin(100)>0 ? " << sin100_positive << "\n";
+#+END_SRC
+but this is not the purpose here.
+
+We give a final illustration
+#+NAME: if-block
+#+BEGIN_SRC pugs :exports both :results output
+  let m:R, m = 2.5;
+  let M:R, M = 2;
+  let has_swapped:B, has_swapped = false;
+
+  if (m>M){
+     let tmp:R, tmp = m;
+     m = M;
+     M = tmp;
+     has_swapped = true;
+  }
+
+  cout << "min = " << m << " max = " << M << " has_swapped = " << has_swapped << "\n";
+#+END_SRC
+#+results: if-block
 
-*** for loops
+*** TODO for loops
 
-*** do while loops
+*** TODO do while loops
 
-*** while loops
+*** TODO while loops
 
-*** break/continue
+*** TODO break/continue
 
 ** TODO Functions<<functions>>