Am Mittwoch, 27. September 2006 01:44 schrieb Allison Randal: > I've committed an updated I/O PDD. I'm close to pronouncing this ready > to implement, so get in your comments now.
I/O Stream Opcodes I really don't like opcodes, when dealing with I/O. 1) opcodes are needed for native int or float - these are nicely JITtable 2) opcodes with PMCs usually call a vtable function that provides necessary virtualization/abstraction: set S0, P0[10] # VTABLE_get_string_keyed_int If a particular PMC doesn't support the vtable function an exception is thrown. Now compare this with an I/O opcode: read S0, P0, 10 # PIO_reads(... P0 ...) If P0 isn't a ParrotIO opcode, this segfaults. See t/pmc/io_1.pir. While we could of course check, what type P0 is, such a check would be needed for every IO opcode. (And see below) 3) opcodes don't work with inheritance, unless a vtable (or method) is provided. subclass P1, 'Array', 'MyArray' new P0, 'MyArray' set S0, P0[10] # VTABLE_get_string_keyed_int The vtable still works, and possibly calls a '__get_string_keyed_int' method, if the 'MyArray' class provides one. But: subclass P1, 'ParrotIO', ['HTTP'; 'Daemon'; 'ClientConn'] ... read S0, P0, 10 # P0 be a ClientConn now Given this, we would have to modify the mentioned check, to also deal with subclasses of 'ParrotIO'. And worse, the IO opcode would need some knowledge about the subclassed ParrotIO to extract the raw PIO structure to carry on with the IO PIO_reads function call. This either violates encapsulation or would need another interface to deal with it. 4) Then we should call a method from the opcode? op read(out STR, invar PMC, in INT) { STRING *meth = Parrot_find_method_with_cache(...) if !(meth) { # error handling } $1 = Parrot_run_meth_fromc_args(...); # or alternatively # emulate set_args # emulate get_results pc = VTABLE_invoke(...) ... } That is, we'd re-implement the 'callmethodcc' opcode for every IO opcode, without any further improvement. Just the opposite. We would add code duplication, and we'd possibly add a Continuation barrier by adding this indirection. 5) I/O layers When we look at ParrotIO as an object with methods, the layering boils down to simple inheritance. Adding a layer is just a subclass operations, where some methods are overridden. All the extra code that deals with layers is likely unnecessary then. Or IOW the I/O layer models mimicks some class functionality, which should better be done by existing class code. 6) Sockets Currently the socket API is part of the PIO virtual function table. This is suboptimal, as the socket API is exposed to non-socket PIOs as well. ParrotSocket isa ParrotIO BufferedIO isa ParrotIO ... or some such would be a better choice. The Perl5 equivalences are probably a good model for this. > Allison my 2c, leo