
# Architektúra

Phasis je štvorstupňový stromový interpret s príležitostným použitím virtuálneho stroja s bajtkódom. Tok dát je takýto:

```
JS text
  │
  ▼
┌──────────┐
│  Lexer   │  src/Lexer/
└────┬─────┘
     ▼ tokens
┌──────────┐
│  Parser  │  src/Parser/
└────┬─────┘
     ▼ AST nodes
┌──────────────┐
│ Interpreter  │  src/Runtime/
│  + Bytecode  │  src/Bytecode/
│      VM      │
└────┬─────────┘
     ▼ JsValue
PHP host
```

Každý stupeň je trieda PHP s malým rozhraním, ktoré využíva nasledujúci stupeň. Fáza prepojenia chýba — parsovanie vytvorí AST, ktorý interpret priamo prechádza.

## Lexikálny analyzátor

`src/Lexer/Lexer.php` prevádza zdrojový text na prúd inštancií `Token`. Každý token je nemenná štruktúra: typ (výčet `TokenType`, približne 80 možností), hodnota, riadok, stĺpec.

Lexikálny analyzátor spracúva:

- Číselné literály — desiatkové, hexadecimálne (`0x`), osmičkové (`0o`), binárne (`0b`), exponenciálne a s oddeľovačmi číslic.
- Reťazcové literály — jednoduché a dvojité úvodzovky, všetky escape sekvencie a šablónové literály s vnorenými výrazmi.
- Literály regulárnych výrazov — úplná tokenizácia `/pattern/flags` so zohľadnením toho, či má byť `/` regulárny výraz alebo delenie.
- Identifikátory, kľúčové slová, interpunkcia.
- Komentáre (riadkové a blokové), zachované ako nepodstatné prvky.
- Zdroj Unicode — bajty UTF-8 interpretované ako zdroj JS UTF-16.

Výstupom je generátor, ktorý postupne vracia tokeny podľa potreby. Syntaktický analyzátor ich spracúva s jedn tokenovým náhľadom dopredu.

## Parser

`src/Parser/Parser.php` je ručne napísaný Prattov syntaktický analyzátor. Priorita operátorov vo výrazoch je určená v `src/Parser/Precedence.php`. Príkazy sa analyzujú samostatne rekurzívnym zostupom.

Vytvára nemenné uzly AST z `src/Ast/`. Každý uzol nesie informáciu o zdrojovej pozícii pre výpis zásobníka a hlásenie chýb.

Významné tvary:

- **Výraz**: `Literal`, `Identifier`, `BinaryExpression`, `UnaryExpression`, `AssignmentExpression`, `CallExpression`, `MemberExpression`, `ArrowFunction`, `ObjectExpression`, `ArrayExpression`, `ConditionalExpression`, `TemplateLiteral`, `SpreadElement`, `NewExpression`, `ThisExpression`, `SequenceExpression`, `TaggedTemplate`, `ClassExpression`, `YieldExpression`, `AwaitExpression`.
- **Príkaz**: `BlockStatement`, `IfStatement`, `ForStatement`, `ForInStatement`, `ForOfStatement`, `WhileStatement`, `DoWhileStatement`, `SwitchStatement`, `ReturnStatement`, `ThrowStatement`, `TryStatement`, `BreakStatement`, `ContinueStatement`, `ExpressionStatement`.
- **Deklarácia**: `VariableDeclaration`, `FunctionDeclaration`, `ClassDeclaration`, `ImportDeclaration`.
- **Vzor** (destrukturalizácia): `ArrayPattern`, `ObjectPattern`, `RestElement`, `AssignmentPattern`.

Automatické vkladanie bodkočiarok sa podľa špecifikácie vykonáva v syntaktickom analyzátore, nie v lexikálnom analyzátore.

## Interpret

`src/Runtime/Interpreter.php` prechádza strom AST. Navštívi každý uzol a vráti `JsValue` (alebo `Completion` pri príkazoch, ktoré menia tok riadenia).

Kľúčové podporné triedy:

