
# البنية

Phasis هو متجوّل شجرة من أربع مراحل مع آلة افتراضية للبايت كود تعمل عند الحاجة. ومسار البيانات هو:

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

كل مرحلة هي صنف PHP بواجهة صغيرة تستهلكها المرحلة التالية. لا توجد خطوة ربط؛ فالتحليل ينتج شجرة بنية مجردة، ويمر عليها المفسّر مباشرةً.

## المحلّل المعجمي

يحوّل `src/Lexer/Lexer.php` النص المصدر إلى تدفق من مثيلات `Token`. وكل رمز بنية للقراءة فقط تضم النوع (تعداد `TokenType` بنحو 80 حالة) والقيمة والسطر والعمود.

يتعامل المحلّل المعجمي مع:

- القيم العددية الحرفية — عشرية وسداسية عشرية (`0x`) وثمانية (`0o`) وثنائية (`0b`) وأسية، مع فواصل الأرقام.
- السلاسل الحرفية — علامات اقتباس مفردة ومزدوجة، وكل تسلسلات الهروب، والقوالب الحرفية ذات التعبيرات المتداخلة.
- التعبيرات النمطية الحرفية — تحليل كامل للرموز وفق `/pattern/flags`، مع مراعاة الحالات التي ينبغي فيها تفسير `/` كتعبير نمطي أو كعملية قسمة.
- المعرّفات والكلمات المفتاحية وعلامات الترقيم.
- التعليقات السطرية والكتلية، مع الاحتفاظ بها كمعلومات إضافية.
- مصدر Unicode — تُفسَّر بايتات UTF-8 على أنها مصدر JS بترميز UTF-16.

المخرجات مولّد يُصدر الرموز عند الحاجة. ويستهلكها المحلّل مع استباق رمز واحد.

## المحلّل

`src/Parser/Parser.php` محلّل Pratt مكتوب يدويًا. وتوجد أسبقية التعبيرات في `src/Parser/Precedence.php`. أما التعليمات فتستخدم أسلوب التحليل التنازلي العودي الخاص بها.

ينتج عقد شجرة بنية مجردة غير قابلة للتغيير من `src/Ast/`. وتحتفظ كل عقدة بموضعها في المصدر لتتبّع مكدس الاستدعاءات والإبلاغ عن الأخطاء.

أشكال بارزة:

- **التعبير**: `Literal`، `Identifier`، `BinaryExpression`، `UnaryExpression`، `AssignmentExpression`، `CallExpression`، `MemberExpression`، `ArrowFunction`، `ObjectExpression`، `ArrayExpression`، `ConditionalExpression`، `TemplateLiteral`، `SpreadElement`، `NewExpression`، `ThisExpression`، `SequenceExpression`، `TaggedTemplate`، `ClassExpression`، `YieldExpression`، `AwaitExpression`.
- **التعليمة**: `BlockStatement`، `IfStatement`، `ForStatement`، `ForInStatement`، `ForOfStatement`، `WhileStatement`، `DoWhileStatement`، `SwitchStatement`، `ReturnStatement`، `ThrowStatement`، `TryStatement`، `BreakStatement`، `ContinueStatement`، `ExpressionStatement`.
- **التصريح**: `VariableDeclaration`، `FunctionDeclaration`، `ClassDeclaration`، `ImportDeclaration`.
- **النمط** (التفكيك): `ArrayPattern`، `ObjectPattern`، `RestElement`، `AssignmentPattern`.

يُنفَّذ الإدراج التلقائي للفاصلة المنقوطة في المحلّل (وليس في الماسح اللغوي) وفقًا للمواصفات.

## المفسّر

`src/Runtime/Interpreter.php` هو متجوّل AST. يزور كل عقدة ويعيد `JsValue` (أو `Completion` للعبارات التي تغيّر تدفّق التحكم).

الفئات المساندة الأساسية:

