Иван Стеценко: ЯП zephir. Панацея или лечение?
TRANSCRIPT
ZephirЕще один язык программирования
О чем будем слушать?
• Суть интерпретируемого PHP и как с этим жить.
• Панацея Zephir. “А что там под капотом?”
• “Как выучить Zephir за 21 день.”
• Что же будет дальше?
Суть интерпретируемого PHP и как с этим жить.
Переменные
typedef union _zvalue_value { long lval; double dval; struct { char *val; int len; } str; HashTable *ht; zend_object_value obj;} zvalue_value;
typedef struct _zval_struct { zvalue_value value; zend_uint refcount__gc; zend_uchar type; zend_uchar is_ref__gc;} zval;
Массивы
typedef struct _hashtable { uint nTableSize; uint nTableMask; uint nNumOfElements; ulong nNextFreeElement; Bucket *pInternalPointer; Bucket *pListHead; Bucket *pListTail; Bucket **arBuckets; dtor_func_t pDestructor; zend_bool persistent; unsigned char nApplyCount; zend_bool bApplyProtection;#if ZEND_DEBUG int inconsistent;#endif} HashTable;
typedef struct bucket { ulong h; uint nKeyLength; void *pData; void *pDataPtr; struct bucket *pListNext; struct bucket *pListLast; struct bucket *pNext; struct bucket *pLast; const char *arKey;} Bucket;
Функции
• Создание стека для функции.
• Передача аргументов в стек.
• Вызов функции.
• Парсинг аргументов.
• Логика.
• Возврат значений.
• Удаление стека.
Панацея Zephir. “А что там под капотом?”
Zephir - Zend Engine Php Intermediate
Zephir - высокоуровневый язык программирования для быстрого и простого создания PHP extensions.
Мотивация
• С — сложно.
• Zend Engine — сложно + страшно + долго.
• С+Zend Engine — (сложно+страшно)^2.
Решение
Zephir — DSL (Domain Specific Language).
*.zep
С-parser (json)
Static analysis + Block Optimisation
Code generation + Optimisation
С + Zephir KernelMake files
Что под капотом?
AST
namespace Test;
abstract class SimpleClass{ abstract public function simpleMethod(string something);}
[{
"char": 8,"file": "/User/firecoder/test/simpleclass.zep","line": 3,"name": "Test","type": "namespace"
},{
"abstract": 1,"char": 14,"file": "/User/firecoder/test/simpleclass.zep","final": 0,"line": 3,"name": "SimpleClass","type": "class""definition": {
"char": 14,"file": "/User/firecoder/test/simpleclass.zep","line": 3,"methods": [
{"char": 28,"file":
"/User/firecoder/test/simpleclass.zep","line": 5,"name": "simpleMethod","parameters": [
{"char": 59,"const": 0,"data-type":
"string","file":
"/User/firecoder/test/simpleclass.zep","line": 5,"mandatory":
0,"name":
"something","reference": 0,"type":
"parameter"}
],"type": "method","visibility": [
"abstract","public"
]}
]}
}]
$HOME/test/simpleclass.zep
Чем отличается от PHP• Декларативный стиль.
• Статическая/динамическая типизация.
• Пространства имен - обязательно!
• Запрещен глобальный код.
• Компиляция Ahead-of-time.
• Безопасная работа с памятью.
Динамическая типизация
Практически ничем не отличается от PHP
Декларативный стиль: объявили и только после используем
var a, b, c;
// Initialize variableslet a = "hello", b = false;
// Change their valueslet a = 10, b = “140";
// Perform operations between themlet c = a + b;
Поддерживаемые типы
booleaninteger
float/doublestringarrayobject
resourcenull
Статическая типизация
• Более эффективный статический анализ кода при компиляции.
• Возможность провести дополнительные оптимизации при компиляции.
• Лучший выбор для высокопроизводительных приложений.
Поддерживаемые типы
booleanunsigned integer/integer
unsigned char/charunsigned long/long
float/doublestringarray
// Dynamicalvar a = 1;
// arraysvar b = [1, 2, 3];array b = [1, 2, 3];array c = [1: 'a', "index": false];
// Staticalint a = -1;let a = false; // automatically casted to 0let a = "string"; // throws a compiler exception
uint a = 1;float pi = 3.14;bool a = true;string a = "Test string";char a = 'A';
// Objectsvar myObject;let myObject = new \stdClass(), myObject->property = "value";
Немного переменных
StringCharArrayLong
Double
Встроенные методы
Функционал в объектно-ориентированном стиле для всех имеющихся типов
string s;s->length(); // strlen()s->trim(); // trim()s->upperfirst(); // ucfirst()
array a = [1: "one", "two": 2];a->rev(); // array_reverse()a->keys(); // array_keys()a->hasKey(“one”); array b;a->merge(b) // array_merge()
int a = -1;a->pow(2);
Встроенные методы
https://github.com/phalcon/zephir/tree/master/Library/Types
Встроенные методы для array
array arr, usigned, signed; arr = [1, 5, -200, 666, -15];
arr->walk(function(int value) {
if (value >= 0) {let signed[] = value;
} else {let usigned[] = value;
}}
);
array arr = [1, 4, 42, 6, 100500];array powArray = arr->map(value => pow(value, 4));
• Парадигма ООП.• Один файл - один класс.
Пространства имен
mylibrary/router.zep mylibrary/router/exception.zep
Методы/Функции• Можем указать тип возвращаемых
данных.
• Можем указать тип параметров.
• Тип передаваемого аргумента приводится к ожидаемому в случае, если они не совпадают, и это возможно.
• Можем указать read-only параметры.
• Имеем сахар для get, set, toString.
namespace Test;
class Hello{ const HELLO = "hello"; protected customString = null { get, set };
public function say(string word) -> string { return word; }
public function sayHelloTo(string! name) -> string { return this::HELLO . " " . name; }
public function sayHello() { return this::HELLO; }}
Маленький класс
Имеем возможность использовать функции PHP.
namespace MyLibrary;
class Encoder{ public function encode(string text) { if strlen(text) != 0 { if function_exists("my_custom_encoder") { return my_custom_encoder(text); } else { return base64_encode(text); } } return false; }}
Функции
Не можем присвоить результат функции к переменной статического типа.
namespace MyLibrary;
class Encoder{ public function encode(string text) -> string | bool { string encoded = "";
if strlen(text) != 0 { let encoded = (string) base64_encode(text); return '(' . encoded . ')'; } return false; }}
Функции
config.json
• Оптимизации при трансляции.
• Warnings при статическом анализе.
• Глобальные переменные на расширение.
• Общая информация.
• Блок phpinfo()
Оптимизации при трансляции
• static-type-inference• static-type-inference-second-pass • local-context-pass • constant-folding • static-constant-class-folding • call-gatherer-pass
Включить:
$ zephir -fstatic-type-inference -flocal-context-pass build
Function call optimizers
• Уходим от PHP_FUNCTION.
• Используем функции вшитые в C или пишем свои.
Подмена вызовов типичных функций из ядра Zend Engine на оптимизированные свои.
Алгоритм работы
1. $ zephir init test
2. Пишем код проекта.
3. $ zephir build
4. Add extension=test.so to your php.ini
Дополнительные возможности
• Генерация автокомплита для IDE
• Генерация документации
Будущее Zephir
• PHP 7 (Zend Engine 3)
• Больше оптимизаций
• Переработка архитектуры на компоненты
• Развитие Zephir Runtime
• ZephirVM
Переписать часть ядра Symfony на Zephir.
@firec0der
Мои планы