- **`Environment`** (`src/Runtime/Environment.php`) — reťazec lexikálnych rozsahov. Každé volanie funkcie vytvorí nové prostredie odkazujúce na svoj lexikálny rodičovský rozsah. `var` sa prenáša do rozsahu funkcie; `let` / `const` majú rozsah bloku a TDZ.
- **`CallStack`** (`src/Runtime/CallStack.php`) — explicitný zásobník s limitom hĺbky. Volania funkcií a metód pridávajú rámce; výnimky ich odvíjajú.
- **`Completion`** (`src/Runtime/Completion.php`) — rozlíšená únia hodnôt `normal`, `return`, `throw`, `break`, `continue`, s voliteľnou hodnotou a označením.
- **`Reference`** (`src/Runtime/Reference.php`) — referenčný typ podľa špecifikácie na vyhodnocovanie ľavej strany priradení a `delete`.

## Hodnoty

Hodnoty JavaScript sú objekty PHP v rámci `src/Value/`. Každá implementuje rozhranie `JsValue` a obsahuje vlastné metódy na konverziu typov (`toNumber()`, `toString()`, `toBoolean()`).

| Trieda | Typ JS |
|---|---|
| `JsUndefined` | `undefined` (singleton) |
| `JsNull` | `null` (singleton) |
| `JsBoolean` | `true` / `false` |
| `JsNumber` | IEEE 754 double; zachováva NaN, ±Infinity, ±0 |
| `JsString` | Sémantika reťazcov UTF-16 |
| `JsObject` | Základný objekt s mapou vlastností a reťazcom prototypov |
| `JsArray` | Rozširuje `JsObject` a sleduje dĺžku |
| `JsFunction` | Uzáver so zachyteným `Environment` |
| `JsSymbol` | Primitívny symbol |
| `JsBigInt` | Ľubovoľná presnosť prostredníctvom bcmath |
| `JsProxy` | Všetkých 13 záchytných metód, možnosť odvolania |
| `JsPromise` | Synchrónny vykonávač + front mikroúloh |
| `JsGenerator` | Dvojrežimový: snímka rámca (tela skompilované do bajtkódu; pozri [Virtuálny stroj s bajtkódom § Generátory so snímkou rámca](https://phasis.inline0.dev/sk/docs/advanced/bytecode-vm)) s náhradnou možnosťou PHP Fiber pre `yield*`, try-with-yield a asynchrónne generátory |
| `JsMap`, `JsSet`, `JsWeakMap`, `JsWeakSet`, `JsWeakRef`, `JsFinalizationRegistry` | kolekcie |
| `JsArrayBuffer`, `JsSharedArrayBuffer`, `JsDataView`, `JsTypedArray` | binárne údaje |

Spracovanie čísel je historicky najväčším zdrojom chýb: `NaN !== NaN` musí byť true a `-0 === 0` musí byť true; okrajové prípady ToNumber si vyžadujú presné bitové spracovanie. Trieda `Spec/TypeConversion` implementuje algoritmy špecifikácie doslovne a je vyčerpávajúco testovaná.

## Vstavaná knižnica

`src/BuiltIn/` poskytuje všetky objekty štandardnej knižnice: `Array`, `String`, `Object`, `Math`, `JSON`, `Date`, `RegExp`, `Map`, `Set`, `Promise`, `Proxy`, `Reflect`, `Symbol`, `BigInt`, `TypedArray`, `Temporal`, `Intl`, `console` a tiež balíky Web Platform / Fetch (`URL`, `Headers`, `Request`, `Response`, `Blob`, `FormData`, úplné Streams, `EventTarget`, `AbortController`/`AbortSignal`, `DOMException`, `structuredClone`, `performance`, `TextEncoder`/`TextDecoder`, `atob`/`btoa`), `crypto` + `SubtleCrypto`, `WebSocket`, `XMLHttpRequest` a slučku udalostí (`setTimeout`, `setInterval`, `queueMicrotask`, `AsyncContext`).

Každá vstavaná funkcia je statická metóda `install()` na triede. `Engine` ich pri vytváraní volá v poradí podľa závislostí. Každá definuje reťazec prototypov, nainštaluje metódy ako inštancie `JsFunction` obalené okolo uzáverov PHP a sprístupní konštruktor ako globálnu premennú.

## Prepojenie PHP↔JS

Konverzia hodnôt cez hranicu prebieha na dvoch miestach:

- **`Phasis\Interop\PhpToJs::convert()`** — hodnota PHP na `JsValue`, používa sa pre argumenty `setGlobal()`, `call()` a návratové hodnoty hostiteľských funkcií. Volateľná hodnota PHP sa zmení na `JsFunction`, ktorého telo ju volá.
- **`PhpToJs::toPhp()`** — `JsValue` na PHP pre argumenty hostiteľskej funkcie.
- **`Engine::toPhp()`** (súkromné) — `JsValue` na PHP pre výsledky `eval()` a `call()`.

Neexistuje prepojenie objektov: objekty PHP, ktoré nie sú volateľné, sa konvertujú na `undefined` ([problém č. 18](https://github.com/inline0/phasis/issues/18)). Trieda `JsToPhp` v `src/Bytecode/` nesúvisí s interoperabilitou; ide o transpiler opísaný nižšie. Pravidlá konverzie sú uvedené v časti [Konverzia hodnôt](https://phasis.inline0.dev/sk/docs/interop/values).

## Spracovanie chýb

Nezachytená výnimka JS `throw` sa zmení na PHP `Phasis\Exceptions\JsThrowable`; chyby vyvolané samotným jadrom sa zobrazia ako `Phasis\Exceptions\TypeError`, `RangeError` alebo `ReferenceError`, ktoré sú všetky podtriedami `Phasis\Exceptions\RuntimeError`. V jadre zachytáva JS `try` / `catch` výnimky `JsThrowable`, všetky `RuntimeError` a `Phasis\Exceptions\SyntaxError`. Ostatné výnimky PHP vrátane tých, ktoré vyhodia hostiteľské funkcie, sa nekonvertujú a prejdú priamo k volajúcemu PHP ([problém č. 20](https://github.com/inline0/phasis/issues/20)).

Existujú dva limity: strop zásobníka volaní (`CallStack::maxDepth`, 4,096 rámcov a ochrana s 8,192 rámcami pre transpilarované uzávery) a `maxLoopIterations`, nastavovaný cez `Engine::setLimit()`, ktorý vynucuje iba stromový interpret ([problém č. 19](https://github.com/inline0/phasis/issues/19)). Pri prekročení oboch limitov sa vyhodí `Phasis\Exceptions\InternalError`. Neplatia žiadne limity dĺžky reťazca, veľkosti výstupu ani času vykonávania.

## Virtuálny stroj s bajtkódom

Horúce funkcie sa prekladajú dvoma spôsobmi. `JsToPhp` (v `src/Bytecode/`) vytvára PHP uzáver pre telá funkcií s číselnými hodnotami a množstvom lokálnych premenných, ktorý dokáže trasovací JIT nástroja PHP skompilovať do natívneho kódu; pipeline prekladá čítania `new Ctor(args)`, `obj.method(args)` a `this.member`, čo stačí na to, aby typický vzor metódy triedy vo vnútri cyklu úplne obišiel VM. Všetko ostatné sa skompiluje do plochého bajtkódu, ktorý vykonáva `VM::execute`. Používa vlastný zásobník volaní, ktorý udržiava každé volanie JS v jednom rámci PHP, a inline cache pre čítania metód prototypu pre každý PC. Jednoduché telá generátorov sa tiež kompilujú do bajtkódu a `Op::YIELD` zachytáva snímku rámca na halde namiesto prechodu cez Fiber PHP.

Všetky konštrukcie, ktoré kompilátor nepreloží (e.g. `with`, `try` s premenenou väzbou v bloku catch, `yield*`, asynchrónne generátory), sa vykonávajú pomocou stromového interpretera. Úplný opis mechanizmu nájdete v časti [Virtuálny stroj bajtkódu](https://phasis.inline0.dev/sk/docs/advanced/bytecode-vm).
