Skip to content

Commit c1b0fd5

Browse files
desIstUrGuaddesIstUrGuad
authored andcommitted
commitierung der kochung
1 parent fd7161c commit c1b0fd5

File tree

4 files changed

+180
-18
lines changed

4 files changed

+180
-18
lines changed

LE.md

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# Generics syntax
2+
3+
## Generic classes and interfaces
4+
5+
### Basic case
6+
```lhp
7+
class GenericTestClass<T> {
8+
// T can be used as type alias inside of 'GenericTestClass'
9+
public function __construct(
10+
private T $property
11+
) {}
12+
13+
public function getMyT(): T {
14+
return $this->property;
15+
}
16+
17+
public function setMyT(T $newValue) {
18+
$this->property = $newValue;
19+
}
20+
}
21+
```
22+
23+
### Multiple Generics
24+
```lehp
25+
class GenericTestClass<T, U> {
26+
// T and U can now be used as type aliases inside of 'GenericTestClass'
27+
28+
public function __construct(
29+
private T $first,
30+
private U $second
31+
) {}
32+
33+
public function getFirst(): T {
34+
return $this->first;
35+
}
36+
37+
public function setFirst(T $value) {
38+
$this->first = $value;
39+
}
40+
41+
public function getSecond(): U {
42+
return $this->second;
43+
}
44+
45+
public function setSecond(U $value) {
46+
$this->second = $value;
47+
}
48+
}
49+
```
50+
51+
### Bounded Gerics
52+
```lehp
53+
interface Serializable {
54+
public function serialize(): string;
55+
}
56+
57+
class BoundedGenericClass<T: Serializable> {
58+
public function __construct(
59+
private T $serializable
60+
) {}
61+
62+
public function getSerialized(): string
63+
{
64+
return $this->serializable->serialize();
65+
}
66+
67+
public function getAsSerializable(): Serializable
68+
{
69+
return (Serializable) $this->serializable; // cast optional
70+
}
71+
72+
public function getObject(): T
73+
{
74+
return $this->serializable;
75+
}
76+
}
77+
```
78+
79+
### A little bit more complex
80+
```
81+
interface Serializer<T> {
82+
public function serialize(T $object): string;
83+
}
84+
85+
class RandomAssSerializableContaier<T, K: Serializer<T>> {
86+
87+
private array $content = [];
88+
89+
public function __construct(
90+
private K serializer
91+
) {}
92+
93+
public function add(T $toAdd)
94+
{
95+
$content[] = $toAdd;
96+
}
97+
98+
public function asSerializedList(): array
99+
{
100+
return array_map(
101+
fn ($obj) $this->serializer->serialize($obj),
102+
$this->content
103+
);
104+
}
105+
}
106+
```
107+
## Functions
108+
### Basic case
109+
```
110+
function noOp<T>(T $in): T
111+
{
112+
return $in;
113+
}
114+
```
115+
116+
### A bit more complex
117+
```
118+
interface Serializer<T> {
119+
public function serialize(T $object): string;
120+
}
121+
122+
function serialize<T, K: Serializer<T>>(T $in, K $serializer): string
123+
{
124+
return $serializer->serialize($in);
125+
}
126+
```

Zend/zend_language_parser.y

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -291,18 +291,23 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
291291
%type <ast> function_name non_empty_member_modifiers
292292
%type <ast> property_hook property_hook_list optional_property_hook_list hooked_property property_hook_body
293293
%type <ast> optional_parameter_list
294-
%type <ast> generic_type_parameter_list
295-
%type <ast> generic_type_parameters
294+
%type <ast> nested_generic_type_parameter_list
295+
%type <ast> nested_generic_type_parameters
296296
%type <ast> generic_type
297297
%type <ast> non_empty_generic_type_parameters
298+
%type <ast> generic_type_with_constraint
299+
%type <ast> generic_type_parameter_list_with_constraints
300+
%type <ast> class_or_fuction_decl_generic_type_parameters
301+
%type <ast> simple_generic_type
302+
%type <ast> simple_generic_type_parameter_list
303+
%type <ast> non_empty_simple_generic_type_parameters
298304

299305
%type <num> returns_ref function fn is_reference is_variadic property_modifiers property_hook_modifiers
300306
%type <num> method_modifiers class_const_modifiers member_modifier optional_cpp_modifiers
301307
%type <num> class_modifiers class_modifier anonymous_class_modifiers anonymous_class_modifiers_optional use_type backup_fn_flags
302308

303309
%type <ptr> backup_lex_pos
304310
%type <str> backup_doc_comment
305-
%type <str> generic_param_name
306311

307312
%type <ident> reserved_non_modifiers semi_reserved
308313

@@ -607,25 +612,60 @@ is_variadic:
607612

608613
class_declaration_statement:
609614
class_modifiers T_CLASS { $<num>$ = CG(zend_lineno); }
610-
T_STRING generic_type_parameters extends_from implements_list backup_doc_comment '{' class_statement_list '}'
615+
T_STRING class_or_fuction_decl_generic_type_parameters extends_from implements_list backup_doc_comment '{' class_statement_list '}'
611616
{ $$ = zend_ast_create_decl(ZEND_AST_CLASS, $1, $<num>3, $8, zend_ast_get_str($4), $6, $7, $10, $5, NULL); }
612617
| T_CLASS { $<num>$ = CG(zend_lineno); }
613-
T_STRING generic_type_parameters extends_from implements_list backup_doc_comment '{' class_statement_list '}'
618+
T_STRING class_or_fuction_decl_generic_type_parameters extends_from implements_list backup_doc_comment '{' class_statement_list '}'
614619
{ $$ = zend_ast_create_decl(ZEND_AST_CLASS, 0, $<num>2, $7, zend_ast_get_str($3), $5, $6, $9, $4, NULL); }
615620
;
616621

