Heptagon

Langage fonctionnel à flux de données

\RA produits des automates

node identite(x : int) returns (o : int)
let
  o = x;
tel

Nœud = fonction de flots

Compilation

Fichier .ept \xrightarrow{hept} fichiers .c \xrightarrow{gcc} exécutable

heptc -target c -s identite test.ept

heptc -i -target c -s identite test.ept :

val identite(x : int :: .) returns (o : int :: .)

\text{identite. } int^{\omega} \ra int^{\omega}

Monde simple, les objets définis sont utilisés.

node identite(x : int) returns (o : int)
var y : int
let
  o = x;
tel

y doit être utilisé.

Heptagon n’est pas un langage impératif, on définit des équations.
On fait des conjonctions (définitions simultanées), l’ordre n’est pas important ; tout est vrai.

Insensible à l’ordre des équations
\RA Définitions mutuellement récursives

Dans un programme Heptagon valide, on peut toujours calculer une valeur. Rejette les programmes non causaux (le compilateur fait une analyse de causalité/productivité).

y = y (* erreur de causalité *)

Programmation Flots-de-données et causalité

Opérateurs combinatoires

node f() returns (x, y : int, z : bool)
let
  x = 1;
  y = 42;
  z = false;
tel

node g() returns (o: int)
let
  (* motif *)
  (x, y, z) = f();
  o = x;
tel

Equivaut à :

0 1 2 3 4
x 1 1 1 1 1
y 42 42 42 42 42
z False False False False False
x+y 43 43 43 43 43

e expression Heptagon
\lb e \rb sémantique de e (une suite)
\lb l \rb_{n} = l avec \lb l \rb_{n} la constante littérale (42, 1, \text{False}) (n c’est l’instant n aka le temps)
\lb e_{1} + e_{2} \rb_{n} = \lb e_{1} \rb_{n} + \lb e_{2} \rb_{n}
\lb e_{1} - e_{2} \rb_{n} = \lb e_{1} \rb_{n} - \lb e_{2} \rb_{n}

\lb e_{1} \text{ op } e_{2} \rb_{n} = \lb e_{1} \rb_{n} \text{ op } \lb e_{2} \rb_{n} avec \text{op} un opérateur quelconque

\lb\text{if }e_{1}\text{ then }e_{2}\text{ else }e_{3}\rb_{n} = \begin{cases} \lb e_{2} \rb_{n} & \text{ si } \lb e_{1} \rb_{n} = \text{ True} \\\\ \lb e_{3} \rb_{n} & \text{ si } \lb e_{1} \rb_{n} = \text{ False} \end{cases}

Opérateurs séquentiels

0 1 2
x x_0 x_1 x_2
y y_{0} y_{1} y_{2}
x fby y x_{0} y_{0} y_{1}

Comportement temporel, il y a un état.

Exercice

(* Définir un noeud half dont la sortie o est un
   flot booléen qui alterne entre les valeurs
   true et false, en commençant par true. *)
node half() returns (o : bool)
let
  o = true fby not o;
tel

(* on peut aussi faire *)
node half() returns (o : bool)
let
  o = true fby false fby o;
tel

Chronogramme associé :

0 1 2
true fby not o True False True
not o False True False
En Heptagon, = est une équation.
o = true fby not o
  = true fby not (true fby not o)
  = true fby (not true) fby not (not o)
  = true fby false fby o (* c'est notre solution 2 !!*)
  = true fby false fby true fby false fby ...

Notes

e1 fby e2 fby e3 = e1 fby (e2 fby e3) ce qui est la conséquence de chaîner plusieurs fby.
\RA associatif à droite

Exercice

(* o1 est comme la fonction half(), o2 est l'inverse en gros *)
node halves() returns (o1, o2 : bool)
let
  o1 = true fby o2;
  o2 = false fby o1; (* on peut aussi faire o2 = not o1 *)
tel

Exercice

Disgression : positif, c’est >= 0, positivee (anglais) c’est > 0

node j() returns (nat, pos : int)
let
  nat = 0 fby pos; (* suite des naturels *)
  pos = nat + 1;   (* suite des naturels *strictement positifs* *)
tel

En faisant une équation :

nat = 0 fby pos
    = 0 fby (nat + 1)
    = 0 fby ((0 fby (nat + 1)) + 1)
    = 0 fby 1 fby (nat + 2)
    = 0 fby 1 fby ((0 fby (nat + 1)) + 2)
    = 0 fby 1 fby 2 fby (nat + 3) 

Exemple

node j4() returns (x : int)
let
  x = 0 -> (pre x + 1);
tel
0 1 2
x = 0 -> pre x + 1 0 1 2
pre x nil 0 1
pre x + 1 nil 1 2

\lb e_{1} e_{1} \text{ fby } e_{2} \rb_{n} = \lb e_{1} \ra \text{pre } e_{2} \rb_{n} = \begin{cases} \lb e_{1} \rb_{0} & \text{ si } n = 0 \\\\ \lb \text{pre } e_{2} \rb_{n} = \lb e_{2} \rb_{n-1} & \text{ si } n > 0 \end{cases}

Analyses statiques

Typage, causalité, initialisation, horloges…

Causalité

```ocaml
node j() returns (nat, pos : int)
let
  nat = 0 -> pos; 
  pos = nat + 1;
tel

Dessin_08-10-2024_13.36.32.excalidraw

Mémo lecture erreur
|| = en parallèle
^qqch = je dois lire qqch
^pos < nat = je dois lire pos avant nat

$ hept -s j -t test.ept 
File "test.ept", line 1-5, characters 0-3:
>node j() returns (nat, pos : int)
>let
>  nat = 0 -> pos;
>  pos = nat + 1;
>tel
Causality error: the following constraint is not causal.
^pos < nat
 || ^nat < pos