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

Reply via email to