///|
/// Generator expression helpers.

///|
fn genexp_filters_to_condition(filters : Array[Expr]) -> Expr? {
  if filters.length() == 0 {
    None
  } else if filters.length() == 1 {
    Some(filters[0])
  } else {
    Some(Expr::BoolOp(op=BoolOp::And, values=filters))
  }
}

///|
fn genexp_to_generator_body(
  elt : Expr,
  clauses : Array[CompClause],
  filters : Array[Expr],
) -> Array[Stmt] {
  let filters = unowned_comprehension_filters(clauses, filters)
  let inner : Array[Stmt] = [Stmt::Yield(Some(elt))]
  let conditioned = match genexp_filters_to_condition(filters) {
    Some(cond) => [Stmt::If(condition=cond, body=inner, else_body=[])]
    None => inner
  }
  let mut body = conditioned
  let mut i = clauses.length()
  while i > 0 {
    i = i - 1
    let clause = clauses[i]
    for j = clause.filters.length() - 1; j >= 0; j = j - 1 {
      body = [Stmt::If(condition=clause.filters[j], body~, else_body=[])]
    }
    body = [
      Stmt::For(target=clause.target, iter=clause.iter, body~, else_body=[]),
    ]
  }
  body
}

///|
fn genexp_local_taken(locals : Array[(String, Value)], name : String) -> Bool {
  for pair in locals {
    if pair.0 == name {
      return true
    }
  }
  false
}

///|
fn fresh_genexp_local(locals : Array[(String, Value)]) -> String {
  let base = "__mpython_genexp_iter".to_string()
  if !genexp_local_taken(locals, base) {
    return base
  }
  let mut i = 0
  while true {
    let candidate = base + "_" + i.to_string()
    if !genexp_local_taken(locals, candidate) {
      return candidate
    }
    i = i + 1
  }
  base
}