next up previous contents index PLPL moodlepserratamodulosperlmonksperldocapuntes LHPgoogleetsiiullpcgull
Sig: Práctica: Cálculo de las Sup: La Estructura de los Ant: Práctica: Casando y Transformando Err: Si hallas una errata ...

Asignación de Direcciones

Esta suele ser considerada la primera de las fases de síntesis. Las anteriores lo eran de análisis. La fase de análisis es una transformación $ texto\ fuente \rightarrow arbol$ , mientras que la fase síntesis es una transformación inversa $ arbol \rightarrow texto\ objeto$ que produce una ``linealización'' del árbol. En general, se ubican en la fase de síntesis todas las tareas que dependan del lenguaje objeto.

La asignación de direcciones depende de la máquina objetivo en cuanto conlleva consideraciones sobre la longitud de palabra, las unidades de memoria direccionables, la compactación de objetos pequeños (por ejemplo, valores lógicos), el alineamiento a fronteras de palabra, etc.

En nuestro caso debemos distinguir entre las cadenas y las variables enteras.

Las constantes literales (como "hola") se almacenan concatenadas en orden de aparición textual. Una variable de tipo cadena ocupa dos palabras, una dando su dirección y otra dando su longitud.

sub factor() {
  my ($e, $id, $str, $num);

  if ($lookahead eq 'NUM') { ... }
  elsif ($lookahead eq 'ID') { ... }
  elsif ($lookahead eq 'STR') {
    $str = $value;
    my ($offset, $length) = Address::Assignment::str($str);
    match('STR');
    return STR->new(OFFSET => $offset, LENGTH => $length, TYPE => $string_type);
  }
  elsif ($lookahead eq '(') { ... }
  else { Error::fatal("Se esperaba (, NUM o ID"); }
}

El código de la subrutina Address::Assignment::str es:

  sub str {
    my $str = shift;
    my $len = length($str);
    my $offset = length($data);
    $data .= $str;
    return ($offset, $len);
  }
Una posible mejora es la que se describe en el punto 2 de la práctica 4.13.1.

Hemos supuesto que las variables enteras y las referencias ocupan una palabra. Cada vez que una variable es declarada, se le computa su dirección relativa:

# declaration -> type idlist
# type        -> INT | STRING
sub declaration() {
  my ($t, $decl, @il);

  if (($lookahead eq 'INT') or ($lookahead eq 'STRING')) {
    $t = &type(); @il = &idlist();
    &Semantic::Analysis::set_types($t, @il);
    &Address::Assignment::compute_address($t, @il);
    $decl = [$t, \@il];
    return bless $decl, 'DECL';
  }
  else { Error::fatal('Se esperaba un tipo'); }
}

Se usa una variable $global_address para llevar la cuenta de la última dirección utilizada y se introduce un atributo ADDRESS en la tabla de símbolos:

  sub compute_address {
    my $type = shift;
    my @id_list = @_;

    for my $i (@id_list) {
      $symbol_table{$i}->{ADDRESS} = $global_address;
      $global_address += $type->LENGTH;
    }
  }

Por último situamos todas las cadenas después de las variables del programa fuente:

  ... 
  ##### En compile, despues de haber calculado las direcciones
  Tree::Transform::match_and_transform_list(
    NODES => $tree->{STS},
    PATTERN => sub { 
      $_[0]->isa('STR')
    },
    ACTION => sub { $_[0]->{OFFSET} += $global_address; }
  );

Esta aproximación es bastante simplista en cuanto que usa una palabra por carácter. El punto 3 de la práctica 4.13.1 propone una mejora.



Subsecciones
next up previous contents index PLPL moodlepserratamodulosperlmonksperldocapuntes LHPgoogleetsiiullpcgull
Sig: Práctica: Cálculo de las Sup: La Estructura de los Ant: Práctica: Casando y Transformando Err: Si hallas una errata ...
Casiano Rodríguez León
2012-05-22