617-
generic_type_parameters:
618-
T_GENERIC_START generic_type_parameter_list possible_comma T_GENERIC_END { $$ = $2; }
622+
// only support e.g. "<T, S, A>"
623+
non_empty_simple_generic_type_parameters:
624+
T_GENERIC_START simple_generic_type_parameter_list T_GENERIC_END { $$ = $2; }
625+
;
626+
627+
// only support e.g. "SomeType<T, S, A>"
628+
simple_generic_type:
629+
T_STRING { $$ = zend_ast_create_zval_from_str(zend_ast_get_str($1)); }
630+
| T_STRING non_empty_simple_generic_type_parameters { $$ = zend_ast_create(ZEND_AST_GENERIC_TYPE, zend_ast_create_zval_from_str(zend_ast_get_str($1)), $2); }
631+
;
632+
633+
// only support e.g. "T, S, A"
634+
simple_generic_type_parameter_list:
635+
T_STRING { $$ = zend_ast_create_list(1, ZEND_AST_GENERIC_TYPE_PARAM_LIST, $1); }
636+
| generic_type_parameter_list_with_constraints ',' T_STRING { $$ = zend_ast_list_add($1, $3); }
637+
;
638+
639+
// supports bounded types, e.g. "<T : SomeInterface, S : SomeClass>"
640+
class_or_fuction_decl_generic_type_parameters:
641+
T_GENERIC_START generic_type_parameter_list_with_constraints T_GENERIC_END { $$ = $2; }
619642
| %empty { $$ = NULL; }
620643
;
621644

622-
generic_type_parameter_list:
645+
// supports bounded types, e.g. "T : SomeInterface, S : SomeClass"
646+
generic_type_parameter_list_with_constraints:
647+
generic_type_with_constraint { $$ = zend_ast_create_list(1, ZEND_AST_GENERIC_TYPE_PARAM_LIST, $1); }
648+
| generic_type_parameter_list_with_constraints ',' generic_type_with_constraint { $$ = zend_ast_list_add($1, $3); }
649+
;
650+
651+
// supports bounded types, e.g. "T : SomeInterface"
652+
generic_type_with_constraint:
653+
T_STRING { $$ = zend_ast_create_zval_from_str(zend_ast_get_str($1)); }
654+
| T_STRING ':' simple_generic_type { $$ = zend_ast_create(ZEND_AST_GENERIC_TYPE, zend_ast_create_zval_from_str(zend_ast_get_str($1)), $3); }
655+
;
656+
657+
nested_generic_type_parameters:
658+
T_GENERIC_START nested_generic_type_parameter_list T_GENERIC_END { $$ = $2; }
659+
| %empty { $$ = NULL; }
660+
;
661+
662+
nested_generic_type_parameter_list:
623663
generic_type { $$ = zend_ast_create_list(1, ZEND_AST_GENERIC_TYPE_PARAM_LIST, $1); }
624-
| generic_type_parameter_list ',' generic_type { $$ = zend_ast_list_add($1, $3); }
664+
| nested_generic_type_parameter_list ',' generic_type { $$ = zend_ast_list_add($1, $3); }
625665
;
626666

627667
non_empty_generic_type_parameters:
628-
T_GENERIC_START generic_type_parameter_list possible_comma T_GENERIC_END { $$ = $2; }
668+
T_GENERIC_START nested_generic_type_parameter_list T_GENERIC_END { $$ = $2; }
629669
;
630670

631671
generic_type:
@@ -896,9 +936,9 @@ type_expr_without_static:
896936

897937
//TODO add generic type params to AST
898938
type_without_static:
899-
T_ARRAY generic_type_parameters { $$ = zend_ast_create_ex(ZEND_AST_TYPE, IS_ARRAY); }
939+
T_ARRAY nested_generic_type_parameters { $$ = zend_ast_create_ex(ZEND_AST_TYPE, IS_ARRAY); }
900940
| T_CALLABLE { $$ = zend_ast_create_ex(ZEND_AST_TYPE, IS_CALLABLE); }
901-
| name generic_type_parameters { $$ = $1; }
941+
| name nested_generic_type_parameters { $$ = $1; }
902942
;
903943

904944
union_type_without_static_element:
@@ -1390,10 +1430,6 @@ backup_doc_comment:
13901430
%empty { $$ = CG(doc_comment); CG(doc_comment) = NULL; }
13911431
;
13921432

1393-
generic_param_name:
1394-
%empty { $$ = CG(doc_comment); CG(doc_comment) = NULL; }
1395-
;
1396-
13971433
backup_fn_flags:
13981434
%prec PREC_ARROW_FUNCTION %empty { $$ = CG(extra_fn_flags); CG(extra_fn_flags) = 0; }
13991435
;

t.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?php
2-
class test!🥖K!🥖!🥖bruh!🥥!🥥{
2+
class test!🥖lebruh, bruh : LELE!🥥 extends bruh {
33
public function __construct(
44
public K $lol
55
){

tree.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22
$tokens = token_get_all('<?php
33
4-
class test!🥖K!🥥{
4+
class test!🥖bruh : LELE, lebruh!🥥 {
55
public function __construct(
66
public !🥖K!🥥 $lol
77
){

0 commit comments

Comments
 (0)