Skip to content

Collections #15429

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 48 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
31167bb
Collection: Add Token
derickr May 12, 2023
93c8497
Collection: Add Parser Rules
derickr May 12, 2023
1babb8c
Collection: Add AST Code
derickr May 12, 2023
1e6faf2
Collection: Clean Up Class Entry
derickr May 12, 2023
4b8fce9
Collection: Init and Storage
derickr May 12, 2023
982c297
Collection: Add test file
derickr May 12, 2023
1c4bb90
Collection: Add Interface
derickr May 12, 2023
84bf653
Collection: Add Write Handler
derickr May 12, 2023
56c4223
Collection: Make Check Type Public
derickr May 12, 2023
f845b94
Collection: Add Read Handler
derickr May 12, 2023
91e1ddc
Collection: Add Has Handler
derickr May 12, 2023
6d695b1
Collection: Add Unset Handler
derickr May 12, 2023
19c22ce
Collection: Add more tests
derickr May 4, 2023
97b0f82
Add 'collection' name for AST output
derickr May 5, 2023
546a89f
Split up collection syntax into collection(Seq|Dict)
derickr Jun 22, 2023
e7815be
Separated interfaces into SeqCollection and DictCollection
derickr Jun 22, 2023
41df61d
Add Seq::add and Dict:add functions
derickr Jun 22, 2023
c2084d3
Test for type checking against generic collection types.
Crell Jun 23, 2023
48d5e71
Add a representative sample of additional operations.
Crell Jun 24, 2023
7958ca1
Add tests for the sample operations. These will not pass yet, naturally.
Crell Jun 24, 2023
ac6e449
Comment out unimplemented functions
derickr Jun 26, 2023
1493f6b
Rename test file with logical names
derickr Jun 26, 2023
6c844dc
Mark tests as XFAIL
derickr Jun 26, 2023
052885d
Macro-ify function registration
derickr Jun 26, 2023
b7031ca
Implement Sequence' remove/has/get
derickr Jun 27, 2023
1c06826
Implement sequence 'update/with/without' functions
derickr Jun 28, 2023
1ff66ab
Implement dict 'remove/has/get/update/with/without' functions
derickr Jun 28, 2023
5128b48
Better error messages and more tests for unhappy paths
derickr Jun 30, 2023
ad6cbfc
Change syntax to: collection(Variant) name<<K => T>>
derickr Jun 30, 2023
41eabba
Use two seperate tokens so we can have a 'Collection' class again
derickr Jul 11, 2023
9ef908e
Implement Sequence::map()
derickr Jul 17, 2023
cf2b4c9
Change syntax to: collection(Variant) name<K => T>
derickr Jul 17, 2023
2ea005b
Implement Dictionary::map()
derickr Jul 18, 2023
3133071
Add new tokens to tokenizer extension
derickr Jul 28, 2023
ec42167
Simplify scanner as there can't be a classname with () in it anyway
derickr Jul 28, 2023
0beda3c
Implement Sequence::concat()
derickr Jul 31, 2023
ad90408
Implement Dictionary::concat()
derickr Jul 31, 2023
db2616d
Remove superfluous and wrong code
derickr Aug 7, 2023
de78df6
Implement Sequence::equals()
derickr Aug 7, 2023
93e95e3
Implement Sequence's compare_objects handler
derickr Aug 7, 2023
91d6fbc
Fixed segfault when value wasn't an object
derickr Aug 8, 2023
9b6ba6a
Implement Dictionary::equals() and comparison handler
derickr Aug 8, 2023
7128fff
Add short cut for comparisons if both objects are identical
derickr Aug 8, 2023
3ba4b11
Add test case to compare Seq with Dict
derickr Aug 8, 2023
d5c03b9
Implement Sequence::+ and Sequence::+= operators
derickr Aug 14, 2023
874d099
Renumber indexes in Sequence collections when an item is removed
derickr Aug 8, 2023
383b3e1
Fixed invocation for zend_compile_typename
derickr Jun 3, 2024
4693f3b
Add extra test file
derickr Jun 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions Zend/tests/collection/collection_dict_basic.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
--TEST--
Collection: Dictionary
--FILE--
<?php
class Article
{
function __construct(public string $title)
{
}
}

collection(Dict) Articles<string => Article>
{
}

$c = new Articles;
$c["nine"] = new Article("First Test");
$c["ten"] = new Article("Second Test");
$c->add("seven", new Article("Third Test"));

