|
1 | 1 | # Type Builders |
2 | 2 |
|
3 | | -// TODO |
| 3 | +The Type Builder is a factory class that acts as a layer between the |
| 4 | +[type declaration](basic-types.md) (like `non-empty-string`) and the |
| 5 | +[type instance](types.md) (like `NonEmptyStringType`). |
| 6 | + |
| 7 | +To register types in the `Mapper`, a [platform is used](mapper-platforms.md) |
| 8 | +containing a set of type builders that analyze the type description (and AST) |
| 9 | +and create a set of [type instances](types.md) used directly at runtime for |
| 10 | +checking and casting values. |
| 11 | + |
| 12 | +To better understand the tasks of the builder, it makes sense to look at the |
| 13 | +graph illustrating the process of compiling a type when calling |
| 14 | +`$mapper->denormalize(42)` that should return `int(42)` using built-in |
| 15 | +`TypeInterface<int>` type |
| 16 | + |
| 17 | +<code-block lang="mermaid" xmlns=""> |
| 18 | +<![CDATA[ |
| 19 | +flowchart TD |
| 20 | + Input["int(42)"] .-> Mapper["Mapper::denormalize(42)"] |
| 21 | + Mapper -. "cast value 42 using TypeInterface" .-> Type |
| 22 | + Mapper -- "start compilation" --> Extractor["TypeExtractor::extract(42)"] |
| 23 | + Extractor -- "for int(42) value the string("int") was inferred" --> Parser["TypeParser::parse("int")"] |
| 24 | + Parser -- "definition string("int") was parsed to AST object(TypeStatement)" --> Repository["TypeRepository::findType(TypeStatement)"] |
| 25 | + Platform -- "configure builders list<TypeBuilderInterface>" --> Repository |
| 26 | + Repository -. TypeInterface<int> .-> Type["TypeInterface<int>::cast(42)"] |
| 27 | + Type .-> Output["int(42)"] |
| 28 | +]]> |
| 29 | +</code-block> |
| 30 | + |
| 31 | +The diagram is quite complex, and it's okay if you don't quite understand |
| 32 | +the process. The main thing is that it makes sense: |
| 33 | +- [The platform](mapper-platforms.md) contains a set of type builders and |
| 34 | + [registers](standard-platform.md#additional-types) them in the repository. |
| 35 | +- The type builder returns a [specific `TypeInterface<T>`](types.md) from the |
| 36 | + type declaration string (or more precisely, from its Abstract Syntax Tree). |
| 37 | + |
| 38 | + |
| 39 | +That is, the code of type builder of `int<0, 10>` looks something like this: |
| 40 | + |
| 41 | +```php |
| 42 | +class IntTypeBuilder interface TypeBuilderInterface |
| 43 | +{ |
| 44 | + public function build(TypeStatement $stmt): TypeInterface |
| 45 | + { |
| 46 | + // [[[Expects named type|basic-types.md]]] |
| 47 | + assert($stmt instanceof NamedTypeNode); |
| 48 | + // [[[Expects 2 template arguments|generic-types.md]]] |
| 49 | + assert(count($stmt->arguments) === 2); |
| 50 | + // [[[Expects no shape fields|shape-types.md]]] |
| 51 | + assert($stmt->fields === null); |
| 52 | + |
| 53 | + return new IntType( |
| 54 | + name: $stmt->name->toString(), // string("int"); |
| 55 | + min: $stmt->arguments[0]->getValue(), // int(0) |
| 56 | + max: $stmt->arguments[1]->getValue(), // int(10) |
| 57 | + ); |
| 58 | + } |
| 59 | +} |
| 60 | +``` |
| 61 | + |
| 62 | +<warning> |
| 63 | +This is not an exact declaration and is used as an example. |
| 64 | + |
| 65 | +It's also worth noting that not all checks are performed in the |
| 66 | +example. For example, the type of the template arguments (that they are |
| 67 | +integers) also makes sense to check. |
| 68 | +</warning> |
| 69 | + |
| 70 | +<tip> |
| 71 | +You can read more about custom type builders in the |
| 72 | +<a href="custom-type-builder.md">"custom type builders" page</a>. |
| 73 | +</tip> |
0 commit comments