Projekt Vala je jedním z oficiálních projektů GNOME a usiluje o rozšíření možností vývoje nativně běžících aplikací o výhody, které jsou typické pro vývoj kódu kompilovaného do byte code (např. platforma Mono) a interpretovaného kódu (např. Python). V rámci projektu byl navržen programovací jazyk Vala.

Součásti projektu Vala V rámci Valy je vyvíjen překladač Valy a navrhovány jazyky Vala a Genie. S projektem Vala úzce souvisí projekt aplikačního frameworku Dova.

Jazyk Vala se velmi podobá jazyku C#. Většina rozdílů mezi oběma jazyky vyplývá ze zamýšleného odlišného principu překladu a ze zaměření Valy na platformu GNOME. Jazyk Vala je nejvýznamnějším jazykem projektu Vala.

Překlad Valy neprobíhá obvyklým způsobem. Překladač zdrojový kód naparsuje a transformuje jej na strojový kódZ hlediska licencí GNU je tento kód chápán jako strojový. Licence definují zdrojový kód jako preferovanou formu díla určenou pro jeho modifikace. Zdrojovým kódem je tedy pouze kód ve Vale. Všechny nezdrojové formy díla (včetně přeloženého kódu v jazyce C) jsou považovány za strojový kód. v jazyce C, který je ekvivalentní původnímu zdrojovému kódu v jazyce Vala. Při této transformaci využívá v GNOME běžnou abstrakci typů přes GObjecty (GLib Object System). Získaný strojový kód v C je určen k překladu do zvoleného formátu spustitelných souborů (např. executable and linkable format (ELF)) ve standardním kompilátoru GCC jako běžný C zdrojový kód. Překladač vala compiler (program valac) umožňuje všechny tyto fáze překladu provést buď najednou, nebo provést pouze transformaci do zdrojového kódu v C.

Vala se primárně zaměřuje na GNOME, které vyžaduje Linux nebo příbuzné UNIXové systémy. Přesto lze překlad Valy provést na jakémkoli systému, na kterém je dostupná knihovna GLib a překladač GCC nebo jeho porty.

Jazyk Genie se inspiruje jazykem Python. Překlad zdrojového kód Genie je analogický překladu Valy. Význam Genie je okrajový.

Jazyk Vala

„Ahoj, světe!“ Tento ukázkový minimální program typu Hello world vypíše řetězec "Ahoj".

print("Ahoj");

Překladač valac tento kód uložený v souboru demo.vala během překladu transformuje na následující kód v jazyce C. Jeho uložení se provede příkazem "valac demo.vala -C".

/* demo.c generated by valac 0.14.0, the Vala compiler * generated from demo.vala, do not modify */

#include <glib.h> #include <glib-object.h>

void _vala_main (void);

void _vala_main (void) { g_print ("Ahoj"); }

int main (int argc, char ** argv) { g_type_init (); _vala_main (); return 0; }

Vstupní bod je při čistě objektově orientovaném programování statickou metodou hlavní třídy programu. Třídy jsou obvykle potomky GLib.Object (zkráceně jen Object). Následuje neminimalistický Hello World program v objektovém stylu:

