├── .gitignore ├── README.md ├── crowdin.yml ├── el-gr ├── arrays.md ├── builtin-methods.md ├── closures.md ├── command-line.md ├── config.md ├── control-structures.md ├── exceptions.md ├── functions.md ├── globals.md ├── installation.md ├── introduction.md ├── language.md ├── license.md ├── lifecycle.md ├── motivation.md ├── oop.md ├── operator-precedence.md ├── operators.md ├── optimizations.md ├── optimizers.md ├── phpinfo.md ├── right-menu.json ├── sidebar.json ├── static-analysis.md ├── tutorial.md ├── types.md ├── warnings.md └── welcome.md ├── en ├── arrays.md ├── builtin-methods.md ├── closures.md ├── command-line.md ├── config.md ├── control-structures.md ├── exceptions.md ├── functions.md ├── globals.md ├── installation.md ├── introduction.md ├── language.md ├── license.md ├── lifecycle.md ├── motivation.md ├── oop.md ├── operator-precedence.md ├── operators.md ├── optimizations.md ├── optimizers.md ├── phpinfo.md ├── right-menu.json ├── sidebar.json ├── static-analysis.md ├── tutorial.md ├── types.md ├── warnings.md └── welcome.md ├── es-es ├── arrays.md ├── builtin-methods.md ├── closures.md ├── command-line.md ├── config.md ├── control-structures.md ├── exceptions.md ├── functions.md ├── globals.md ├── installation.md ├── introduction.md ├── language.md ├── license.md ├── lifecycle.md ├── motivation.md ├── oop.md ├── operator-precedence.md ├── operators.md ├── optimizations.md ├── optimizers.md ├── phpinfo.md ├── right-menu.json ├── sidebar.json ├── static-analysis.md ├── tutorial.md ├── types.md ├── warnings.md └── welcome.md ├── ru-ru ├── arrays.md ├── builtin-methods.md ├── closures.md ├── command-line.md ├── config.md ├── control-structures.md ├── exceptions.md ├── functions.md ├── globals.md ├── installation.md ├── introduction.md ├── language.md ├── license.md ├── lifecycle.md ├── motivation.md ├── oop.md ├── operator-precedence.md ├── operators.md ├── optimizations.md ├── optimizers.md ├── phpinfo.md ├── right-menu.json ├── sidebar.json ├── static-analysis.md ├── tutorial.md ├── types.md ├── warnings.md └── welcome.md ├── tr-tr ├── arrays.md ├── builtin-methods.md ├── closures.md ├── command-line.md ├── config.md ├── control-structures.md ├── exceptions.md ├── functions.md ├── globals.md ├── installation.md ├── introduction.md ├── language.md ├── license.md ├── lifecycle.md ├── motivation.md ├── oop.md ├── operator-precedence.md ├── operators.md ├── optimizations.md ├── optimizers.md ├── phpinfo.md ├── right-menu.json ├── sidebar.json ├── static-analysis.md ├── tutorial.md ├── types.md ├── warnings.md └── welcome.md ├── uk-ua ├── arrays.md ├── builtin-methods.md ├── closures.md ├── command-line.md ├── config.md ├── control-structures.md ├── exceptions.md ├── functions.md ├── globals.md ├── installation.md ├── introduction.md ├── language.md ├── license.md ├── lifecycle.md ├── motivation.md ├── oop.md ├── operator-precedence.md ├── operators.md ├── optimizations.md ├── optimizers.md ├── phpinfo.md ├── right-menu.json ├── sidebar.json ├── static-analysis.md ├── tutorial.md ├── types.md ├── warnings.md └── welcome.md └── zh-cn ├── arrays.md ├── builtin-methods.md ├── closures.md ├── command-line.md ├── config.md ├── control-structures.md ├── exceptions.md ├── functions.md ├── globals.md ├── installation.md ├── introduction.md ├── language.md ├── license.md ├── lifecycle.md ├── motivation.md ├── oop.md ├── operator-precedence.md ├── operators.md ├── optimizations.md ├── optimizers.md ├── phpinfo.md ├── right-menu.json ├── sidebar.json ├── static-analysis.md ├── tutorial.md ├── types.md ├── warnings.md └── welcome.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea/ 3 | nbproject/ 4 | */_build/doctrees/ 5 | */_build/html/ 6 | */_build/latex/* 7 | !*/_build/latex/ZephirDocumentation.pdf 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Zephir Documentation 2 | 3 | [![Crowdin](https://d322cqt584bo4o.cloudfront.net/zephir-documentation/localized.svg)](https://crowdin.com/project/zephir-documentation) 4 | 5 | 6 | ## Welcome 7 | This repository the documentation for the [Zephir Language](https://zephir-lang.com). The documentation can be found [here](https://docs.zephir-lang.com) 8 | 9 | ## Changes/Corrections 10 | If you see any problems in the documentation, feel free to issue a Pull Request. 11 | 12 | Pull requests are only accepted in the source language which is English `en` 13 | 14 | ## Localization 15 | We welcome contributions in localizing the documentation. Our localization is handled by our friends at [Crowdin](https://crowdin.com), who very generously offered their platform for our project. 16 | 17 | You can visit [the project in Crowdin](https://crowdin.com/project/zephir-documentation) and start translating there. Crowdin will issue pull requests to this repository automatically when new translations come in and we manually update the website that hosts our documents. -------------------------------------------------------------------------------- /crowdin.yml: -------------------------------------------------------------------------------- 1 | files: 2 | - source: /en/*.md 3 | translation: /%locale%/%original_file_name% 4 | - source: /en/*.json 5 | translation: /%locale%/%original_file_name% 6 | -------------------------------------------------------------------------------- /el-gr/arrays.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'el-gr' 4 | version: '0.12' 5 | --- 6 | 7 | # Πίνακες 8 | 9 | Array manipulation in Zephir provides a way to use PHP [array](https://www.php.net/manual/en/language.types.array.php). An array is an implementation of a [hash table](https://en.wikipedia.org/wiki/Hash_table). 10 | 11 | 12 | 13 | ## Declaring Array Variables 14 | 15 | Array variables can be declared using the keywords 'var' or 'array': 16 | 17 | ```zephir 18 | var a = []; // array variable, its type can be changed 19 | array b = []; // array variable, its type cannot be changed across execution 20 | ``` 21 | 22 | 23 | 24 | ## Creating Arrays 25 | 26 | An array is created by enclosing its elements in square brackets: 27 | 28 | ##### Creating an empty array 29 | 30 | ```zephir 31 | let elements = []; 32 | ``` 33 | 34 | ##### Creating an array with elements 35 | 36 | ```zephir 37 | let elements = [1, 3, 4]; 38 | ``` 39 | 40 | ##### Creating an array with elements of different types 41 | 42 | ```zephir 43 | let elements = ["first", 2, true]; 44 | ``` 45 | 46 | ##### A multidimensional array 47 | 48 | ```zephir 49 | let elements = [[0, 1], [4, 5], [2, 3]]; 50 | ``` 51 | 52 | As PHP, hashes or dictionaries are supported: 53 | 54 | ##### Creating a hash with string keys 55 | 56 | ```zephir 57 | let elements = ["foo": "bar", "bar": "foo"]; 58 | ``` 59 | 60 | ##### Creating a hash with numeric keys 61 | 62 | ```zephir 63 | let elements = [4: "bar", 8: "foo"]; 64 | ``` 65 | 66 | ##### Creating a hash with mixed string and numeric keys 67 | 68 | ```zephir 69 | let elements = [4: "bar", "foo": 8]; 70 | ``` 71 | 72 | 73 | 74 | ## Updating arrays 75 | 76 | Arrays are updated in the same way as PHP, using square brackets: 77 | 78 | ##### Updating an array with a string key 79 | 80 | ```zephir 81 | let elements["foo"] = "bar"; 82 | ``` 83 | 84 | ##### Updating an array with a numeric key 85 | 86 | ```zephir 87 | let elements[0] = "bar"; 88 | ``` 89 | 90 | ##### Updating multi-dimensional array 91 | 92 | ```zephir 93 | let elements[0]["foo"] = "bar"; 94 | let elements["foo"][0] = "bar"; 95 | ``` 96 | 97 | 98 | 99 | ## Appending elements 100 | 101 | Elements can be appended at the end of the array as follows: 102 | 103 | ##### Append an element to the array 104 | 105 | ```zephir 106 | let elements[] = "bar"; 107 | ``` 108 | 109 | 110 | 111 | ## Reading elements from arrays 112 | 113 | It is possible to read array elements as follows: 114 | 115 | ##### Getting an element using the string key `foo` 116 | 117 | ```zephir 118 | let foo = elements["foo"]; 119 | ``` 120 | 121 | ##### Getting an element using the numeric key 0 122 | 123 | ```zephir 124 | let foo = elements[0]; 125 | ``` -------------------------------------------------------------------------------- /el-gr/closures.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'el-gr' 4 | version: '0.12' 5 | --- 6 | 7 | # Closures 8 | 9 | You can use closures (a.k.a. anonymous functions) in Zephir; these are PHP compatible and can be returned to the PHP userland: 10 | 11 | ```zephir 12 | namespace MyLibrary; 13 | 14 | class Functional 15 | { 16 | 17 | public function map(array! data) 18 | { 19 | return function(number) { 20 | return number * number; 21 | }; 22 | } 23 | } 24 | ``` 25 | 26 | It also can be executed directly within Zephir, and passed as a parameter to other functions/methods: 27 | 28 | ```zephir 29 | namespace MyLibrary; 30 | 31 | class Functional 32 | { 33 | 34 | public function map(array! data) 35 | { 36 | return data->map(function(number) { 37 | return number * number; 38 | }); 39 | } 40 | } 41 | ``` 42 | 43 | A short syntax is also available to define closures: 44 | 45 | ```zephir 46 | namespace MyLibrary; 47 | 48 | class Functional 49 | { 50 | 51 | public function map(array! data) 52 | { 53 | return data->map(number => number * number); 54 | } 55 | } 56 | ``` -------------------------------------------------------------------------------- /el-gr/command-line.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'el-gr' 4 | version: '0.12' 5 | --- 6 | 7 | # The Zephir Command Line 8 | 9 | Once Zephir is installed, you'll use the `zephir` command to manage the Zephir compiler for your projects. This chapter, and the ones following, are about the command itself, how to use it, and how to understand the things it outputs. 10 | 11 | As of Zephir 0.11.7, the compiler makes use of `stderr` for displaying error messages. This means you can handle error outputs separately from normal ones, like so: 12 | 13 | ```bash 14 | zephir generate 2> errors.log 1> /dev/null 15 | ``` 16 | 17 | 18 | 19 | ## `zephir api` 20 | 21 | Generates an HTML API based on the classes exposed in the extension 22 | 23 | - `--backend=BACKEND`: Backend used to generate HTML API (default: `ZendEngine3`) 24 | - `--path=PATH` (or `-p PATH`): The API theme to be used 25 | - `--output=OUTPUT` (or `-o OUTPUT`): Output directory to generate theme 26 | - `--options=OPTIONS`: Theme options 27 | - `--url=URL`: The base URL to be used when generating links 28 | 29 | 30 | 31 | ## `zephir build` 32 | 33 | This is a meta command that just calls the [`generate`](#zephir-generate), [`compile`](#zephir-compile), and [`install`](#zephir-install) commands. Check those commands for more information on supported options and behaviors for each. 34 | 35 | 36 | 37 | ## `zephir clean` 38 | 39 | Cleans any object files created by the extension 40 | 41 | 42 | 43 | ## `zephir compile` 44 | 45 | Compile a Zephir extension 46 | 47 | - `--backend=BACKEND`: Backend used to build extension (default: `ZendEngine3`) 48 | - `--dev`: Build the extension in development mode 49 | - `--no-dev`: Build the extension in production mode 50 | 51 | Using `--dev` option will force building and installing the extension in development mode (debug symbols and no optimizations). An extension compiled with debugging symbols means you can run a program or library through a debugger and the debugger's output will be user friendlier. These debugging symbols also enlarge the program or library significantly. 52 | 53 | NOTE: Zephir development mode will be enabled silently if your PHP binary was compiled in a debug configuration. 54 | 55 | In some cases, we would like to get production ready extension even if the PHP binary was compiled in a debug configuration. Use `--no-dev` option to achieve this behavior. 56 | 57 | Additionally, any of the options available [under `extra` in the configuration file](/{{ page.version }}/{{ page.language }}/config#extra) can also be passed as options, here, such as `--export-classes` and `--indent=tabs`. 58 | 59 | 60 | 61 | ## `zephir fullclean` 62 | 63 | Cleans any object files created by the extension (including files generated by phpize) 64 | 65 | 66 | 67 | ## `zephir generate` 68 | 69 | Generates C code from the Zephir code 70 | 71 | - `--backend=BACKEND`: Backend used to build extension (default: `ZendEngine3`) 72 | 73 | 74 | 75 | ## `zephir help` 76 | 77 | Displays help for a command 78 | 79 | 80 | 81 | ## `zephir init` 82 | 83 | Initializes a Zephir extension `zephir init ` 84 | 85 | - `namespace`: The extension namespace 86 | - `--backend=BACKEND`: Backend used to create extension (default: `ZendEngine3`) 87 | 88 | 89 | 90 | ## `zephir install` 91 | 92 | Installs the extension in the extension directory (may require root password) 93 | 94 | - `--dev`: Install the extension in development mode 95 | - `--no-dev`: Install the extension in production mode 96 | 97 | 98 | 99 | ## `zephir list` 100 | 101 | Lists commands 102 | 103 | 104 | 105 | ## `zephir stubs` 106 | 107 | Generates stubs that can be used in a PHP IDE 108 | 109 | - `--backend=BACKEND`: Backend used to generate stubs (default: `ZendEngine3`) 110 | -------------------------------------------------------------------------------- /el-gr/exceptions.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'el-gr' 4 | version: '0.12' 5 | --- 6 | 7 | # Exceptions 8 | 9 | Zephir implements exceptions at a very low level, providing similar behavior and functionality to PHP. 10 | 11 | When an exception is thrown, a `catch` block can be used to capture the exception and allow the developer to provide proper handling: 12 | 13 | Exceptions can be thrown inside the `try` block. Handling happens in the `catch` block, exactly as in PHP: 14 | 15 | ```zephir 16 | var e; 17 | try { 18 | 19 | throw new \Exception("This is an exception"); 20 | 21 | } catch \Exception, e { 22 | 23 | echo e->getMessage(); 24 | } 25 | ``` 26 | 27 | Zephir also provides a "silent" `try` block, that simply ignores any exceptions produced within that block: 28 | 29 | ```zephir 30 | try { 31 | throw new \Exception("This is an exception"); 32 | } 33 | ``` 34 | 35 | If you don't need an exception variable when 'catch'ing, then you can safely not provide it: 36 | 37 | ```zephir 38 | try { 39 | 40 | throw new \Exception("This is an exception"); 41 | 42 | } catch \Exception { 43 | 44 | echo "An exception occur!"; 45 | } 46 | ``` 47 | 48 | A single `catch` block can be used to catch multiple types of exception: 49 | 50 | ```zephir 51 | var e; 52 | try { 53 | 54 | throw new \Exception("This is an exception"); 55 | 56 | } catch \RuntimeException|\Exception, e { 57 | 58 | echo e->getMessage(); 59 | } 60 | ``` 61 | 62 | Zephir allows you to throw literals or static typed variables as if they were the message of the exception: 63 | 64 | ```zephir 65 | // throw new \Exception("Test"); 66 | throw "Test"; 67 | 68 | // throw new \Exception((string) 't'); 69 | throw 't'; 70 | 71 | // throw new \Exception((string) 123); 72 | throw 123; 73 | 74 | // throw new \Exception((string) 123.123); 75 | throw 123.123; 76 | ``` 77 | 78 | Zephir's exceptions provide the same methods to know where the exception happened that PHP's exceptions do. That is, `Exception::getFile()` and `Exception::getLine()` return the location in the Zephir code where the exception was thrown: 79 | 80 | ```bash 81 | Exception: The static method 'someMethod' does not exist on model 'Robots' 82 | File=phalcon/mvc/model.zep Line=4042 83 | #0 /home/scott/test.php(64): Phalcon\Mvc\Model::__callStatic('someMethod', Array) 84 | #1 /home/scott/test.php(64): Robots::someMethod() 85 | #2 {main} 86 | ``` -------------------------------------------------------------------------------- /el-gr/functions.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'el-gr' 4 | version: '0.12' 5 | --- 6 | 7 | # Calling Functions 8 | 9 | PHP has a rich library of functions that you can use within your extensions. To call a PHP function you simply use it as normal within your Zephir code: 10 | 11 | ```zephir 12 | namespace MyLibrary; 13 | 14 | class Encoder 15 | { 16 | public function encode(var text) 17 | { 18 | if strlen(text) != 0 { 19 | return base64_encode(text); 20 | } 21 | return false; 22 | } 23 | } 24 | ``` 25 | 26 | You can also call functions that are expected to exist in the PHP userland, but are not necessarily built in to PHP itself: 27 | 28 | ```zephir 29 | namespace MyLibrary; 30 | 31 | class Encoder 32 | { 33 | 34 | public function encode(var text) 35 | { 36 | if strlen(text) != 0 { 37 | if function_exists("my_custom_encoder") { 38 | return my_custom_encoder(text); 39 | } else { 40 | return base64_encode(text); 41 | } 42 | } 43 | return false; 44 | } 45 | } 46 | ``` 47 | 48 | Note that all PHP functions only receive and return dynamic variables. If you pass a static typed variable as a parameter, a temporary dynamic variable will automatically be used as a bridge in order to call the function: 49 | 50 | ```zephir 51 | namespace MyLibrary; 52 | 53 | class Encoder 54 | { 55 | public function encode(string text) 56 | { 57 | if strlen(text) != 0 { 58 | // an implicit dynamic variable is created to 59 | // pass the static typed 'text' as parameter 60 | return base64_encode(text); 61 | } 62 | return false; 63 | } 64 | } 65 | ``` 66 | 67 | Similarly, functions return dynamic values, which cannot be directly assigned to static variables without the appropriate explicit cast: 68 | 69 | ```zephir 70 | namespace MyLibrary; 71 | 72 | class Encoder 73 | { 74 | public function encode(string text) 75 | { 76 | string encoded = ""; 77 | 78 | if strlen(text) != 0 { 79 | let encoded = (string) base64_encode(text); 80 | return "(" . encoded . ")"; 81 | } 82 | return false; 83 | } 84 | } 85 | ``` 86 | 87 | Zephir also provides a way for you to call functions dynamically, such as: 88 | 89 | ```zephir 90 | namespace MyLibrary; 91 | 92 | class Encoder 93 | { 94 | public function encode(var callback, string text) 95 | { 96 | return {callback}(text); 97 | } 98 | } 99 | ``` -------------------------------------------------------------------------------- /el-gr/globals.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'el-gr' 4 | version: '0.12' 5 | --- 6 | 7 | # Extension Globals 8 | 9 | PHP extensions provide a way to define globals within an extension. Reading/writing globals should be faster than any other global mechanisms (like static members). You can use extension globals to set up configuration options that change the behavior of your library. 10 | 11 | In Zephir, extension globals are restricted to simple scalar types like `int`/`bool`/`double`/`char`, etc. Complex types such as string/array/object/resource are not allowed here. 12 | 13 | You can enable extension globals by adding the following structure to your `config.json`: 14 | 15 | ```json 16 | { 17 | "globals": { 18 | "allow_some_feature": { 19 | "type": "bool", 20 | "default": true, 21 | "module": true 22 | }, 23 | "number_times": { 24 | "type": "int", 25 | "default": 10 26 | }, 27 | "some_component.my_setting_1": { 28 | "type": "bool", 29 | "default": true 30 | }, 31 | "some_component.my_setting_2": { 32 | "type": "int", 33 | "default": 100 34 | } 35 | } 36 | } 37 | ``` 38 | 39 | Each global has the following structure: 40 | 41 | ```json 42 | "": { 43 | "type": "", 44 | "default": 45 | } 46 | ``` 47 | 48 | Compound (namespaced) globals have the following structure: 49 | 50 | ```json 51 | ".": { 52 | "type": "", 53 | "default": 54 | } 55 | ``` 56 | 57 | The optional `module` key, if present, places that global's initialization process into the module-wide `GINIT` lifecycle event, which just means it will only be set up once per PHP process, rather than being reinitialized for every request, which is the default: 58 | 59 | ```json 60 | { 61 | "globals": { 62 | "allow_some_feature": { 63 | "type": "bool", 64 | "default": true, 65 | "module": true 66 | }, 67 | "number_times": { 68 | "type": "int", 69 | "default": 10 70 | } 71 | } 72 | } 73 | ``` 74 | 75 | In the example above, `allow_some_feature` is set up only once at startup; `number_times` is set up at the start of each request. 76 | 77 | Inside any method, you can read/write extension globals using the built-in functions `globals_get`/`globals_set`: 78 | 79 | ```zephir 80 | globals_set("allow_some_feature", true); 81 | let someFeature = globals_get("allow_some_feature"); 82 | ``` 83 | 84 | If you want to change these globals from PHP, a good option is include a method aimed at this: 85 | 86 | ```zephir 87 | namespace Test; 88 | 89 | class MyOptions 90 | { 91 | 92 | public static function setOptions(array options) 93 | { 94 | boolean someOption, anotherOption; 95 | 96 | if fetch someOption, options["some_option"] { 97 | globals_set("some_option", someOption); 98 | } 99 | 100 | if fetch anotherOption, options["another_option"] { 101 | globals_set("another_option", anotherOption); 102 | } 103 | } 104 | } 105 | ``` 106 | 107 | Extension globals cannot be dynamically accessed, since the C code generated by the `globals_get`/`globals_set` optimizers must be resolved at compilation time: 108 | 109 | ```zephir 110 | let myOption = "someOption"; 111 | 112 | // will throw a compiler exception 113 | let someOption = globals_get(myOption); 114 | ``` -------------------------------------------------------------------------------- /el-gr/license.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'el-gr' 4 | version: '0.12' 5 | --- 6 | 7 | # License 8 | 9 | MIT License 10 | 11 | Copyright (c) 2013-present Zephir Team 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /el-gr/operator-precedence.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'el-gr' 4 | version: '0.12' 5 | --- 6 | 7 | # Operator Precedence 8 | **Operator precedence** determines how operators are parsed. Operators with higher precedence become the operands of operators with lower precedence. For example, in the expression `1 + 5 * 3`, the answer is 16 and not 18 because the multiplication (`*`) operator has a higher precedence than the addition (`+`) operator. Parentheses may be used to force precedence, if necessary. For instance: `(1 + 5) * 3` evaluates to 18. 9 | 10 | 11 | 12 | ## Associativity 13 | When operators have equal precedence their **associativity** determines how the operators are grouped. For example `-` is _left-associative_, so `1 - 2 - 3` is grouped as `(1 - 2) - 3` and evaluates to `-4`. `=` on the other hand is _right-associative_, so `let a = b = c` is grouped as `let a = (b = c)`. 14 | 15 | Operators of equal precedence that are _non-associative_ cannot be used next to one another. For example: 16 | ```zep 17 | new new Foo(); 18 | ``` 19 | is illegal in Zephir, because the `new` is non-associative. At the moment, `new` is the only non-associative operator in Zephir. 20 | 21 | Use of parentheses, even when not strictly necessary, can often increase readability of the code, by making grouping explicit, rather than relying on the implicit operator precedence and associativity. 22 | 23 | 24 | 25 | ## Precedence Table 26 | The following table lists the operators in order of precedence, with the highest-precedence ones at the top. Operators on the same line have equal precedence, in which case associativity decides grouping. 27 | 28 | | Precedence | Operators | Operator type | Associativity | 29 | | ---------- | -------------------------------- | ----------------------------------- | --------------- | 30 | | 1 | `->` | Member Access | right-to-left | 31 | | 2 | `~` | Bitwise NOT | right-to-left | 32 | | 3 | `!` | Logical NOT | right-to-left | 33 | | 4 | `new` | new | non-associative | 34 | | 5 | `clone` | clone | right-to-left | 35 | | 6 | `typeof` | Type-of | right-to-left | 36 | | 7 | `..`, `...` | Inclusive/exclusive range | left-to-right | 37 | | 8 | `isset`, `fetch`, `empty` | Exclusive range | right-to-left | 38 | | 9 | `*`, `/`, `%` | Multiplication, Division, Remainder | left-to-right | 39 | | 10 | `+`, `-`, `.` | Addition, Subtraction, Concat | left-to-right | 40 | | 11 | `<<`, `>>` | Bitwise shift left/right | left-to-right | 41 | | 12 | `<`, `<=`, `=>`, `>` | Comparison | left-to-right | 42 | | 13 | `==`, `!==`, `===`, `!==` | Comparison | left-to-right | 43 | | 14 | `&` | Bitwise AND, references | left-to-right | 44 | | 15 | `^` | Bitwise XOR | left-to-right | 45 | | 16 | `|` | Bitwise OR | left-to-right | 46 | | 17 | `instanceof` | Instance-of | left-to-right | 47 | | 18 | `&&` | Logical AND | left-to-right | 48 | | 19 | `||` | Logical OR | left-to-right | 49 | | 20 | `likely`, `unlikely` | Branch prediction | right-to-left | 50 | | 21 | `?` | Logical | right-to-left | 51 | | 21 | `=>` | Closure Arrow | right-to-left | 52 | -------------------------------------------------------------------------------- /el-gr/phpinfo.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'el-gr' 4 | version: '0.12' 5 | --- 6 | 7 | # Phpinfo() sections 8 | 9 | Like most extensions, Zephir extensions are able to show information in the [phpinfo()](https://php.net/manual/en/function.phpinfo.php) output. This information is usually related to directives, environment data, etc. 10 | 11 | By default, every Zephir extension automatically adds a basic table to the `phpinfo()` output showing the extension version, and any INI options the extension supports. 12 | 13 | You can add more directives by adding the following configuration to the `config.json` file: 14 | 15 | ```json 16 | "info": [ 17 | { 18 | "header": ["Directive", "Value"], 19 | "rows": [ 20 | ["setting1", "value1"], 21 | ["setting2", "value2"] 22 | ] 23 | }, 24 | { 25 | "header": ["Directive", "Value"], 26 | "rows": [ 27 | ["setting3", "value3"], 28 | ["setting4", "value4"] 29 | ] 30 | } 31 | ] 32 | ``` 33 | 34 | This information will be shown as follows: 35 | 36 | ![](/assets/content/info.png) -------------------------------------------------------------------------------- /el-gr/sidebar.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "text": "Welcome", 4 | "url": "welcome" 5 | }, 6 | { 7 | "text": "Why Zephir", 8 | "url": "motivation" 9 | }, 10 | { 11 | "text": "Introducing Zephir", 12 | "url": "introduction" 13 | }, 14 | { 15 | "text": "Installation", 16 | "url": "installation" 17 | }, 18 | { 19 | "text": "Tutorial", 20 | "url": "tutorial" 21 | }, 22 | { 23 | "text": "Basic Syntax", 24 | "url": "language" 25 | }, 26 | { 27 | "text": "Types", 28 | "url": "types" 29 | }, 30 | { 31 | "text": "Operators", 32 | "url": "operators" 33 | }, 34 | { 35 | "text": "Operator Precedence", 36 | "url": "operator-precedence" 37 | }, 38 | { 39 | "text": "Πίνακες", 40 | "url": "arrays" 41 | }, 42 | { 43 | "text": "Classes and objects", 44 | "url": "oop" 45 | }, 46 | { 47 | "text": "Built-in methods", 48 | "url": "builtin-methods" 49 | }, 50 | { 51 | "text": "Control structures", 52 | "url": "control-structures" 53 | }, 54 | { 55 | "text": "Exceptions", 56 | "url": "exceptions" 57 | }, 58 | { 59 | "text": "Calling functions", 60 | "url": "functions" 61 | }, 62 | { 63 | "text": "Closures", 64 | "url": "closures" 65 | }, 66 | { 67 | "text": "Custom optimizers", 68 | "url": "optimizers" 69 | }, 70 | { 71 | "text": "Configuration file", 72 | "url": "config" 73 | }, 74 | { 75 | "text": "Command Line", 76 | "url": "command-line" 77 | }, 78 | { 79 | "text": "Lifecycle hooks", 80 | "url": "lifecycle" 81 | }, 82 | { 83 | "text": "Extension globals", 84 | "url": "globals" 85 | }, 86 | { 87 | "text": "phpinfo() sections", 88 | "url": "phpinfo" 89 | }, 90 | { 91 | "text": "Static analysis", 92 | "url": "static-analysis" 93 | }, 94 | { 95 | "text": "Optimizations", 96 | "url": "optimizations" 97 | }, 98 | { 99 | "text": "Compiler warnings", 100 | "url": "warnings" 101 | }, 102 | { 103 | "text": "License", 104 | "url": "license" 105 | } 106 | ] 107 | -------------------------------------------------------------------------------- /el-gr/static-analysis.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'el-gr' 4 | version: '0.12' 5 | --- 6 | 7 | # Static Analysis 8 | 9 | Zephir's compiler provides static analysis of the compiled code. The idea behind this feature is to help the developer to find potential problems and avoid unexpected behaviors, well before runtime. 10 | 11 | 12 | 13 | ## Conditional Unassigned Variables 14 | 15 | Static Analysis of assignments tries to identify if a variable is used before it's assigned: 16 | 17 | ```zephir 18 | class Utils 19 | { 20 | public function someMethod(b) 21 | { 22 | string a; char c; 23 | 24 | if b == 10 { 25 | let a = "hello"; 26 | } 27 | 28 | //a could be unitialized here 29 | for c in a { 30 | echo c, PHP_EOL; 31 | } 32 | } 33 | } 34 | ``` 35 | 36 | The above example illustrates a common situation. The variable `a` is assigned only when `b` is equal to 10, then it's required to use the value of this variable - but it could be uninitialized. Zephir detects this, automatically initializes the variable to an empty string, and generates a warning alerting the developer: 37 | 38 | ```bash 39 | Warning: Variable 'a' was assigned for the first time in conditional branch, 40 | consider initialize it in its declaration in 41 | /home/scott/test/test/utils.zep on 21 [conditional-initialization] 42 | 43 | for c in a { 44 | ``` 45 | 46 | Finding such errors is sometimes tricky, however static analysis helps the programmer to find bugs in advance. 47 | 48 | 49 | 50 | ## Dead Code Elimination 51 | 52 | Zephir informs the developer about unreachable branches in the code and performs dead code elimination, which means it gets rid of all that code from the generated binary, since it cannot be executed anyway: 53 | 54 | ```zephir 55 | class Utils 56 | { 57 | public function someMethod(b) 58 | { 59 | if false { 60 | // This is never executed 61 | echo "hello"; 62 | } 63 | } 64 | } 65 | ``` -------------------------------------------------------------------------------- /el-gr/welcome.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'el-gr' 4 | version: '0.12' 5 | --- 6 | 7 | # Καλώς ορίσατε! 8 | 9 | Welcome to Zephir, an open source, high-level/domain specific language designed to ease the creation and maintainability of extensions for PHP, with a focus on type and memory safety. 10 | 11 | 12 | 13 | ## Μερικά χαρακτηριστικά γνωρίσματα 14 | 15 | Κύρια χαρακτηριστικά της Zephir είναι: 16 | 17 | | Χαρακτηριστικό | Description | 18 | | ----------------- | ---------------------------------------------------- | 19 | | Type system | dynamic/static | 20 | | Memory safety | pointers or direct memory management are not allowed | 21 | | Compilation model | ahead of time | 22 | | Memory model | task-local garbage collection | 23 | 24 | 25 | 26 | ## Μια μικρή γεύση 27 | 28 | The following code registers a class with a method that filters variables, returning their alphabetic characters: 29 | 30 | ```zephir 31 | namespace MyLibrary; 32 | 33 | /** 34 | * Filter 35 | */ 36 | class Filter 37 | { 38 | /** 39 | * Filters a string, returning its alpha charactersa 40 | * 41 | * @param string str 42 | */ 43 | public function alpha(string str) 44 | { 45 | char ch; string filtered = ""; 46 | 47 | for ch in str { 48 | if (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') { 49 | let filtered .= ch; 50 | } 51 | } 52 | 53 | return filtered; 54 | } 55 | } 56 | ``` 57 | 58 | The class can be used from PHP as follows: 59 | 60 | ```php 61 | alpha("01he#l.lo?/1"); // prints hello 65 | ``` 66 | 67 | 68 | 69 | ## External Links 70 | 71 | Below we have collected links to external resources that may interest you: 72 | 73 | - [Type system](https://en.wikipedia.org/wiki/Type_system) 74 | - [Memory safety](https://en.wikipedia.org/wiki/Memory_safety) 75 | - [Ahead-of-time compilation](https://en.wikipedia.org/wiki/Ahead-of-time_compilation) 76 | - [Memory management](https://en.wikipedia.org/wiki/Memory_management) -------------------------------------------------------------------------------- /en/arrays.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'en' 4 | version: '0.12' 5 | --- 6 | 7 | # Arrays 8 | Array manipulation in Zephir provides a way to use PHP [array](https://www.php.net/manual/en/language.types.array.php). An array is an implementation of a [hash table](https://en.wikipedia.org/wiki/Hash_table). 9 | 10 | 11 | ## Declaring Array Variables 12 | Array variables can be declared using the keywords 'var' or 'array': 13 | 14 | ```zephir 15 | var a = []; // array variable, its type can be changed 16 | array b = []; // array variable, its type cannot be changed across execution 17 | ``` 18 | 19 | 20 | ## Creating Arrays 21 | An array is created by enclosing its elements in square brackets: 22 | 23 | ##### Creating an empty array 24 | 25 | ```zephir 26 | let elements = []; 27 | ``` 28 | 29 | ##### Creating an array with elements 30 | 31 | ```zephir 32 | let elements = [1, 3, 4]; 33 | ``` 34 | 35 | ##### Creating an array with elements of different types 36 | 37 | ```zephir 38 | let elements = ["first", 2, true]; 39 | ``` 40 | 41 | ##### A multidimensional array 42 | 43 | ```zephir 44 | let elements = [[0, 1], [4, 5], [2, 3]]; 45 | ``` 46 | 47 | As PHP, hashes or dictionaries are supported: 48 | 49 | ##### Creating a hash with string keys 50 | 51 | ```zephir 52 | let elements = ["foo": "bar", "bar": "foo"]; 53 | ``` 54 | 55 | ##### Creating a hash with numeric keys 56 | 57 | ```zephir 58 | let elements = [4: "bar", 8: "foo"]; 59 | ``` 60 | 61 | ##### Creating a hash with mixed string and numeric keys 62 | 63 | ```zephir 64 | let elements = [4: "bar", "foo": 8]; 65 | ``` 66 | 67 | 68 | ## Updating arrays 69 | Arrays are updated in the same way as PHP, using square brackets: 70 | 71 | ##### Updating an array with a string key 72 | 73 | ```zephir 74 | let elements["foo"] = "bar"; 75 | ``` 76 | 77 | ##### Updating an array with a numeric key 78 | 79 | ```zephir 80 | let elements[0] = "bar"; 81 | ``` 82 | 83 | ##### Updating multi-dimensional array 84 | 85 | ```zephir 86 | let elements[0]["foo"] = "bar"; 87 | let elements["foo"][0] = "bar"; 88 | ``` 89 | 90 | 91 | ## Appending elements 92 | Elements can be appended at the end of the array as follows: 93 | 94 | ##### Append an element to the array 95 | 96 | ```zephir 97 | let elements[] = "bar"; 98 | ``` 99 | 100 | 101 | ## Reading elements from arrays 102 | It is possible to read array elements as follows: 103 | 104 | ##### Getting an element using the string key `foo` 105 | 106 | ```zephir 107 | let foo = elements["foo"]; 108 | ``` 109 | 110 | ##### Getting an element using the numeric key 0 111 | 112 | ```zephir 113 | let foo = elements[0]; 114 | ``` 115 | -------------------------------------------------------------------------------- /en/closures.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'en' 4 | version: '0.12' 5 | --- 6 | 7 | # Closures 8 | You can use closures (a.k.a. anonymous functions) in Zephir; these are PHP compatible and can be returned to the PHP userland: 9 | 10 | ```zephir 11 | namespace MyLibrary; 12 | 13 | class Functional 14 | { 15 | 16 | public function map(array! data) 17 | { 18 | return function(number) { 19 | return number * number; 20 | }; 21 | } 22 | } 23 | ``` 24 | 25 | It also can be executed directly within Zephir, and passed as a parameter to other functions/methods: 26 | 27 | ```zephir 28 | namespace MyLibrary; 29 | 30 | class Functional 31 | { 32 | 33 | public function map(array! data) 34 | { 35 | return data->map(function(number) { 36 | return number * number; 37 | }); 38 | } 39 | } 40 | ``` 41 | 42 | A short syntax is also available to define closures: 43 | 44 | ```zephir 45 | namespace MyLibrary; 46 | 47 | class Functional 48 | { 49 | 50 | public function map(array! data) 51 | { 52 | return data->map(number => number * number); 53 | } 54 | } 55 | ``` 56 | -------------------------------------------------------------------------------- /en/command-line.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'en' 4 | version: '0.12' 5 | --- 6 | 7 | # The Zephir Command Line 8 | 9 | Once Zephir is installed, you'll use the `zephir` command to manage the Zephir compiler 10 | for your projects. This chapter, and the ones following, are about the command itself, how 11 | to use it, and how to understand the things it outputs. 12 | 13 | As of Zephir 0.11.7, the compiler makes use of `stderr` for displaying error messages. 14 | This means you can handle error outputs separately from normal ones, like so: 15 | 16 | ```bash 17 | zephir generate 2> errors.log 1> /dev/null 18 | ``` 19 | 20 | 21 | ## `zephir api` 22 | 23 | Generates an HTML API based on the classes exposed in the extension 24 | 25 | - `--backend=BACKEND`: Backend used to generate HTML API (default: `ZendEngine3`) 26 | - `--path=PATH` (or `-p PATH`): The API theme to be used 27 | - `--output=OUTPUT` (or `-o OUTPUT`): Output directory to generate theme 28 | - `--options=OPTIONS`: Theme options 29 | - `--url=URL`: The base URL to be used when generating links 30 | 31 | 32 | ## `zephir build` 33 | 34 | This is a meta command that just calls the [`generate`](#zephir-generate), [`compile`](#zephir-compile), and [`install`](#zephir-install) commands. 35 | Check those commands for more information on supported options and behaviors for each. 36 | 37 | 38 | ## `zephir clean` 39 | 40 | Cleans any object files created by the extension 41 | 42 | 43 | ## `zephir compile` 44 | 45 | Compile a Zephir extension 46 | 47 | - `--backend=BACKEND`: Backend used to build extension (default: `ZendEngine3`) 48 | - `--dev`: Build the extension in development mode 49 | - `--no-dev`: Build the extension in production mode 50 | 51 | Using `--dev` option will force building and installing the extension in development mode 52 | (debug symbols and no optimizations). An extension compiled with debugging symbols means 53 | you can run a program or library through a debugger and the debugger's output will be user 54 | friendlier. These debugging symbols also enlarge the program or library significantly. 55 | 56 | NOTE: Zephir development mode will be enabled silently if your PHP binary was compiled in 57 | a debug configuration. 58 | 59 | In some cases, we would like to get production ready extension even if the PHP binary was 60 | compiled in a debug configuration. Use `--no-dev` option to achieve this behavior. 61 | 62 | Additionally, any of the options available [under `extra` in the configuration 63 | file](/{{ page.version }}/{{ page.language }}/config#extra) can also be passed as options, here, such as 64 | `--export-classes` and `--indent=tabs`. 65 | 66 | 67 | ## `zephir fullclean` 68 | 69 | Cleans any object files created by the extension (including files generated by phpize) 70 | 71 | 72 | ## `zephir generate` 73 | 74 | Generates C code from the Zephir code 75 | 76 | - `--backend=BACKEND`: Backend used to build extension (default: `ZendEngine3`) 77 | 78 | 79 | ## `zephir help` 80 | 81 | Displays help for a command 82 | 83 | 84 | ## `zephir init` 85 | 86 | Initializes a Zephir extension 87 | `zephir init ` 88 | 89 | - `namespace`: The extension namespace 90 | - `--backend=BACKEND`: Backend used to create extension (default: `ZendEngine3`) 91 | 92 | 93 | ## `zephir install` 94 | 95 | Installs the extension in the extension directory (may require root password) 96 | 97 | - `--dev`: Install the extension in development mode 98 | - `--no-dev`: Install the extension in production mode 99 | 100 | 101 | ## `zephir list` 102 | 103 | Lists commands 104 | 105 | 106 | ## `zephir stubs` 107 | 108 | Generates stubs that can be used in a PHP IDE 109 | 110 | - `--backend=BACKEND`: Backend used to generate stubs (default: `ZendEngine3`) 111 | -------------------------------------------------------------------------------- /en/exceptions.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'en' 4 | version: '0.12' 5 | --- 6 | 7 | # Exceptions 8 | Zephir implements exceptions at a very low level, providing similar behavior and functionality to PHP. 9 | 10 | When an exception is thrown, a `catch` block can be used to capture the exception and allow the developer to provide proper handling: 11 | 12 | Exceptions can be thrown inside the `try` block. Handling happens in the `catch` block, exactly as in PHP: 13 | 14 | ```zephir 15 | var e; 16 | try { 17 | 18 | throw new \Exception("This is an exception"); 19 | 20 | } catch \Exception, e { 21 | 22 | echo e->getMessage(); 23 | } 24 | ``` 25 | 26 | Zephir also provides a "silent" `try` block, that simply ignores any exceptions produced within that block: 27 | 28 | ```zephir 29 | try { 30 | throw new \Exception("This is an exception"); 31 | } 32 | ``` 33 | 34 | If you don't need an exception variable when 'catch'ing, then you can safely not provide it: 35 | 36 | ```zephir 37 | try { 38 | 39 | throw new \Exception("This is an exception"); 40 | 41 | } catch \Exception { 42 | 43 | echo "An exception occur!"; 44 | } 45 | ``` 46 | 47 | A single `catch` block can be used to catch multiple types of exception: 48 | 49 | ```zephir 50 | var e; 51 | try { 52 | 53 | throw new \Exception("This is an exception"); 54 | 55 | } catch \RuntimeException|\Exception, e { 56 | 57 | echo e->getMessage(); 58 | } 59 | ``` 60 | 61 | Zephir allows you to throw literals or static typed variables as if they were the message of the exception: 62 | 63 | ```zephir 64 | // throw new \Exception("Test"); 65 | throw "Test"; 66 | 67 | // throw new \Exception((string) 't'); 68 | throw 't'; 69 | 70 | // throw new \Exception((string) 123); 71 | throw 123; 72 | 73 | // throw new \Exception((string) 123.123); 74 | throw 123.123; 75 | ``` 76 | 77 | Zephir's exceptions provide the same methods to know where the exception happened that PHP's exceptions do. That is, `Exception::getFile()` and `Exception::getLine()` return the location in the Zephir code where the exception was thrown: 78 | 79 | ```bash 80 | Exception: The static method 'someMethod' does not exist on model 'Robots' 81 | File=phalcon/mvc/model.zep Line=4042 82 | #0 /home/scott/test.php(64): Phalcon\Mvc\Model::__callStatic('someMethod', Array) 83 | #1 /home/scott/test.php(64): Robots::someMethod() 84 | #2 {main} 85 | ``` 86 | -------------------------------------------------------------------------------- /en/functions.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'en' 4 | version: '0.12' 5 | --- 6 | 7 | # Calling Functions 8 | PHP has a rich library of functions that you can use within your extensions. To call a PHP function you simply use it as normal within your Zephir code: 9 | 10 | ```zephir 11 | namespace MyLibrary; 12 | 13 | class Encoder 14 | { 15 | public function encode(var text) 16 | { 17 | if strlen(text) != 0 { 18 | return base64_encode(text); 19 | } 20 | return false; 21 | } 22 | } 23 | ``` 24 | 25 | You can also call functions that are expected to exist in the PHP userland, but are not necessarily built in to PHP itself: 26 | 27 | ```zephir 28 | namespace MyLibrary; 29 | 30 | class Encoder 31 | { 32 | 33 | public function encode(var text) 34 | { 35 | if strlen(text) != 0 { 36 | if function_exists("my_custom_encoder") { 37 | return my_custom_encoder(text); 38 | } else { 39 | return base64_encode(text); 40 | } 41 | } 42 | return false; 43 | } 44 | } 45 | ``` 46 | 47 | Note that all PHP functions only receive and return dynamic variables. If you pass a static typed variable as a parameter, a temporary dynamic variable will automatically be used as a bridge in order to call the function: 48 | 49 | ```zephir 50 | namespace MyLibrary; 51 | 52 | class Encoder 53 | { 54 | public function encode(string text) 55 | { 56 | if strlen(text) != 0 { 57 | // an implicit dynamic variable is created to 58 | // pass the static typed 'text' as parameter 59 | return base64_encode(text); 60 | } 61 | return false; 62 | } 63 | } 64 | ``` 65 | 66 | Similarly, functions return dynamic values, which cannot be directly assigned to static variables without the appropriate explicit cast: 67 | 68 | ```zephir 69 | namespace MyLibrary; 70 | 71 | class Encoder 72 | { 73 | public function encode(string text) 74 | { 75 | string encoded = ""; 76 | 77 | if strlen(text) != 0 { 78 | let encoded = (string) base64_encode(text); 79 | return "(" . encoded . ")"; 80 | } 81 | return false; 82 | } 83 | } 84 | ``` 85 | 86 | Zephir also provides a way for you to call functions dynamically, such as: 87 | 88 | ```zephir 89 | namespace MyLibrary; 90 | 91 | class Encoder 92 | { 93 | public function encode(var callback, string text) 94 | { 95 | return {callback}(text); 96 | } 97 | } 98 | ``` 99 | -------------------------------------------------------------------------------- /en/globals.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'en' 4 | version: '0.12' 5 | --- 6 | 7 | # Extension Globals 8 | PHP extensions provide a way to define globals within an extension. Reading/writing globals should be faster than any other global mechanisms (like static members). You can use extension globals to set up configuration options that change the behavior of your library. 9 | 10 | In Zephir, extension globals are restricted to simple scalar types like `int`/`bool`/`double`/`char`, etc. Complex types such as string/array/object/resource are not allowed here. 11 | 12 | You can enable extension globals by adding the following structure to your `config.json`: 13 | 14 | ```json 15 | { 16 | "globals": { 17 | "allow_some_feature": { 18 | "type": "bool", 19 | "default": true, 20 | "module": true 21 | }, 22 | "number_times": { 23 | "type": "int", 24 | "default": 10 25 | }, 26 | "some_component.my_setting_1": { 27 | "type": "bool", 28 | "default": true 29 | }, 30 | "some_component.my_setting_2": { 31 | "type": "int", 32 | "default": 100 33 | } 34 | } 35 | } 36 | ``` 37 | 38 | Each global has the following structure: 39 | 40 | ```json 41 | "": { 42 | "type": "", 43 | "default": 44 | } 45 | ``` 46 | 47 | Compound (namespaced) globals have the following structure: 48 | 49 | ```json 50 | ".": { 51 | "type": "", 52 | "default": 53 | } 54 | ``` 55 | 56 | The optional `module` key, if present, places that global's initialization process into the module-wide `GINIT` lifecycle event, which just means it will only be set up once per PHP process, rather than being reinitialized for every request, which is the default: 57 | 58 | ```json 59 | { 60 | "globals": { 61 | "allow_some_feature": { 62 | "type": "bool", 63 | "default": true, 64 | "module": true 65 | }, 66 | "number_times": { 67 | "type": "int", 68 | "default": 10 69 | } 70 | } 71 | } 72 | ``` 73 | 74 | In the example above, `allow_some_feature` is set up only once at startup; `number_times` is set up at the start of each request. 75 | 76 | Inside any method, you can read/write extension globals using the built-in functions `globals_get`/`globals_set`: 77 | 78 | ```zephir 79 | globals_set("allow_some_feature", true); 80 | let someFeature = globals_get("allow_some_feature"); 81 | ``` 82 | 83 | If you want to change these globals from PHP, a good option is include a method aimed at this: 84 | 85 | ```zephir 86 | namespace Test; 87 | 88 | class MyOptions 89 | { 90 | 91 | public static function setOptions(array options) 92 | { 93 | boolean someOption, anotherOption; 94 | 95 | if fetch someOption, options["some_option"] { 96 | globals_set("some_option", someOption); 97 | } 98 | 99 | if fetch anotherOption, options["another_option"] { 100 | globals_set("another_option", anotherOption); 101 | } 102 | } 103 | } 104 | ``` 105 | 106 | Extension globals cannot be dynamically accessed, since the C code generated by the `globals_get`/`globals_set` optimizers must be resolved at compilation time: 107 | 108 | ```zephir 109 | let myOption = "someOption"; 110 | 111 | // will throw a compiler exception 112 | let someOption = globals_get(myOption); 113 | ``` 114 | -------------------------------------------------------------------------------- /en/license.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'en' 4 | version: '0.12' 5 | --- 6 | 7 | # License 8 | 9 | MIT License 10 | 11 | Copyright (c) 2013-present Zephir Team 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy 14 | of this software and associated documentation files (the "Software"), to deal 15 | in the Software without restriction, including without limitation the rights 16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | copies of the Software, and to permit persons to whom the Software is 18 | furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included in 21 | all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 | THE SOFTWARE. 30 | -------------------------------------------------------------------------------- /en/operator-precedence.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'en' 4 | version: '0.12' 5 | --- 6 | # Operator Precedence 7 | **Operator precedence** determines how operators are parsed. Operators with 8 | higher precedence become the operands of operators with lower precedence. For 9 | example, in the expression `1 + 5 * 3`, the answer is 16 and not 18 because 10 | the multiplication (`*`) operator has a higher precedence than the addition 11 | (`+`) operator. Parentheses may be used to force precedence, if necessary. 12 | For instance: `(1 + 5) * 3` evaluates to 18. 13 | 14 | 15 | ## Associativity 16 | When operators have equal precedence their **associativity** determines how the 17 | operators are grouped. For example `-` is _left-associative_, so `1 - 2 - 3` is 18 | grouped as `(1 - 2) - 3` and evaluates to `-4`. `=` on the other hand is 19 | _right-associative_, so `let a = b = c` is grouped as `let a = (b = c)`. 20 | 21 | Operators of equal precedence that are _non-associative_ cannot be used next to 22 | one another. For example: 23 | ```zep 24 | new new Foo(); 25 | ``` 26 | is illegal in Zephir, because the `new` is non-associative. At the moment, `new` 27 | is the only non-associative operator in Zephir. 28 | 29 | Use of parentheses, even when not strictly necessary, can often increase 30 | readability of the code, by making grouping explicit, rather than relying on 31 | the implicit operator precedence and associativity. 32 | 33 | 34 | ## Precedence Table 35 | The following table lists the operators in order of precedence, with the 36 | highest-precedence ones at the top. Operators on the same line have equal 37 | precedence, in which case associativity decides grouping. 38 | 39 | | Precedence | Operators | Operator type | Associativity | 40 | |------------|---------------------------|-------------------------------------|-----------------| 41 | | 1 | `->` | Member Access | right-to-left | 42 | | 2 | `~` | Bitwise NOT | right-to-left | 43 | | 3 | `!` | Logical NOT | right-to-left | 44 | | 4 | `new` | new | non-associative | 45 | | 5 | `clone` | clone | right-to-left | 46 | | 6 | `typeof` | Type-of | right-to-left | 47 | | 7 | `..`, `...` | Inclusive/exclusive range | left-to-right | 48 | | 8 | `isset`, `fetch`, `empty` | Exclusive range | right-to-left | 49 | | 9 | `*`, `/`, `%` | Multiplication, Division, Remainder | left-to-right | 50 | | 10 | `+`, `-`, `.` | Addition, Subtraction, Concat | left-to-right | 51 | | 11 | `<<`, `>>` | Bitwise shift left/right | left-to-right | 52 | | 12 | `<`, `<=`, `=>`, `>` | Comparison | left-to-right | 53 | | 13 | `==`, `!==`, `===`, `!==` | Comparison | left-to-right | 54 | | 14 | `&` | Bitwise AND, references | left-to-right | 55 | | 15 | `^` | Bitwise XOR | left-to-right | 56 | | 16 | `|` | Bitwise OR | left-to-right | 57 | | 17 | `instanceof` | Instance-of | left-to-right | 58 | | 18 | `&&` | Logical AND | left-to-right | 59 | | 19 | `||` | Logical OR | left-to-right | 60 | | 20 | `likely`, `unlikely` | Branch prediction | right-to-left | 61 | | 21 | `?` | Logical | right-to-left | 62 | | 21 | `=>` | Closure Arrow | right-to-left | 63 | -------------------------------------------------------------------------------- /en/phpinfo.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'en' 4 | version: '0.12' 5 | --- 6 | 7 | # Phpinfo() sections 8 | Like most extensions, Zephir extensions are able to show information in the [phpinfo()](https://php.net/manual/en/function.phpinfo.php) output. This information is usually related to directives, environment data, etc. 9 | 10 | By default, every Zephir extension automatically adds a basic table to the `phpinfo()` output showing the extension version, and any INI options the extension supports. 11 | 12 | You can add more directives by adding the following configuration to the `config.json` file: 13 | 14 | ```json 15 | "info": [ 16 | { 17 | "header": ["Directive", "Value"], 18 | "rows": [ 19 | ["setting1", "value1"], 20 | ["setting2", "value2"] 21 | ] 22 | }, 23 | { 24 | "header": ["Directive", "Value"], 25 | "rows": [ 26 | ["setting3", "value3"], 27 | ["setting4", "value4"] 28 | ] 29 | } 30 | ] 31 | ``` 32 | 33 | This information will be shown as follows: 34 | 35 | ![](/assets/content/info.png) 36 | -------------------------------------------------------------------------------- /en/sidebar.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "text": "Welcome", 4 | "url": "welcome" 5 | }, 6 | { 7 | "text": "Why Zephir", 8 | "url": "motivation" 9 | }, 10 | { 11 | "text": "Introducing Zephir", 12 | "url": "introduction" 13 | }, 14 | { 15 | "text": "Installation", 16 | "url": "installation" 17 | }, 18 | { 19 | "text": "Tutorial", 20 | "url": "tutorial" 21 | }, 22 | { 23 | "text": "Basic Syntax", 24 | "url": "language" 25 | }, 26 | { 27 | "text": "Types", 28 | "url": "types" 29 | }, 30 | { 31 | "text": "Operators", 32 | "url": "operators" 33 | }, 34 | { 35 | "text": "Operator Precedence", 36 | "url": "operator-precedence" 37 | }, 38 | { 39 | "text": "Arrays", 40 | "url": "arrays" 41 | }, 42 | { 43 | "text": "Classes and objects", 44 | "url": "oop" 45 | }, 46 | { 47 | "text": "Built-in methods", 48 | "url": "builtin-methods" 49 | }, 50 | { 51 | "text": "Control structures", 52 | "url": "control-structures" 53 | }, 54 | { 55 | "text": "Exceptions", 56 | "url": "exceptions" 57 | }, 58 | { 59 | "text": "Calling functions", 60 | "url": "functions" 61 | }, 62 | { 63 | "text": "Closures", 64 | "url": "closures" 65 | }, 66 | { 67 | "text": "Custom optimizers", 68 | "url": "optimizers" 69 | }, 70 | { 71 | "text": "Configuration file", 72 | "url": "config" 73 | }, 74 | { 75 | "text": "Command Line", 76 | "url": "command-line" 77 | }, 78 | { 79 | "text": "Lifecycle hooks", 80 | "url": "lifecycle" 81 | }, 82 | { 83 | "text": "Extension globals", 84 | "url": "globals" 85 | }, 86 | { 87 | "text": "phpinfo() sections", 88 | "url": "phpinfo" 89 | }, 90 | { 91 | "text": "Static analysis", 92 | "url": "static-analysis" 93 | }, 94 | { 95 | "text": "Optimizations", 96 | "url": "optimizations" 97 | }, 98 | { 99 | "text": "Compiler warnings", 100 | "url": "warnings" 101 | }, 102 | { 103 | "text": "License", 104 | "url": "license" 105 | } 106 | ] 107 | -------------------------------------------------------------------------------- /en/static-analysis.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'en' 4 | version: '0.12' 5 | --- 6 | 7 | # Static Analysis 8 | Zephir's compiler provides static analysis of the compiled code. The idea behind this feature is to help the developer to find potential problems and avoid unexpected behaviors, well before runtime. 9 | 10 | 11 | ## Conditional Unassigned Variables 12 | Static Analysis of assignments tries to identify if a variable is used before it's assigned: 13 | 14 | ```zephir 15 | class Utils 16 | { 17 | public function someMethod(b) 18 | { 19 | string a; char c; 20 | 21 | if b == 10 { 22 | let a = "hello"; 23 | } 24 | 25 | //a could be unitialized here 26 | for c in a { 27 | echo c, PHP_EOL; 28 | } 29 | } 30 | } 31 | ``` 32 | 33 | The above example illustrates a common situation. The variable `a` is assigned only when `b` is equal to 10, then it's required to use the value of this variable - but it could be uninitialized. Zephir detects this, automatically initializes the variable to an empty string, and generates a warning alerting the developer: 34 | 35 | ```bash 36 | Warning: Variable 'a' was assigned for the first time in conditional branch, 37 | consider initialize it in its declaration in 38 | /home/scott/test/test/utils.zep on 21 [conditional-initialization] 39 | 40 | for c in a { 41 | ``` 42 | 43 | Finding such errors is sometimes tricky, however static analysis helps the programmer to find bugs in advance. 44 | 45 | 46 | ## Dead Code Elimination 47 | Zephir informs the developer about unreachable branches in the code and performs dead code elimination, which means it gets rid of all that code from the generated binary, since it cannot be executed anyway: 48 | 49 | ```zephir 50 | class Utils 51 | { 52 | public function someMethod(b) 53 | { 54 | if false { 55 | // This is never executed 56 | echo "hello"; 57 | } 58 | } 59 | } 60 | ``` 61 | -------------------------------------------------------------------------------- /en/warnings.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'en' 4 | version: '0.12' 5 | --- 6 | 7 | # Compiler Warnings 8 | The compiler raises warnings when it finds situations where the code can be improved, or a potential error can be avoided. 9 | 10 | Warnings can be enabled via command line parameters, or can be added to the `config.json` to enable or disable them more permanently. 11 | 12 | You can enable warnings by passing their name prefixed by `-w`: 13 | 14 | ```bash 15 | zephir -wunused-variable -wnonexistent-function 16 | ``` 17 | 18 | Warnings can be disabled by passing their name prefixed by `-W`: 19 | 20 | ```bash 21 | zephir -Wunused-variable -Wnonexistent-function 22 | ``` 23 | 24 | The following warnings are supported: 25 | 26 | 27 | ## unused-variable 28 | Raised when a variable is declared but it is not used within a method. This warning is enabled by default. 29 | 30 | ```zephir 31 | public function some() 32 | { 33 | var e; // declared but not used 34 | 35 | return false; 36 | } 37 | ``` 38 | 39 | 40 | ## unused-variable-external 41 | Raised when a parameter is declared but it is not used within a method. 42 | 43 | ```zephir 44 | public function sum(a, b, c) // c is not used 45 | { 46 | return a + b; 47 | } 48 | ``` 49 | 50 | 51 | ## possible-wrong-parameter-undefined 52 | Raised when a method is called with a wrong type for a parameter: 53 | 54 | ```zephir 55 | public function some() 56 | { 57 | return this->sum("a string", "another"); // wrong parameters passed 58 | } 59 | 60 | public function sum(int a, int b) 61 | { 62 | return a + b; 63 | } 64 | ``` 65 | 66 | 67 | ## nonexistent-function 68 | Raised when a function is called that does not exist at compile time: 69 | 70 | ```zephir 71 | public function some() 72 | { 73 | someFunction(); // someFunction does not exist 74 | } 75 | ``` 76 | 77 | 78 | ## nonexistent-class 79 | Raised when a class is used that does not exist at compile time: 80 | 81 | ```zephir 82 | public function some() 83 | { 84 | var a; 85 | 86 | let a = new \MyClass(); // MyClass does not exist 87 | } 88 | ``` 89 | 90 | 91 | ## non-valid-isset 92 | Raised when the compiler detects that an 'isset' operation is being made on a non-array or -object value: 93 | 94 | ```zephir 95 | public function some() 96 | { 97 | var b = 1.2; 98 | 99 | return isset b[0]; // variable integer 'b' used as array 100 | } 101 | ``` 102 | 103 | 104 | ## non-array-update 105 | Raised when the compiler detects that an array update operation is being made on a non-array value: 106 | 107 | ```zephir 108 | public function some() 109 | { 110 | var b = 1.2; 111 | let b[0] = true; // variable 'b' cannot be used as array 112 | } 113 | ``` 114 | 115 | 116 | ## non-valid-objectupdate 117 | Raised when the compiler detects that an object update operation is being made on a non-object value: 118 | 119 | ```zephir 120 | public function some() 121 | { 122 | var b = 1.2; 123 | let b->name = true; // variable 'b' cannot be used as object 124 | } 125 | ``` 126 | 127 | 128 | ## non-valid-fetch 129 | Raised when the compiler detects that a 'fetch' operation is being made on a non-array or -object value: 130 | 131 | ##### variable integer 'b' used as array 132 | 133 | ```zephir 134 | public function some() 135 | { 136 | var b = 1.2, a; 137 | fetch a, b[0]; 138 | } 139 | ``` 140 | 141 | 142 | ## invalid-array-index 143 | Raised when the compiler detects that an invalid array index is used: 144 | 145 | ```zephir 146 | public function some(var a) 147 | { 148 | var b = []; 149 | let a[b] = true; 150 | } 151 | ``` 152 | 153 | 154 | ## non-array-append 155 | Raised when the compiler detects that an element is being appended to a non-array variable: 156 | 157 | ```zephir 158 | public function some() 159 | { 160 | var b = false; 161 | let b[] = "some value"; 162 | } 163 | ``` 164 | -------------------------------------------------------------------------------- /en/welcome.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'en' 4 | version: '0.12' 5 | --- 6 | 7 | # Welcome! 8 | Welcome to Zephir, an open source, high-level/domain specific language designed to ease the creation and maintainability of extensions for PHP, with a focus on type and memory safety. 9 | 10 | 11 | ## Some features 12 | Zephir's main features are: 13 | 14 | | Feature | Description | 15 | |--------------------|-------------------------------------------------------| 16 | | Type system | dynamic/static | 17 | | Memory safety | pointers or direct memory management are not allowed | 18 | | Compilation model | ahead of time | 19 | | Memory model | task-local garbage collection | 20 | 21 | 22 | ## A small taste 23 | The following code registers a class with a method that filters variables, returning their alphabetic characters: 24 | 25 | ```zephir 26 | namespace MyLibrary; 27 | 28 | /** 29 | * Filter 30 | */ 31 | class Filter 32 | { 33 | /** 34 | * Filters a string, returning its alpha charactersa 35 | * 36 | * @param string str 37 | */ 38 | public function alpha(string str) 39 | { 40 | char ch; string filtered = ""; 41 | 42 | for ch in str { 43 | if (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') { 44 | let filtered .= ch; 45 | } 46 | } 47 | 48 | return filtered; 49 | } 50 | } 51 | ``` 52 | 53 | The class can be used from PHP as follows: 54 | 55 | ```php 56 | alpha("01he#l.lo?/1"); // prints hello 60 | ``` 61 | 62 | 63 | ## External Links 64 | Below we have collected links to external resources that may interest you: 65 | 66 | - [Type system](https://en.wikipedia.org/wiki/Type_system) 67 | - [Memory safety](https://en.wikipedia.org/wiki/Memory_safety) 68 | - [Ahead-of-time compilation](https://en.wikipedia.org/wiki/Ahead-of-time_compilation) 69 | - [Memory management](https://en.wikipedia.org/wiki/Memory_management) 70 | -------------------------------------------------------------------------------- /es-es/arrays.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'es-es' 4 | version: '0.12' 5 | --- 6 | 7 | # Arrays 8 | 9 | La manipulación de arrays o arreglos en Zephir proporciona una manera de utilizar los [arrays de PHP](https://www.php.net/manual/en/language.types.array.php). Un array es una implementación de una [tabla hash](https://en.wikipedia.org/wiki/Hash_table). 10 | 11 | 12 | 13 | ## Declarar Variables de tipo Array 14 | 15 | Variables de array pueden ser declaradas usando las palabras clave 'var' o 'array': 16 | 17 | ```zephir 18 | var a = []; // variable array, el tipo puede ser cambiado 19 | array b = []; // variable array, el tipo no puede ser cambiado durante la ejecución 20 | ``` 21 | 22 | 23 | 24 | ## Creación de Arrays 25 | 26 | Un array se crea encerrando sus elementos entre corchetes: 27 | 28 | ##### Crear una arreglo vacío 29 | 30 | ```zephir 31 | let elements = []; 32 | ``` 33 | 34 | ##### Crear un arreglo con elementos 35 | 36 | ```zephir 37 | let elements = [1, 3, 4]; 38 | ``` 39 | 40 | ##### Crear un arreglo con elementos de diferentes tipos 41 | 42 | ```zephir 43 | let elements = ["first", 2, true]; 44 | ``` 45 | 46 | ##### Un arreglo multidimensional 47 | 48 | ```zephir 49 | let elements = [[0, 1], [4, 5], [2, 3]]; 50 | ``` 51 | 52 | Al igual que en PHP los hashes o claves están soportadas, también conocidos como arreglos asociativos: 53 | 54 | ##### Creación de un arreglo asociativo con claves de texto 55 | 56 | ```zephir 57 | let elements = ["foo": "bar", "bar": "foo"]; 58 | ``` 59 | 60 | ##### Creación de un array asociativo con claves numéricas 61 | 62 | ```zephir 63 | let elements = [4: "bar", 8: "foo"]; 64 | ``` 65 | 66 | ##### Creación de un array asociativo mixto, con claves de texto y numéricas 67 | 68 | ```zephir 69 | let elements = [4: "bar", "foo": 8]; 70 | ``` 71 | 72 | 73 | 74 | ## Actualización de arrays 75 | 76 | Los arreglos se actualizan en la misma manera que en PHP, utilizando corchetes cuadrados: 77 | 78 | ##### Actualización de un array con una llave de texto 79 | 80 | ```zephir 81 | let elements["foo"] = "bar"; 82 | ``` 83 | 84 | ##### Actualización de un array con una llave numérica 85 | 86 | ```zephir 87 | let elements[0] = "bar"; 88 | ``` 89 | 90 | ##### Actualización de un array multidimensional 91 | 92 | ```zephir 93 | let elements[0]["foo"] = "bar"; 94 | let elements["foo"][0] = "bar"; 95 | ``` 96 | 97 | 98 | 99 | ## Agregando elementos 100 | 101 | Los elementos pueden ser añadidos al final del array de la siguiente manera: 102 | 103 | ##### Añadir un nuevo elemento a un array 104 | 105 | ```zephir 106 | let elements[] = "bar"; 107 | ``` 108 | 109 | 110 | 111 | ## Leyendo elementos desde arrays 112 | 113 | Es posible leer los elementos de la matriz de la siguiente forma: 114 | 115 | ##### Obteniendo un elemento utilizando la clave de texto `foo` 116 | 117 | ```zephir 118 | let foo = elements["foo"]; 119 | ``` 120 | 121 | ##### Obteniendo un elemento utilizando la clave numérica 0 122 | 123 | ```zephir 124 | let foo = elements[0]; 125 | ``` -------------------------------------------------------------------------------- /es-es/closures.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'es-es' 4 | version: '0.12' 5 | --- 6 | 7 | # Closures 8 | 9 | You can use closures (a.k.a. anonymous functions) in Zephir; these are PHP compatible and can be returned to the PHP userland: 10 | 11 | ```zephir 12 | namespace MyLibrary; 13 | 14 | class Functional 15 | { 16 | 17 | public function map(array! data) 18 | { 19 | return function(number) { 20 | return number * number; 21 | }; 22 | } 23 | } 24 | ``` 25 | 26 | It also can be executed directly within Zephir, and passed as a parameter to other functions/methods: 27 | 28 | ```zephir 29 | namespace MyLibrary; 30 | 31 | class Functional 32 | { 33 | 34 | public function map(array! data) 35 | { 36 | return data->map(function(number) { 37 | return number * number; 38 | }); 39 | } 40 | } 41 | ``` 42 | 43 | A short syntax is also available to define closures: 44 | 45 | ```zephir 46 | namespace MyLibrary; 47 | 48 | class Functional 49 | { 50 | 51 | public function map(array! data) 52 | { 53 | return data->map(number => number * number); 54 | } 55 | } 56 | ``` -------------------------------------------------------------------------------- /es-es/command-line.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'es-es' 4 | version: '0.12' 5 | --- 6 | 7 | # The Zephir Command Line 8 | 9 | Once Zephir is installed, you'll use the `zephir` command to manage the Zephir compiler for your projects. This chapter, and the ones following, are about the command itself, how to use it, and how to understand the things it outputs. 10 | 11 | As of Zephir 0.11.7, the compiler makes use of `stderr` for displaying error messages. This means you can handle error outputs separately from normal ones, like so: 12 | 13 | ```bash 14 | zephir generate 2> errors.log 1> /dev/null 15 | ``` 16 | 17 | 18 | 19 | ## `zephir api` 20 | 21 | Generates an HTML API based on the classes exposed in the extension 22 | 23 | - `--backend=BACKEND`: Backend used to generate HTML API (default: `ZendEngine3`) 24 | - `--path=PATH` (or `-p PATH`): The API theme to be used 25 | - `--output=OUTPUT` (or `-o OUTPUT`): Output directory to generate theme 26 | - `--options=OPTIONS`: Theme options 27 | - `--url=URL`: The base URL to be used when generating links 28 | 29 | 30 | 31 | ## `zephir build` 32 | 33 | This is a meta command that just calls the [`generate`](#zephir-generate), [`compile`](#zephir-compile), and [`install`](#zephir-install) commands. Check those commands for more information on supported options and behaviors for each. 34 | 35 | 36 | 37 | ## `zephir clean` 38 | 39 | Cleans any object files created by the extension 40 | 41 | 42 | 43 | ## `zephir compile` 44 | 45 | Compile a Zephir extension 46 | 47 | - `--backend=BACKEND`: Backend used to build extension (default: `ZendEngine3`) 48 | - `--dev`: Build the extension in development mode 49 | - `--no-dev`: Build the extension in production mode 50 | 51 | Using `--dev` option will force building and installing the extension in development mode (debug symbols and no optimizations). An extension compiled with debugging symbols means you can run a program or library through a debugger and the debugger's output will be user friendlier. These debugging symbols also enlarge the program or library significantly. 52 | 53 | NOTE: Zephir development mode will be enabled silently if your PHP binary was compiled in a debug configuration. 54 | 55 | In some cases, we would like to get production ready extension even if the PHP binary was compiled in a debug configuration. Use `--no-dev` option to achieve this behavior. 56 | 57 | Additionally, any of the options available [under `extra` in the configuration file](/{{ page.version }}/{{ page.language }}/config#extra) can also be passed as options, here, such as `--export-classes` and `--indent=tabs`. 58 | 59 | 60 | 61 | ## `zephir fullclean` 62 | 63 | Cleans any object files created by the extension (including files generated by phpize) 64 | 65 | 66 | 67 | ## `zephir generate` 68 | 69 | Generates C code from the Zephir code 70 | 71 | - `--backend=BACKEND`: Backend used to build extension (default: `ZendEngine3`) 72 | 73 | 74 | 75 | ## `zephir help` 76 | 77 | Displays help for a command 78 | 79 | 80 | 81 | ## `zephir init` 82 | 83 | Initializes a Zephir extension `zephir init ` 84 | 85 | - `namespace`: The extension namespace 86 | - `--backend=BACKEND`: Backend used to create extension (default: `ZendEngine3`) 87 | 88 | 89 | 90 | ## `zephir install` 91 | 92 | Installs the extension in the extension directory (may require root password) 93 | 94 | - `--dev`: Install the extension in development mode 95 | - `--no-dev`: Install the extension in production mode 96 | 97 | 98 | 99 | ## `zephir list` 100 | 101 | Lists commands 102 | 103 | 104 | 105 | ## `zephir stubs` 106 | 107 | Generates stubs that can be used in a PHP IDE 108 | 109 | - `--backend=BACKEND`: Backend used to generate stubs (default: `ZendEngine3`) 110 | -------------------------------------------------------------------------------- /es-es/exceptions.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'es-es' 4 | version: '0.12' 5 | --- 6 | 7 | # Exceptions 8 | 9 | Zephir implements exceptions at a very low level, providing similar behavior and functionality to PHP. 10 | 11 | When an exception is thrown, a `catch` block can be used to capture the exception and allow the developer to provide proper handling: 12 | 13 | Exceptions can be thrown inside the `try` block. Handling happens in the `catch` block, exactly as in PHP: 14 | 15 | ```zephir 16 | var e; 17 | try { 18 | 19 | throw new \Exception("This is an exception"); 20 | 21 | } catch \Exception, e { 22 | 23 | echo e->getMessage(); 24 | } 25 | ``` 26 | 27 | Zephir also provides a "silent" `try` block, that simply ignores any exceptions produced within that block: 28 | 29 | ```zephir 30 | try { 31 | throw new \Exception("This is an exception"); 32 | } 33 | ``` 34 | 35 | If you don't need an exception variable when 'catch'ing, then you can safely not provide it: 36 | 37 | ```zephir 38 | try { 39 | 40 | throw new \Exception("This is an exception"); 41 | 42 | } catch \Exception { 43 | 44 | echo "An exception occur!"; 45 | } 46 | ``` 47 | 48 | A single `catch` block can be used to catch multiple types of exception: 49 | 50 | ```zephir 51 | var e; 52 | try { 53 | 54 | throw new \Exception("This is an exception"); 55 | 56 | } catch \RuntimeException|\Exception, e { 57 | 58 | echo e->getMessage(); 59 | } 60 | ``` 61 | 62 | Zephir allows you to throw literals or static typed variables as if they were the message of the exception: 63 | 64 | ```zephir 65 | // throw new \Exception("Test"); 66 | throw "Test"; 67 | 68 | // throw new \Exception((string) 't'); 69 | throw 't'; 70 | 71 | // throw new \Exception((string) 123); 72 | throw 123; 73 | 74 | // throw new \Exception((string) 123.123); 75 | throw 123.123; 76 | ``` 77 | 78 | Zephir's exceptions provide the same methods to know where the exception happened that PHP's exceptions do. That is, `Exception::getFile()` and `Exception::getLine()` return the location in the Zephir code where the exception was thrown: 79 | 80 | ```bash 81 | Exception: The static method 'someMethod' does not exist on model 'Robots' 82 | File=phalcon/mvc/model.zep Line=4042 83 | #0 /home/scott/test.php(64): Phalcon\Mvc\Model::__callStatic('someMethod', Array) 84 | #1 /home/scott/test.php(64): Robots::someMethod() 85 | #2 {main} 86 | ``` -------------------------------------------------------------------------------- /es-es/functions.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'es-es' 4 | version: '0.12' 5 | --- 6 | 7 | # Calling Functions 8 | 9 | PHP has a rich library of functions that you can use within your extensions. To call a PHP function you simply use it as normal within your Zephir code: 10 | 11 | ```zephir 12 | namespace MyLibrary; 13 | 14 | class Encoder 15 | { 16 | public function encode(var text) 17 | { 18 | if strlen(text) != 0 { 19 | return base64_encode(text); 20 | } 21 | return false; 22 | } 23 | } 24 | ``` 25 | 26 | You can also call functions that are expected to exist in the PHP userland, but are not necessarily built in to PHP itself: 27 | 28 | ```zephir 29 | namespace MyLibrary; 30 | 31 | class Encoder 32 | { 33 | 34 | public function encode(var text) 35 | { 36 | if strlen(text) != 0 { 37 | if function_exists("my_custom_encoder") { 38 | return my_custom_encoder(text); 39 | } else { 40 | return base64_encode(text); 41 | } 42 | } 43 | return false; 44 | } 45 | } 46 | ``` 47 | 48 | Note that all PHP functions only receive and return dynamic variables. If you pass a static typed variable as a parameter, a temporary dynamic variable will automatically be used as a bridge in order to call the function: 49 | 50 | ```zephir 51 | namespace MyLibrary; 52 | 53 | class Encoder 54 | { 55 | public function encode(string text) 56 | { 57 | if strlen(text) != 0 { 58 | // an implicit dynamic variable is created to 59 | // pass the static typed 'text' as parameter 60 | return base64_encode(text); 61 | } 62 | return false; 63 | } 64 | } 65 | ``` 66 | 67 | Similarly, functions return dynamic values, which cannot be directly assigned to static variables without the appropriate explicit cast: 68 | 69 | ```zephir 70 | namespace MyLibrary; 71 | 72 | class Encoder 73 | { 74 | public function encode(string text) 75 | { 76 | string encoded = ""; 77 | 78 | if strlen(text) != 0 { 79 | let encoded = (string) base64_encode(text); 80 | return "(" . encoded . ")"; 81 | } 82 | return false; 83 | } 84 | } 85 | ``` 86 | 87 | Zephir also provides a way for you to call functions dynamically, such as: 88 | 89 | ```zephir 90 | namespace MyLibrary; 91 | 92 | class Encoder 93 | { 94 | public function encode(var callback, string text) 95 | { 96 | return {callback}(text); 97 | } 98 | } 99 | ``` -------------------------------------------------------------------------------- /es-es/globals.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'es-es' 4 | version: '0.12' 5 | --- 6 | 7 | # Extension Globals 8 | 9 | PHP extensions provide a way to define globals within an extension. Reading/writing globals should be faster than any other global mechanisms (like static members). You can use extension globals to set up configuration options that change the behavior of your library. 10 | 11 | In Zephir, extension globals are restricted to simple scalar types like `int`/`bool`/`double`/`char`, etc. Complex types such as string/array/object/resource are not allowed here. 12 | 13 | You can enable extension globals by adding the following structure to your `config.json`: 14 | 15 | ```json 16 | { 17 | "globals": { 18 | "allow_some_feature": { 19 | "type": "bool", 20 | "default": true, 21 | "module": true 22 | }, 23 | "number_times": { 24 | "type": "int", 25 | "default": 10 26 | }, 27 | "some_component.my_setting_1": { 28 | "type": "bool", 29 | "default": true 30 | }, 31 | "some_component.my_setting_2": { 32 | "type": "int", 33 | "default": 100 34 | } 35 | } 36 | } 37 | ``` 38 | 39 | Each global has the following structure: 40 | 41 | ```json 42 | "": { 43 | "type": "", 44 | "default": 45 | } 46 | ``` 47 | 48 | Compound (namespaced) globals have the following structure: 49 | 50 | ```json 51 | ".": { 52 | "type": "", 53 | "default": 54 | } 55 | ``` 56 | 57 | The optional `module` key, if present, places that global's initialization process into the module-wide `GINIT` lifecycle event, which just means it will only be set up once per PHP process, rather than being reinitialized for every request, which is the default: 58 | 59 | ```json 60 | { 61 | "globals": { 62 | "allow_some_feature": { 63 | "type": "bool", 64 | "default": true, 65 | "module": true 66 | }, 67 | "number_times": { 68 | "type": "int", 69 | "default": 10 70 | } 71 | } 72 | } 73 | ``` 74 | 75 | In the example above, `allow_some_feature` is set up only once at startup; `number_times` is set up at the start of each request. 76 | 77 | Inside any method, you can read/write extension globals using the built-in functions `globals_get`/`globals_set`: 78 | 79 | ```zephir 80 | globals_set("allow_some_feature", true); 81 | let someFeature = globals_get("allow_some_feature"); 82 | ``` 83 | 84 | If you want to change these globals from PHP, a good option is include a method aimed at this: 85 | 86 | ```zephir 87 | namespace Test; 88 | 89 | class MyOptions 90 | { 91 | 92 | public static function setOptions(array options) 93 | { 94 | boolean someOption, anotherOption; 95 | 96 | if fetch someOption, options["some_option"] { 97 | globals_set("some_option", someOption); 98 | } 99 | 100 | if fetch anotherOption, options["another_option"] { 101 | globals_set("another_option", anotherOption); 102 | } 103 | } 104 | } 105 | ``` 106 | 107 | Extension globals cannot be dynamically accessed, since the C code generated by the `globals_get`/`globals_set` optimizers must be resolved at compilation time: 108 | 109 | ```zephir 110 | let myOption = "someOption"; 111 | 112 | // will throw a compiler exception 113 | let someOption = globals_get(myOption); 114 | ``` -------------------------------------------------------------------------------- /es-es/license.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'es-es' 4 | version: '0.12' 5 | --- 6 | 7 | # Licencia 8 | 9 | MIT License 10 | 11 | Copyright (c) 2013-present Zephir Team 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /es-es/operator-precedence.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'es-es' 4 | version: '0.12' 5 | --- 6 | 7 | # Operator Precedence 8 | **Operator precedence** determines how operators are parsed. Operators with higher precedence become the operands of operators with lower precedence. For example, in the expression `1 + 5 * 3`, the answer is 16 and not 18 because the multiplication (`*`) operator has a higher precedence than the addition (`+`) operator. Parentheses may be used to force precedence, if necessary. For instance: `(1 + 5) * 3` evaluates to 18. 9 | 10 | 11 | 12 | ## Associativity 13 | When operators have equal precedence their **associativity** determines how the operators are grouped. For example `-` is _left-associative_, so `1 - 2 - 3` is grouped as `(1 - 2) - 3` and evaluates to `-4`. `=` on the other hand is _right-associative_, so `let a = b = c` is grouped as `let a = (b = c)`. 14 | 15 | Operators of equal precedence that are _non-associative_ cannot be used next to one another. For example: 16 | ```zep 17 | new new Foo(); 18 | ``` 19 | is illegal in Zephir, because the `new` is non-associative. At the moment, `new` is the only non-associative operator in Zephir. 20 | 21 | Use of parentheses, even when not strictly necessary, can often increase readability of the code, by making grouping explicit, rather than relying on the implicit operator precedence and associativity. 22 | 23 | 24 | 25 | ## Precedence Table 26 | The following table lists the operators in order of precedence, with the highest-precedence ones at the top. Operators on the same line have equal precedence, in which case associativity decides grouping. 27 | 28 | | Precedence | Operadores | Operator type | Associativity | 29 | | ---------- | -------------------------------- | ----------------------------------- | --------------- | 30 | | 1 | `->` | Member Access | right-to-left | 31 | | 2 | `~` | Bitwise NOT | right-to-left | 32 | | 3 | `!` | Logical NOT | right-to-left | 33 | | 4 | `new` | new | non-associative | 34 | | 5 | `clone` | clone | right-to-left | 35 | | 6 | `typeof` | Type-of | right-to-left | 36 | | 7 | `..`, `...` | Inclusive/exclusive range | left-to-right | 37 | | 8 | `isset`, `fetch`, `empty` | Exclusive range | right-to-left | 38 | | 9 | `*`, `/`, `%` | Multiplication, Division, Remainder | left-to-right | 39 | | 10 | `+`, `-`, `.` | Addition, Subtraction, Concat | left-to-right | 40 | | 11 | `<<`, `>>` | Bitwise shift left/right | left-to-right | 41 | | 12 | `<`, `<=`, `=>`, `>` | Comparison | left-to-right | 42 | | 13 | `==`, `!==`, `===`, `!==` | Comparison | left-to-right | 43 | | 14 | `&` | Bitwise AND, references | left-to-right | 44 | | 15 | `^` | Bitwise XOR | left-to-right | 45 | | 16 | `|` | Bitwise OR | left-to-right | 46 | | 17 | `instanceof` | Instance-of | left-to-right | 47 | | 18 | `&&` | Logical AND | left-to-right | 48 | | 19 | `||` | Logical OR | left-to-right | 49 | | 20 | `likely`, `unlikely` | Branch prediction | right-to-left | 50 | | 21 | `?` | Logical | right-to-left | 51 | | 21 | `=>` | Closure Arrow | right-to-left | 52 | -------------------------------------------------------------------------------- /es-es/phpinfo.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'es-es' 4 | version: '0.12' 5 | --- 6 | 7 | # Phpinfo() Secciones 8 | 9 | Like most extensions, Zephir extensions are able to show information in the [phpinfo()](https://php.net/manual/en/function.phpinfo.php) output. Esta información está usualmente relacionada con directivas, datos de entorno, etc. 10 | 11 | Por defecto, cada extensión de Zephir automáticamente agrega una tabla básica de datos a la salida de `phpinfo()` mostrando la versión de la extensión, y cualquier opción INI que soporte la extensión. 12 | 13 | Usted puede agregar más directivas agregando la siguiente configuración al archivo `config.json`: 14 | 15 | ```json 16 | "info": [ 17 | { 18 | "header": ["Directive", "Value"], 19 | "rows": [ 20 | ["setting1", "value1"], 21 | ["setting2", "value2"] 22 | ] 23 | }, 24 | { 25 | "header": ["Directive", "Value"], 26 | "rows": [ 27 | ["setting3", "value3"], 28 | ["setting4", "value4"] 29 | ] 30 | } 31 | ] 32 | ``` 33 | 34 | Esta información se mostrará de la siguiente manera: 35 | 36 | ![](/assets/content/info.png) -------------------------------------------------------------------------------- /es-es/sidebar.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "text": "Welcome", 4 | "url": "welcome" 5 | }, 6 | { 7 | "text": "Why Zephir", 8 | "url": "motivation" 9 | }, 10 | { 11 | "text": "Introducción a Zephir", 12 | "url": "introduction" 13 | }, 14 | { 15 | "text": "Instalación", 16 | "url": "installation" 17 | }, 18 | { 19 | "text": "Tutorial", 20 | "url": "tutorial" 21 | }, 22 | { 23 | "text": "Sintaxis básica", 24 | "url": "language" 25 | }, 26 | { 27 | "text": "Tipos", 28 | "url": "types" 29 | }, 30 | { 31 | "text": "Operadores", 32 | "url": "operators" 33 | }, 34 | { 35 | "text": "Operator Precedence", 36 | "url": "operator-precedence" 37 | }, 38 | { 39 | "text": "Arrays", 40 | "url": "arrays" 41 | }, 42 | { 43 | "text": "Classes and objects", 44 | "url": "oop" 45 | }, 46 | { 47 | "text": "Built-in methods", 48 | "url": "builtin-methods" 49 | }, 50 | { 51 | "text": "Control structures", 52 | "url": "control-structures" 53 | }, 54 | { 55 | "text": "Exceptions", 56 | "url": "exceptions" 57 | }, 58 | { 59 | "text": "Calling functions", 60 | "url": "functions" 61 | }, 62 | { 63 | "text": "Closures", 64 | "url": "closures" 65 | }, 66 | { 67 | "text": "Custom optimizers", 68 | "url": "optimizers" 69 | }, 70 | { 71 | "text": "Configuration file", 72 | "url": "config" 73 | }, 74 | { 75 | "text": "Command Line", 76 | "url": "command-line" 77 | }, 78 | { 79 | "text": "Lifecycle hooks", 80 | "url": "lifecycle" 81 | }, 82 | { 83 | "text": "Extension globals", 84 | "url": "globals" 85 | }, 86 | { 87 | "text": "phpinfo() sections", 88 | "url": "phpinfo" 89 | }, 90 | { 91 | "text": "Static analysis", 92 | "url": "static-analysis" 93 | }, 94 | { 95 | "text": "Optimizations", 96 | "url": "optimizations" 97 | }, 98 | { 99 | "text": "Compiler warnings", 100 | "url": "warnings" 101 | }, 102 | { 103 | "text": "Licencia", 104 | "url": "license" 105 | } 106 | ] 107 | -------------------------------------------------------------------------------- /es-es/static-analysis.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'es-es' 4 | version: '0.12' 5 | --- 6 | 7 | # Static Analysis 8 | 9 | Zephir's compiler provides static analysis of the compiled code. The idea behind this feature is to help the developer to find potential problems and avoid unexpected behaviors, well before runtime. 10 | 11 | 12 | 13 | ## Conditional Unassigned Variables 14 | 15 | Static Analysis of assignments tries to identify if a variable is used before it's assigned: 16 | 17 | ```zephir 18 | class Utils 19 | { 20 | public function someMethod(b) 21 | { 22 | string a; char c; 23 | 24 | if b == 10 { 25 | let a = "hello"; 26 | } 27 | 28 | //a could be unitialized here 29 | for c in a { 30 | echo c, PHP_EOL; 31 | } 32 | } 33 | } 34 | ``` 35 | 36 | The above example illustrates a common situation. The variable `a` is assigned only when `b` is equal to 10, then it's required to use the value of this variable - but it could be uninitialized. Zephir detects this, automatically initializes the variable to an empty string, and generates a warning alerting the developer: 37 | 38 | ```bash 39 | Warning: Variable 'a' was assigned for the first time in conditional branch, 40 | consider initialize it in its declaration in 41 | /home/scott/test/test/utils.zep on 21 [conditional-initialization] 42 | 43 | for c in a { 44 | ``` 45 | 46 | Finding such errors is sometimes tricky, however static analysis helps the programmer to find bugs in advance. 47 | 48 | 49 | 50 | ## Dead Code Elimination 51 | 52 | Zephir informs the developer about unreachable branches in the code and performs dead code elimination, which means it gets rid of all that code from the generated binary, since it cannot be executed anyway: 53 | 54 | ```zephir 55 | class Utils 56 | { 57 | public function someMethod(b) 58 | { 59 | if false { 60 | // This is never executed 61 | echo "hello"; 62 | } 63 | } 64 | } 65 | ``` -------------------------------------------------------------------------------- /es-es/welcome.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'es-es' 4 | version: '0.12' 5 | --- 6 | 7 | # ¡Bienvenido! 8 | 9 | Bienvenido a Zephir, un lenguaje de código abierto de alto nivel/dominio específico, diseñado para facilitar la creación y mantenimiento de extensiones para PHP con un enfoque de tipo y cuidado de memoria. 10 | 11 | 12 | 13 | ## Algunas características 14 | 15 | Las principales características de Zephir son: 16 | 17 | | Características | Descripción | 18 | | --------------------- | ------------------------------------------------------- | 19 | | Tipo de sistema | dinámica/estática | 20 | | Ahorro de memoria | punteros o gestión de memoria directa no está permitido | 21 | | Modelo de compilación | adelantado | 22 | | Modelo de memoria | recolección local de basura | 23 | 24 | 25 | 26 | ## Una pequeña prueba 27 | 28 | El siguiente código registra una clase con un método que filtra variables, regresando sus caracteres alfabéticos: 29 | 30 | ```zephir 31 | namespace MyLibrary; 32 | 33 | /** 34 | * Filtro 35 | */ 36 | class Filter 37 | { 38 | /** 39 | * Filtra una cadena de texto, retornando solo caracteres alfabéticos 40 | * 41 | * @param string str 42 | */ 43 | public function alpha(string str) 44 | { 45 | char ch; string filtered = ""; 46 | 47 | for ch in str { 48 | if (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') { 49 | let filtered .= ch; 50 | } 51 | } 52 | 53 | return filtered; 54 | } 55 | } 56 | ``` 57 | 58 | La clase puede ser utiliza desde PHP de la siguiente manera: 59 | 60 | ```php 61 | alpha("01ho#.la?/1"); // imprime hola 65 | ``` 66 | 67 | 68 | 69 | ## Enlaces externos 70 | 71 | A continuación hemos recopilado enlaces a recursos externos que te pueden interesar: 72 | 73 | - [Tipo de sistema](https://en.wikipedia.org/wiki/Type_system) 74 | - [Ahorro de memoria](https://en.wikipedia.org/wiki/Memory_safety) 75 | - [Compilación Ahead-of-time](https://en.wikipedia.org/wiki/Ahead-of-time_compilation) 76 | - [Gestión de la memoria](https://en.wikipedia.org/wiki/Memory_management) -------------------------------------------------------------------------------- /ru-ru/arrays.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'ru-ru' 4 | version: '0.12' 5 | --- 6 | 7 | # Массивы 8 | 9 | Работа с массивами в Zephir происходит таким же образом как и с [массивами в PHP](https://www.php.net/manual/en/language.types.array.php). An array is an implementation of a [hash table](https://en.wikipedia.org/wiki/Hash_table). 10 | 11 | 12 | 13 | ## Объявление массивов 14 | 15 | Массивы могут быть объявлены с помощью ключевых слов 'var' или 'array': 16 | 17 | ```zephir 18 | var a = []; // массив, с возможностью переопределения типа 19 | array b = []; // массив, без возможности переопределения типа 20 | ``` 21 | 22 | 23 | 24 | ## Создание массивов 25 | 26 | Массив создается путём заключения его элементов в квадратные скобки: 27 | 28 | ##### Создание пустого массива 29 | 30 | ```zephir 31 | let elements = []; 32 | ``` 33 | 34 | ##### Создание массива с элементами 35 | 36 | ```zephir 37 | let elements = [1, 3, 4]; 38 | ``` 39 | 40 | ##### Создание массива с элементами разных типов 41 | 42 | ```zephir 43 | let elements = ["first", 2, true]; 44 | ``` 45 | 46 | ##### Создание многомерного массива 47 | 48 | ```zephir 49 | let elements = [[0, 1], [4, 5], [2, 3]]; 50 | ``` 51 | 52 | Как и в PHP, поддерживаются простые (списки) и ассоциативные массивы: 53 | 54 | ##### Создание массива с строковыми ключами 55 | 56 | ```zephir 57 | let elements = ["foo": "bar", "bar": "foo"]; 58 | ``` 59 | 60 | ##### Создание массива с числовыми ключами 61 | 62 | ```zephir 63 | let elements = [4: "bar", 8: "foo"]; 64 | ``` 65 | 66 | ##### Создание массива со смешанными ключами (строковые и числовые) 67 | 68 | ```zephir 69 | let elements = [4: "bar", "foo": 8]; 70 | ``` 71 | 72 | 73 | 74 | ## Обновление массивов 75 | 76 | Массивы обновляются так же, как в PHP, используя квадратные скобки: 77 | 78 | ##### Обновление массива с строковым ключём 79 | 80 | ```zephir 81 | let elements["foo"] = "bar"; 82 | ``` 83 | 84 | ##### Обновление массива с числовым ключем 85 | 86 | ```zephir 87 | let elements[0] = "bar"; 88 | ``` 89 | 90 | ##### Обновление многомерного массива 91 | 92 | ```zephir 93 | let elements[0]["foo"] = "bar"; 94 | let elements["foo"][0] = "bar"; 95 | ``` 96 | 97 | 98 | 99 | ## Добавление элементов 100 | 101 | Элементы могут быть добавлены в конце массива следующим образом: 102 | 103 | ##### Добавление элемента в массив 104 | 105 | ```zephir 106 | let elements[] = "bar"; 107 | ``` 108 | 109 | 110 | 111 | ## Чтение элементов из массивов 112 | 113 | Можно прочитать элементы массива следующим образом: 114 | 115 | ##### Получение элемента используя строковый ключ `foo` 116 | 117 | ```zephir 118 | let foo = elements["foo"]; 119 | ``` 120 | 121 | ##### Получение элемента используя числовой ключ 0 122 | 123 | ```zephir 124 | let foo = elements[0]; 125 | ``` -------------------------------------------------------------------------------- /ru-ru/closures.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'ru-ru' 4 | version: '0.12' 5 | --- 6 | 7 | # Замыкания 8 | 9 | В Zephir вы можете использовать анонимные функции (также известные как замыкания); Они совместимы с PHP и могут передаваться в область видимости PHP кода: 10 | 11 | ```zephir 12 | namespace MyLibrary; 13 | 14 | class Functional 15 | { 16 | 17 | public function map(array! data) 18 | { 19 | return function(number) { 20 | return number * number; 21 | }; 22 | } 23 | } 24 | ``` 25 | 26 | Они также могут быть выполнены непосредственно в Zephir, и переданы в качестве параметра другим функциям/методам: 27 | 28 | ```zephir 29 | namespace MyLibrary; 30 | 31 | class Functional 32 | { 33 | 34 | public function map(array! data) 35 | { 36 | return data->map(function(number) { 37 | return number * number; 38 | }); 39 | } 40 | } 41 | ``` 42 | 43 | Для определения замыканий доступен также короткий синтаксис: 44 | 45 | ```zephir 46 | namespace MyLibrary; 47 | 48 | class Functional 49 | { 50 | 51 | public function map(array! data) 52 | { 53 | return data->map(number => number * number); 54 | } 55 | } 56 | ``` -------------------------------------------------------------------------------- /ru-ru/exceptions.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'ru-ru' 4 | version: '0.12' 5 | --- 6 | 7 | # Исключения 8 | 9 | Zephir реализует исключения на очень низком уровне, обеспечивая подобное PHP поведение и функциональность. 10 | 11 | Когда генерируется исключение, блок `catch` может быть использован для перехвата исключения и предоставления разработчику возможности обеспечить надлежащую обработку: 12 | 13 | Исключения могут быть выброшены внутри блока `try`. Обработка происходит в блоке `catch` точно так же, как в PHP: 14 | 15 | ```zephir 16 | var e; 17 | try { 18 | 19 | throw new \Exception("Это - исключение"); 20 | 21 | } catch \Exception, e { 22 | 23 | echo e->getMessage(); 24 | } 25 | ``` 26 | 27 | Zephir также предоставляет "тихий" блок `try`, который просто игнорирует любые исключения, генерируемые внутри этого блока: 28 | 29 | ```zephir 30 | try { 31 | throw new \Exception("Это исключение"); 32 | } 33 | ``` 34 | 35 | Если вам не нужна переменная исключения при его перехвате, вы можете не указать её: 36 | 37 | ```zephir 38 | try { 39 | 40 | throw new \Exception("Это исключение"); 41 | 42 | } catch \Exception { 43 | 44 | echo "An exception occur!"; 45 | } 46 | ``` 47 | 48 | Один `catch` блок может использоваться для перехвата нескольких типов исключений: 49 | 50 | ```zephir 51 | var e; 52 | try { 53 | 54 | throw new \Exception("Это исключение"); 55 | 56 | } catch \RuntimeException|\Exception, e { 57 | 58 | echo e->getMessage(); 59 | } 60 | ``` 61 | 62 | Zephir позволяет выбрасывать любые литеры или статически типизированные переменные, как если бы они были сообщением исключения: 63 | 64 | ```zephir 65 | // throw new \Exception("Тест"); 66 | throw "Тест"; 67 | 68 | // throw new \Exception((string) 't'); 69 | throw 't'; 70 | 71 | // throw new \Exception((string) 123); 72 | throw 123; 73 | 74 | // throw new \Exception((string) 123.123); 75 | throw 123.123; 76 | ``` 77 | 78 | Исключения Zephir предоставляют те же методы, что и исключения PHP, чтобы узнать, где произошло исключение. Таким образом, `Exception::getFile()` и ` Exception::getLine()` возвращают имя файла и номер строки соотвественно, где в Zephir коде было выброшено исключение: 79 | 80 | ```bash 81 | Exception: The static method 'someMethod' does not exist on model 'Robots' 82 | File=phalcon/mvc/model.zep Line=4042 83 | #0 /home/scott/test.php(64): Phalcon\Mvc\Model::__callStatic('someMethod', Array) 84 | #1 /home/scott/test.php(64): Robots::someMethod() 85 | #2 {main} 86 | ``` -------------------------------------------------------------------------------- /ru-ru/functions.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'ru-ru' 4 | version: '0.12' 5 | --- 6 | 7 | # Вызов функций 8 | 9 | PHP имеет богатую библиотеку функций, которые вы можете использовать в своих расширениях. Чтобы вызвать функцию PHP, вы просто используете её как обычно в своем коде Zephir: 10 | 11 | ```zephir 12 | namespace MyLibrary; 13 | 14 | class Encoder 15 | { 16 | public function encode(var text) 17 | { 18 | if strlen(text) != 0 { 19 | return base64_encode(text); 20 | } 21 | return false; 22 | } 23 | } 24 | ``` 25 | 26 | Вы также можете вызывать функции, которые, как ожидается, существуют в пользовательском окружении PHP, но не встроены в PHP: 27 | 28 | ```zephir 29 | namespace MyLibrary; 30 | 31 | class Encoder 32 | { 33 | 34 | public function encode(var text) 35 | { 36 | if strlen(text) != 0 { 37 | if function_exists("my_custom_encoder") { 38 | return my_custom_encoder(text); 39 | } else { 40 | return base64_encode(text); 41 | } 42 | } 43 | return false; 44 | } 45 | } 46 | ``` 47 | 48 | Обратите внимание, что все PHP-функции только получают и возвращают динамические переменные. Если вы передаете статически типизированную переменную в качестве параметра, то в качестве моста для вызова функции будет создана временная динамическая переменная: 49 | 50 | ```zephir 51 | namespace MyLibrary; 52 | 53 | class Encoder 54 | { 55 | public function encode(string text) 56 | { 57 | if strlen(text) != 0 { 58 | // an implicit dynamic variable is created to 59 | // pass the static typed 'text' as parameter 60 | return base64_encode(text); 61 | } 62 | return false; 63 | } 64 | } 65 | ``` 66 | 67 | Аналогично, функции возвращают динамические значения, которые не могут быть напрямую назначены статическим переменным без соответствующего приведения: 68 | 69 | ```zephir 70 | namespace MyLibrary; 71 | 72 | class Encoder 73 | { 74 | public function encode(string text) 75 | { 76 | string encoded = ""; 77 | 78 | if strlen(text) != 0 { 79 | let encoded = (string) base64_encode(text); 80 | return "(" . encoded . ")"; 81 | } 82 | return false; 83 | } 84 | } 85 | ``` 86 | 87 | Zephir также предоставляет способ для динамического вызова функций, например: 88 | 89 | ```zephir 90 | namespace MyLibrary; 91 | 92 | class Encoder 93 | { 94 | public function encode(var callback, string text) 95 | { 96 | return {callback}(text); 97 | } 98 | } 99 | ``` -------------------------------------------------------------------------------- /ru-ru/globals.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'ru-ru' 4 | version: '0.12' 5 | --- 6 | 7 | # Глобальные параметры расширения 8 | 9 | PHP расширения предоставляют способ определения глобальных переменных, которые будут доступны из любого места расширения. Операции чтения и записи таких переменных обычно выполняются быстрее, чем любые другие глобальные механизмы (например, доступ к статическим членам). Глобальные переменные расширения можно использовать для настройки параметров конфигурации, которые изменяют поведение вашей библиотеки. 10 | 11 | В Zephir глобальные переменные ограничены простыми скалярными типами такими как `int`, `bool`, `double`, `char` и т.д. Здесь не допускаются комплексные типы, такие как строки, массивы, объекты и ресурсы. 12 | 13 | Вы можете ввести глобальные переменные в расширение, добавив следующую структуру в `config.json`: 14 | 15 | ```json 16 | { 17 | "globals": { 18 | "allow_some_feature": { 19 | "type": "bool", 20 | "default": true, 21 | "module": true 22 | }, 23 | "number_times": { 24 | "type": "int", 25 | "default": 10 26 | }, 27 | "some_component.my_setting_1": { 28 | "type": "bool", 29 | "default": true 30 | }, 31 | "some_component.my_setting_2": { 32 | "type": "int", 33 | "default": 100 34 | } 35 | } 36 | } 37 | ``` 38 | 39 | Каждая глобальная переменная имеет следующую структуру: 40 | 41 | ```json 42 | "": { 43 | "type": "", 44 | "default": 45 | } 46 | ``` 47 | 48 | Составные (именованные) глобальные переменные имеют следующую структуру: 49 | 50 | ```json 51 | ".": { 52 | "type": "", 53 | "default": 54 | } 55 | ``` 56 | 57 | Необязательный ключ `module`, если он присутствует, помещает процесс инициализации параметра в глобальное событие расширения `GINIT`. Это означает, что параметр будет инициализирован указанным значением только один раз для каждого процесса PHP, а не будет повторно инициализирован для каждого запроса, что является значением по умолчанию: 58 | 59 | ```json 60 | { 61 | "globals": { 62 | "allow_some_feature": { 63 | "type": "bool", 64 | "default": true, 65 | "module": true 66 | }, 67 | "number_times": { 68 | "type": "int", 69 | "default": 10 70 | } 71 | } 72 | } 73 | ``` 74 | 75 | В примере выше, `allow_some_feature` настраивается только один раз при запуске; `number_times` устанавливается в начале каждого запроса. 76 | 77 | Доступ к глобальным переменным может быть осуществлён из любого метода расширения при помощи встроенных функций `globals_get` и `globals_set`: 78 | 79 | ```zephir 80 | globals_set("allow_some_feature", true); 81 | let someFeature = globals_get("allow_some_feature"); 82 | ``` 83 | 84 | Если вы хотите получать доступ к этим глобальным переменным из PHP, то неплохим вариантом является создание метода, направленного на это: 85 | 86 | ```zephir 87 | namespace Test; 88 | 89 | class MyOptions 90 | { 91 | 92 | public static function setOptions(array options) 93 | { 94 | boolean someOption, anotherOption; 95 | 96 | if fetch someOption, options["some_option"] { 97 | globals_set("some_option", someOption); 98 | } 99 | 100 | if fetch anotherOption, options["another_option"] { 101 | globals_set("another_option", anotherOption); 102 | } 103 | } 104 | } 105 | ``` 106 | 107 | Доступ к глобальным переменным расширения не может быть осуществлен с помощью динамически вычисляемого кода. Это связанно с тем, что C-код, сгенерированный оптимизаторами функций `globals_get` и `globals_set`, должен быть вычислен во время компиляции: 108 | 109 | ```zephir 110 | let myOption = "someOption"; 111 | 112 | // Выбросит ошибку компиляции 113 | let someOption = globals_get(myOption); 114 | ``` -------------------------------------------------------------------------------- /ru-ru/license.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'ru-ru' 4 | version: '0.12' 5 | --- 6 | 7 | # Лицензионное соглашение 8 | 9 | Лицензия MIT 10 | 11 | Copyright (c) 2013 - по настоящее время: Команда Zephir 12 | 13 | Данная лицензия разрешает лицам, получившим копию данного программного обеспечения и сопутствующей документации (в дальнейшем именуемыми «Программное Обеспечение»), безвозмездно использовать Программное Обеспечение без ограничений, включая неограниченное право на использование, копирование, изменение, слияние, публикацию, распространение, сублицензирование и/или продажу копий Программного Обеспечения, а также лицам, которым предоставляется данное Программное Обеспечение, при соблюдении следующих условий: 14 | 15 | Указанное выше уведомление об авторском праве и данные условия должны быть включены во все копии или значимые части данного Программного Обеспечения. 16 | 17 | ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ ГАРАНТИИ ТОВАРНОЙ ПРИГОДНОСТИ, СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ НАЗНАЧЕНИЮ И ОТСУТСТВИЯ НАРУШЕНИЙ, НО НЕ ОГРАНИЧИВАЯСЬ ИМИ. НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ НЕ НЕСУТ ОТВЕТСТВЕННОСТИ ПО КАКИМ-ЛИБО ИСКАМ, ЗА УЩЕРБ ИЛИ ПО ИНЫМ ТРЕБОВАНИЯМ, В ТОМ ЧИСЛЕ, ПРИ ДЕЙСТВИИ КОНТРАКТА, ДЕЛИКТЕ ИЛИ ИНОЙ СИТУАЦИИ, ВОЗНИКШИМ ИЗ-ЗА ИСПОЛЬЗОВАНИЯ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ ИЛИ ИНЫХ ДЕЙСТВИЙ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ. -------------------------------------------------------------------------------- /ru-ru/operator-precedence.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'ru-ru' 4 | version: '0.12' 5 | --- 6 | 7 | # Operator Precedence 8 | **Operator precedence** determines how operators are parsed. Operators with higher precedence become the operands of operators with lower precedence. For example, in the expression `1 + 5 * 3`, the answer is 16 and not 18 because the multiplication (`*`) operator has a higher precedence than the addition (`+`) operator. Parentheses may be used to force precedence, if necessary. For instance: `(1 + 5) * 3` evaluates to 18. 9 | 10 | 11 | 12 | ## Associativity 13 | When operators have equal precedence their **associativity** determines how the operators are grouped. For example `-` is _left-associative_, so `1 - 2 - 3` is grouped as `(1 - 2) - 3` and evaluates to `-4`. `=` on the other hand is _right-associative_, so `let a = b = c` is grouped as `let a = (b = c)`. 14 | 15 | Operators of equal precedence that are _non-associative_ cannot be used next to one another. For example: 16 | ```zep 17 | new new Foo(); 18 | ``` 19 | is illegal in Zephir, because the `new` is non-associative. At the moment, `new` is the only non-associative operator in Zephir. 20 | 21 | Use of parentheses, even when not strictly necessary, can often increase readability of the code, by making grouping explicit, rather than relying on the implicit operator precedence and associativity. 22 | 23 | 24 | 25 | ## Precedence Table 26 | The following table lists the operators in order of precedence, with the highest-precedence ones at the top. Operators on the same line have equal precedence, in which case associativity decides grouping. 27 | 28 | | Precedence | Операторы | Operator type | Associativity | 29 | | ---------- | -------------------------------- | ----------------------------------- | --------------- | 30 | | 1 | `->` | Member Access | right-to-left | 31 | | 2 | `~` | Bitwise NOT | right-to-left | 32 | | 3 | `!` | Logical NOT | right-to-left | 33 | | 4 | `new` | new | non-associative | 34 | | 5 | `clone` | clone | right-to-left | 35 | | 6 | `typeof` | Type-of | right-to-left | 36 | | 7 | `..`, `...` | Inclusive/exclusive range | left-to-right | 37 | | 8 | `isset`, `fetch`, `empty` | Exclusive range | right-to-left | 38 | | 9 | `*`, `/`, `%` | Multiplication, Division, Remainder | left-to-right | 39 | | 10 | `+`, `-`, `.` | Addition, Subtraction, Concat | left-to-right | 40 | | 11 | `<<`, `>>` | Bitwise shift left/right | left-to-right | 41 | | 12 | `<`, `<=`, `=>`, `>` | Comparison | left-to-right | 42 | | 13 | `==`, `!==`, `===`, `!==` | Comparison | left-to-right | 43 | | 14 | `&` | Bitwise AND, references | left-to-right | 44 | | 15 | `^` | Bitwise XOR | left-to-right | 45 | | 16 | `|` | Bitwise OR | left-to-right | 46 | | 17 | `instanceof` | Instance-of | left-to-right | 47 | | 18 | `&&` | Logical AND | left-to-right | 48 | | 19 | `||` | Logical OR | left-to-right | 49 | | 20 | `likely`, `unlikely` | Branch prediction | right-to-left | 50 | | 21 | `?` | Logical | right-to-left | 51 | | 21 | `=>` | Closure Arrow | right-to-left | 52 | -------------------------------------------------------------------------------- /ru-ru/phpinfo.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'ru-ru' 4 | version: '0.12' 5 | --- 6 | 7 | # Секции phpinfo() 8 | 9 | Как и большинство расширений, расширения написанные на Zephir могут отображать информацию при выводе [phpinfo()](https://php.net/manual/en/function.phpinfo.php). Обычно эта информация относится к директивам, данным окружения и т.п. 10 | 11 | По умолчанию, каждое Zephir расширение добавляет базовую таблицу в вывод `phpinfo()` отображающую версию расширения. 12 | 13 | Вы можете добавить больше директив, добавив следующую конфигурацию в файл `config.json`: 14 | 15 | ```json 16 | "info": [ 17 | { 18 | "header": ["Directive", "Value"], 19 | "rows": [ 20 | ["setting1", "value1"], 21 | ["setting2", "value2"] 22 | ] 23 | }, 24 | { 25 | "header": ["Directive", "Value"], 26 | "rows": [ 27 | ["setting3", "value3"], 28 | ["setting4", "value4"] 29 | ] 30 | } 31 | ] 32 | ``` 33 | 34 | Эта информация будет отображена следующим образом: 35 | 36 | ![](/assets/content/info.png) -------------------------------------------------------------------------------- /ru-ru/sidebar.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "text": "Добро пожаловать", 4 | "url": "welcome" 5 | }, 6 | { 7 | "text": "Почему Zephir", 8 | "url": "motivation" 9 | }, 10 | { 11 | "text": "Введение в Zephir", 12 | "url": "introduction" 13 | }, 14 | { 15 | "text": "Установка", 16 | "url": "installation" 17 | }, 18 | { 19 | "text": "Урок", 20 | "url": "tutorial" 21 | }, 22 | { 23 | "text": "Базовый синтаксис", 24 | "url": "language" 25 | }, 26 | { 27 | "text": "Типы", 28 | "url": "types" 29 | }, 30 | { 31 | "text": "Операторы", 32 | "url": "operators" 33 | }, 34 | { 35 | "text": "Operator Precedence", 36 | "url": "operator-precedence" 37 | }, 38 | { 39 | "text": "Массивы", 40 | "url": "arrays" 41 | }, 42 | { 43 | "text": "Классы и объекты", 44 | "url": "oop" 45 | }, 46 | { 47 | "text": "Встроенные методы", 48 | "url": "builtin-methods" 49 | }, 50 | { 51 | "text": "Управляющие структуры", 52 | "url": "control-structures" 53 | }, 54 | { 55 | "text": "Исключения", 56 | "url": "exceptions" 57 | }, 58 | { 59 | "text": "Вызов функции", 60 | "url": "functions" 61 | }, 62 | { 63 | "text": "Замыкания", 64 | "url": "closures" 65 | }, 66 | { 67 | "text": "Настраиваемые оптимизаторы", 68 | "url": "optimizers" 69 | }, 70 | { 71 | "text": "Конфигурационный файл", 72 | "url": "config" 73 | }, 74 | { 75 | "text": "Командная строка", 76 | "url": "command-line" 77 | }, 78 | { 79 | "text": "Хуки жизненного цикла", 80 | "url": "lifecycle" 81 | }, 82 | { 83 | "text": "Глобальные параметры расширения", 84 | "url": "globals" 85 | }, 86 | { 87 | "text": "Секции phpinfo()", 88 | "url": "phpinfo" 89 | }, 90 | { 91 | "text": "Статический анализ", 92 | "url": "static-analysis" 93 | }, 94 | { 95 | "text": "Оптимизации", 96 | "url": "optimizations" 97 | }, 98 | { 99 | "text": "Предупреждения компилятора", 100 | "url": "warnings" 101 | }, 102 | { 103 | "text": "Лицензионное соглашение", 104 | "url": "license" 105 | } 106 | ] 107 | -------------------------------------------------------------------------------- /ru-ru/static-analysis.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'ru-ru' 4 | version: '0.12' 5 | --- 6 | 7 | # Статический анализ 8 | 9 | Компилятор Zephir предоставляет возможность статического анализа компилируемого кода. Идея этой функции заключается в том, чтобы помочь разработчику найти потенциальные проблемы и избежать неожиданного поведения задолго до времени исполнения. 10 | 11 | 12 | 13 | ## Условные неинициализированные переменные 14 | 15 | При присвоении значения переменно статический анализатор пытается определить, используется ли переменная до ее инициализации: 16 | 17 | ```zephir 18 | class Utils 19 | { 20 | public function someMethod(b) 21 | { 22 | string a; char c; 23 | 24 | if b == 10 { 25 | let a = "привет"; 26 | } 27 | 28 | // Есть вероятность, что переменная "a" не определена 29 | for c in a { 30 | echo c, PHP_EOL; 31 | } 32 | } 33 | } 34 | ``` 35 | 36 | Приведенный выше пример иллюстрирует общую ситуацию. Переменной `a` будет присвоено значение только в том случае, если переменная `b` равна 10, но как видно из этого примера, значение проверяемой переменной не определено в явном виде. Компилятор Zephir определяет это, автоматически инициализирует переменную в пустую строку и генерирует предупреждение разработчику: 37 | 38 | ```bash 39 | Warning: Variable 'a' was assigned for the first time in conditional branch, 40 | consider initialize it in its declaration in 41 | /home/scott/test/test/utils.zep on 21 [conditional-initialization] 42 | 43 | for c in a { 44 | ``` 45 | 46 | Обнаружить такие ошибки иногда сложно, однако статический анализ помогает программисту обнаружить ошибки заранее. 47 | 48 | 49 | 50 | ## Удаление мёртвого кода 51 | 52 | Zephir информирует разработчика о недоступных ветвях в коде и выполняет удаление мертвого кода, это означает, что он избавляется от всего этого кода из сгенерированного двоичного файла, поскольку он никогда не сможет быть запущен: 53 | 54 | ```zephir 55 | class Utils 56 | { 57 | public function someMethod(b) 58 | { 59 | if false { 60 | // Этот код никогда не выполнится 61 | echo "hello"; 62 | } 63 | } 64 | } 65 | ``` -------------------------------------------------------------------------------- /ru-ru/welcome.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'ru-ru' 4 | version: '0.12' 5 | --- 6 | 7 | # Добро пожаловать! 8 | 9 | Встречайте Zephir, открытый, высокоуровневый, специализированный язык разработанный для быстрого и удобного создания расширений для PHP с упором на типизацию и безопасное управление памятью. 10 | 11 | 12 | 13 | ## Некоторые особенности 14 | 15 | Основные особенности Zephir: 16 | 17 | | Особенность | Описание | 18 | | ----------------------------- | --------------------------------------------- | 19 | | Система типов | динамическая/статическая | 20 | | Безопасность доступа к памяти | указатели и ручное выделение памяти запрещены | 21 | | Модель компиляции | перед исполнением (AOT-компиляция) | 22 | | Управление памятью | свой сборщик мусора | 23 | 24 | 25 | 26 | ## Попробуйте 27 | 28 | Этот код регистрирует класс с методом, который оставляет в строке только буквы: 29 | 30 | ```zephir 31 | namespace MyLibrary; 32 | 33 | /** 34 | * Filter 35 | */ 36 | class Filter 37 | { 38 | /** 39 | * Filters a string, returning its alpha charactersa 40 | * 41 | * @param string str 42 | */ 43 | public function alpha(string str) 44 | { 45 | char ch; string filtered = ""; 46 | 47 | for ch in str { 48 | if (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') { 49 | let filtered .= ch; 50 | } 51 | } 52 | 53 | return filtered; 54 | } 55 | } 56 | ``` 57 | 58 | А теперь используем этот класс в PHP: 59 | 60 | ```php 61 | alpha("01he#l.lo?/1"); // выведет hello 65 | ``` 66 | 67 | 68 | 69 | ## Внешние ссылки 70 | 71 | Ниже мы собрали ссылки на внешние ресурсы, которые могу вас заинтересовать: 72 | 73 | - [Система типов](https://en.wikipedia.org/wiki/Type_system) 74 | - [Безопасность доступа к памяти](https://en.wikipedia.org/wiki/Memory_safety) 75 | - [AOT-компиляция](https://en.wikipedia.org/wiki/Ahead-of-time_compilation) 76 | - [Управление памятью](https://en.wikipedia.org/wiki/Memory_management) -------------------------------------------------------------------------------- /tr-tr/arrays.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'tr-tr' 4 | version: '0.12' 5 | --- 6 | 7 | # Arrays 8 | 9 | Array manipulation in Zephir provides a way to use PHP [array](https://www.php.net/manual/en/language.types.array.php). An array is an implementation of a [hash table](https://en.wikipedia.org/wiki/Hash_table). 10 | 11 | 12 | 13 | ## Declaring Array Variables 14 | 15 | Array variables can be declared using the keywords 'var' or 'array': 16 | 17 | ```zephir 18 | var a = []; // array variable, its type can be changed 19 | array b = []; // array variable, its type cannot be changed across execution 20 | ``` 21 | 22 | 23 | 24 | ## Creating Arrays 25 | 26 | An array is created by enclosing its elements in square brackets: 27 | 28 | ##### Creating an empty array 29 | 30 | ```zephir 31 | let elements = []; 32 | ``` 33 | 34 | ##### Creating an array with elements 35 | 36 | ```zephir 37 | let elements = [1, 3, 4]; 38 | ``` 39 | 40 | ##### Creating an array with elements of different types 41 | 42 | ```zephir 43 | let elements = ["first", 2, true]; 44 | ``` 45 | 46 | ##### A multidimensional array 47 | 48 | ```zephir 49 | let elements = [[0, 1], [4, 5], [2, 3]]; 50 | ``` 51 | 52 | As PHP, hashes or dictionaries are supported: 53 | 54 | ##### Creating a hash with string keys 55 | 56 | ```zephir 57 | let elements = ["foo": "bar", "bar": "foo"]; 58 | ``` 59 | 60 | ##### Creating a hash with numeric keys 61 | 62 | ```zephir 63 | let elements = [4: "bar", 8: "foo"]; 64 | ``` 65 | 66 | ##### Creating a hash with mixed string and numeric keys 67 | 68 | ```zephir 69 | let elements = [4: "bar", "foo": 8]; 70 | ``` 71 | 72 | 73 | 74 | ## Updating arrays 75 | 76 | Arrays are updated in the same way as PHP, using square brackets: 77 | 78 | ##### Updating an array with a string key 79 | 80 | ```zephir 81 | let elements["foo"] = "bar"; 82 | ``` 83 | 84 | ##### Updating an array with a numeric key 85 | 86 | ```zephir 87 | let elements[0] = "bar"; 88 | ``` 89 | 90 | ##### Updating multi-dimensional array 91 | 92 | ```zephir 93 | let elements[0]["foo"] = "bar"; 94 | let elements["foo"][0] = "bar"; 95 | ``` 96 | 97 | 98 | 99 | ## Appending elements 100 | 101 | Elements can be appended at the end of the array as follows: 102 | 103 | ##### Append an element to the array 104 | 105 | ```zephir 106 | let elements[] = "bar"; 107 | ``` 108 | 109 | 110 | 111 | ## Reading elements from arrays 112 | 113 | It is possible to read array elements as follows: 114 | 115 | ##### Getting an element using the string key `foo` 116 | 117 | ```zephir 118 | let foo = elements["foo"]; 119 | ``` 120 | 121 | ##### Getting an element using the numeric key 0 122 | 123 | ```zephir 124 | let foo = elements[0]; 125 | ``` -------------------------------------------------------------------------------- /tr-tr/closures.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'tr-tr' 4 | version: '0.12' 5 | --- 6 | 7 | # Closures 8 | 9 | You can use closures (a.k.a. anonymous functions) in Zephir; these are PHP compatible and can be returned to the PHP userland: 10 | 11 | ```zephir 12 | namespace MyLibrary; 13 | 14 | class Functional 15 | { 16 | 17 | public function map(array! data) 18 | { 19 | return function(number) { 20 | return number * number; 21 | }; 22 | } 23 | } 24 | ``` 25 | 26 | It also can be executed directly within Zephir, and passed as a parameter to other functions/methods: 27 | 28 | ```zephir 29 | namespace MyLibrary; 30 | 31 | class Functional 32 | { 33 | 34 | public function map(array! data) 35 | { 36 | return data->map(function(number) { 37 | return number * number; 38 | }); 39 | } 40 | } 41 | ``` 42 | 43 | A short syntax is also available to define closures: 44 | 45 | ```zephir 46 | namespace MyLibrary; 47 | 48 | class Functional 49 | { 50 | 51 | public function map(array! data) 52 | { 53 | return data->map(number => number * number); 54 | } 55 | } 56 | ``` -------------------------------------------------------------------------------- /tr-tr/command-line.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'tr-tr' 4 | version: '0.12' 5 | --- 6 | 7 | # The Zephir Command Line 8 | 9 | Once Zephir is installed, you'll use the `zephir` command to manage the Zephir compiler for your projects. This chapter, and the ones following, are about the command itself, how to use it, and how to understand the things it outputs. 10 | 11 | As of Zephir 0.11.7, the compiler makes use of `stderr` for displaying error messages. This means you can handle error outputs separately from normal ones, like so: 12 | 13 | ```bash 14 | zephir generate 2> errors.log 1> /dev/null 15 | ``` 16 | 17 | 18 | 19 | ## `zephir api` 20 | 21 | Generates an HTML API based on the classes exposed in the extension 22 | 23 | - `--backend=BACKEND`: Backend used to generate HTML API (default: `ZendEngine3`) 24 | - `--path=PATH` (or `-p PATH`): The API theme to be used 25 | - `--output=OUTPUT` (or `-o OUTPUT`): Output directory to generate theme 26 | - `--options=OPTIONS`: Theme options 27 | - `--url=URL`: The base URL to be used when generating links 28 | 29 | 30 | 31 | ## `zephir build` 32 | 33 | This is a meta command that just calls the [`generate`](#zephir-generate), [`compile`](#zephir-compile), and [`install`](#zephir-install) commands. Check those commands for more information on supported options and behaviors for each. 34 | 35 | 36 | 37 | ## `zephir clean` 38 | 39 | Cleans any object files created by the extension 40 | 41 | 42 | 43 | ## `zephir compile` 44 | 45 | Compile a Zephir extension 46 | 47 | - `--backend=BACKEND`: Backend used to build extension (default: `ZendEngine3`) 48 | - `--dev`: Build the extension in development mode 49 | - `--no-dev`: Build the extension in production mode 50 | 51 | Using `--dev` option will force building and installing the extension in development mode (debug symbols and no optimizations). An extension compiled with debugging symbols means you can run a program or library through a debugger and the debugger's output will be user friendlier. These debugging symbols also enlarge the program or library significantly. 52 | 53 | NOTE: Zephir development mode will be enabled silently if your PHP binary was compiled in a debug configuration. 54 | 55 | In some cases, we would like to get production ready extension even if the PHP binary was compiled in a debug configuration. Use `--no-dev` option to achieve this behavior. 56 | 57 | Additionally, any of the options available [under `extra` in the configuration file](/{{ page.version }}/{{ page.language }}/config#extra) can also be passed as options, here, such as `--export-classes` and `--indent=tabs`. 58 | 59 | 60 | 61 | ## `zephir fullclean` 62 | 63 | Cleans any object files created by the extension (including files generated by phpize) 64 | 65 | 66 | 67 | ## `zephir generate` 68 | 69 | Generates C code from the Zephir code 70 | 71 | - `--backend=BACKEND`: Backend used to build extension (default: `ZendEngine3`) 72 | 73 | 74 | 75 | ## `zephir help` 76 | 77 | Displays help for a command 78 | 79 | 80 | 81 | ## `zephir init` 82 | 83 | Initializes a Zephir extension `zephir init ` 84 | 85 | - `namespace`: The extension namespace 86 | - `--backend=BACKEND`: Backend used to create extension (default: `ZendEngine3`) 87 | 88 | 89 | 90 | ## `zephir install` 91 | 92 | Installs the extension in the extension directory (may require root password) 93 | 94 | - `--dev`: Install the extension in development mode 95 | - `--no-dev`: Install the extension in production mode 96 | 97 | 98 | 99 | ## `zephir list` 100 | 101 | Lists commands 102 | 103 | 104 | 105 | ## `zephir stubs` 106 | 107 | Generates stubs that can be used in a PHP IDE 108 | 109 | - `--backend=BACKEND`: Backend used to generate stubs (default: `ZendEngine3`) 110 | -------------------------------------------------------------------------------- /tr-tr/exceptions.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'tr-tr' 4 | version: '0.12' 5 | --- 6 | 7 | # Exceptions 8 | 9 | Zephir implements exceptions at a very low level, providing similar behavior and functionality to PHP. 10 | 11 | When an exception is thrown, a `catch` block can be used to capture the exception and allow the developer to provide proper handling: 12 | 13 | Exceptions can be thrown inside the `try` block. Handling happens in the `catch` block, exactly as in PHP: 14 | 15 | ```zephir 16 | var e; 17 | try { 18 | 19 | throw new \Exception("This is an exception"); 20 | 21 | } catch \Exception, e { 22 | 23 | echo e->getMessage(); 24 | } 25 | ``` 26 | 27 | Zephir also provides a "silent" `try` block, that simply ignores any exceptions produced within that block: 28 | 29 | ```zephir 30 | try { 31 | throw new \Exception("This is an exception"); 32 | } 33 | ``` 34 | 35 | If you don't need an exception variable when 'catch'ing, then you can safely not provide it: 36 | 37 | ```zephir 38 | try { 39 | 40 | throw new \Exception("This is an exception"); 41 | 42 | } catch \Exception { 43 | 44 | echo "An exception occur!"; 45 | } 46 | ``` 47 | 48 | A single `catch` block can be used to catch multiple types of exception: 49 | 50 | ```zephir 51 | var e; 52 | try { 53 | 54 | throw new \Exception("This is an exception"); 55 | 56 | } catch \RuntimeException|\Exception, e { 57 | 58 | echo e->getMessage(); 59 | } 60 | ``` 61 | 62 | Zephir allows you to throw literals or static typed variables as if they were the message of the exception: 63 | 64 | ```zephir 65 | // throw new \Exception("Test"); 66 | throw "Test"; 67 | 68 | // throw new \Exception((string) 't'); 69 | throw 't'; 70 | 71 | // throw new \Exception((string) 123); 72 | throw 123; 73 | 74 | // throw new \Exception((string) 123.123); 75 | throw 123.123; 76 | ``` 77 | 78 | Zephir's exceptions provide the same methods to know where the exception happened that PHP's exceptions do. That is, `Exception::getFile()` and `Exception::getLine()` return the location in the Zephir code where the exception was thrown: 79 | 80 | ```bash 81 | Exception: The static method 'someMethod' does not exist on model 'Robots' 82 | File=phalcon/mvc/model.zep Line=4042 83 | #0 /home/scott/test.php(64): Phalcon\Mvc\Model::__callStatic('someMethod', Array) 84 | #1 /home/scott/test.php(64): Robots::someMethod() 85 | #2 {main} 86 | ``` -------------------------------------------------------------------------------- /tr-tr/functions.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'tr-tr' 4 | version: '0.12' 5 | --- 6 | 7 | # Calling Functions 8 | 9 | PHP has a rich library of functions that you can use within your extensions. To call a PHP function you simply use it as normal within your Zephir code: 10 | 11 | ```zephir 12 | namespace MyLibrary; 13 | 14 | class Encoder 15 | { 16 | public function encode(var text) 17 | { 18 | if strlen(text) != 0 { 19 | return base64_encode(text); 20 | } 21 | return false; 22 | } 23 | } 24 | ``` 25 | 26 | You can also call functions that are expected to exist in the PHP userland, but are not necessarily built in to PHP itself: 27 | 28 | ```zephir 29 | namespace MyLibrary; 30 | 31 | class Encoder 32 | { 33 | 34 | public function encode(var text) 35 | { 36 | if strlen(text) != 0 { 37 | if function_exists("my_custom_encoder") { 38 | return my_custom_encoder(text); 39 | } else { 40 | return base64_encode(text); 41 | } 42 | } 43 | return false; 44 | } 45 | } 46 | ``` 47 | 48 | Note that all PHP functions only receive and return dynamic variables. If you pass a static typed variable as a parameter, a temporary dynamic variable will automatically be used as a bridge in order to call the function: 49 | 50 | ```zephir 51 | namespace MyLibrary; 52 | 53 | class Encoder 54 | { 55 | public function encode(string text) 56 | { 57 | if strlen(text) != 0 { 58 | // an implicit dynamic variable is created to 59 | // pass the static typed 'text' as parameter 60 | return base64_encode(text); 61 | } 62 | return false; 63 | } 64 | } 65 | ``` 66 | 67 | Similarly, functions return dynamic values, which cannot be directly assigned to static variables without the appropriate explicit cast: 68 | 69 | ```zephir 70 | namespace MyLibrary; 71 | 72 | class Encoder 73 | { 74 | public function encode(string text) 75 | { 76 | string encoded = ""; 77 | 78 | if strlen(text) != 0 { 79 | let encoded = (string) base64_encode(text); 80 | return "(" . encoded . ")"; 81 | } 82 | return false; 83 | } 84 | } 85 | ``` 86 | 87 | Zephir also provides a way for you to call functions dynamically, such as: 88 | 89 | ```zephir 90 | namespace MyLibrary; 91 | 92 | class Encoder 93 | { 94 | public function encode(var callback, string text) 95 | { 96 | return {callback}(text); 97 | } 98 | } 99 | ``` -------------------------------------------------------------------------------- /tr-tr/globals.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'tr-tr' 4 | version: '0.12' 5 | --- 6 | 7 | # Extension Globals 8 | 9 | PHP extensions provide a way to define globals within an extension. Reading/writing globals should be faster than any other global mechanisms (like static members). You can use extension globals to set up configuration options that change the behavior of your library. 10 | 11 | In Zephir, extension globals are restricted to simple scalar types like `int`/`bool`/`double`/`char`, etc. Complex types such as string/array/object/resource are not allowed here. 12 | 13 | You can enable extension globals by adding the following structure to your `config.json`: 14 | 15 | ```json 16 | { 17 | "globals": { 18 | "allow_some_feature": { 19 | "type": "bool", 20 | "default": true, 21 | "module": true 22 | }, 23 | "number_times": { 24 | "type": "int", 25 | "default": 10 26 | }, 27 | "some_component.my_setting_1": { 28 | "type": "bool", 29 | "default": true 30 | }, 31 | "some_component.my_setting_2": { 32 | "type": "int", 33 | "default": 100 34 | } 35 | } 36 | } 37 | ``` 38 | 39 | Each global has the following structure: 40 | 41 | ```json 42 | "": { 43 | "type": "", 44 | "default": 45 | } 46 | ``` 47 | 48 | Compound (namespaced) globals have the following structure: 49 | 50 | ```json 51 | ".": { 52 | "type": "", 53 | "default": 54 | } 55 | ``` 56 | 57 | The optional `module` key, if present, places that global's initialization process into the module-wide `GINIT` lifecycle event, which just means it will only be set up once per PHP process, rather than being reinitialized for every request, which is the default: 58 | 59 | ```json 60 | { 61 | "globals": { 62 | "allow_some_feature": { 63 | "type": "bool", 64 | "default": true, 65 | "module": true 66 | }, 67 | "number_times": { 68 | "type": "int", 69 | "default": 10 70 | } 71 | } 72 | } 73 | ``` 74 | 75 | In the example above, `allow_some_feature` is set up only once at startup; `number_times` is set up at the start of each request. 76 | 77 | Inside any method, you can read/write extension globals using the built-in functions `globals_get`/`globals_set`: 78 | 79 | ```zephir 80 | globals_set("allow_some_feature", true); 81 | let someFeature = globals_get("allow_some_feature"); 82 | ``` 83 | 84 | If you want to change these globals from PHP, a good option is include a method aimed at this: 85 | 86 | ```zephir 87 | namespace Test; 88 | 89 | class MyOptions 90 | { 91 | 92 | public static function setOptions(array options) 93 | { 94 | boolean someOption, anotherOption; 95 | 96 | if fetch someOption, options["some_option"] { 97 | globals_set("some_option", someOption); 98 | } 99 | 100 | if fetch anotherOption, options["another_option"] { 101 | globals_set("another_option", anotherOption); 102 | } 103 | } 104 | } 105 | ``` 106 | 107 | Extension globals cannot be dynamically accessed, since the C code generated by the `globals_get`/`globals_set` optimizers must be resolved at compilation time: 108 | 109 | ```zephir 110 | let myOption = "someOption"; 111 | 112 | // will throw a compiler exception 113 | let someOption = globals_get(myOption); 114 | ``` -------------------------------------------------------------------------------- /tr-tr/license.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'tr-tr' 4 | version: '0.12' 5 | --- 6 | 7 | # License 8 | 9 | MIT License 10 | 11 | Copyright (c) 2013-present Zephir Team 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /tr-tr/operator-precedence.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'tr-tr' 4 | version: '0.12' 5 | --- 6 | 7 | # Operator Precedence 8 | **Operator precedence** determines how operators are parsed. Operators with higher precedence become the operands of operators with lower precedence. For example, in the expression `1 + 5 * 3`, the answer is 16 and not 18 because the multiplication (`*`) operator has a higher precedence than the addition (`+`) operator. Parentheses may be used to force precedence, if necessary. For instance: `(1 + 5) * 3` evaluates to 18. 9 | 10 | 11 | 12 | ## Associativity 13 | When operators have equal precedence their **associativity** determines how the operators are grouped. For example `-` is _left-associative_, so `1 - 2 - 3` is grouped as `(1 - 2) - 3` and evaluates to `-4`. `=` on the other hand is _right-associative_, so `let a = b = c` is grouped as `let a = (b = c)`. 14 | 15 | Operators of equal precedence that are _non-associative_ cannot be used next to one another. For example: 16 | ```zep 17 | new new Foo(); 18 | ``` 19 | is illegal in Zephir, because the `new` is non-associative. At the moment, `new` is the only non-associative operator in Zephir. 20 | 21 | Use of parentheses, even when not strictly necessary, can often increase readability of the code, by making grouping explicit, rather than relying on the implicit operator precedence and associativity. 22 | 23 | 24 | 25 | ## Precedence Table 26 | The following table lists the operators in order of precedence, with the highest-precedence ones at the top. Operators on the same line have equal precedence, in which case associativity decides grouping. 27 | 28 | | Precedence | Operators | Operator type | Associativity | 29 | | ---------- | -------------------------------- | ----------------------------------- | --------------- | 30 | | 1 | `->` | Member Access | right-to-left | 31 | | 2 | `~` | Bitwise NOT | right-to-left | 32 | | 3 | `!` | Logical NOT | right-to-left | 33 | | 4 | `new` | new | non-associative | 34 | | 5 | `clone` | clone | right-to-left | 35 | | 6 | `typeof` | Type-of | right-to-left | 36 | | 7 | `..`, `...` | Inclusive/exclusive range | left-to-right | 37 | | 8 | `isset`, `fetch`, `empty` | Exclusive range | right-to-left | 38 | | 9 | `*`, `/`, `%` | Multiplication, Division, Remainder | left-to-right | 39 | | 10 | `+`, `-`, `.` | Addition, Subtraction, Concat | left-to-right | 40 | | 11 | `<<`, `>>` | Bitwise shift left/right | left-to-right | 41 | | 12 | `<`, `<=`, `=>`, `>` | Comparison | left-to-right | 42 | | 13 | `==`, `!==`, `===`, `!==` | Comparison | left-to-right | 43 | | 14 | `&` | Bitwise AND, references | left-to-right | 44 | | 15 | `^` | Bitwise XOR | left-to-right | 45 | | 16 | `|` | Bitwise OR | left-to-right | 46 | | 17 | `instanceof` | Instance-of | left-to-right | 47 | | 18 | `&&` | Logical AND | left-to-right | 48 | | 19 | `||` | Logical OR | left-to-right | 49 | | 20 | `likely`, `unlikely` | Branch prediction | right-to-left | 50 | | 21 | `?` | Logical | right-to-left | 51 | | 21 | `=>` | Closure Arrow | right-to-left | 52 | -------------------------------------------------------------------------------- /tr-tr/phpinfo.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'tr-tr' 4 | version: '0.12' 5 | --- 6 | 7 | # Phpinfo() sections 8 | 9 | Like most extensions, Zephir extensions are able to show information in the [phpinfo()](https://php.net/manual/en/function.phpinfo.php) output. This information is usually related to directives, environment data, etc. 10 | 11 | By default, every Zephir extension automatically adds a basic table to the `phpinfo()` output showing the extension version, and any INI options the extension supports. 12 | 13 | You can add more directives by adding the following configuration to the `config.json` file: 14 | 15 | ```json 16 | "info": [ 17 | { 18 | "header": ["Directive", "Value"], 19 | "rows": [ 20 | ["setting1", "value1"], 21 | ["setting2", "value2"] 22 | ] 23 | }, 24 | { 25 | "header": ["Directive", "Value"], 26 | "rows": [ 27 | ["setting3", "value3"], 28 | ["setting4", "value4"] 29 | ] 30 | } 31 | ] 32 | ``` 33 | 34 | This information will be shown as follows: 35 | 36 | ![](/assets/content/info.png) -------------------------------------------------------------------------------- /tr-tr/sidebar.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "text": "Welcome", 4 | "url": "welcome" 5 | }, 6 | { 7 | "text": "Why Zephir", 8 | "url": "motivation" 9 | }, 10 | { 11 | "text": "Introducing Zephir", 12 | "url": "introduction" 13 | }, 14 | { 15 | "text": "Installation", 16 | "url": "installation" 17 | }, 18 | { 19 | "text": "Tutorial", 20 | "url": "tutorial" 21 | }, 22 | { 23 | "text": "Basic Syntax", 24 | "url": "language" 25 | }, 26 | { 27 | "text": "Types", 28 | "url": "types" 29 | }, 30 | { 31 | "text": "Operators", 32 | "url": "operators" 33 | }, 34 | { 35 | "text": "Operator Precedence", 36 | "url": "operator-precedence" 37 | }, 38 | { 39 | "text": "Arrays", 40 | "url": "arrays" 41 | }, 42 | { 43 | "text": "Classes and objects", 44 | "url": "oop" 45 | }, 46 | { 47 | "text": "Built-in methods", 48 | "url": "builtin-methods" 49 | }, 50 | { 51 | "text": "Control structures", 52 | "url": "control-structures" 53 | }, 54 | { 55 | "text": "Exceptions", 56 | "url": "exceptions" 57 | }, 58 | { 59 | "text": "Calling functions", 60 | "url": "functions" 61 | }, 62 | { 63 | "text": "Closures", 64 | "url": "closures" 65 | }, 66 | { 67 | "text": "Custom optimizers", 68 | "url": "optimizers" 69 | }, 70 | { 71 | "text": "Configuration file", 72 | "url": "config" 73 | }, 74 | { 75 | "text": "Command Line", 76 | "url": "command-line" 77 | }, 78 | { 79 | "text": "Lifecycle hooks", 80 | "url": "lifecycle" 81 | }, 82 | { 83 | "text": "Extension globals", 84 | "url": "globals" 85 | }, 86 | { 87 | "text": "phpinfo() sections", 88 | "url": "phpinfo" 89 | }, 90 | { 91 | "text": "Static analysis", 92 | "url": "static-analysis" 93 | }, 94 | { 95 | "text": "Optimizations", 96 | "url": "optimizations" 97 | }, 98 | { 99 | "text": "Compiler warnings", 100 | "url": "warnings" 101 | }, 102 | { 103 | "text": "License", 104 | "url": "license" 105 | } 106 | ] 107 | -------------------------------------------------------------------------------- /tr-tr/static-analysis.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'tr-tr' 4 | version: '0.12' 5 | --- 6 | 7 | # Static Analysis 8 | 9 | Zephir's compiler provides static analysis of the compiled code. The idea behind this feature is to help the developer to find potential problems and avoid unexpected behaviors, well before runtime. 10 | 11 | 12 | 13 | ## Conditional Unassigned Variables 14 | 15 | Static Analysis of assignments tries to identify if a variable is used before it's assigned: 16 | 17 | ```zephir 18 | class Utils 19 | { 20 | public function someMethod(b) 21 | { 22 | string a; char c; 23 | 24 | if b == 10 { 25 | let a = "hello"; 26 | } 27 | 28 | //a could be unitialized here 29 | for c in a { 30 | echo c, PHP_EOL; 31 | } 32 | } 33 | } 34 | ``` 35 | 36 | The above example illustrates a common situation. The variable `a` is assigned only when `b` is equal to 10, then it's required to use the value of this variable - but it could be uninitialized. Zephir detects this, automatically initializes the variable to an empty string, and generates a warning alerting the developer: 37 | 38 | ```bash 39 | Warning: Variable 'a' was assigned for the first time in conditional branch, 40 | consider initialize it in its declaration in 41 | /home/scott/test/test/utils.zep on 21 [conditional-initialization] 42 | 43 | for c in a { 44 | ``` 45 | 46 | Finding such errors is sometimes tricky, however static analysis helps the programmer to find bugs in advance. 47 | 48 | 49 | 50 | ## Dead Code Elimination 51 | 52 | Zephir informs the developer about unreachable branches in the code and performs dead code elimination, which means it gets rid of all that code from the generated binary, since it cannot be executed anyway: 53 | 54 | ```zephir 55 | class Utils 56 | { 57 | public function someMethod(b) 58 | { 59 | if false { 60 | // This is never executed 61 | echo "hello"; 62 | } 63 | } 64 | } 65 | ``` -------------------------------------------------------------------------------- /tr-tr/welcome.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'tr-tr' 4 | version: '0.12' 5 | --- 6 | 7 | # Welcome! 8 | 9 | Welcome to Zephir, an open source, high-level/domain specific language designed to ease the creation and maintainability of extensions for PHP, with a focus on type and memory safety. 10 | 11 | 12 | 13 | ## Some features 14 | 15 | Zephir's main features are: 16 | 17 | | Feature | Description | 18 | | ----------------- | ---------------------------------------------------- | 19 | | Type system | dynamic/static | 20 | | Memory safety | pointers or direct memory management are not allowed | 21 | | Compilation model | ahead of time | 22 | | Memory model | task-local garbage collection | 23 | 24 | 25 | 26 | ## A small taste 27 | 28 | The following code registers a class with a method that filters variables, returning their alphabetic characters: 29 | 30 | ```zephir 31 | namespace MyLibrary; 32 | 33 | /** 34 | * Filter 35 | */ 36 | class Filter 37 | { 38 | /** 39 | * Filters a string, returning its alpha charactersa 40 | * 41 | * @param string str 42 | */ 43 | public function alpha(string str) 44 | { 45 | char ch; string filtered = ""; 46 | 47 | for ch in str { 48 | if (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') { 49 | let filtered .= ch; 50 | } 51 | } 52 | 53 | return filtered; 54 | } 55 | } 56 | ``` 57 | 58 | The class can be used from PHP as follows: 59 | 60 | ```php 61 | alpha("01he#l.lo?/1"); // prints hello 65 | ``` 66 | 67 | 68 | 69 | ## External Links 70 | 71 | Below we have collected links to external resources that may interest you: 72 | 73 | - [Type system](https://en.wikipedia.org/wiki/Type_system) 74 | - [Memory safety](https://en.wikipedia.org/wiki/Memory_safety) 75 | - [Ahead-of-time compilation](https://en.wikipedia.org/wiki/Ahead-of-time_compilation) 76 | - [Memory management](https://en.wikipedia.org/wiki/Memory_management) -------------------------------------------------------------------------------- /uk-ua/arrays.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'uk-ua' 4 | version: '0.12' 5 | --- 6 | 7 | # Масиви 8 | 9 | Робота з масивами в Zephir здійснюється таким самим чином, [як і в PHP](https://www.php.net/manual/en/language.types.array.php). An array is an implementation of a [hash table](https://en.wikipedia.org/wiki/Hash_table). 10 | 11 | 12 | 13 | ## Оголошення масивів 14 | 15 | Масив можна оголосити за допомогою двох ключслів `var` та `array`: 16 | 17 | ```zephir 18 | var a = []; // масив, з можливістю зміни типу 19 | array b = []; // масив, без можливості зміни типу 20 | ``` 21 | 22 | 23 | 24 | ## Створення масивів 25 | 26 | Масив створюється шляхом укладення його елементів в квадратні дужки: 27 | 28 | ##### Створення порожнього масиву 29 | 30 | ```zephir 31 | let elements = []; 32 | ``` 33 | 34 | ##### Створення масиву з елементами 35 | 36 | ```zephir 37 | let elements = [1, 3, 4]; 38 | ``` 39 | 40 | ##### Створення масиву з елементами різних типів 41 | 42 | ```zephir 43 | let elements = ["first", 2, true]; 44 | ``` 45 | 46 | ##### Створення багатовимірного масиву 47 | 48 | ```zephir 49 | let elements = [[0, 1], [4, 5], [2, 3]]; 50 | ``` 51 | 52 | Як і в PHP, підтримуються прості (списки) і асоціативні масиви: 53 | 54 | ##### Створення масиву з рядковими ключами 55 | 56 | ```zephir 57 | let elements = ["foo": "bar", "bar": "foo"]; 58 | ``` 59 | 60 | ##### Створення масиву з числовими ключами 61 | 62 | ```zephir 63 | let elements = [4: "bar", 8: "foo"]; 64 | ``` 65 | 66 | ##### Створення масиву з змішаними ключами (рядковими та числовими) 67 | 68 | ```zephir 69 | let elements = [4: "bar", "foo": 8]; 70 | ``` 71 | 72 | 73 | 74 | ## Оновлення масивів 75 | 76 | Масиви оновлюються таким же чином, як і PHP, використовуючи квадратні дужки: 77 | 78 | ##### Оновлення масиву з рядковим ключем 79 | 80 | ```zephir 81 | let elements["foo"] = "bar"; 82 | ``` 83 | 84 | ##### Оновлення масиву з числовим ключем 85 | 86 | ```zephir 87 | let elements[0] = "bar"; 88 | ``` 89 | 90 | ##### Оновлення багатовимірного масиву 91 | 92 | ```zephir 93 | let elements[0]["foo"] = "bar"; 94 | let elements["foo"][0] = "bar"; 95 | ``` 96 | 97 | 98 | 99 | ## Додавання елементів 100 | 101 | Елементи можуть бути додані в кінці масиву наступним чином: 102 | 103 | ##### Додавання елемента до масиву 104 | 105 | ```zephir 106 | let elements[] = "bar"; 107 | ``` 108 | 109 | 110 | 111 | ## Читання елементів з масивів 112 | 113 | Прочитати елементи масиву можна наступним чином: 114 | 115 | ##### Отримання елемента, використовуючи рядковий ключ `foo` 116 | 117 | ```zephir 118 | let foo = elements["foo"]; 119 | ``` 120 | 121 | ##### Отримання елемента за допомогою числового ключа 0 122 | 123 | ```zephir 124 | let foo = elements[0]; 125 | ``` -------------------------------------------------------------------------------- /uk-ua/closures.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'uk-ua' 4 | version: '0.12' 5 | --- 6 | 7 | # Closures 8 | 9 | You can use closures (a.k.a. anonymous functions) in Zephir; these are PHP compatible and can be returned to the PHP userland: 10 | 11 | ```zephir 12 | namespace MyLibrary; 13 | 14 | class Functional 15 | { 16 | 17 | public function map(array! data) 18 | { 19 | return function(number) { 20 | return number * number; 21 | }; 22 | } 23 | } 24 | ``` 25 | 26 | It also can be executed directly within Zephir, and passed as a parameter to other functions/methods: 27 | 28 | ```zephir 29 | namespace MyLibrary; 30 | 31 | class Functional 32 | { 33 | 34 | public function map(array! data) 35 | { 36 | return data->map(function(number) { 37 | return number * number; 38 | }); 39 | } 40 | } 41 | ``` 42 | 43 | A short syntax is also available to define closures: 44 | 45 | ```zephir 46 | namespace MyLibrary; 47 | 48 | class Functional 49 | { 50 | 51 | public function map(array! data) 52 | { 53 | return data->map(number => number * number); 54 | } 55 | } 56 | ``` -------------------------------------------------------------------------------- /uk-ua/exceptions.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'uk-ua' 4 | version: '0.12' 5 | --- 6 | 7 | # Exceptions 8 | 9 | Zephir implements exceptions at a very low level, providing similar behavior and functionality to PHP. 10 | 11 | When an exception is thrown, a `catch` block can be used to capture the exception and allow the developer to provide proper handling: 12 | 13 | Exceptions can be thrown inside the `try` block. Handling happens in the `catch` block, exactly as in PHP: 14 | 15 | ```zephir 16 | var e; 17 | try { 18 | 19 | throw new \Exception("This is an exception"); 20 | 21 | } catch \Exception, e { 22 | 23 | echo e->getMessage(); 24 | } 25 | ``` 26 | 27 | Zephir also provides a "silent" `try` block, that simply ignores any exceptions produced within that block: 28 | 29 | ```zephir 30 | try { 31 | throw new \Exception("This is an exception"); 32 | } 33 | ``` 34 | 35 | If you don't need an exception variable when 'catch'ing, then you can safely not provide it: 36 | 37 | ```zephir 38 | try { 39 | 40 | throw new \Exception("This is an exception"); 41 | 42 | } catch \Exception { 43 | 44 | echo "An exception occur!"; 45 | } 46 | ``` 47 | 48 | A single `catch` block can be used to catch multiple types of exception: 49 | 50 | ```zephir 51 | var e; 52 | try { 53 | 54 | throw new \Exception("This is an exception"); 55 | 56 | } catch \RuntimeException|\Exception, e { 57 | 58 | echo e->getMessage(); 59 | } 60 | ``` 61 | 62 | Zephir allows you to throw literals or static typed variables as if they were the message of the exception: 63 | 64 | ```zephir 65 | // throw new \Exception("Test"); 66 | throw "Test"; 67 | 68 | // throw new \Exception((string) 't'); 69 | throw 't'; 70 | 71 | // throw new \Exception((string) 123); 72 | throw 123; 73 | 74 | // throw new \Exception((string) 123.123); 75 | throw 123.123; 76 | ``` 77 | 78 | Zephir's exceptions provide the same methods to know where the exception happened that PHP's exceptions do. That is, `Exception::getFile()` and `Exception::getLine()` return the location in the Zephir code where the exception was thrown: 79 | 80 | ```bash 81 | Exception: The static method 'someMethod' does not exist on model 'Robots' 82 | File=phalcon/mvc/model.zep Line=4042 83 | #0 /home/scott/test.php(64): Phalcon\Mvc\Model::__callStatic('someMethod', Array) 84 | #1 /home/scott/test.php(64): Robots::someMethod() 85 | #2 {main} 86 | ``` -------------------------------------------------------------------------------- /uk-ua/functions.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'uk-ua' 4 | version: '0.12' 5 | --- 6 | 7 | # Виклик функцій 8 | 9 | PHP has a rich library of functions that you can use within your extensions. To call a PHP function you simply use it as normal within your Zephir code: 10 | 11 | ```zephir 12 | namespace MyLibrary; 13 | 14 | class Encoder 15 | { 16 | public function encode(var text) 17 | { 18 | if strlen(text) != 0 { 19 | return base64_encode(text); 20 | } 21 | return false; 22 | } 23 | } 24 | ``` 25 | 26 | You can also call functions that are expected to exist in the PHP userland, but are not necessarily built in to PHP itself: 27 | 28 | ```zephir 29 | namespace MyLibrary; 30 | 31 | class Encoder 32 | { 33 | 34 | public function encode(var text) 35 | { 36 | if strlen(text) != 0 { 37 | if function_exists("my_custom_encoder") { 38 | return my_custom_encoder(text); 39 | } else { 40 | return base64_encode(text); 41 | } 42 | } 43 | return false; 44 | } 45 | } 46 | ``` 47 | 48 | Note that all PHP functions only receive and return dynamic variables. If you pass a static typed variable as a parameter, a temporary dynamic variable will automatically be used as a bridge in order to call the function: 49 | 50 | ```zephir 51 | namespace MyLibrary; 52 | 53 | class Encoder 54 | { 55 | public function encode(string text) 56 | { 57 | if strlen(text) != 0 { 58 | // an implicit dynamic variable is created to 59 | // pass the static typed 'text' as parameter 60 | return base64_encode(text); 61 | } 62 | return false; 63 | } 64 | } 65 | ``` 66 | 67 | Similarly, functions return dynamic values, which cannot be directly assigned to static variables without the appropriate explicit cast: 68 | 69 | ```zephir 70 | namespace MyLibrary; 71 | 72 | class Encoder 73 | { 74 | public function encode(string text) 75 | { 76 | string encoded = ""; 77 | 78 | if strlen(text) != 0 { 79 | let encoded = (string) base64_encode(text); 80 | return "(" . encoded . ")"; 81 | } 82 | return false; 83 | } 84 | } 85 | ``` 86 | 87 | Zephir also provides a way for you to call functions dynamically, such as: 88 | 89 | ```zephir 90 | namespace MyLibrary; 91 | 92 | class Encoder 93 | { 94 | public function encode(var callback, string text) 95 | { 96 | return {callback}(text); 97 | } 98 | } 99 | ``` -------------------------------------------------------------------------------- /uk-ua/globals.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'uk-ua' 4 | version: '0.12' 5 | --- 6 | 7 | # Extension Globals 8 | 9 | PHP extensions provide a way to define globals within an extension. Reading/writing globals should be faster than any other global mechanisms (like static members). You can use extension globals to set up configuration options that change the behavior of your library. 10 | 11 | In Zephir, extension globals are restricted to simple scalar types like `int`/`bool`/`double`/`char`, etc. Complex types such as string/array/object/resource are not allowed here. 12 | 13 | You can enable extension globals by adding the following structure to your `config.json`: 14 | 15 | ```json 16 | { 17 | "globals": { 18 | "allow_some_feature": { 19 | "type": "bool", 20 | "default": true, 21 | "module": true 22 | }, 23 | "number_times": { 24 | "type": "int", 25 | "default": 10 26 | }, 27 | "some_component.my_setting_1": { 28 | "type": "bool", 29 | "default": true 30 | }, 31 | "some_component.my_setting_2": { 32 | "type": "int", 33 | "default": 100 34 | } 35 | } 36 | } 37 | ``` 38 | 39 | Each global has the following structure: 40 | 41 | ```json 42 | "": { 43 | "type": "", 44 | "default": 45 | } 46 | ``` 47 | 48 | Compound (namespaced) globals have the following structure: 49 | 50 | ```json 51 | ".": { 52 | "type": "", 53 | "default": 54 | } 55 | ``` 56 | 57 | The optional `module` key, if present, places that global's initialization process into the module-wide `GINIT` lifecycle event, which just means it will only be set up once per PHP process, rather than being reinitialized for every request, which is the default: 58 | 59 | ```json 60 | { 61 | "globals": { 62 | "allow_some_feature": { 63 | "type": "bool", 64 | "default": true, 65 | "module": true 66 | }, 67 | "number_times": { 68 | "type": "int", 69 | "default": 10 70 | } 71 | } 72 | } 73 | ``` 74 | 75 | In the example above, `allow_some_feature` is set up only once at startup; `number_times` is set up at the start of each request. 76 | 77 | Inside any method, you can read/write extension globals using the built-in functions `globals_get`/`globals_set`: 78 | 79 | ```zephir 80 | globals_set("allow_some_feature", true); 81 | let someFeature = globals_get("allow_some_feature"); 82 | ``` 83 | 84 | If you want to change these globals from PHP, a good option is include a method aimed at this: 85 | 86 | ```zephir 87 | namespace Test; 88 | 89 | class MyOptions 90 | { 91 | 92 | public static function setOptions(array options) 93 | { 94 | boolean someOption, anotherOption; 95 | 96 | if fetch someOption, options["some_option"] { 97 | globals_set("some_option", someOption); 98 | } 99 | 100 | if fetch anotherOption, options["another_option"] { 101 | globals_set("another_option", anotherOption); 102 | } 103 | } 104 | } 105 | ``` 106 | 107 | Extension globals cannot be dynamically accessed, since the C code generated by the `globals_get`/`globals_set` optimizers must be resolved at compilation time: 108 | 109 | ```zephir 110 | let myOption = "someOption"; 111 | 112 | // згенерує помилку компіляції 113 | let someOption = globals_get(myOption); 114 | ``` -------------------------------------------------------------------------------- /uk-ua/license.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'uk-ua' 4 | version: '0.12' 5 | --- 6 | 7 | # License 8 | 9 | MIT License 10 | 11 | Copyright (c) 2013-present Zephir Team 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /uk-ua/operator-precedence.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'uk-ua' 4 | version: '0.12' 5 | --- 6 | 7 | # Operator Precedence 8 | **Operator precedence** determines how operators are parsed. Operators with higher precedence become the operands of operators with lower precedence. For example, in the expression `1 + 5 * 3`, the answer is 16 and not 18 because the multiplication (`*`) operator has a higher precedence than the addition (`+`) operator. Parentheses may be used to force precedence, if necessary. For instance: `(1 + 5) * 3` evaluates to 18. 9 | 10 | 11 | 12 | ## Associativity 13 | When operators have equal precedence their **associativity** determines how the operators are grouped. For example `-` is _left-associative_, so `1 - 2 - 3` is grouped as `(1 - 2) - 3` and evaluates to `-4`. `=` on the other hand is _right-associative_, so `let a = b = c` is grouped as `let a = (b = c)`. 14 | 15 | Operators of equal precedence that are _non-associative_ cannot be used next to one another. For example: 16 | ```zep 17 | new new Foo(); 18 | ``` 19 | is illegal in Zephir, because the `new` is non-associative. At the moment, `new` is the only non-associative operator in Zephir. 20 | 21 | Use of parentheses, even when not strictly necessary, can often increase readability of the code, by making grouping explicit, rather than relying on the implicit operator precedence and associativity. 22 | 23 | 24 | 25 | ## Precedence Table 26 | The following table lists the operators in order of precedence, with the highest-precedence ones at the top. Operators on the same line have equal precedence, in which case associativity decides grouping. 27 | 28 | | Precedence | Оператори | Operator type | Associativity | 29 | | ---------- | -------------------------------- | ----------------------------------- | --------------- | 30 | | 1 | `->` | Member Access | right-to-left | 31 | | 2 | `~` | Bitwise NOT | right-to-left | 32 | | 3 | `!` | Logical NOT | right-to-left | 33 | | 4 | `new` | new | non-associative | 34 | | 5 | `clone` | clone | right-to-left | 35 | | 6 | `typeof` | Type-of | right-to-left | 36 | | 7 | `..`, `...` | Inclusive/exclusive range | left-to-right | 37 | | 8 | `isset`, `fetch`, `empty` | Exclusive range | right-to-left | 38 | | 9 | `*`, `/`, `%` | Multiplication, Division, Remainder | left-to-right | 39 | | 10 | `+`, `-`, `.` | Addition, Subtraction, Concat | left-to-right | 40 | | 11 | `<<`, `>>` | Bitwise shift left/right | left-to-right | 41 | | 12 | `<`, `<=`, `=>`, `>` | Comparison | left-to-right | 42 | | 13 | `==`, `!==`, `===`, `!==` | Comparison | left-to-right | 43 | | 14 | `&` | Bitwise AND, references | left-to-right | 44 | | 15 | `^` | Bitwise XOR | left-to-right | 45 | | 16 | `|` | Bitwise OR | left-to-right | 46 | | 17 | `instanceof` | Instance-of | left-to-right | 47 | | 18 | `&&` | Logical AND | left-to-right | 48 | | 19 | `||` | Logical OR | left-to-right | 49 | | 20 | `likely`, `unlikely` | Branch prediction | right-to-left | 50 | | 21 | `?` | Logical | right-to-left | 51 | | 21 | `=>` | Closure Arrow | right-to-left | 52 | -------------------------------------------------------------------------------- /uk-ua/phpinfo.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'uk-ua' 4 | version: '0.12' 5 | --- 6 | 7 | # Розділи в phpinfo() 8 | 9 | Як і більшість PHP-розширень, розширення написані на Zephir здатні показати інформацію у виводі [phpinfo()](https://php.net/manual/en/function.phpinfo.php). Зазвичай ця інформація відноситься до директив, даних оточення і т.д. 10 | 11 | Типово, кожне Zephir-розширення додає базову таблицю у вивід `phpinfo()`, яка показує версію розширення. 12 | 13 | Ви можете додати більше директив, додавши наступну конфігурацію в файл `config.json`: 14 | 15 | ```json 16 | "info": [ 17 | { 18 | "header": ["Directive", "Value"], 19 | "rows": [ 20 | ["setting1", "value1"], 21 | ["setting2", "value2"] 22 | ] 23 | }, 24 | { 25 | "header": ["Directive", "Value"], 26 | "rows": [ 27 | ["setting3", "value3"], 28 | ["setting4", "value4"] 29 | ] 30 | } 31 | ] 32 | ``` 33 | 34 | Ця інформація буде показана наступним чином: 35 | 36 | ![](/assets/content/info.png) -------------------------------------------------------------------------------- /uk-ua/sidebar.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "text": "Welcome", 4 | "url": "welcome" 5 | }, 6 | { 7 | "text": "Why Zephir", 8 | "url": "motivation" 9 | }, 10 | { 11 | "text": "Представляємо Zephir", 12 | "url": "introduction" 13 | }, 14 | { 15 | "text": "Встановлення", 16 | "url": "installation" 17 | }, 18 | { 19 | "text": "Навчальний посібник", 20 | "url": "tutorial" 21 | }, 22 | { 23 | "text": "Базовий синтаксис", 24 | "url": "language" 25 | }, 26 | { 27 | "text": "Типи", 28 | "url": "types" 29 | }, 30 | { 31 | "text": "Оператори", 32 | "url": "operators" 33 | }, 34 | { 35 | "text": "Operator Precedence", 36 | "url": "operator-precedence" 37 | }, 38 | { 39 | "text": "Масиви", 40 | "url": "arrays" 41 | }, 42 | { 43 | "text": "Classes and objects", 44 | "url": "oop" 45 | }, 46 | { 47 | "text": "Built-in methods", 48 | "url": "builtin-methods" 49 | }, 50 | { 51 | "text": "Control structures", 52 | "url": "control-structures" 53 | }, 54 | { 55 | "text": "Exceptions", 56 | "url": "exceptions" 57 | }, 58 | { 59 | "text": "Calling functions", 60 | "url": "functions" 61 | }, 62 | { 63 | "text": "Closures", 64 | "url": "closures" 65 | }, 66 | { 67 | "text": "Custom optimizers", 68 | "url": "optimizers" 69 | }, 70 | { 71 | "text": "Configuration file", 72 | "url": "config" 73 | }, 74 | { 75 | "text": "Command Line", 76 | "url": "command-line" 77 | }, 78 | { 79 | "text": "Lifecycle hooks", 80 | "url": "lifecycle" 81 | }, 82 | { 83 | "text": "Extension globals", 84 | "url": "globals" 85 | }, 86 | { 87 | "text": "phpinfo() sections", 88 | "url": "phpinfo" 89 | }, 90 | { 91 | "text": "Static analysis", 92 | "url": "static-analysis" 93 | }, 94 | { 95 | "text": "Optimizations", 96 | "url": "optimizations" 97 | }, 98 | { 99 | "text": "Compiler warnings", 100 | "url": "warnings" 101 | }, 102 | { 103 | "text": "License", 104 | "url": "license" 105 | } 106 | ] 107 | -------------------------------------------------------------------------------- /uk-ua/static-analysis.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'uk-ua' 4 | version: '0.12' 5 | --- 6 | 7 | # Static Analysis 8 | 9 | Zephir's compiler provides static analysis of the compiled code. The idea behind this feature is to help the developer to find potential problems and avoid unexpected behaviors, well before runtime. 10 | 11 | 12 | 13 | ## Conditional Unassigned Variables 14 | 15 | Static Analysis of assignments tries to identify if a variable is used before it's assigned: 16 | 17 | ```zephir 18 | class Utils 19 | { 20 | public function someMethod(b) 21 | { 22 | string a; char c; 23 | 24 | if b == 10 { 25 | let a = "hello"; 26 | } 27 | 28 | //a could be unitialized here 29 | for c in a { 30 | echo c, PHP_EOL; 31 | } 32 | } 33 | } 34 | ``` 35 | 36 | The above example illustrates a common situation. The variable `a` is assigned only when `b` is equal to 10, then it's required to use the value of this variable - but it could be uninitialized. Zephir detects this, automatically initializes the variable to an empty string, and generates a warning alerting the developer: 37 | 38 | ```bash 39 | Warning: Variable 'a' was assigned for the first time in conditional branch, 40 | consider initialize it in its declaration in 41 | /home/scott/test/test/utils.zep on 21 [conditional-initialization] 42 | 43 | for c in a { 44 | ``` 45 | 46 | Finding such errors is sometimes tricky, however static analysis helps the programmer to find bugs in advance. 47 | 48 | 49 | 50 | ## Dead Code Elimination 51 | 52 | Zephir informs the developer about unreachable branches in the code and performs dead code elimination, which means it gets rid of all that code from the generated binary, since it cannot be executed anyway: 53 | 54 | ```zephir 55 | class Utils 56 | { 57 | public function someMethod(b) 58 | { 59 | if false { 60 | // This is never executed 61 | echo "hello"; 62 | } 63 | } 64 | } 65 | ``` -------------------------------------------------------------------------------- /uk-ua/welcome.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'uk-ua' 4 | version: '0.12' 5 | --- 6 | 7 | # Вітаємо! 8 | 9 | Вас вітає Zephir — проект з відкритим вихідним кодом, високорівнева/предметно-орієнтована мова спроектована для полегшення створення й супроводу розширень для PHP з акцентом на тип та безпеку доступу до пам'яті. 10 | 11 | 12 | 13 | ## Деякі особливості 14 | 15 | Основними особливостями Zephir-у є: 16 | 17 | | Особливість | Опис | 18 | | --------------------------- | -------------------------------------------------- | 19 | | Система типізації | динамічна/статична | 20 | | Безпечний доступ до пам'яті | вказівники або пряме керування пам'яттю заборонені | 21 | | Компіляційна модель | компіляція виконується заздалегідь | 22 | | Модель пам'яті | свій збирач сміття | 23 | 24 | 25 | 26 | ## Скуштуйте 27 | 28 | Наступний код реєструє клас з методом, який фільтрує змінні, повертаючи лише їхні алфавітні символи: 29 | 30 | ```zephir 31 | namespace MyLibrary; 32 | 33 | /** 34 | * Фільтр 35 | */ 36 | class Filter 37 | { 38 | /** 39 | * Фільтрує рядок, повертаючи його альфа-символи 40 | * 41 | * @param string str 42 | */ 43 | public function alpha(string str) 44 | { 45 | char ch; string filtered = ""; 46 | 47 | for ch in str { 48 | if (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') { 49 | let filtered .= ch; 50 | } 51 | } 52 | 53 | return filtered; 54 | } 55 | } 56 | ``` 57 | 58 | Цей клас можна виконати з PHP наступним чином: 59 | 60 | ```php 61 | alpha("01he#l.lo?/1"); // виведе hello 65 | ``` 66 | 67 | 68 | 69 | ## Зовнішні посилання 70 | 71 | Нижче ми зібрали посилання на зовнішні ресурси, які можуть вас зацікавити: 72 | 73 | - [Система типізації](https://en.wikipedia.org/wiki/Type_system) 74 | - [Безпечний доступ до пам'яті](https://en.wikipedia.org/wiki/Memory_safety) 75 | - [Ahead-of-time (AOT) компіляція](https://en.wikipedia.org/wiki/Ahead-of-time_compilation) 76 | - [Керування пам’яттю](https://en.wikipedia.org/wiki/Memory_management) -------------------------------------------------------------------------------- /zh-cn/arrays.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'zh-cn' 4 | version: '0.12' 5 | --- 6 | 7 | # 数组 8 | 9 | Zephir中的数组操作提供了一种类似PHP [数组](https://www.php.net/manual/en/language.types.array.php)的方法。 An array is an implementation of a [hash table](https://en.wikipedia.org/wiki/Hash_table). 10 | 11 | 12 | 13 | ## 声明数组变量 14 | 15 | 数组变量可以使用关键字 "var" 或 "array" 来声明: 16 | 17 | ```zephir 18 | var a = []; // 数组变量,其类型可以改变 19 | array b = []; // 数组变量,其类型不能在执行过程中更改 20 | ``` 21 | 22 | 23 | 24 | ## 创建数组 25 | 26 | 通过将其元素括在方括号中创建数组: 27 | 28 | ##### 创建空数组 29 | 30 | ```zephir 31 | let elements = []; 32 | ``` 33 | 34 | ##### 创建包含元素的数组 35 | 36 | ```zephir 37 | let elements = [1, 3, 4]; 38 | ``` 39 | 40 | ##### 使用不同类型的元素创建数组 41 | 42 | ```zephir 43 | let elements = ["first", 2, true]; 44 | ``` 45 | 46 | ##### 多维数组 47 | 48 | ```zephir 49 | let elements = [[0, 1], [4, 5], [2, 3]]; 50 | ``` 51 | 52 | 就像 PHP,哈希或字典都支持的: 53 | 54 | ##### 使用字符串键创建哈希 55 | 56 | ```zephir 57 | let elements = ["foo": "bar", "bar": "foo"]; 58 | ``` 59 | 60 | ##### 使用数字键创建哈希 61 | 62 | ```zephir 63 | let elements = [4: "bar", 8: "foo"]; 64 | ``` 65 | 66 | ##### 使用字符串和数字键混合创建哈希 67 | 68 | ```zephir 69 | let elements = [4: "bar", "foo": 8]; 70 | ``` 71 | 72 | 73 | 74 | ## Updating arrays 75 | 76 | Arrays are updated in the same way as PHP, using square brackets: 77 | 78 | ##### 使用字符串键名更新数组 79 | 80 | ```zephir 81 | let elements["foo"] = "bar"; 82 | ``` 83 | 84 | ##### 使用数字键更新数组 85 | 86 | ```zephir 87 | let elements[0] = "bar"; 88 | ``` 89 | 90 | ##### 多维数组 91 | 92 | ```zephir 93 | let elements[0]["foo"] = "bar"; 94 | let elements["foo"][0] = "bar"; 95 | ``` 96 | 97 | 98 | 99 | ## 追加元素 100 | 101 | 元素可以追加到数组的末尾, 如下所示: 102 | 103 | ##### 向数组追加一个元素 104 | 105 | ```zephir 106 | let elements[] = "bar"; 107 | ``` 108 | 109 | 110 | 111 | ## 从数组中读取元素 112 | 113 | 可以读取数组元素, 如下所示: 114 | 115 | ##### 使用字符串键获取元素 `foo` 116 | 117 | ```zephir 118 | let foo = elements["foo"]; 119 | ``` 120 | 121 | ##### 使用数字键0获取元素 122 | 123 | ```zephir 124 | let foo = elements[0]; 125 | ``` -------------------------------------------------------------------------------- /zh-cn/builtin-methods.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'zh-cn' 4 | version: '0.12' 5 | --- 6 | 7 | # 内建方法 8 | 9 | 如前所述,Zephir提倡面向对象编程。 与静态类型相关的变量也可以作为对象处理。 10 | 11 | 比较这两种方法: 12 | 13 | ```zephir 14 | public function binaryToHex(string! s) -> string 15 | { 16 | var o = "", n; char ch; 17 | 18 | for ch in range(0, strlen(s)) { 19 | let n = sprintf("%X", ch); 20 | if strlen(n) < 2 { 21 | let o .= "0" . n; 22 | } else { 23 | let o .= n; 24 | } 25 | } 26 | return o; 27 | } 28 | ``` 29 | 30 | 与 31 | 32 | ```zephir 33 | public function binaryToHex(string! s) -> string 34 | { 35 | var o = "", n; char ch; 36 | 37 | for ch in range(0, s->length()) { 38 | let n = ch->toHex(); 39 | if n->length() < 2 { 40 | let o .= "0" . n; 41 | } else { 42 | let o .= n; 43 | } 44 | } 45 | return o; 46 | } 47 | ``` 48 | 49 | 它们都有相同的功能,但是第二个使用的是面向对象编程。 对静态类型变量调用方法对性能没有任何影响,因为Zephir在内部将代码从面向对象版本转换为过程版本。 50 | 51 | 52 | 53 | ## String 54 | 55 | 下面的字符串内置方法可用: 56 | 57 | | OO | 实际过程 | 说明 | 58 | | -------------------- | --------------------- | ---------------------- | 59 | | `s->format()` | `sprintf(s, "%s", x)` | 返回格式化的字符串 | 60 | | `s->index("foo")` | `strpos(s, "foo")` | 查找字符串中第一个出现的子字符串的位置 | 61 | | `s->length()` | `strlen(s)` | 获取字符串长度 | 62 | | `s->lower()` | `strtolower(s)` | 使字符串小写 | 63 | | `s->lowerfirst()` | `lcfirst(s)` | 使字符串的第一个字符小写 | 64 | | `s->md5()` | `md5(s)` | 计算字符串的 md5 哈希 | 65 | | `s->sha1()` | `sha1(s)` | 计算字符串的 sha1 哈希 | 66 | | `s->trim()` | `trim(s)` | 删除字符串的开头和结尾的空格 (或其他字符) | 67 | | `s->trimleft()` | `ltrim(s)` | 从字符串开头的条带空白 (或其他字符) | 68 | | `s->trimright()` | `rtrim(s)` | 删除字符串末端的空白字符(或者其他字符) | 69 | | `s->upper()` | `strtoupper(s)` | 使字符串大写 | 70 | | `s->upperfirst()` | `ucfirst(s)` | 使字符串的第一个字符大写 | 71 | 72 | 73 | 74 | ## Array 75 | 76 | 可用的数组内置方法如下: 77 | 78 | | OO | 实际过程 | 说明 | 79 | | -------------------- | ----------------------- | ----------------------- | 80 | | `a->combine(b)` | `array_combine(a, b)` | 通过使用一个数组表示键, 为其值创建另一个数组 | 81 | | `a->diff()` | `array_diff(a)` | 计算数组的差异 | 82 | | `a->flip()` | `array_flip(a)` | 将数组中的所有键与其关联的值交换 | 83 | | `a->hasKey()` | `array_key_exists(a)` | 检查数组中是否存在给定的键或索引 | 84 | | `a->intersect(b)` | `array_intersect(a, b)` | 计算数组的交集 | 85 | | `a->join(" ")` | `join(" ", a)` | 使用字符串联接数组元素 | 86 | | `a->keys()` | `array_keys(a)` | 返回数组的所有键或键的子集 | 87 | | `a->merge(b)` | `array_merge(a, b)` | 合并一个或多个数组 | 88 | | `a->pad()` | `array_pad(a, b)` | 以指定长度将一个值填充进数组 | 89 | | `a->rev()` | `array_reverse(a)` | 返回具有相反顺序的元素的数组 | 90 | | `a->reversed()` | `array_reverse(a)` | 返回具有相反顺序的元素的数组 | 91 | | `a->split()` | `array_chunk(a)` | 将数组拆分为多个块 | 92 | | `a->values()` | `array_values(a)` | 返回数组的所有值 | 93 | | `a->walk()` | `array_walk(a)` | 使用用户自定义函数对数组中的每个元素做回调处理 | 94 | 95 | 96 | 97 | ## Char 98 | 99 | 提供了以下字符内置方法: 100 | 101 | | OO | 实际过程 | 102 | | ---------------- | ------------------- | 103 | | `ch->toHex()` | `sprintf("%X", ch)` | 104 | 105 | 106 | 107 | ## Integer 108 | 109 | 以下是可用的整数内置方法: 110 | 111 | | OO | 实际过程 | 112 | | ------------- | -------- | 113 | | `i->abs()` | `abs(i)` | -------------------------------------------------------------------------------- /zh-cn/closures.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'zh-cn' 4 | version: '0.12' 5 | --- 6 | 7 | # 闭 包 8 | 9 | 您可以在Zephir中使用闭包(也称为匿名函数);这些是PHP兼容的,可以返回给PHP代码块: 10 | 11 | ```zephir 12 | namespace MyLibrary; 13 | 14 | class Functional 15 | { 16 | 17 | public function map(array! data) 18 | { 19 | return function(number) { 20 | return number * number; 21 | }; 22 | } 23 | } 24 | ``` 25 | 26 | 它也可以直接在Zephir中执行,并作为参数传递给其他函数/方法: 27 | 28 | ```zephir 29 | namespace MyLibrary; 30 | 31 | class Functional 32 | { 33 | 34 | public function map(array! data) 35 | { 36 | return data->map(function(number) { 37 | return number * number; 38 | }); 39 | } 40 | } 41 | ``` 42 | 43 | 一个简短的语法也可以用来定义闭包: 44 | 45 | ```zephir 46 | namespace MyLibrary; 47 | 48 | class Functional 49 | { 50 | 51 | public function map(array! data) 52 | { 53 | return data->map(number => number * number); 54 | } 55 | } 56 | ``` -------------------------------------------------------------------------------- /zh-cn/exceptions.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'zh-cn' 4 | version: '0.12' 5 | --- 6 | 7 | # 例外情况 8 | 9 | Zephir以非常低的级别实现异常,为PHP提供类似的行为和功能。 10 | 11 | 抛出异常时,可以使用` catch `块来捕获异常并允许开发人员提供正确的处理: 12 | 13 | 可以在`try`语句中抛出异常。 和PHP一样,在`catch`中捕获异常并处理 14 | 15 | ```zephir 16 | var e; 17 | try { 18 | 19 | throw new \Exception("This is an exception"); 20 | 21 | } catch \Exception, e { 22 | 23 | echo e->getMessage(); 24 | } 25 | ``` 26 | 27 | Zephir 还提供了一个“安静”`try`语句,用来忽略产生的任何异常: 28 | 29 | ```zephir 30 | try { 31 | throw new \Exception("This is an exception"); 32 | } 33 | ``` 34 | 35 | 如果在<0>catch中不处理异常,可以不提供异常变量: 36 | 37 | ```zephir 38 | try { 39 | 40 | throw new \Exception("This is an exception"); 41 | 42 | } catch \Exception { 43 | 44 | echo "An exception occur!"; 45 | } 46 | ``` 47 | 48 | 在`catch`中捕获多个异常: 49 | 50 | ```zephir 51 | var e; 52 | try { 53 | 54 | throw new \Exception("This is an exception"); 55 | 56 | } catch \RuntimeException|\Exception, e { 57 | 58 | echo e->getMessage(); 59 | } 60 | ``` 61 | 62 | Zephir允许您抛出文字或静态类型变量,就像它们是异常的消息一样: 63 | 64 | ```zephir 65 | // throw new \Exception("Test"); 66 | throw "Test"; 67 | 68 | // throw new \Exception((string) 't'); 69 | throw 't'; 70 | 71 | // throw new \Exception((string) 123); 72 | throw 123; 73 | 74 | // throw new \Exception((string) 123.123); 75 | throw 123.123; 76 | ``` 77 | 78 | Zephir's exceptions provide the same methods to know where the exception happened that PHP's exceptions do. That is, `Exception::getFile()` and `Exception::getLine()` return the location in the Zephir code where the exception was thrown: 79 | 80 | ```bash 81 | Exception: The static method 'someMethod' does not exist on model 'Robots' 82 | File=phalcon/mvc/model.zep Line=4042 83 | #0 /home/scott/test.php(64): Phalcon\Mvc\Model::__callStatic('someMethod', Array) 84 | #1 /home/scott/test.php(64): Robots::someMethod() 85 | #2 {main} 86 | ``` -------------------------------------------------------------------------------- /zh-cn/functions.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'zh-cn' 4 | version: '0.12' 5 | --- 6 | 7 | # 调用函数 8 | 9 | PHP有一个丰富的函数库,您可以在扩展中使用它们。 要调用PHP函数,只需在Zephir代码中正常使用它: 10 | 11 | ```zephir 12 | namespace MyLibrary; 13 | 14 | class Encoder 15 | { 16 | public function encode(var text) 17 | { 18 | if strlen(text) != 0 { 19 | return base64_encode(text); 20 | } 21 | return false; 22 | } 23 | } 24 | ``` 25 | 26 | 您还可以调用预期存在于PHP用户区中的函数,但不一定是内置于PHP本身: 27 | 28 | ```zephir 29 | namespace MyLibrary; 30 | 31 | class Encoder 32 | { 33 | 34 | public function encode(var text) 35 | { 36 | if strlen(text) != 0 { 37 | if function_exists("my_custom_encoder") { 38 | return my_custom_encoder(text); 39 | } else { 40 | return base64_encode(text); 41 | } 42 | } 43 | return false; 44 | } 45 | } 46 | ``` 47 | 48 | 请注意,所有PHP函数仅接收和返回动态变量。 如果将静态类型变量作为参数传递,则临时动态变量将自动用作桥接器以调用该函数: 49 | 50 | ```zephir 51 | namespace MyLibrary; 52 | 53 | class Encoder 54 | { 55 | public function encode(string text) 56 | { 57 | if strlen(text) != 0 { 58 | // an implicit dynamic variable is created to 59 | // pass the static typed 'text' as parameter 60 | return base64_encode(text); 61 | } 62 | return false; 63 | } 64 | } 65 | ``` 66 | 67 | 类似地,函数返回动态值,如果没有适当的显式强制转换,则无法直接将其分配给静态变量: 68 | 69 | ```zephir 70 | namespace MyLibrary; 71 | 72 | class Encoder 73 | { 74 | public function encode(string text) 75 | { 76 | string encoded = ""; 77 | 78 | if strlen(text) != 0 { 79 | let encoded = (string) base64_encode(text); 80 | return "(" . encoded . ")"; 81 | } 82 | return false; 83 | } 84 | } 85 | ``` 86 | 87 | Zephir还为您提供了一种动态调用函数的方法,例如: 88 | 89 | ```zephir 90 | namespace MyLibrary; 91 | 92 | class Encoder 93 | { 94 | public function encode(var callback, string text) 95 | { 96 | return {callback}(text); 97 | } 98 | } 99 | ``` -------------------------------------------------------------------------------- /zh-cn/globals.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'zh-cn' 4 | version: '0.12' 5 | --- 6 | 7 | # 全局扩展 8 | 9 | PHP扩展提供了一种在扩展中定义全局变量的方法。 读/写全局变量应该比任何其他全局机制(如静态成员)更快。 您可以使用扩展全局变量来设置更改库行为的配置选项。 10 | 11 | 在Zephir中,扩展全局变量仅限于简单的标量类型,如` int / bool / double / char 等。 此处不允许使用复杂类型,例如字符串/数组/对象/资源。

12 | 13 |

您可以通过将以下结构添加到 config.json `来启用扩展全局变量: 14 | 15 | ```json 16 | { 17 | "globals": { 18 | "allow_some_feature": { 19 | "type": "bool", 20 | "default": true, 21 | "module": true 22 | }, 23 | "number_times": { 24 | "type": "int", 25 | "default": 10 26 | }, 27 | "some_component.my_setting_1": { 28 | "type": "bool", 29 | "default": true 30 | }, 31 | "some_component.my_setting_2": { 32 | "type": "int", 33 | "default": 100 34 | } 35 | } 36 | } 37 | ``` 38 | 39 | 每个全局具有以下结构: 40 | 41 | ```json 42 | "": { 43 | "type": "", 44 | "default": 45 | } 46 | ``` 47 | 48 | 复合(命名空间)全局变量具有以下结构: 49 | 50 | ```json 51 | ".": { 52 | "type": "", 53 | "default": 54 | } 55 | ``` 56 | 57 | 可选的`module键(如果存在)将全局的初始化过程放入模块范围的 GINIT 生命周期事件中,这意味着它只会在每个PHP进程中设置一次, 而不是为每个请求重新初始化,这是默认值:

58 | 59 |
{
 60 |     "globals": {
 61 |         "allow_some_feature": {
 62 |             "type": "bool",
 63 |             "default": true,
 64 |             "module": true
 65 |         },
 66 |         "number_times": {
 67 |             "type": "int",
 68 |             "default": 10
 69 |         }
 70 |     }
 71 | }
 72 | `
73 | 74 | 在上面的例子中,`allow_some_feature`在启动时只设置一次;`number_times`是在每个请求开始时设置的。 75 | 76 | 在任何方法中,您可以使用内置函数` globals_get ` / ` globals_set `读/写扩展全局变量: 77 | 78 | ```zephir 79 | globals_set("allow_some_feature", true); 80 | let someFeature = globals_get("allow_some_feature"); 81 | ``` 82 | 83 | 如果你想从PHP中改变这些全局变量,一个好的选择是包含一个针对这个的方法: 84 | 85 | ```zephir 86 | namespace Test; 87 | 88 | class MyOptions 89 | { 90 | 91 | public static function setOptions(array options) 92 | { 93 | boolean someOption, anotherOption; 94 | 95 | if fetch someOption, options["some_option"] { 96 | globals_set("some_option", someOption); 97 | } 98 | 99 | if fetch anotherOption, options["another_option"] { 100 | globals_set("another_option", anotherOption); 101 | } 102 | } 103 | } 104 | ``` 105 | 106 | 不能动态访问扩展全局, 因为 `globals_get`/`globals_set` 优化器生成的 c 代码必须在编译时解析: 107 | 108 | ```zephir 109 | let myOption = "someOption"; 110 | 111 | // 将抛出编译器异常 112 | let someOption = globals_get(myOption); 113 | ``` -------------------------------------------------------------------------------- /zh-cn/introduction.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'zh-cn' 4 | version: '0.12' 5 | --- 6 | 7 | # Zephir 简介 8 | 9 | Zephir 是一种语言, 它能够满足 php 开发人员的主要需求, 他们试图编写和编译可由 php 执行的代码。 它是动态的/静态类型的, 它的一些功能为 php 开发人员所熟悉。 10 | 11 | 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](https://translate.google.com/#en/en/zaefire). 12 | 13 | 14 | 15 | ## Hello World! 16 | 17 | 每种语言都有自己的 "Hello World!" 示例。 在 Zephir 中, 这个介绍性示例展示了该语言的一 些重要功能。 18 | 19 | Zephir 中的代码必须放在类中。 该语言旨在创建面向对象的库框架, 因此不允许在类之外使用代码。 此外, 还需要命名空间: 20 | 21 | ```zephir 22 | namespace Test; 23 | 24 | /** 25 | * This is a sample class 26 | */ 27 | class Hello 28 | { 29 | /** 30 | * This is a sample method 31 | */ 32 | public function say() 33 | { 34 | echo "Hello World!"; 35 | } 36 | } 37 | ``` 38 | 39 | 编译此类后, 它将生成以下代码, 该代码由 gcc/clang/vc ++ 透明地编译: 40 | 41 | ```c 42 | #ifdef HAVE_CONFIG_H 43 | #include "config.h" 44 | #endif 45 | 46 | #include "php.h" 47 | #include "php_test.h" 48 | #include "test.h" 49 | 50 | #include "kernel/main.h" 51 | 52 | /** 53 | * This is a sample class 54 | */ 55 | ZEPHIR_INIT_CLASS(Test_Hello) { 56 | ZEPHIR_REGISTER_CLASS(Test, Hello, hello, test_hello_method_entry, 0); 57 | return SUCCESS; 58 | } 59 | 60 | /** 61 | * This is a sample method 62 | */ 63 | PHP_METHOD(Test_Hello, say) { 64 | php_printf("%s", "Hello World!"); 65 | } 66 | ``` 67 | 68 | 实际上, 使用 Zephir 的开发人员必须知道甚至理解 c, 这是不希望的。但是, 如果您对编译器、php 内部或 c 语言本身有任何经验, 这将使您更清楚地了解在使用 Zephir 时内部发生的情况。 69 | 70 | 71 | 72 | ## 一个 Zephir 的尝试 73 | 74 | 在下面的例子中,我们将描述足够多的细节来理解发生了什么。 目标是让您了解Zephir中的编程是什么样子的。 我们将在后面的章节中探索细节的特性。 75 | 76 | 下面的例子很简单; 它实现了一个类和一个方法,以及一个检查数组类型的小程序。 77 | 78 | 让我们详细检查代码,以便开始学习Zephir语法。 在短短几行代码中有很多细节! 我们将在这里解释其大意: 79 | 80 | ```zephir 81 | namespace Test; 82 | 83 | /** 84 | * MyTest (test/mytest.zep) 85 | */ 86 | class MyTest 87 | { 88 | public function someMethod() 89 | { 90 | /* Variables must be declared */ 91 | var myArray; 92 | int i = 0, length; 93 | 94 | /* Create an array */ 95 | let myArray = ["hello", 0, 100.25, false, null]; 96 | 97 | /* Count the array into a 'int' variable */ 98 | let length = count(myArray); 99 | 100 | /* Print value types */ 101 | while i < length { 102 | echo typeof myArray[i], "\n"; 103 | let i++; 104 | } 105 | 106 | return myArray; 107 | } 108 | } 109 | ``` 110 | 111 | 在该方法中,第一行使用`var`和`int`关键字。 用于在局部作用域中声明一个变量。 方法中使用的每个变量都必须使用其各自的类型声明。 这个声明不是可选的——它帮助编译器警告您输入错误的变量,或者警告您使用超出范围的变量,这通常会导致运行时错误。 112 | 113 | 使用关键字`var`声明动态变量。 可以将这些变量分配并重新分配给不同的类型。 另一方面, `i` 和 `length` 变量是静态类型的整数变量, 在整个程序执行中只能有整数值。 114 | 115 | 与 php 不同的是, 你不需要在变量名前面放一个美元符号 ($)。 116 | 117 | Zephir 遵循与 java、c#、c++ 等相同的注释约定。 `//评论 到了一行的末尾, 而 /* 注释 */` 可以跨越线边界。 118 | 119 | 默认情况下, 变量是不可变的。 这意味着 Zephir 预计大多数变量将保持不变。 保持其初始值的变量可以由编译器优化为静态常量。 当需要更改变量值时, 必须使用关键字 `let`: 120 | 121 | ```zephir 122 | /* Create an array */ 123 | let myArray = ["hello", 0, 100.25, false, null]; 124 | ``` 125 | 126 | 默认情况下, 数组是动态类型的, 就像 php 中一样-它们可能包含不同类型的值。 PHP的函数可以在Zephir代码中调用。 在下一个示例中, 调用函数 `count`, 但编译器可以执行优化, 如避免此调用, 因为它已经知道数组的大小: 127 | 128 | ```zephir 129 | /* Count the array into a 'int' variable */ 130 | let length = count(myArray); 131 | ``` 132 | 133 | 控件流语句中的括号是可选的。 如果你觉得这样做更舒服,你可以使用它们,但不是必须的。 134 | 135 | ```zephir 136 | while i < length { 137 | echo typeof myArray[i], "\n"; 138 | let i++; 139 | } 140 | ``` 141 | 142 | 由于PHP只处理动态变量,因此方法总是返回动态变量。 这意味着如果返回静态类型的变量,在PHP端您将得到一个可用于PHP代码的动态变量。 注意,内存是由编译器自动管理的,类似于PHP的管理方式,所以您不需要像在C中那样分配或释放内存。 -------------------------------------------------------------------------------- /zh-cn/language.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'zh-cn' 4 | version: '0.12' 5 | --- 6 | 7 | # 基本语法 8 | 9 | 在本章中, 我们将讨论文件和命名空间、变量声明、杂项语法约定以及其他几个一般概念的组织。 10 | 11 | 12 | 13 | ## 在文件和命名空间中组织代码 14 | 15 | 在 php 中, 您可以将代码放置在任何文件中, 而不需要特定的结构。 在 Zephir中, 每个文件都必须包含一个类 (并且只有一个类)。 每个类都必须有一个命名空间, 并且目录结构必须与所使用的类和命名空间的名称相匹配。 (这类似于 psr-4 自动加载约定, 只是它是由语言本身强制执行的。 16 | 17 | 例如, 给定以下结构, 每个文件中的类必须是: 18 | 19 | ```bash 20 | mylibrary/ 21 | router/ 22 | exception.zep # 23 | router.zep # MyLibrary\Router 24 | ``` 25 | 26 | Class in `mylibrary/router.zep`: 27 | 28 | ```zephir 29 | namespace MyLibrary; 30 | 31 | class Router 32 | { 33 | 34 | } 35 | ``` 36 | 37 | Class in `mylibrary/router/exception.zep`: 38 | 39 | ```zephir 40 | namespace MyLibrary\Router; 41 | 42 | class Exception extends \Exception 43 | { 44 | 45 | } 46 | ``` 47 | 48 | 如果文件或类不在预期文件中, 则 Zephir 将引发编译器异常, 反之亦然。 49 | 50 | 51 | 52 | ## 指令分离 53 | 54 | 您可能已经注意到, 前一章中的代码示例中很少有分号。 您可以使用分号分隔语句和表达式, 如 java、c/c ++、php 和类似语言: 55 | 56 | ```zephir 57 | myObject->myMethod(1, 2, 3); echo "world"; 58 | ``` 59 | 60 | 61 | 62 | ## 注释 63 | 64 | Zephir 支持 "c"/"c++" 注释。 这是行注释 `// ...`, 这是多行注释 `/* ... */`: 65 | 66 | ```zephir 67 | // this is a one line comment 68 | 69 | /** 70 | * multi-line comment 71 | */ 72 | ``` 73 | 74 | 在大多数语言中,注释只是编译器/解释器忽略的文本。 在Zephir中,多行注释也用作docblock,它们被导出到生成的代码中,因此它们是语言的一部分! 75 | 76 | 如果docblock不在预期的位置,编译器将抛出异常。 77 | 78 | 79 | 80 | ## 变量声明 81 | 82 | 在Zephir中,必须声明给定范围中使用的所有变量。 这为编译器执行优化和验证提供了重要信息。 变量必须是唯一的标识符,它们不能是保留字。 83 | 84 | ```zephir 85 | // 在同一指令中声明相同类型的变量 86 | var a, b, c; 87 | 88 | // 在单独的行中声明每个变量 89 | var a; 90 | var b; 91 | var c; 92 | ``` 93 | 94 | 变量可以选择有一个初始兼容的默认值: 95 | 96 | ```zephir 97 | // 使用默认值声明变量 98 | var a = "hello", b = 0, c = 1.0; 99 | int d = 50; bool some = true; 100 | ``` 101 | 102 | 变量名区分大小写,以下变量不同: 103 | 104 | ```zephir 105 | // 不同的变量 106 | var somevalue, someValue, SomeValue; 107 | ``` 108 | 109 | 110 | 111 | ## 变量作用域 112 | 113 | 所有声明的变量都局部作用于声明它们的方法: 114 | 115 | ```zephir 116 | namespace Test; 117 | 118 | class MyClass 119 | { 120 | public function someMethod1() 121 | { 122 | int a = 1, b = 2; 123 | return a + b; 124 | } 125 | 126 | public function someMethod2() 127 | { 128 | int a = 3, b = 4; 129 | return a + b; 130 | } 131 | } 132 | ``` 133 | 134 | 135 | 136 | ## 超全局 137 | 138 | Zephir不支持全局变量——不允许从PHP代码块访问全局变量。 然而,您可以访问PHP的超全局变量,如下所示: 139 | 140 | ```zephir 141 | // 从_POST获取值 142 | let price = _POST["price"]; 143 | 144 | // 从_SERVER读取值 145 | let requestMethod = _SERVER["REQUEST_METHOD"]; 146 | ``` 147 | 148 | 149 | 150 | ## 本地符号表 151 | 152 | PHP中的每个方法或上下文都有一个符号表,允许您以非常动态的方式编写变量: 153 | 154 | ```php 155 | 20 | 21 | ## initializers 22 | 23 | `initializers` 块如下所示: 24 | 25 | ```json 26 | { 27 | "initializers": [ 28 | { 29 | "globals": [ 30 | { 31 | "include": "my/awesome/library.h", 32 | "code": "setup_globals_deps(TSRMLS_C)" 33 | } 34 | ], 35 | "module": [ 36 | { 37 | "include": "my/awesome/library.h", 38 | "code": "setup_module_deps(TSRMLS_C)" 39 | } 40 | ], 41 | "request": [ 42 | { 43 | "include": "my/awesome/library.h", 44 | "code": "some_c_function(TSRMLS_C)" 45 | }, 46 | { 47 | "include": "my/awful/library.h", 48 | "code": "some_other_c_function(TSRMLS_C)" 49 | } 50 | ] 51 | } 52 | ] 53 | } 54 | ``` 55 | 56 | 这个块负责定义到上面图中显示的Init事件的钩子。 其中有三个:`globals`用于设置全局变量空间;`module`用于设置扩展本身需要功能的任何内容;`request`用于设置扩展来处理单个请求。 57 | 58 | 59 | 60 | ## destructors 61 | 62 | `destructors` 块如下所示: 63 | 64 | ```json 65 | { 66 | "destructors": [ 67 | { 68 | "request": [ 69 | { 70 | "include": "my/awesome/library.h", 71 | "code": "c_function_for_shutting_down(TSRMLS_C)" 72 | }, 73 | { 74 | "include": "my/awful/library.h", 75 | "code": "some_other_c_function_than_the_other_ones(TSRMLS_C)" 76 | } 77 | ], 78 | "post-request": [ 79 | { 80 | "include": "my/awesome/library.h", 81 | "code": "c_function_for_cleaning_up_after_the_response_is_sent(TSRMLS_C)" 82 | } 83 | ], 84 | "module": [ 85 | { 86 | "include": "my/awesome/library.h", 87 | "code": "release_module_deps(TSRMLS_C)" 88 | } 89 | ], 90 | "globals": [ 91 | { 92 | "include": "my/awesome/library.h", 93 | "code": "release_globals_deps(TSRMLS_C)" 94 | } 95 | ] 96 | } 97 | ] 98 | } 99 | ``` 100 | 101 | 正如 `initializers` 块负责定义上图中显示的 init 事件中的挂钩一样, *this* 块负责定义关机事件中的挂钩。 有四个:`request`响应之前敲定任何数据发送到客户端,`post-request`清理响应被发送后,`module模块扩展后的清理本身PHP进程关闭之前, 和globals`清理全局变量空间。 -------------------------------------------------------------------------------- /zh-cn/motivation.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'zh-cn' 4 | version: '0.12' 5 | --- 6 | 7 | # 为什么选择 Zephir? 8 | 9 | 今天的 php 应用程序必须平衡许多问题, 包括稳定性、性能和功能。 每个 php 应用程序都基于一组公共组件, 这些组件也是许多其他应用程序的基础。 10 | 11 | 这些常见组件是库、框架或两者的组合。 一旦安装, 框架很少改变, 并且作为应用程序的基础, 它们必须具有很高的功能, 而且速度也非常快。 12 | 13 | 获得快速和可靠的库可能会很复杂, 因为通常在它们上实现了高水平的抽象。 考虑到基础库或框架很少更改的限制, 可以利用编译来提高性能和资源消耗, 构建提供此功能的扩展。 14 | 15 | 使用 Zephir, 您可以实现可从 php 使用的面向对象的库/框架/应用程序, 使您的应用程序更快, 同时改善用户体验。 16 | 17 | 18 | 19 | ## 如果你是一个 php 程序员... 20 | 21 | PHP是web应用程序开发中最流行的语言之一。 像PHP这样的动态类型和解释语言由于其灵活性提供了非常高的生产力。 22 | 23 | 由于是第4版,PHP基于Zend引擎实现。 这是一个虚拟机,它通过字节码表示来执行PHP代码。 Zend 引擎几乎出现在世界上所有PHP安装中。 使用Zephir,您可以为在Zend引擎下运行的PHP创建扩展。 24 | 25 | PHP是Zephir的宿主,显然它们有很多相似之处; 然而,它们有重要的区别,使得Zephir有了自己的个性。 例如,Zephir更加严格,由于编译步骤的原因,它可能使您的生产率低于PHP。 26 | 27 | 28 | 29 | ## 如果你是一个 C 程序员..。 30 | 31 | C语言是有史以来最强大、最流行的语言之一。 实际上,PHP是用C编写的,这也是PHP扩展可用的原因之一。 C允许您自由地管理内存,使用低级类型,甚至内联程序集例程。 32 | 33 | 然而,与PHP或Zephir相比,在C中开发大型应用程序所花费的时间要比预期的长得多,而且如果您不是经验丰富的开发人员,有些错误可能很难发现。 34 | 35 | Zephir是为了安全而设计的,因此它不实现指针或手动内存管理,因此如果您是C程序员,您会觉得Zephir不如C程序员强大,但比C程序员更友好。 36 | 37 | 38 | 39 | ## 编译 vs 解释 40 | 41 | 编译通常会减慢开发速度; 在运行代码之前,您需要更多的耐心来编译代码。 另一方面,解释倾向于降低代码性能,以提高开发人员的工作效率。 也就是说,在某些情况下,解释代码和编译代码的速度没有明显的区别。 42 | 43 | Zephir需要编译您的代码,但其功能是从PHP中使用的,PHP是经过解释的。 44 | 45 | 一旦编译了代码,就不需要再这样做了。 每次运行解释代码时都会对其进行解释。 开发人员可以决定其应用程序的哪些部分应位于 Zephir 中, 而哪些部分不应该在 Zephir 中。 46 | 47 | 48 | 49 | ## 静态类型化 vs 动态类型化的语言 50 | 51 | 一般来说, 在静态类型化语言中, 变量在其生存期内绑定到特定类型。 它的类型不能更改, 它只能引用与类型兼容的实例和操作。 使用了类似 c/c ++ 等语言的方案: 52 | 53 | ```zephir 54 | int a = 0; 55 | a = "hello"; // not allowed 56 | ``` 57 | 58 | 在动态类型中, 类型绑定到值, 而不是变量。 因此,一个变量可以引用一个类型的值,然后被重新分配到一个不相关类型的值。 Javascript/PHP 是一个动态类型语言的例子: 59 | 60 | ```zephir 61 | var a = 0; 62 | a = "hello"; // allowed 63 | ``` 64 | 65 | 尽管动态语言具有生产率优势,但它可能不是所有应用程序的最佳选择,尤其是对于非常大的代码库和高性能应用程序。 66 | 67 | 优化动态语言(如PHP) 的性能比优化静态语言(如c) 更具有挑战性。在静态语言中,优化器可以利用附加在变量本身上的类型信息来做出决策。 在动态语言中, 优化器可用的此类线索较少, 因此优化选择更加困难。 68 | 69 | 虽然最近在动态语言优化方面取得的进展很有希望 (如 jit 编译), 但它们落后于静态语言的最新发展。 因此, 如果您需要非常高性能, 静态语言可能是更安全的选择。 70 | 71 | 静态语言的另一个小好处是编译器执行的额外检查。 编译器找不到逻辑错误, 这些错误的重要性要大得多, 但编译器可以提前找到仅在运行时动态语言中才能找到的错误。 72 | 73 | Zephir 是静态和动态类型化的, 允许您在可能的情况下利用这两种方法。 74 | 75 | 76 | 77 | ## 编译方案 78 | 79 | Zephir提供本机代码生成(目前通过编译到C)。 像gcc/clang/vc++这样的编译器会优化并将代码编译成机器代码。 下图显示了该过程的工作原理: 80 | 81 | ![编译方案](/assets/content/scheme.png) 82 | 83 | 除了Zephir提供的优化之外,随着时间的推移,编译器已经实现并成熟了许多优化,这些优化可以提高编译应用程序的性能: 84 | 85 | * [GCC 优化](https://gcc.gnu.org/onlinedocs/gcc-4.1.0/gcc/Optimize-Options.html) 86 | * [LLVM 传递](https://llvm.org/docs/Passes.html) 87 | * [Visual C/C++ 优化](https://msdn.microsoft.com/en-us/library/k1ack8f1.aspx) 88 | 89 | 90 | 91 | ## 代码保护 92 | 93 | 在某些情况下,编译不会显著提高性能。 这可能是因为瓶颈位于应用程序的I/O绑定部分(很可能),而不是计算/内存绑定。 然而,编译代码也可以为您的应用程序带来一定程度的知识保护。 使用Zephir,生成本地二进制文件,您还可以将原始代码“隐藏”给用户或客户。 94 | 95 | 96 | 97 | ## 结语 98 | 99 | Zephir的创建不是为了替代PHP或C. 相反,我们认为它是对它们的补充,允许PHP开发人员尝试进行代码编译和静态类型。 Zephir试图将C和PHP世界的优点结合起来,寻找使应用程序更快的机会。 -------------------------------------------------------------------------------- /zh-cn/operator-precedence.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'zh-cn' 4 | version: '0.12' 5 | --- 6 | 7 | # Operator Precedence 8 | **Operator precedence** determines how operators are parsed. Operators with higher precedence become the operands of operators with lower precedence. For example, in the expression `1 + 5 * 3`, the answer is 16 and not 18 because the multiplication (`*`) operator has a higher precedence than the addition (`+`) operator. Parentheses may be used to force precedence, if necessary. For instance: `(1 + 5) * 3` evaluates to 18. 9 | 10 | 11 | 12 | ## Associativity 13 | When operators have equal precedence their **associativity** determines how the operators are grouped. For example `-` is _left-associative_, so `1 - 2 - 3` is grouped as `(1 - 2) - 3` and evaluates to `-4`. `=` on the other hand is _right-associative_, so `let a = b = c` is grouped as `let a = (b = c)`. 14 | 15 | Operators of equal precedence that are _non-associative_ cannot be used next to one another. For example: 16 | ```zep 17 | new new Foo(); 18 | ``` 19 | is illegal in Zephir, because the `new` is non-associative. At the moment, `new` is the only non-associative operator in Zephir. 20 | 21 | Use of parentheses, even when not strictly necessary, can often increase readability of the code, by making grouping explicit, rather than relying on the implicit operator precedence and associativity. 22 | 23 | 24 | 25 | ## Precedence Table 26 | The following table lists the operators in order of precedence, with the highest-precedence ones at the top. Operators on the same line have equal precedence, in which case associativity decides grouping. 27 | 28 | | Precedence | 运算符 | Operator type | Associativity | 29 | | ---------- | -------------------------------- | ----------------------------------- | --------------- | 30 | | 1 | `->` | Member Access | right-to-left | 31 | | 2 | `~` | Bitwise NOT | right-to-left | 32 | | 3 | `!` | Logical NOT | right-to-left | 33 | | 4 | `new` | new | non-associative | 34 | | 5 | `clone` | clone | right-to-left | 35 | | 6 | `typeof` | Type-of | right-to-left | 36 | | 7 | `..`, `...` | Inclusive/exclusive range | left-to-right | 37 | | 8 | `isset`, `fetch`, `empty` | Exclusive range | right-to-left | 38 | | 9 | `*`, `/`, `%` | Multiplication, Division, Remainder | left-to-right | 39 | | 10 | `+`, `-`, `.` | Addition, Subtraction, Concat | left-to-right | 40 | | 11 | `<<`, `>>` | Bitwise shift left/right | left-to-right | 41 | | 12 | `<`, `<=`, `=>`, `>` | Comparison | left-to-right | 42 | | 13 | `==`, `!==`, `===`, `!==` | Comparison | left-to-right | 43 | | 14 | `&` | Bitwise AND, references | left-to-right | 44 | | 15 | `^` | Bitwise XOR | left-to-right | 45 | | 16 | `|` | Bitwise OR | left-to-right | 46 | | 17 | `instanceof` | Instance-of | left-to-right | 47 | | 18 | `&&` | Logical AND | left-to-right | 48 | | 19 | `||` | Logical OR | left-to-right | 49 | | 20 | `likely`, `unlikely` | Branch prediction | right-to-left | 50 | | 21 | `?` | Logical | right-to-left | 51 | | 21 | `=>` | Closure Arrow | right-to-left | 52 | -------------------------------------------------------------------------------- /zh-cn/phpinfo.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'zh-cn' 4 | version: '0.12' 5 | --- 6 | 7 | # phpinfo () 部分 8 | 9 | 与大多数扩展一样, Zephir 扩展能够在 [phpinfo()](https://php.net/manual/en/function.phpinfo.php) 输出中显示信息。 这些信息通常与指令、环境数据等有关。 10 | 11 | 默认情况下, 每个 Zephir扩展都会自动向显示扩展版本和扩展所支持的任何 ini 选项的 `phpinfo()` 输出中添加一个基本表。 12 | 13 | 通过向 `config.json` 文件中添加以下配置, 可以添加更多指令: 14 | 15 | ```json 16 | "info": [ 17 | { 18 | "header": ["Directive", "Value"], 19 | "rows": [ 20 | ["setting1", "value1"], 21 | ["setting2", "value2"] 22 | ] 23 | }, 24 | { 25 | "header": ["Directive", "Value"], 26 | "rows": [ 27 | ["setting3", "value3"], 28 | ["setting4", "value4"] 29 | ] 30 | } 31 | ] 32 | ``` 33 | 34 | 此信息将如下所示: 35 | 36 | ![](/assets/content/info.png) -------------------------------------------------------------------------------- /zh-cn/sidebar.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "text": "Welcome", 4 | "url": "welcome" 5 | }, 6 | { 7 | "text": "Why Zephir", 8 | "url": "motivation" 9 | }, 10 | { 11 | "text": "Zephir 简介", 12 | "url": "introduction" 13 | }, 14 | { 15 | "text": "安装", 16 | "url": "installation" 17 | }, 18 | { 19 | "text": "教程", 20 | "url": "tutorial" 21 | }, 22 | { 23 | "text": "基本语法", 24 | "url": "language" 25 | }, 26 | { 27 | "text": "类型", 28 | "url": "types" 29 | }, 30 | { 31 | "text": "运算符", 32 | "url": "operators" 33 | }, 34 | { 35 | "text": "Operator Precedence", 36 | "url": "operator-precedence" 37 | }, 38 | { 39 | "text": "数组", 40 | "url": "arrays" 41 | }, 42 | { 43 | "text": "Classes and objects", 44 | "url": "oop" 45 | }, 46 | { 47 | "text": "Built-in methods", 48 | "url": "builtin-methods" 49 | }, 50 | { 51 | "text": "Control structures", 52 | "url": "control-structures" 53 | }, 54 | { 55 | "text": "例外情况", 56 | "url": "exceptions" 57 | }, 58 | { 59 | "text": "Calling functions", 60 | "url": "functions" 61 | }, 62 | { 63 | "text": "闭 包", 64 | "url": "closures" 65 | }, 66 | { 67 | "text": "自定义优化器", 68 | "url": "optimizers" 69 | }, 70 | { 71 | "text": "Configuration file", 72 | "url": "config" 73 | }, 74 | { 75 | "text": "Command Line", 76 | "url": "command-line" 77 | }, 78 | { 79 | "text": "生命周期钩子", 80 | "url": "lifecycle" 81 | }, 82 | { 83 | "text": "Extension globals", 84 | "url": "globals" 85 | }, 86 | { 87 | "text": "phpinfo() sections", 88 | "url": "phpinfo" 89 | }, 90 | { 91 | "text": "Static analysis", 92 | "url": "static-analysis" 93 | }, 94 | { 95 | "text": "优化", 96 | "url": "optimizations" 97 | }, 98 | { 99 | "text": "Compiler warnings", 100 | "url": "warnings" 101 | }, 102 | { 103 | "text": "License", 104 | "url": "license" 105 | } 106 | ] 107 | -------------------------------------------------------------------------------- /zh-cn/static-analysis.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'zh-cn' 4 | version: '0.12' 5 | --- 6 | 7 | # 静态分析 8 | 9 | Zephir 的编译器提供对已编译代码的静态分析。 此功能背后的想法是在运行时之前帮助开发人员发现潜在的问题, 避免意外的行为 。 10 | 11 | 12 | 13 | ## 条件未分配的变量 14 | 15 | 工作分配的静态分析尝试确定变量在赋值之前是否已使用: 16 | 17 | ```zephir 18 | class Utils 19 | { 20 | public function someMethod(b) 21 | { 22 | string a; char c; 23 | 24 | if b == 10 { 25 | let a = "hello"; 26 | } 27 | 28 | //a could be unitialized here 29 | for c in a { 30 | echo c, PHP_EOL; 31 | } 32 | } 33 | } 34 | ``` 35 | 36 | 上面的示例说明了一种常见情况。 只有当 `b` 等于 10时, 才会分配变量 `a`, 然后需要使用此变量的值--但它可能未初始化。 Zephir 检测到这一点, 自动将变量初始化为空字符串, 并生成警告开发人员: 37 | 38 | ```bash 39 | 警告:第一次在条件分支中分配变量a, 40 | 考虑在声明中初始化它 41 | 42 | /home/scott/test/test/utils.zep on 21 [conditional-initialization] 43 | 44 | for c in a { 45 | ``` 46 | 47 | 发现这样的错误有时是很棘手的, 但是静态分析可以帮助程序员提前发现错误。 48 | 49 | 50 | 51 | ## 死码消除 52 | 53 | Zephir 通知开发人员代码中无法访问的分支, 并执行死代码消除, 这意味着它将从生成的二进制文件中删除所有代码, 因为它无论如何都无法执行: 54 | 55 | ```zephir 56 | class Utils 57 | { 58 | public function someMethod(b) 59 | { 60 | if false { 61 | // This is never executed 62 | echo "hello"; 63 | } 64 | } 65 | } 66 | ``` -------------------------------------------------------------------------------- /zh-cn/warnings.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'zh-cn' 4 | version: '0.12' 5 | --- 6 | 7 | # 编译警告 8 | 9 | 当发现代码可以改进或避免潜在错误的情况时,编译器会发出警告。 10 | 11 | 警告可以通过命令行参数启用,也可以添加到`config.json`以更永久地启用或禁用它们。 12 | 13 | 可以通过将警告的名称以`-w`为前缀传递来启用警告: 14 | 15 | ```bash 16 | zephir -wunused-variable -wnonexistent-function 17 | ``` 18 | 19 | 警告可以通过传递前缀为`-W`的名称来禁用: 20 | 21 | ```bash 22 | zephir -Wunused-variable -Wnonexistent-function 23 | ``` 24 | 25 | 支持以下警告: 26 | 27 | 28 | 29 | ## unused-variable 30 | 31 | 在声明变量但在方法中未使用时引发。 此警告默认启用。 32 | 33 | ```zephir 34 | public function some() 35 | { 36 | var e; // declared but not used 37 | 38 | return false; 39 | } 40 | ``` 41 | 42 | 43 | 44 | ## unused-variable-external 45 | 46 | 当一个参数被声明但在方法中没有使用时引发。 47 | 48 | ```zephir 49 | public function sum(a, b, c) // c is not used 50 | { 51 | return a + b; 52 | } 53 | ``` 54 | 55 | 56 | 57 | ## possible-wrong-parameter-undefined 58 | 59 | 当一个方法以错误的类型调用参数时引发: 60 | 61 | ```zephir 62 | public function some() 63 | { 64 | return this->sum("a string", "another"); // wrong parameters passed 65 | } 66 | 67 | public function sum(int a, int b) 68 | { 69 | return a + b; 70 | } 71 | ``` 72 | 73 | 74 | 75 | ## nonexistent-function 76 | 77 | 调用编译时不存在的函数时引发: 78 | 79 | ```zephir 80 | public function some() 81 | { 82 | someFunction(); // someFunction does not exist 83 | } 84 | ``` 85 | 86 | 87 | 88 | ## nonexistent-class 89 | 90 | 当使用编译时不存在的类时引发: 91 | 92 | ```zephir 93 | public function some() 94 | { 95 | var a; 96 | 97 | let a = new \MyClass(); // MyClass does not exist 98 | } 99 | ``` 100 | 101 | 102 | 103 | ## non-valid-isset 104 | 105 | 当编译器检测到正在对非数组或-对象值执行“isset”操作时引发: 106 | 107 | ```zephir 108 | public function some() 109 | { 110 | var b = 1.2; 111 | 112 | return isset b[0]; // variable integer 'b' used as array 113 | } 114 | ``` 115 | 116 | 117 | 118 | ## non-array-update 119 | 120 | 当编译器检测到正在对非数组值执行数组更新操作时引发: 121 | 122 | ```zephir 123 | public function some() 124 | { 125 | var b = 1.2; 126 | let b[0] = true; // variable 'b' cannot be used as array 127 | } 128 | ``` 129 | 130 | 131 | 132 | ## non-valid-objectupdate 133 | 134 | 当编译器检测到正在对非对象值进行对象更新操作时引发: 135 | 136 | ```zephir 137 | public function some() 138 | { 139 | var b = 1.2; 140 | let b->name = true; // variable 'b' cannot be used as object 141 | } 142 | ``` 143 | 144 | 145 | 146 | ## non-valid-fetch 147 | 148 | 当编译器检测到正在对非数组或-对象值进行'fetch'操作时引发: 149 | 150 | ##### 变量整数'b'用作数组 151 | 152 | ```zephir 153 | public function some() 154 | { 155 | var b = 1.2, a; 156 | fetch a, b[0]; 157 | } 158 | ``` 159 | 160 | 161 | 162 | ## invalid-array-index 163 | 164 | 当编译器检测到使用了无效的数组索引时引发: 165 | 166 | ```zephir 167 | public function some(var a) 168 | { 169 | var b = []; 170 | let a[b] = true; 171 | } 172 | ``` 173 | 174 | 175 | 176 | ## non-array-append 177 | 178 | 当编译器检测到一个元素被附加到一个非数组变量时引发: 179 | 180 | ```zephir 181 | public function some() 182 | { 183 | var b = false; 184 | let b[] = "some value"; 185 | } 186 | ``` -------------------------------------------------------------------------------- /zh-cn/welcome.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | language: 'zh-cn' 4 | version: '0.12' 5 | --- 6 | 7 | # 欢迎! 8 | 9 | Zephir,一种开源的高级语言,旨在简化PHP扩展的创建和可维护性,重点关注类型和内存安全性。 10 | 11 | 12 | 13 | ## 一些特征 14 | 15 | Zephir 的主要特点是: 16 | 17 | | 属性 | 说明 | 18 | | ---- | -------------- | 19 | | 类型系统 | 动态/静态 | 20 | | 内存安全 | 不允许使用指针或直接内存管理 | 21 | | 编译模型 | 预编译 | 22 | | 内存模型 | 任务本地垃圾回收 | 23 | 24 | 25 | 26 | ## 一个小尝试 27 | 28 | 下面的代码使用筛选变量的方法注册一个类, 返回它们的字母字符: 29 | 30 | ```zephir 31 | namespace MyLibrary; 32 | 33 | /** 34 | * Filter 35 | */ 36 | class Filter 37 | { 38 | /** 39 | * 过滤一个字符串,返回它的alpha字符 40 | * 41 | * @param string str 42 | */ 43 | public function alpha(string str) 44 | { 45 | char ch; string filtered = ""; 46 | 47 | for ch in str { 48 | if (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') { 49 | let filtered .= ch; 50 | } 51 | } 52 | 53 | return filtered; 54 | } 55 | } 56 | ``` 57 | 58 | 该类可从 php 中使用, 如下所示: 59 | 60 | ```php 61 | alpha("01he#l.lo?/1"); // prints hello 65 | ``` 66 | 67 | 68 | 69 | ## 外部链接 70 | 71 | 下面我们收集了您可能感兴趣的外部资源链接: 72 | 73 | - [类型系统](https://en.wikipedia.org/wiki/Type_system) 74 | - [内存安全](https://en.wikipedia.org/wiki/Memory_safety) 75 | - [预编译](https://en.wikipedia.org/wiki/Ahead-of-time_compilation) 76 | - [内存管理](https://en.wikipedia.org/wiki/Memory_management) --------------------------------------------------------------------------------