Hi All. I am working on adding fully dynamic arrays to SourcePawn. I have three proposals in flight, and I would be grateful to get your input on them.
Overall Feature
In all three proposals, the following type of code will be possible:
PHP Code:
new array[]; // New resizable array of length 0.
array += [1]; // Add an element to the array.
new value = array.pop(); // Get 1 back.
Resizing an array with a constant size would not work. In all proposals, you can create global, dynamic arrays, resize them, assign them, etc. In all proposals, some amount of garbage collection is required. In all proposals, arrays passed to functions are still passed by-reference.
Proposal 1: Arrays are references
In this proposal, we would break existing copy semantics. All arrays in Pawn would be treated as references, and you could pass them anywhere, a lot like pointers in Java or C.
PHP Code:
new Float:a[3] = {0.0, 1.0, 2.0};
new Float:b[3] = {4.0, 5.0, 6.0};
a = b;
a[0] = 10.0;
// b[0] is now 10.0!
Currently in Pawn, the final assignment only changes
a. In this proposal, it would change
b as well, because
a was changed to point to
b.
Pros: Easy to implement, consistent behavior, makes sense for objects/structs/2D arrays. Assignment is fast.
Cons: Makes all 1D array creation much slower unless we implement analyses or excellent garbage collection to mitigate that.
Proposal 2: Arrays are values
In this proposal, we would preserve existing copy semantics. All arrays in Pawn would be treated as values, and assigning one array to another would fully copy its contents.
PHP Code:
new g_Players[];
MakePlayerList() {
new players[];
for (new i = 1; i <= MaxClients; i++) {
if (IsClientInGame(i))
players += [i];
}
g_Players = players;
In this example, the final assignment would copy the contents of
players into
g_Players, and changing one would not affect the other.
Pros: Preserves existing semantics, consistent behavior. 1D array creation does not need fancy internal magic to be fast.
Cons: Assigning an array anywhere becomes an expensive, unbounded copy. 2D+ arrays become extremely expensive to move around.
Proposal 3: Hybrid
In this proposal, we would try to capture the best of both worlds. Arrays with a constant size would continue to act as values, as in proposal 2. However, a new kind of reference array could be declared with:
PHP Code:
new g_Players[*];
MakePlayerList() {
new players[*];
for (new i = 1; i <= MaxClients; i++) {
if (IsClientInGame(i))
players += [i];
}
g_Players = players;
This creates the subtle difference that the new syntax would be needed to move references around:
PHP Code:
new String:dictionary[*][*];
Fill(String:dictionary[][], const String:str[]) {
dictionary += [str]; // Illegal!
}
Fill(String:dictionary[*][*], const String:str[]) {
dictionary += [str]; // Illegal!
}
Fill(String:dictionary[][], const String:str[*]) {
dictionary += [str]; // Illegal!
}
// This one works!
Fill(String:dictionary[*][*], const String:str[*]) {
dictionary += [str];
}
However, you could still pass them around as "normal" arrays, including into functions which expect non-dynamic arrays. Just assignment would not work (as it does not now).
Pros: Best of both worlds, fine-grained performance control.
Cons: Requires the programmer to understand the difference between reference and value arrays.
__________________