tagged release 0.6.4
[parrot.git] / languages / jako / lib / Jako / Construct / Statement / Call.pm
blobf9b14b471b92b91ab36b90296bfc618e1b22cbb7
2 # Call.pm
4 # Copyright (C) 2002-2005, The Perl Foundation.
5 # This program is free software. It is subject to the same license
6 # as the Parrot interpreter.
8 # $Id$
11 use strict;
12 use warnings;
14 package Jako::Construct::Statement::Call;
16 use Carp;
18 use base qw(Jako::Construct::Statement);
20 sub new {
21 my $class = shift;
22 my ( $block, $ident, @args ) = @_;
24 confess( "Block (" . ref($block) . ") is not!" )
25 unless UNIVERSAL::isa( $block, 'Jako::Construct::Block' );
26 confess( "Ident (" . ref($ident) . ") is not!" )
27 unless UNIVERSAL::isa( $ident, 'Jako::Construct::Expression::Value::Identifier' );
29 my $name = $ident->value;
31 my $self = bless {
32 BLOCK => $block,
34 NAME => $name,
35 ARGS => [@args],
37 DEBUG => 1,
38 LINE => $ident->line,
39 FILE => $ident->file
40 }, $class;
42 $block->push_content($self);
44 return $self;
47 sub name { return shift->{NAME}; }
48 sub args { return @{ shift->{ARGS} }; }
51 # compile()
54 sub compile {
55 my $self = shift;
56 my ($compiler) = @_;
58 my $name = $self->name;
60 # $self->DEBUG(0, "Searching for symbol '$name'...");
62 my $sym = $self->block->find_symbol($name);
64 $self->SYNTAX_ERROR( "Call to unknown sub '%s'.", $name ) unless $sym;
66 my %props = $sym->props;
68 my @args = $self->args;
70 my @formal_args = $sym->args;
72 $self->SYNTAX_ERROR( "Wrong number of arguments (expected %d, got %d) in call to '%s'.",
73 scalar(@formal_args), scalar(@args), $name )
74 unless @formal_args == @args;
76 for ( my $i = 0 ; $i < @args ; $i++ ) {
77 my ( $formal_arg_type, $formal_arg_name ) = @{ $formal_args[$i] };
78 my $actual_arg_type;
80 if ( UNIVERSAL::isa( $args[$i], 'Jako::Construct::Expression::Value::Identifier' ) ) {
81 my $arg_sym = $self->block->find_symbol( $args[$i]->value );
82 $self->SYNTAX_ERROR( "Undefined identifier '%s'.", $args[$i]->value ) unless $arg_sym;
83 $actual_arg_type = $arg_sym->type;
85 else {
86 $actual_arg_type = $args[$i]->type;
89 $self->INTERNAL_ERROR( "Can't determine type of formal argument (%s)!", $formal_arg_name )
90 unless defined $formal_arg_type;
92 $self->INTERNAL_ERROR( "Can't determine type of actual argument (%s)!", ref $args[$i] )
93 unless defined $actual_arg_type;
95 if ( $formal_arg_type->name ne $actual_arg_type->name ) {
96 my $temp = $compiler->temp_reg($formal_arg_type);
97 my $value = $args[$i]->compile($compiler);
98 $compiler->emit(" $temp = $value");
99 $args[$i] = $temp;
101 else {
102 $args[$i] = $args[$i]->compile($compiler);
106 if ( exists $props{op} ) {
107 my $op = $props{op};
109 # $self->DEBUG(0, "Calling %s%s...", $name, ($op ? ' (op $op)' : ' as op'));
111 if ( defined $op ) {
112 $name = $op->value;
113 $name =~ s/(^"|"$)//g;
116 $name =~ s/^.*:://; # Strip namespaces off ops.
118 $compiler->emit( " $name ", join( ", ", @args ) );
120 else {
122 # $self->DEBUG(0, "Calling '%s' as regular or NCI sub (props = %s)...", $name, join(", ", %props));
124 $name =~ s/::/__/g;
126 if ( exists $props{fn} or exists $props{fnlib} ) {
127 $name .= "_THUNK";
130 $compiler->emit( " _${name}(" . join( ", ", @args ) . ")" );
133 return 1;
137 # sax()
140 sub sax {
141 my $self = shift;
142 my ($handler) = @_;
144 $handler->start_element( { Name => 'call', Attributes => { name => $self->name } } );
145 $_->sax($handler) foreach $self->args;
146 $handler->end_element( { Name => 'call' } );
151 # Local Variables:
152 # mode: cperl
153 # cperl-indent-level: 4
154 # fill-column: 100
155 # End:
156 # vim: expandtab shiftwidth=4: