- unfocus x ou unfocus r ?
    unfocus r plus facile pour l'inférence du unfocus
    MAIS unfocus x plus facile pour l'inférence du focus si on change
    le focus en : focus x as R (cf plus bas)

    Mon choix : unfocus S as R
    CA CHANGE TOUTES LES VARIABLES [S] en [R]
    (d'ailleurs le focus aussi dans l'autre sens)

- a-t-on vraiment besoin du sous-typage ?
    uniquement pour l'inférence et on peut s'en passer en réduisant
    la force de l'inférence du adopt
    mais je préfère une inférence du adopt puissante, donc je le mets

il manque dans l'ast :
- les fonctions logiques (expressions) et leur déclaration
- les termes et prédicats
- les types logiques

changements par rapport à neocap :

(*
- adopt devient let x = adopt S in R
    le "let x =" est important pour pouvoir inférer les adoptions si on supprime
    le sous-typage
PAS BESOIN EN FAIT
*)

- typage de x.f : on regarde CAPS INTER {R^xog, S -° R} aussi pour tous les
    parents (si R = x.r et x : [R'] on se pose la question récursivement pour
    R')

- besoin du sous-typage, penser à changer les règles de typage

remarque sur l'unification :
  elle n'est utilisée que pour unifier à l'appel de fonctions polymorphes
  en fait
  comme on ne peut pas backtracker, ça peut faire des trucs bizarres
  avec l'inférence du adopt, mais tant pis

remarque sur l'inférence des focus :
  ils ne sont intéressants que pour x.f <- e, et c'est magique on a donc
  la variable x, celle qui devra subir le focus, à disposition
  on rajoute alors x->y dans la substitution svar, où y est frais
  on insère, si R est frais :
    let region R
    let y = focus x in R

simplification de l'inférence des focus :
  * si on remplace l'instruction par :
      focus x as R
    alors on peut changer la règle de typage pour mettre carrément x: [R]
    dans l'environnement à la place du type qu'il avait avant
  * ensuite pour le unfocus :
      unfocus x as R
    on change à nouveau le type de x
  * comment est-ce qu'on infère alors les focus ? c'est simple, on n'en a
    besoin que pour x.f <- e, et si x: [R] et R^o n'est pas obtenable, on essaye
    un focus x as R
  * comment est-ce qu'on infère les unfocus maintenant qu'on DOIT avoir une
    variable sous la main ? on cherche dans l'environnement la variable,
    si elle n'y est pas c'est que le focus a été fait hors de la fonction
    courante, ce qui n'est pas forcément très utile a priori
    OU ALORS, on prend
      unfocus S (as R éventuellement)
    et la règle de typage CHANGE DANS L'ENVIRONNEMENT les variables de type
    [S] en des variables de type [R]
  * par contre ça ne marche pas bien pour les if

remarque sur l'inférence des adopt :
  une expression ne génère pas d'adoption :
    - entiers, booléens, unit, opérations binaires : trivial
    - variables : leur type est donné par l'environnement
    - sélection x.f : on vérifie juste qu'on a bien une permission pour x
    - application logique f(e, ..., e) : la fonction est polymorphe en ses
      régions
  donc en gros le typage des expressions est très simple et ne demande pas
  l'insertion d'opérations sur les régions
  MAIS ATTENTION : une fois l'expression typée, si alors des opérations sont
    insérées avant l'expression, cela peut faire disparaître des permissions
    nécessaires et il faut retyper l'expression
  par contre on peut avoir besoin d'adoptions si le type de l'expression
  est unifié ensuite avec un autre :
    - les adoptions peuvent être en profondeur
  POUR L'INSTANT : on adopte quand l'expression est une variable, mais on
    ne peut donc pas adopter quand l'expression est x.f, en gros c'est pas
    super ; mais il n'y a que trois endroits où on peut unifier :
      - dans une affectation ;
      - dans un appel ;
      - dans le return ;
    donc on pourrait aussi décider qu'on met toujours des variables à ces
    endroits là ; mais ça ne résoudrait pas toujours le problème si par
    exemple on fait (let x = y.f) après que (z = y.f) ait été adopté

remarque sur la comparaison de pointeurs :
  toujours autorisée quelque soit la région, mais warning éventuel selon
  les permissions si les régions sont différentes

remarque sur le scope des régions :
  let region R: Long;
  let x = new [R];
  x.value <- 0;
  pack x;
  weaken x;
  if ... then
  {
    let region S: Long
    focus x as S
  }
  ici à la fin de la branche then on a la permission S->R, qui doit disparaître
  puisque S est hors de portée
  ==> soit on infère un unfocus,
  ==> soit on dit que c'est une erreur de type (puisque j'aimerais éviter
      de perdre des permissions),
  ==> soit on fait juste un warning

pourquoi j'ai choisi x.r et non R.r où R est singleton, déjà ? :p ah oui,
  pour dire que le type [R.r] n'a pas de sens quand R peut changer d'état ;
  pourrait-on s'en sortir en changeant les types le long de l'exécution ?

typage du if :
  - environnement : on prend celui d'avant le if
    ? est-ce qu'il faut que si une variable a changé de type de la même façon
      dans les deux branches, on lui garde ce nouveau type ?
      - je pense que oui
  - permissions : on enlève toutes celles qui mentionnent des régions hors de
    portée
  - inférence :
    ? si on a S->R et S est hors de portée, doit-on tenter un unfocus ?
      - je pense que oui
    - ensuite on peut insérer des unpack et des weaken pour égaliser les
      permissions si possible ; pour cela on fait un point fixe sur l'opération
      suivante : prendre deux permissions différentes sur la même région,
      si c'est R^c / R^o faire unpack R à gauche,
      si c'est R^e / R^g faire weaken empty R à gauche,
      si c'est R^c / R^g faire weaken single R à gauche,
      et réciproquement,
      jusqu'à ce qu'on ne puisse plus, et là les permissions doivent être
      identiques sinon on fait une erreur de typage
