use Parrot::Vtable;
use strict;

my %vtable = parse_vtable();


while (<DATA>) {
    next if /^#/ or /^$/;

    my ($n, $op, $vtable_entry) =  split;    
    my $vtable_entry = $vtable_entry || $op;
    
    die "Can't find $vtable_entry in vtable, line $.\n"
        unless exists $vtable{$vtable_entry};
    
    my $type = $vtable{$vtable_entry}{meth_type};
    
    if ($type eq "unique") {
        print opblock($n, $op, $vtable_entry, "p");       
    } 
    elsif ($type eq "num") {    
        print opblock($n, $op, $vtable_entry, "p");
        print opblock($n, $op, $vtable_entry, "i|ic", "int");
        print opblock($n, $op, $vtable_entry, "n|nc", "float");
    } 
    elsif ($type eq "str") {
        print opblock($n, $op, $vtable_entry, "p", "");      
    }
    else { "Coding error - undefined type $type\n"; }
}

sub opblock {
    my ($n, $op, $vtable_entry, $register_type, $expanded_type) = @_;    
    my ($params, $metparams);
            
    if ($n == 3) {
       # Three-address function
       $params = "p, p, $register_type";
       $metparams = '$2,$3,$1';       
    
    } 
    elsif ($n == 2) {
        # Unary function
        $params = "p, p";
        $metparams = '$2,$1';
    }            
    
    $expanded_type = "_" . $expanded_type if $expanded_type;
    
    return <<EOO;
AUTO_OP $op ($params) {
   (\$2->vtable->$vtable_entry$expanded_type)(interpreter, $metparams);
}

EOO
} 

__DATA__
# Three-address functions
3 add
3 sub subtract
3 mul multiply
3 div divide
3 mod modulus
3 concat concatenate
3 and logical_and
3 or logical_or
# Unary functions
2 not logical_not
