next up previous contents index PLPL moodlepserratamodulosperlmonksperldocapuntes LHPgoogleetsiiullpcgull
Sig: Comprobación de Tipos: Sentencia Sup: Análisis de Tipos Ant: Comprobación de Tipos: Sentencias Err: Si hallas una errata ...


Comprobación de Tipos: Llamadas a Funciones

Guía de Ruta para la Comprobación de Tipos de las LLamadas

La comprobación de tipos en una llamada a función conlleva los siguientes pasos:

  1. Líneas 4 y 5: comprobamos que la variable que se usa en la llamada fue efectivamente declarada como función
  2. Línea 14: El número de argumentos y el número de parámetros declarados debe coincidir
  3. En las líneas de la 19 a la 35 analizamos la compatibilidad de tipo de cada uno de los argumentos con su correspondiente parámetro:
    1. En la línea 21 se obtiene el nodo correspondiente al argumento. Si es necesario se harán las coherciones (líneas 22 y 23)
    2. En la línea 25 comprobamos la compatibilidad de tipos. En el caso de los arrays la compatibilidad no se limita a la igualdad de referencias: consideraremos compatibles arrays que difieren en la primera dimensión. Así las declaraciones int a[10][20] y int b[5][20] se considerarán compatibles pero int c[10][10] y int d[10][20] no.

La forma del Árbol de las LLamadas

La siguiente sesión con el depurador ilustra la forma del árbol de análisis en las llamadas:

pl@nereida:~/Lbook/code/Simple-Types/script$ perl -wd usetypes.pl prueba23.c 2
main::(usetypes.pl:5):  my $filename = shift || die "Usage:\n$0 file.c\n";
  DB<1> f Types.eyp
1       2       3       4       5       6       7       #line 8 "Types.eyp"
8
9:      use strict;
10:     use Carp;
  DB<2> c 598
 1 int f(char a[10], int b) {
 2   return a[5];
 3 }
 4
 5 int h(int x) {
 6   return x*2;
 7 }
 8
 9 int g() {
10   char x[5];
11   int y[19][30];
12   f(x,h(y[1][1]));
13 }
Simple::Types::compile(Types.eyp:598):
598:     set_types($t);        # Init basic types
Ejecutamos hasta la línea 598, justo después de terminar el análisis de ámbito y antes de comenzar con la fase de comprobación de tipos.

A continuación mostramos una versión compacta del árbol. Para ello suprimimos la salida de notas a pie de página ''vaciando'' el método footnotes:

  DB<3> insert_method(qw{PROGRAM FUNCTION}, 'footnote', sub {}) # Avoid footnotes
  DB<4> p $t->str
PROGRAM(
  FUNCTION[f](RETURN(VARARRAY(TERMINAL[a:2],INDEXSPEC(INUM(TERMINAL[5:2]))))),
  FUNCTION[h](RETURN(TIMES(VAR(TERMINAL[x:6]),INUM(TERMINAL[2:6])))),
  FUNCTION[g](
    FUNCTIONCALL(
      TERMINAL[f:12],
      ARGLIST(
        VAR(TERMINAL[x:12]),
        FUNCTIONCALL(
          TERMINAL[h:12],
          ARGLIST(VARARRAY(TERMINAL[y:12],INDEXSPEC(INUM(TERMINAL[1:12]),INUM(TERMINAL[1:12]))))
)))))
  DB<6> p $t->descendant(".2.0")->str
FUNCTIONCALL(
  TERMINAL[f:12],
  ARGLIST(
    VAR(TERMINAL[x:12]),
    FUNCTIONCALL(
      TERMINAL[h:12],
      ARGLIST(VARARRAY(TERMINAL[y:12],INDEXSPEC(INUM(TERMINAL[1:12]),INUM(TERMINAL[1:12])))))))
  DB<7> p $t->descendant(".2.0")->{t}->str
F(X_2(A_10(CHAR),INT),INT)

La sesión ilustra como la función insert_method puede ser utilizada para introducir métodos en las clases influyendo en la presentación del árbol. Veamos un segundo ejemplo en el que eliminamos la presentación de la información asociada con los nodos:

  DB<8> insert_method(qw{FUNCTION TERMINAL}, 'info', sub {})
  DB<9> x $t->str
0  'PROGRAM(
      FUNCTION(RETURN(VARARRAY(TERMINAL,INDEXSPEC(INUM(TERMINAL))))),
      FUNCTION(RETURN(TIMES(VAR(TERMINAL),INUM(TERMINAL)))),
      FUNCTION(
        FUNCTIONCALL(TERMINAL,ARGLIST(VAR(TERMINAL),i
          FUNCTIONCALL(
            TERMINAL,
            ARGLIST(VARARRAY(TERMINAL,INDEXSPEC(INUM(TERMINAL),INUM(TERMINAL)))))))))'

Código de Comprobación de las LLamadas

Sigue el código de comprobación de tipos de las llamadas:

pl@nereida:~/doc/casiano/PLBOOK/PLBOOK/code/Simple-Types/lib/Simple$ \
                           sed -ne '/^func/,234p' Trans.trg | cat -n
 1  functioncall: FUNCTIONCALL($f, ARGLIST)
 2    => {
 3      # Before type checking attribute "t" has the declaration of $f
 4      my $ftype = $FUNCTIONCALL->{t};
 5
 6       type_error(" Variable '".$f->value."' was not declared as function", $f->line)
 7      unless $ftype->isa("F");
 8
 9      my @partypes = $ftype->child(0)->children;
10
11      my @args = $ARGLIST->children;    # actual arguments
12      my $numargs = @args;    # Number of actual arguments
13      my $numpar = @partypes; # Number of declared parameters
14
15      # Check number of args
16        type_error("Function '".$f->value."' called with $numargs args expected $numpar",$f->line)
17      if ($numargs != $numpar);
18
19      # Check type compatibility between args
20      # Do type cohercion if needed
21      for (0..$#args) {
22        my $pt = shift @partypes;
23        my $ch = $ARGLIST->child($_);
24        $ch = char2int($ARGLIST, $_) if $pt == $INT;
25        $ch = int2char($ARGLIST, $_) if $pt == $CHAR;
26
27        my $cht = $ch->{t};
28        unless (array_compatible($cht, $pt)) {
29          type_error(
30            "Type of argument " .($_+1)." in call to " .$f->value." differs from expected",
31            $f->line
32          )
33        }
34      }
35
36      # Now attribute "t" has the type of the node
37      $FUNCTIONCALL->{t} = $ftype->child(1);
38      return 1;
39    }

Arrays que Difieren en la Primera Dimensión

La función array_compatible sigue la costumbre C de considerar compatibles arrays que difieren en la primera dimensión. Véase la conducta de gcc al respecto:

pl@nereida:~/Lbook/code/Simple-Types/script$ cat -n ArrayChecking.c
     1  #include <stdio.h>
     2
     3  void f(int a[3][3]) {
     4    a[1][2] = 5;
     5  }
     6
     7  main() {
     8    int b[2][3];
     9    f(b);
    10    printf("%d\n",b[1][2]);
    11  }
pl@nereida:~/Lbook/code/Simple-Types/script$ gcc ArrayChecking.c
pl@nereida:~/Lbook/code/Simple-Types/script$ a.out
5

Recordemos el código de la función array_compatible:

pl@nereida:~/doc/casiano/PLBOOK/PLBOOK/code/Simple-Types/lib/Simple$ sed -ne '96,124p' Trans.trg | cat -n
 1  { # support for arrays
 2
 3    sub compute_dimensionality {
..      .......................................................
14    }
15
16    sub is_array {
..      ....................................
20    }
21
22    sub array_compatible {
23      my ($a1, $a2) = @_;
24
25      return 1 if $a1 == $a2;
26      # int a[10][20] and int b[5][20] are considered compatibles
27      return (is_array($a1) && is_array($a2) && ($a1->child(0) == $a2->child(0)));
28    }
29  }

Ejemplos

pl@nereida:~/Lbook/code/Simple-Types/script$ usetypes.pl prueba07.c 2
 1 int a,b,e[10][20];
 2
 3 g() {}
 4
 5 int f(char c) {
 6 char d;
 7  c = 'X';
 8  g(e[d], 'A'+c);
 9  if (c > 0) {
10    int d;
11    d = a + b;
12  }
13  c = d * 2;
14  return c;
15 }
16
Type Error at line 8: Function 'g' called with 2 args expected 0

pl@nereida:~/Lbook/code/Simple-Types/script$ usetypes.pl prueba22.c 2
 1 int f(char a[10], int b) {
 2   return a[5];
 3 }
 4
 5 int h(int x) {
 6   return x*2;
 7 }
 8
 9 int g() {
10   char x[5];
11   int y[19][30];
12   f(x,h(y));
13 }
Type Error at line 12: Type of argument 1 in call to h differs from expected



Subsecciones
next up previous contents index PLPL moodlepserratamodulosperlmonksperldocapuntes LHPgoogleetsiiullpcgull
Sig: Comprobación de Tipos: Sentencia Sup: Análisis de Tipos Ant: Comprobación de Tipos: Sentencias Err: Si hallas una errata ...
Casiano Rodríguez León
2012-05-22