llenguatge de programació From Wikipedia, the free encyclopedia
El Cyclone és un llenguatge de programació derivat del llenguatge C creat per tal de superar les vulnerabilitats d'aquest sense perdre la potència i el control dels recursos que el caracteritzen per a la programació de sistemes.[1] El seu desenvolupament va començar com un projecte conjunt entre AT&T Labs Research[2] i el grup de Greg Morrisett a la universitat Cornell, el 2001. La versió 1.0 va sortir el 8 de maig de 2006
![]() |
Aquest article o secció necessita l'atenció d'un expert en la matèria. |
Tipus | llenguatge de programació ![]() |
---|---|
Data de creació | 2002 ![]() |
Disseny | AT&T Labs ![]() |
Desenvolupador | AT&T ![]() |
Influenciat per | C ![]() |
Pàgina web | cyclone.thelanguage.org ![]() |
El Cyclone millora la seguretat, introdueix subtipus (estructurals, d'allotjament, etc.), incorpora un allotjament dinàmic insòlit (per regions lèxiques (gestió automàtica), dinàmiques (gestió directa) i al munt amb recol·lector de brossa opcional) i afegeix característiques de llenguatges de més alt nivell del tipus de ML.
Descàrrega i instal·lació[3]
// fitxer hola-mon.cyc
#include <stdio.h>
#include <core.h>
using Core; // importa espai de noms Core
int main(int argc, string_t ? args)
{
if (argc <= 1) {
printf("Ús: %s <nom>\n", args[0]);
return 1;
}
printf("Hola des de Cyclone, %s\n", args[1]);
return 0;
}
// fi de fitxer
Compilació i execució
cyclone hola-mon.cyc -o hola-mon ./hola-mon
Cyclone introdueix les següents restriccions i comprovacions:
<=
numelts (punter)
...
Cyclone introdueix les següents característiques de llenguatges de més alt nivell
namespace Pep {
int x = 0;
int f() { return x; }
}
namespace Jan {
using Pep { // importa els identificadors de l'espai Pep
int g() { return f();
}
}
// ara estem fora de l'àmbit del using, caldrà qualificar amb "espai::"
int h() { return Pep::f(); }
}
Estructura igual amb camps addicionals, permet l'ús de punters al subtipus en el lloc de punters d'un tipus.
#include <stdio.h>
typedef struct Punt {float x,y;} *punt_t;
typedef struct PuntAcolorit {float x,y; int color;} *cpunt_t;
float xcoord (punt_t p) {
return p→x;
}
int main() {
cpunt_t cpunt = new PuntAcolorit {1.0, 2.0, 15} ;
float x = xcoord(cpunt) ;
printf ("la x és %.2f\n", x) ;
return 0 ;
}
_ a = 1000; // el compilador infereix tipus int
{ for i < topall : expr(i) }
equival a un inicialitzador de vector, amb valors { expr(i) | i = 0 .. (topall - 1) }
int dobles[100] = { for i < 100 : 2*i }
Estructures anònimes, per ex.:
$(int, char*) parell = $(10, "abc") ;
Vegeu ref.[9]
@tagged union T {
int Integer;
const char *@fat String;
};
union T x = {.Integer = 3};
union T y = {.String = "hola"};
bool printT(union T w) {
if (tagcheck(w.Integer))
printf("%d",w);
else
printf("%s",w);
}
datatype T {
Integer(int);
String(const char *@fat);
};
// equivalent aprox. en llenguatge SML: datatype T = Integer of int | String of string
datatype T.Integer x = Integer(3);
datatype T.String y = String("hola");
void printT(datatype T *@notnull a) {
switch (a) {
case &Integer(i): printf("%d",i); return;
case &String(s): printf("%s",s); return;
}
}
FILE *f = fopen("nom_fitxer","r");
int c;
try {
c = getc((FILE *@notnull) f);
}
catch {
case &Null_Exception:
printf("Error en obrir nom_fitxer\n");
exit(1);
case &Invalid_argument(msg):
printf("Error: argument invàlid(%s)\n", msg);
exit(1);
}
@extensible datatype exn {
Excepcio_meva(char *@fat);
};
throw new Excepcio_meva("tururut");
Vegeu ref.[12]
// funció que intercanvia elements d'una tupla2
$(`b,`a) intercanvia($(`a,`b) x) {
return $(x[1],x[0]); }
struct List<`a> {`a hd; struct List<`a> * tl; };
typedef struct List<`a> *list_t<`a>;
list_t<int> ilist = new List{1,new List{2,null}};
list_t<string_t> slist = new List{.hd = "primera",
.tl = new List{"segona",null}};
Vegeu ref.[13]
int suma($(int,int,int) args) {
let $(x,y,z) = args;
return (x+y+z);
}
En un switch:[14]
extern int f(int);
int g(int x, int y) { // retorna f(x)*f(y)
switch($(f(x),f(y))) {
case $(0,_) : fallthru; // salta al case següent
case $(_,0) : return 0;
case $(1,b) : fallthru(b+1-1); // salta, assignant (b+1-1) al primer elem. de la tupla2
case $(a,b) && b == 1 : return a; // amb guardes
case $(a,b) : return a*b; // és un error si els case no són exhaustius.
}
}
Vegeu ref.[15] Tipus d'estructura tal que ∃ un tipus `a per a la signatura especificada. Les estructures amb tipus explícit que concorden en són subtipus.
struct T { <`a> `a f1; `a f2; };
Per ex. el tipus de int A[n]. Vegeu "Verificació estàtica"[16]
Les crides han de satisfer la precondició @requires estàticament
int f(const int n, int *A)
@requires(n == numelts(A)) // precondició
@ensures(0 <= return_value < n) // postcondició
{...}
Vegeu ref.[17] L'allotjament es materialitza en regions:[18] àmbits locals a la pila, lèxiques (allotj. dinàmic que mor amb el bloc), dinàmiques (vida controlable) o al munt (vida universal). Per què un punter a una regió sigui segur la regió ha d'estar viva.
void bar(int *@region(`r) x, int *@region(`s) y : {`s} > `r) { ... }
// la restricció admet una llista sep. per comes {`r1, `r2, ..,`rn} > `r // indica que `r ha de sobreviure a totes les de la llista
Els àmbits d'allotjament local constitueixen una regió cadascun.
L'àmbit principal d'una funció porta per nom de regió la cometa revessa seguida del nom de la funció, per ex. void fun (..) {...} tindrà per nom de regió, `fun
En un sub-àmbit delimitat per claus {} podem fer referència a la regió local posant una etiqueta a l'àmbit, per ex. L:{...} serà la regió `L
Cada regió en allotjament dinàmic és una llista encadenada de pàgines.
(ang.: heap) (regió `H) amb recol·lector de memòria brossa.
// new tipus expr_inicialitzadora // new inicialitzador_de_vector
// new allotja al Heap, rnew (regió) .. ho fa en una regió específica
struct Punt {float x,y;} ;
Punt *p = new Punt {1.0, 2.0};
// [r]malloc ([regió,] mida) i [r]calloc(..) suportats però desaconsellats
anomenades LIFO (Last In First Out) o lèxiques, són a l'estil de Tofte & Talpin amb temps de vida associat a l'àmbit corresp.[20]
#include <stdio.h>
struct Punt {float x,y;} ;
int main() {
_ a = 1 ;
{ // inici de l'àmbit
region lifo; // creació de la regió lèxica d'allotj. dinàmic.
_ p = rnew(lifo) Punt {1.0, 2.0}; // hi allotjem un objecte
printf ("la x és %.2f\n", p→x) ;
} // en sortir de l'àmbit es desallotja automàticament la regió lèxica
return 0 ;
}
Vegeu ref.[21] Denominada en l'original "Restricted Pointer Aliasing" (capacitat d'obtenir còpies d'un punter) amb valors ALIASABLE, UNIQUE, REFCNT.
Els dos darrers valors permeten alliberar l'espai allotjat individualment sense esperar que s'alliberi tota una regió
int *@aqual(UNIQUE) p = rnew(regio, UNIQUE) tipus expr_inicialitzadora int *\U p = ... // notació curta equivalent
int *@aqual(REFCNT) p = rnew(regio, REFCNT) tipus expr_inicialitzadora int *\RC p = ... // notació curta equivalent
amb temps de vida controlable, comprovant-ne l'existència en temps d'execució en fer-ne ús.
#include <core.h>
struct List<`a, `r> {`a hd; struct List<`a, `r> *`r tl; };
typedef struct List<`a, `r> *`r list_t<`a, `r>;
int main() {
// Creem una regió dinàmica
let Core::NewDynamicRegion{<`r> key} = Core::new_ukey();
// En aquest punt, ens referirem a la regió `r per
// especificar tipus, però encara no hi podem accedir
list_t<int,`r> x = NULL; // allotjament a la regió `r obtinguda a la instrucció ''let''
// utilitzem open per a accedir-hi en el sub-àmbit següent
{ region h = open(key); // consumeix l'única còpia del punter únic key
x = rnew(h) List(3,x);
} // en sortir descompta la còpia del punter únic key
// en un altre sub-àmbit tornem a treballar-hi
{ region h = open(key);
int i = x→hd + 1;
x = rnew (h) List(i,x);
}
// Finalment destruïm la clau i la regió
Core::free_ukey(key);
return 0 ;
}
...
Vegeu.[22] Extreu informació de tipus, d'arxius capçaleres de C instal·lades al sistema i les converteix a capçaleres de Cyclone incorporant els tipus que intervinguin en les definicions.
Cal crear un arxiu d'especificació especif.cys amb indicacions per a cada capçalera.
sys/types.h: include {tipusA tipusB ...} ; els_meus/biblio.h: include {tipusD tipusE ...} ;
Els arxius de capçalera a tractar han d'estar a /usr/include o /usr/local/include (si vols fer-ho amb un arxiu de capçalera en un altre directori, has d'establir i exportar la var. d'entorn C_INCLUDE_PATH o CPLUS_INCLUDE_PATH) i el nom de directori dins l'arxiu no pot tenir especificació de versió, per ex. "-2.0" (caldrà posar-lo directament a C_INCLUDE_PATH). El resultat va al directori ./BUILDLIB.OUT o al directori especificat a l'opció -d
Cal executar amb l'opció -v (verbose) per comprovar si hi ha hagut errors.
buildlib -v especif.cys