class Trida.AhojSvete : GLib.Object { void pozdrav () { stdout.printf ("Ahoj světe\n");

public static int main(string[] args) { var objekt = new Trida.AhojSvete (); objekt.pozdrav(); return 0;

Syntaxe a sémantika Valy Základy syntaxe Valy, způsob komentování, nejběžnější operátory a predikáty (např. +, ++, %, <) a nejběžnější klíčová slova pro řízení průchodu kódem (např. for, if, while) se neliší od C, C++, Javy, C# a dalších podobných jazyků.

Normou jazyka definované primitivní datové typy jsou prázdný typ (void), celé číslo (int, long, short, char), celé číslo s garantovaným platformově nezávislým rozsahem (int8, int16, int32, int64), pravdivostní hodnota (bool) s možnými hodnotami pravda (true) a nepravda (false), reálná čísla (float, double), reference na UTF-32 řetězec znaků (string), typ proměnné (Type).

Dále Vala umožňuje programátorovi definovat vlastní: struktury (struct), výčty (enum), třídy (class), rozhraní (interface), jmenné prostory (namespace), iterátory, typy delegátů. Delegáty (delegate) jsou jiný, praktičtější zápis ukazatelů na funkce známých z jazyka C. Atributy kódu a mnohé další výrazové prostředky především souvisejí s použitím na platformě GNOME. Atribut kódu se zapisuje před svůj kód ve tvaru [nazev_atributu(prvni_parametr="hodnota", druhy_parametr="hodnota", treti_parametr="hodnota")].

Dále Vala obsahuje následující: Všechny celočíselné typy mají znaménkovou hodnotu (např. int) a bezznaménkovou hodnotu značenou prefixem u (např. uint). Vala umožňuje automatické zjišťování typů (type inference). Klíčové slovo var nahrazuje typ, který jednoznačně vyplývá z kontextu celého zdrojového kódu. Vala umožňuje zápis anonymních funkcí s pomocí lambda výrazu reprezentovaným operátorem =>. Anonymní funkce jsou ve Vale reálný uzávěr. Každý typ má nullovatelnou a nenullovatelnou variantu. Název nullovatelné varianty má jako příponu otazník (např. string?). Vala má neomezenou pointerovou aritmetiku podobně jako např. C++. Podobně jako v C++ jsou pole jiný, praktičtější zápis pointerové aritmetiky. Tedy pole jsou ukazatele a zápisy x[i] je synonymem k *(x + i). Operátor koalescence je označen dvěma otazníky ??. Funkce může měnit hodnotu proměnné z hlediska volajícího kontextu. Takto měněné parametry funkce musí být označeny klíčovými slovy out nebo ref. Klíčové slovo out označuje proměnnou, která je funkci předána neinicializovaná a kterou funkce pro volající stranu inicializuje. Klíčové slovo ref označuje proměnnou, která je funkci předána inicializovaná. Programátor může zadat do definice funkce podmínky, které podle teoretického rozboru jsou nesplněny pouze při nekorektním běhu programu. Při nesplnění podmínek je program ukončen. Následující příklad ukazuje použití klíčových slov requires, ensures a result. Klíčové slovo requires (resp. ensure) označuje výraz typu bool, který musí být splněn při vstupu do (resp. při skončení) funkce. Klíčové slovo result je hodnota vracená funkcí používaná k zapsání ensures podmínky.

int kontrolovana_funkce(int hodnota) requires (hodnota <= maximalni_povolena_hodnota) requires (hodnota >= minimalni_povolena_hodnota) ensures (result <= maximalni_teoreticky_mozny_vysledek) { // tělo funkce }

Datový typ typu proměnné lze získat operátorem typeof, známým z jazyka C (dialektu užívaným standardním kompilátorem GCC). Operátor is zjišťuje, zda lze provést přetypování. Při využití GLib registrace typů vrací metoda get_type() typ třídy. Operátor as slouží k snadnému zápisu dynamického přetypování; A as B je přehlednější zápis A is B ? (A) B : null;. K explicitnímu přetypování nullovatelného typu na korespondující nenulovatelný typ se používá zápis (!) promenna. Vala podporuje generické programování, k jehož zápisu používá obvyklou syntaxi s lomenými závorkami. Vala podporuje v definici parametrů funkce výpustku značenou ve stylu jazyka C třemi tečkami. Seznam názvů parametrů se získá funkcí va_list() a zadaný parametr v definici funkce uvádí typ hodnot parametrů.

void funkce_s_neznamym_poctem_argumentu(string fixed, ...) { var seznam_argumentu = va_list(); string? klic; string hodnota; while (klic = l.arg()) { hodnota = seznam_argumentu.arg(); stdout.printf("Argument jménem %s má hodnotu %s.", klic, hodnota);

Vala poměrně nečekaným způsobem pracuje s řetězci a zavádí operátor @. V řetězcích uvozených operátorem @ se názvy proměnných a výrazy uzavřené závorkou následující za znakem $ vyčíslují. Z důvodů interoperability kódu ve Vale se zdrojovými kódy a knihovnami v jiných jazycích může vynucovat konkrétní pojmenování proměnných a jiných uživatelem definovaných symbolů. V této situaci může dojít ke kolizi pojmenovaní proměnných s klíčovými slovy Valy. Prefix @ způsobuje, že parser Valy klíčové slovo interpretuje jako běžný identifikátor. Ve verbatim řetězcích (oddělovač """) nedochází k escapování znaků.

/* ukázka použití operátoru @ a verbatim řetězce vypisované řetězce jsou přepsané v komentářích řetězce jsou vypisovány na samostatné řádky (řádkový zlom realizuje \n) */ static void main() { int i = 1; int j = 6;

stdout.printf(@"hodnota proměnné i (resp. j) a je $i (resp. $j)\n"); // hodnota proměnné i (resp. j) a je 1 (resp. 6) stdout.printf(@"hodnota výrazu i + j je $(i + j)\n"); // hodnota výrazu i + j je 7 stdout.printf(@"špatně napsaný výraz $i+j\n"); // špatně napsaný výraz 1+j

string @for = "řetězec pojmenovaný klíčovým slovem for"; stdout.printf(@"Hodnota proměnné for je $(@for)\n"); // Hodnota proměnné for je řetězec pojmenovaný klíčovým slovem for stdout.printf("Hodnota proměnné for je " + @for + "\n"); // Hodnota proměnné for je řetězec pojmenovaný klíčovým slovem for

stdout.printf("""verbatim řetězec vypíše "\\"\n """ + "\n"); //verbatim řetězec vypíše "\\"\n }

Koncepce objektů ve Vala má tyto zvláštnosti: Vedle běžných modifikátorů přístupu public, private a protected existuje další modifikátor internal. Internal slouží k zpřístupnění symbolu pouze v rámci jednoho projektu (balíčku). Například internal skryje proměnné VAPI souboru před uživatelskou aplikací. Lze definovat vlastnosti a jejich gettery a settery. Není podporována vícenásobná dědičnost. Rodičovská třída se označuje klíčovým slovem base. Vala umožňuje různé pojmenování konstruktorů a destruktorů. I přesto, že je použita automatická správa paměti, lze volat destruktor explicitně. Destruktor je od konstruktoru odlišen obvyklým prefixem ~.

Následující ukázkový kód demonstruje použití standardních getterů a setterů u vlastností prvni_mereni a druhe_mereni, definování vlastních getterů a setterů u vlastnosti mereni a různě pojmenované konstruktory.

class mereni { public double prvni_mereni { private set; get; default = 0;

public double druhe_mereni { internal set; get; default = 0;

public mereni.vycet(double prvni, double druhy) { prvni_mereni = prvni; druhe_mereni = druhy;

public mereni.stejna_hodnota(double hodnota) { prumer = hodnota;

public mereni() {

public double prumer { private set { prvni_mereni = value; druhe_mereni = value;

get { return (prvni_mereni + druhe_mereni) / 2;

void main() { var m = new mereni(); print(@"$(m.prvni_mereni)"); // vypíše defaultní hodnotu 0 m = new mereni.vycet(9.98,9.93); m = new mereni.stejna_hodnota(10); }

Vala umožňuje přistupovat ke konvenčně pojmenovaným metodám tříd přes speciální úspornou syntaxi. Nejčastěji se využívají indexery, přetypování na řetězec, řezy, definování iterátoru a definování prvků množiny. Použití ukazuje následující příklad.

class priklad { int[] i = {10,2,345,5,89};

public string? get(int index) { if (index > 4) return null; return @"$(i[index])";

public void set(int index, int hodnota) { i[index] = hodnota;

public int slice(long zacatek, long konec) { int vysledek = 0; for (int j = 0; j < 5; j++) { if (j < zacatek) continue; if (j > konec) break; vysledek += i[j];

return vysledek;

public bool contains(int klic) { for (int j = 0; j < 5; j++) { if (i[j] == klic) return true;

return false;

public string to_string() { return @"$(i) $(i) $(i) $(i) $(i)\n";

public trida_iteratoru iterator() { return new trida_iteratoru(this);

class trida_iteratoru { int index = 0; priklad p;

public bool next() { if (index > 4) return false; return true;

public string? next_value() { string vysledek = null; if (index < 5) vysledek = @"$(p[index])"; index++; return vysledek;

public trida_iteratoru(priklad p) { this.p = p;

void main() { var p = new priklad(); print(@"$(p)\n"); //print(p.get); print(p.to_string()); //print(p.to_string()); p = p[2:4]; //p.set(1, p.slice(0,3)); print(p.to_string()); print(11 in p); //print(p.contains(11)); print(p ?? "neplatny index"); //p == null ? p : "neplatny index";

foreach (string s in p) { print(s);

V rozumných případech již tyto metody přirozeně definuje norma jazyka. Konkrétně je předdefinováno převádění čísel na řetězec, řezy (slice) řetězců, iterátory u množin a podobně. Často používané řezy řetězců fungují ve Vale stejně jako v Pythonu.