var_dump($c);

var_dump(isset($c["eight"]));
var_dump(isset($c["nine"]));
var_dump(isset($c["ten"]));

var_dump($c["nine"]);

unset($c["nine"]);
var_dump(isset($c["nine"]));

try {
var_dump(isset($c[11]));
} catch (Error $e) {
echo get_class($e), ': ', $e->getMessage(), "\n";
}
?>
--EXPECTF--
object(Articles)#%d (%d) {
["value"]=>
array(3) {
["nine"]=>
object(Article)#%d (%d) {
["title"]=>
string(10) "First Test"
}
["ten"]=>
object(Article)#%d (%d) {
["title"]=>
string(11) "Second Test"
}
["seven"]=>
object(Article)#%d (%d) {
["title"]=>
string(10) "Third Test"
}
}
}
bool(false)
bool(true)
bool(true)
object(Article)#%d (%d) {
["title"]=>
string(10) "First Test"
}
bool(false)
TypeError: Key type int of element does not match Articles dictionary key type string
82 changes: 82 additions & 0 deletions Zend/tests/collection/collection_dict_concat-errors.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
--TEST--
Collection: Dictionary: Concat Errors
--FILE--
<?php

class Book {
public function __construct(public string $title) {}
}
class DutchBook extends Book {}

class Article {
public function __construct(public string $subject) {}
}

collection(Dict) Books<string => Book> {}
collection(Dict) YBooks<int => Book> {}
collection(Dict) DutchBooks<string => DutchBook> {}
collection(Dict) Articles<string => Article> {}

$c1 = new Books();
$c1->add("one", new Book('Title 1'));
$c1->add("two", new Book('Title 2'));

$y1 = new YBooks();
$y1->add(1970, new Book('Title 1'));
$y1->add(1971, new Book('Title 2'));

$d1 = new DutchBooks();
$d1->add("één", new DutchBook('Titel 1'));
$d1->add("twee", new DutchBook('Titel 2'));

$a2 = new Articles();
$a2->add("three", new Article('Subject 1'));
$a2->add("four", new Article('Subject 2'));

try {
$c1->concat(new Book('Title E'));
} catch (TypeError $e) {
echo get_class($e), ': ', $e->getMessage(), "\n";
}

try {
$c1->concat($a2);
} catch (TypeError $e) {
echo get_class($e), ': ', $e->getMessage(), "\n";
}

try {
$cr = $c1->concat($d1);
echo "Inheritence: OK\n";
} catch (TypeError $e) {
echo get_class($e), ': ', $e->getMessage(), "\n";
}

try {
$cr = $d1->concat($c1);
} catch (TypeError $e) {
echo get_class($e), ': ', $e->getMessage(), "\n";
}

try {
$why = $c1->concat($y1);
var_dump( $why );
} catch (TypeError $e) {
echo get_class($e), ': ', $e->getMessage(), "\n";
}

try {
$why = $y1->concat($c1);
var_dump( $why );
} catch (TypeError $e) {
echo get_class($e), ': ', $e->getMessage(), "\n";
}

?>
--EXPECT--
TypeError: Books::concat(): Argument #1 ($other) must be of type DictCollection, Book given
TypeError: Value type Books does not match Article collection item type Book
Inheritence: OK
TypeError: Value type DutchBooks does not match Book collection item type DutchBook
TypeError: Key type int of element does not match Books dictionary key type string
TypeError: Key type string of element does not match YBooks dictionary key type int
70 changes: 70 additions & 0 deletions Zend/tests/collection/collection_dict_concat_idx.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
--TEST--
Collection: Dictionary: Concat (int key)
--FILE--
<?php

class Book {
public function __construct(public string $title) {}
}

collection(Dict) Books<int => Book> {}

$c1 = new Books();
$c2 = new Books();

$c1->add(41, new Book('Title 1'));
$c1->add(42, new Book('Title 2'));

$c2->add(43, new Book('Title 3'));
$c2->add(44, new Book('Title 4'));

$c3 = $c1->concat($c2);

// Four items.
var_dump($c3);

// Still two items.
var_dump($c1);

