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.