Представляємо Zephir

Zephir - мова, яка відповідає основним потребам розробника PHP, який намагається написати та скомпілювати код, який може бути виконаний з-під PHP. Він має динамічну/статичну типізацію і деякі його функції будуть знайомі PHP-розробникам.

Zephir це скорочення слів Z(end) E(ngine)/PH(P)/I(nte)r(mediate). While this suggests that the pronunciation should be “zephyr”, the creators of Zephir actually pronounce it zaefire.

Привіт світ!

Кожна мова має власний приклад написання «Привіт світ» програми. У цьому вступі продемонстровано деякі важливі особливості мови.

Код в Zephir повинен розміщатися в класах. Мова призначена для створення об’єктно-орієнтованих бібліотек/фреймворків, тому код за межами класу не допускається. Крім того, необхідно вказувати простір імен:

namespace Test;

/**
 * Це зразок класу
 */
class Hello
{
    /**
     * Це зразок методу
     */
    public function say()
    {
        echo "Привіт світ!";
    }
}

Після компіляції код матиме вигляд, наведений нижче. Такий код без перешкод буде скомпільований за допомогою gcc/clang/vc++:

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "php_test.h"
#include "test.h"

#include "kernel/main.h"

/**
 * Це зразок класу
 */
ZEPHIR_INIT_CLASS(Test_Hello) {
    ZEPHIR_REGISTER_CLASS(Test, Hello, hello, test_hello_method_entry, 0);
    return SUCCESS;
}

/**
 * Це зразок методу
 */
PHP_METHOD(Test_Hello, say) {
    php_printf("%s", "Привіт світ!");
}

Насправді, розробник, який використовує Zephir, не повинен знати або навіть зрозуміти C. Однак, якщо у вас є досвід роботи з компіляторами, мовою С або ж знання внутрішньої будови PHP - це дасть змогу чіткіше зрозуміти, як працює Zephir з середини.

Смак Зефіру

У наступних прикладах ми опишемо лише частину деталей, щоб зрозуміти, що відбувається. Задум в тому, щоб показати вам, на що схоже програмування на Zephir. Деталі ми розберемо в наступних розділах.

Наступний приклад дуже простий; він реалізує клас і метод, який є маленькою програмою, що перевіряє типи масиву.

Розгляньмо детальніше цей код, щоб ви могли почати вивчати синтаксис Zephir. Ці рядки містять багацько деталей! Ми пояснимо загальні ідеї:

namespace Test;

/**
 * MyTest (test/mytest.zep)
 */
class MyTest
{
    public function someMethod()
    {
        /* Змінні мають бути оголошені */
        var myArray;
        int i = 0, length;

        /* Створюємо масив */
        let myArray = ["hello", 0, 100.25, false, null];

        /* Рахуємо довжину масиву в змінні типу 'int' (ціле число) */
        let length = count(myArray);

        /* Друкуємо значення */
        while i < length {
            echo typeof myArray[i], "\n";
            let i++;
        }

        return myArray;
    }
}

Перший рядок у цьому методі містить ключові слова var та int. Вони використовуються для оголошення змінної в локальній області. Кожна змінна, яка використовується в методі, повинна бути оголошена з відповідним типом. Оголошення є обов’язковим, це допомагає компілятору попередити вас про помилкові змінні, або змінні, які оголошені за межами локальної області видимості, що в свою чергу призведе до помилок під час виконання.

Динамічні змінні оголошуються з ключовим словом var. Ці змінні можна призначити і перепризначити для різних типів. З іншого боку, i та length є цілочисельними статично типізованими змінними, які можуть мати цей тип до кінця виконання програми.

Відміну від PHP вам не потрібно ставити знак долара ($) перед іменами змінних.

Zephir підтримує такий же синтаксис коментарів як у Java, C#, C++ і т. д. Тег // comment закоментовує поточний рядок, а /* comment */ може закоментувати кілька рядків.

Початково, змінні є незмінними. Це означає, що Zephir очікує, що більшість змінних не буде змінюватися. Змінні, які зберігаються своє початкове значення при компіляції можуть бути оптимізовані до статичних констант. Якщо значення змінної повинне змінюватися, ви повинні використовувати ключслово let:

/* Створюємо масив */
let myArray = ["hello", 0, 100.25, false, null];

Початково, масиви є динамічнотипізованими, як в PHP. Вони можуть містити значення різних типів. Функції з PHP можна використовувати у Zephir. У наступному прикладі викликається функція count, але компілятор може виконати оптимізацію і взагалі не робити виклику, оскільки він уже знає розмір масиву:

/* Підрахувати розмір масиву в змінну типу 'int */
let length = count(myArray);

Дужки у потоках керування є необов’язковими. Ви можете використовувати їх, якщо вам так зручніше.

while i < length {
    echo typeof myArray[i], "\n";
    let i++;
}

Оскільки PHP працює лише з динамічними змінними, методи завжди повертають динамічні змінні. Це означає, якщо повернути статичнотипізовану змінну, то з боку PHP ми отримаємо динамічнотипізовану змінну й зможемо використати її в своєму PHP-коді. Зверніть увагу. Компілятор сам керує пам’яттю, так само, як це робить PHP. Тому вам не потрібно хвилюватися про виділення чи звільнення пам’яті, як це є в C.