- **`Environment`** (`src/Runtime/Environment.php`) — سلسلة نطاق معجمية. تنشئ كل مكالمة دالة بيئة جديدة تشير إلى والدها المعجمي. يُرفع `var` إلى نطاق الدالة؛ أما `let` و`const` فنطاقهما كتلي ولهما TDZ.
- **`CallStack`** (`src/Runtime/CallStack.php`) — مكدس صريح بحد أقصى للعمق. تدفع مكالمات الدوال والطرائق إطارات إليه، وتفكّ الاستثناءات هذه الإطارات.
- **`Completion`** (`src/Runtime/Completion.php`) — اتحاد مميّز من `normal` و`return` و`throw` و`break` و`continue`، إضافة إلى قيمة وتسمية اختياريتين.
- **`Reference`** (`src/Runtime/Reference.php`) — نوع Reference في المواصفات لتقييم الطرف الأيسر في عمليات الإسناد و`delete`.

## القيم

قيم JavaScript هي كائنات PHP ضمن `src/Value/`. يطبّق كل منها الواجهة `JsValue` ويحمل طرائق تحويل النوع الخاصة به (`toNumber()` و`toString()` و`toBoolean()`).

| الفئة | نوع JS |
|---|---|
| `JsUndefined` | `undefined` (مفردة) |
| `JsNull` | `null` (مفردة) |
| `JsBoolean` | `true` / `false` |
| `JsNumber` | عدد عشري مزدوج وفق IEEE 754؛ يحافظ على NaN و±Infinity و±0 |
| `JsString` | دلالات السلاسل وفق UTF-16 |
| `JsObject` | كائن أساسي بخريطة خصائص وسلسلة نماذج أولية |
| `JsArray` | يوسّع `JsObject` مع تتبّع الطول |
| `JsFunction` | إغلاق يلتقط `Environment` |
| `JsSymbol` | قيمة أولية Symbol |
| `JsBigInt` | دقة اعتباطية عبر bcmath |
| `JsProxy` | الفخاخ الـ13 كلها، قابلة للإلغاء |
| `JsPromise` | منفّذ متزامن + طابور مهام دقيقة |
| `JsGenerator` | وضع مزدوج: لقطة إطار (أجسام مترجمة إلى بايت كود؛ راجع [مولّدات لقطة الإطار في آلة البايت كود](https://phasis.inline0.dev/ar/docs/advanced/bytecode-vm)) مع خيار احتياطي باستخدام Fiber من PHP لـ`yield*` وtry-with-yield والمولّدات غير المتزامنة |
| `JsMap` و`JsSet` و`JsWeakMap` و`JsWeakSet` و`JsWeakRef` و`JsFinalizationRegistry` | مجموعات |
| `JsArrayBuffer` و`JsSharedArrayBuffer` و`JsDataView` و`JsTypedArray` | بيانات ثنائية |

يمثّل التعامل مع الأعداد أكبر مصدر منفرد للأخطاء التاريخية: يجب أن يكون `NaN !== NaN` صحيحًا، ويجب أن يكون `-0 === 0` صحيحًا، وتتطلب الحالات الطرفية لـToNumber عناية دقيقة على مستوى البتات. تطبّق الفئة `Spec/TypeConversion` خوارزميات المواصفات حرفيًا، وقد خضعت لاختبارات شاملة.

## المكتبة المضمّنة

يوفّر `src/BuiltIn/` كل كائنات المكتبة القياسية: `Array` و`String` و`Object` و`Math` و`JSON` و`Date` و`RegExp` و`Map` و`Set` و`Promise` و`Proxy` و`Reflect` و`Symbol` و`BigInt` و`TypedArray` و`Temporal` و`Intl` و`console`، إلى جانب حزم Web Platform وFetch (`URL` و`Headers` و`Request` و`Response` و`Blob` و`FormData` وStreams كاملة و`EventTarget` و`AbortController`/`AbortSignal` و`DOMException` و`structuredClone` و`performance` و`TextEncoder`/`TextDecoder` و`atob`/`btoa`)، و`crypto` + `SubtleCrypto` و`WebSocket` و`XMLHttpRequest` وحلقة الأحداث (`setTimeout` و`setInterval` و`queueMicrotask` و`AsyncContext`).

كل مكوّن مضمّن هو طريقة static من `install()` في فئة. يستدعيها `Engine` بترتيب الاعتماد عند الإنشاء. ويعرّف كل منها سلسلة النماذج الأولية الخاصة به، ويثبّت الطرائق ككائنات `JsFunction` مغلّفة حول إغلاقات PHP، ويتيح المُنشئ كعنصر عام.

## جسر PHP↔JS

يتم تحويل القيم عبر الحدود في موضعين:

- **`Phasis\Interop\PhpToJs::convert()`** — قيمة PHP إلى `JsValue`، وتُستخدم من قبل `setGlobal()` ومعاملات `call()` والقيم المعادة من دوال المضيف. يتحول callable من PHP إلى `JsFunction` يستدعي جسمه ذلك العنصر.
- **`PhpToJs::toPhp()`** — من `JsValue` إلى PHP لمعاملات دالة المضيف.
- **`Engine::toPhp()`** (خاص) — من `JsValue` إلى PHP لنتائج `eval()` و`call()`.

لا يوجد جسر للكائنات: تتحول كائنات PHP غير القابلة للاستدعاء إلى `undefined` ([المشكلة #18](https://github.com/inline0/phasis/issues/18)). لا علاقة لفئة `JsToPhp` في `src/Bytecode/` بالتشغيل البيني؛ فهي أداة التحويل الموضحة أدناه. قواعد التحويل موثقة في [تحويل القيم](https://phasis.inline0.dev/ar/docs/interop/values).

## معالجة الأخطاء

يتحوّل `throw` غير المعالج في JS إلى PHP `Phasis\Exceptions\JsThrowable`؛ أما الأخطاء التي يرفعها المحرك نفسه فتظهر كـ`Phasis\Exceptions\TypeError` أو `RangeError` أو `ReferenceError`، وكلها فئات فرعية من `Phasis\Exceptions\RuntimeError`. داخل المحرك، يلتقط `try` / `catch` في JS كلاً من `JsThrowable` وأي `RuntimeError` و`Phasis\Exceptions\SyntaxError`. أما استثناءات PHP الأخرى، بما فيها تلك التي تطلقها دوال المضيف، فلا يجري تحويلها وتنتقل مباشرة إلى مستدعي PHP ([المشكلة #20](https://github.com/inline0/phasis/issues/20)).

يوجد حدّان: سقف مكدس الاستدعاءات (`CallStack::maxDepth`، 4,096 إطارًا، إضافة إلى حارس من 8,192 إطارًا للإغلاقات المحوّلة) و`maxLoopIterations`، الذي يُضبط عبر `Engine::setLimit()` ولا يطبّقه سوى متجوّل الشجرة ([المشكلة #19](https://github.com/inline0/phasis/issues/19)). كلاهما يطلق `Phasis\Exceptions\InternalError`. لا توجد حدود لطول السلسلة أو حجم المخرجات أو زمن التنفيذ.

## آلة البايت كود

تُحوّل الدوال كثيرة الاستخدام بطريقتين. يصدر `JsToPhp` (في `src/Bytecode/`) إغلاق PHP للأجسام التي تكثر فيها الأعداد أو المتغيرات المحلية، ويمكن لمترجم JIT التتبّعي في PHP تجميعه إلى شيفرة أصلية؛ إذ تحوّل سلسلة المعالجة قراءات `new Ctor(args)` و`obj.method(args)` و`this.member`، وهذا يكفي لجعل النمط الشائع لطريقة فئة داخل حلقة يتجاوز الآلة الافتراضية بالكامل. أما كل ما عدا ذلك فيُترجم إلى بايت كود مسطّح يستهلكه `VM::execute`، مع مكدس استدعاءات مخصص يُبقي كل استدعاء JS داخل إطار PHP واحد، وذاكرة تخزين مؤقت مضمنة لكل PC لقراءات طرائق النماذج الأولية. كما تُترجم أجسام المولّدات البسيطة إلى بايت كود، إذ تلتقط `Op::YIELD` لقطة إطار على الكومة بدلًا من العبور عبر Fiber من PHP.

أي بنية لا يحوّلها المترجم (e.g و`with` و`try` مع catch يعيد الربط و`yield*` والمولّدات غير المتزامنة) تعود إلى متجوّل الشجرة. راجع [آلة البايت كود](https://phasis.inline0.dev/ar/docs/advanced/bytecode-vm) للاطلاع على الآلية كاملة.
