## Programovací jazyk

Tato kapitola přidává ukazatele a (TODO!) operátor přetypování.

### Definice

V definici podprogramu umožníme, aby se na místě návratového typu
objevilo klíčové slovo ‹void›, které značí, že výsledek vyhodnocení
podprogramu «není hodnota».

### Hodnoty a typy

V této kapitole přidáváme velmi důležitou novou třídu hodnot, a
společně s ní příslušné typy. Je-li ‹T› libovolný typ, pak ‹T *› je
typ „ukazatele na objekt typu ‹T›“. Hodnota typu ‹T *› je
reprezentovaná celým číslem bez znaménka, které odpovídá «adrese»,
na které je uložen příslušný objekt.¹

Klíčové slovo ‹void› označuje (pseudo)typ ‹void›. Nejedná se o typ
v běžném smyslu, protože neexistuje žádná hodnota typu ‹void›.
Abychom odlišili „běžné“ typy (s existujícími hodnotami), zavedeme
pojem «hodnotový typ». Typ ‹void› je tak prvním typem, který
hodnotový není.

Přesto, že nemůže existovat hodnota typu ‹void›, je možné napsat
«výraz» tohoto typu. Takový výraz ale není možné ve většině případů
použít jako podvýraz. Jediná místa, kde se «podvýraz» typu ‹void›
objevit smí, jsou:

 • libovolný operand operátoru čárka (nezávisle),
 • ‹e₁› a ‹e₂› ve výrazu ‹ternary ≡ e₀ ? e₁ : e₂› – pak je typ
   výrazu ‹ternary› jako celku také ‹void›,²
 • ‹e₁› ve výrazu přetypování ‹( void ) e₁›.

Je-li ‹expr› výraz typu ‹void›, může se také objevit v příkazu tvaru
‹expr;› (příkaz tvořený výrazem – v tomto případě se ovšem nejedná
o podvýraz).

¹ To neznamená, že objekt je s touto adresou pevně svázán – pouze
  to, že kdykoliv může být objekt «sekvenčně pozorován», bude
  k nalezení na této adrese.
² Pravidla pro typy ‹e₁› a ‹e₂› zároveň vynucují, že musí být
  ‹void› oba nebo ani jeden.

### Výrazy

Tato kapitola zavádí tři nové tvary výrazů. Abychom ale mohli tyto
výrazy správně popsat, musíme nejprve upravit způsob, jakým
uvažujeme o vyhodnocení výrazů a zavést několik nových pojmů.

Některé výrazy je možné «vyhodnotit na objekt» – prozatím se jedná
pouze o výrazy tvaru ‹jméno› kde ‹jméno› pojmenovává nějakou
proměnnou.¹ Vyhodnotí-li se nějaký výraz na objekt, další postup
závisí na «kontextu» v jakém se objevuje:

 1. Většina podvýrazů tvoří «r-kontexty», tzn. takové, které
    očekávají hodnotu – např. operandy aritmetických nebo relačních
    operátorů, parametry předávané podprogramu, pravý operand
    operátoru přiřazení, atd. Je-li nějaký podvýraz vyhodnocen na
    objekt v «r-kontextu», je z tohoto objektu navíc «přečtena
    hodnota» a výsledkem výrazu je až tato hodnota.
 2. Některé podvýrazy jsou ale «l-kontextem» a v takovém případě se
    vyhodnocení zastaví určením «objektu» a čtení hodnoty ze
    získaného objektu se «neprovede». Jedná se zejména o levý
    operand přiřazovacího operátoru (odtud také název «l-kontext»).

Objektu získanému vyhodnocením výrazu se říká také «l-hodnota»
(chceme-li pak zdůraznit, že mluvíme o „normálních“ «hodnotách» a
nikoliv «objektech»/«l-hodnotách», můžeme použít také pojem
«r-hodnota»).

Nyní můžeme konečně přistoupit k popisu nových tvarů výrazů:

 1. Výraz ‹*expr₁›, tzv. «dereferenci», lze použít pouze
    vyhodnotí-li se ‹expr₁› na «platný ukazatel» (jedná-li se
    o ukazatel neplatný, program je chybný a jeho chování není
    určeno), a vyhodnotí se na «objekt» (l-hodnotu), který je tímto
    ukazatelem popsán. Je-li výraz ‹expr₁› typu ‹T *›, je výraz
    ‹*expr₁› typu ‹T›.
 2. Výraz ‹&expr₁› lze použít jen tehdy, vyhodnotí-li se ‹expr₁› na
    «objekt» (je l-hodnotou) a výsledkem je «ukazatel» na tento
    objekt. Unární operátor ‹&› se anglicky nazývá „address of“,
    nicméně jeho výsledkem není striktně vzato adresa.² Je-li
    výraz ‹expr₁› typu ‹T›, je výraz ‹&expr₁› typu ‹T *›.
 3. ‹expr₁ = expr₂› (jedná se o zobecnění již zavedeného ‹var =
    expr₂›) lze použít, vyhodnotí-li se ‹expr₁› na objekt (tzn.
    ‹expr₁› popisuje l-hodnotu). Efektem tohoto výrazu je, že
    hodnota uložená v takto popsaném objektu se přepíše na hodnotu,
    kterou získáme vyhodnocením výrazu ‹expr₂›.

¹ Na rozdíl od jazyka C++ výrazy tvaru ‹var = e₁› ani tvaru ‹e₀ ? e₁
  : e₂› nikdy objekt nepopisují (nejsou l-hodnotami).
² Tuto zkratku si můžeme dovolit pouze proto, že použití operátoru
  ‹&› donutí překladač „zafixovat“ pozorovatelnou adresu objektu –
  každé použití ‹&› na objekt musí vrátit stejnou hodnotu a každá
  dereference takto získaného ukazatele musí, po dobu jeho
  platnosti, popisovat tento objekt.

### Příkazy

Příkaz ‹return› v definici podprogramu bez návratové hodnoty
(návratový typ je ‹void›) píšeme ‹return;› – nesmí se zde zejména
objevit výraz.