?>
--EXPECTF--
object(Books)#%d (1) {
["value"]=>
array(4) {
[41]=>
object(Book)#%d (1) {
["title"]=>
string(7) "Title 1"
}
[42]=>
object(Book)#%d (1) {
["title"]=>
string(7) "Title 2"
}
[43]=>
object(Book)#%d (1) {
["title"]=>
string(7) "Title 3"
}
[44]=>
object(Book)#%d (1) {
["title"]=>
string(7) "Title 4"
}
}
}
object(Books)#%d (1) {
["value"]=>
array(2) {
[41]=>
object(Book)#%d (1) {
["title"]=>
string(7) "Title 1"
}
[42]=>
object(Book)#%d (1) {
["title"]=>
string(7) "Title 2"
}
}
}
70 changes: 70 additions & 0 deletions Zend/tests/collection/collection_dict_concat_key.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
--TEST--
Collection: Dictionary: Concat (string key)
--FILE--
<?php

class Book {
public function __construct(public string $title) {}
}

collection(Dict) Books<string => Book> {}

$c1 = new Books();
$c2 = new Books();

$c1->add('one', new Book('Title 1'));
$c1->add('two', new Book('Title 2'));

$c2->add('three', new Book('Title 3'));
$c2->add('four', new Book('Title 4'));

$c3 = $c1->concat($c2);

// Four items.
var_dump($c3);

// Still two items.
var_dump($c1);

?>
--EXPECTF--
object(Books)#%d (1) {
["value"]=>
array(4) {
["one"]=>
object(Book)#%d (1) {
["title"]=>
string(7) "Title 1"
}
["two"]=>
object(Book)#%d (1) {
["title"]=>
string(7) "Title 2"
}
["three"]=>
object(Book)#%d (1) {
["title"]=>
string(7) "Title 3"
}
["four"]=>
object(Book)#%d (1) {
["title"]=>
string(7) "Title 4"
}
}
}
object(Books)#%d (1) {
["value"]=>
array(2) {
["one"]=>
object(Book)#%d (1) {
["title"]=>
string(7) "Title 1"
}
["two"]=>
object(Book)#%d (1) {
["title"]=>
string(7) "Title 2"
}
}
}
95 changes: 95 additions & 0 deletions Zend/tests/collection/collection_dict_equality.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
--TEST--
Collection: Dictionary: Equals
--FILE--
<?php

class Book {
public function __construct(public string $title) {}
}

collection(Dict) Books<string => Book> {}
collection(Dict) BooksOther<string => Book> {}
collection(Dict) YearBooks<int => Book> {}

$c1 = new Books();
$c1->add('one', new Book('Title 1'));
$c1->add('two', new Book('Title 2'));

$c2 = new Books();
$c2->add('one', new Book('Title 1'));
$c2->add('two', new Book('Title 2'));

$c3 = new Books();
$c3->add('one', new Book('Title 1'));
$c3->add('two', new Book('Title 2'));
$c3->add('tri', new Book('Title 3'));

$c4 = new Books();
$c4->add('one', new Book('Title 1'));
$c4->add('XXX', new Book('Title X'));
$c4->add('two', new Book('Title 2'));

$c5 = new Books();
$c5->add('one', new Book('Title 1'));
$c5->add('two', new Book('Title X'));
$c5->add('tri', new Book('Title 2'));

$c6 = new Books();
$c6->add('one', new Book('Title 1'));
$c6->add('XXX', new Book('Title 2'));
$c6->add('tri', new Book('Title 3'));

$c7 = new BooksOther();
$c7->add('one', new Book('Title 1'));
$c7->add('two', new Book('Title 2'));

$c8 = new YearBooks();
$c8->add(1970, new Book('Title 1'));
$c8->add(1971, new Book('Title 2'));

$c9 = new Books();
$c9->add('two', new Book('Title 2'));
$c9->add('one', new Book('Title 1'));


// True
var_dump($c1->equals($c1));
var_dump($c1->equals($c2));
var_dump($c1->equals($c7));
var_dump($c1->equals($c9));

$c2['tri'] = new Book('Title 3');

var_dump($c2->equals($c3));

// False
var_dump($c1->equals($c2));
var_dump($c1->equals($c8));
var_dump($c3->equals($c4));
var_dump($c3->equals($c5));
var_dump($c3->equals($c6));

unset($c4['XXX']);

// True
var_dump($c1->equals($c4));

unset($c6['XXX']);
$c6['two'] = new Book('Title 2');

// True
var_dump($c3->equals($c6));
?>
--EXPECTF--
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(true)
bool(true)
Loading
Loading