 
 
 
 
 
 
 
 
 
 










 
$tree = Syntax::Analysis::parser; ... # otras fases ########code generation local $target = ""; # target code $tree->translate; ...
en la cadena $target dejamos el código emitido.
Cada método visita los hijos, traduciéndolos y añadiendo 
el código que fuera necesario para la traducción del nodo.
sub PROGRAM::translate {
  my $tree = shift;
  $target .= "DATA ". $data."\n" if $data;
  $tree->STS->translate;
}
Traducir la lista de sentencias es concatenar la traducción de cada una de las sentencias en la lista:
sub STATEMENTS::translate {
  my $statements = shift;
  my @statements = @{$statements};
  for my $s (@statements) {
    $s->translate;
  }
}
Si suponemos que disponemos en el ensamblador de nuestra máquina
objeto de instrucciones PRINT_INT  y PRINT_STR
que imprimen el contenido 
de la expresión que esta en la cima de la pila, la traducción será:
sub PRINT::translate {
  my $self = shift;
  $self->EXPRESSION->translate;
  if ($self->EXPRESSION->TYPE == $int_type) { emit "PRINT_INT\n"; }
  else {emit "PRINT_STR\n"; }
}
Asi, si la sentencia era P c, donde c es del tipo cadena, 
se debería eventualmente llamar al método de traducción del identificador:
sub ID::translate {
  my $self = shift;
  my $id = $self->VAL;
  my $type =  Semantic::Analysis::get_type($id);
  if ($type == $int_type) {
    emit "LOAD ".$symbol_table{$id}->{ADDRESS}."\n";
  }
  else {
    emit "LOAD_STRING ".$symbol_table{$id}->{ADDRESS}."\n";
  }
}
la función emit simplemente concatena el código 
producido a la salida:
sub emit { $target .= shift; }
Para la traducción de una sentencia de asignación
supondremos de la existencia de isntrucciones STORE_INT
y STORE_STRING. La instrucción STORE_STRING asume 
que en la cima de la pila están la dirección y la cadena a almacenar.
sub ASSIGN::translate {
  my $self = shift;
  $self->RIGHT->translate;
  my $id = $self->LEFT;
  $id->translate;
  my $type =  Semantic::Analysis::get_type($id->VAL);
  if ($type == $int_type) {
    emit "STORE_INT\n";
  }
  else {
    emit "STORE_STRING\n";
  }
}
Si se está traduciendo una sentencia como a = "hola",
se acabará llamando al método 
de traducción asociado con la clase STR
el cual actúa empujando la dirección y la longitud de la cadena en
la pila:
sub STR::translate {
  my $self = shift;
  emit "PUSHSTR ".$self->OFFSET." ".$self->LENGTH."\n";
}
Así la traducción de este fuente:
$ cat test06.tutu string a; a = "hola"; p a
es:
$ ./main.pl test06.tutu test06.ok $ cat test06.ok DATA 2, hola PUSHSTR 2 4 PUSHADDR 0 STORE_STRING LOAD_STRING 0 PRINT_STR
El resto de los métodos de traducción es similar:
sub LEFTVALUE::translate {
  my $id = shift ->VAL;
  emit "PUSHADDR ".$symbol_table{$id}->{ADDRESS}."\n";
}
sub NUM::translate {
  my $self = shift;
  emit "PUSH ".$self->VAL."\n";
}
sub PLUS::translate {
  my $self = shift;
  $self->LEFT->translate;
  $self->RIGHT->translate;
  emit "PLUS\n";
}
sub TIMES::translate {
  my $self = shift;
  $self->LEFT->translate;
  $self->RIGHT->translate;
  emit "MULT\n";
}
Veamos un ejemplo. Dado el código fuente:
$ cat test02.tutu int a,b; string c; a = 2+3; b = 3*4; c = "hola"; p c; c = "mundo"; p c; p 9+2; p a+1; p b+1el código generado es:
$ ./main.pl test02.tutu test02.ok $ cat test02.ok DATA 4, holamundo PUSH 5 PUSHADDR 0 STORE_INT PUSH 12 PUSHADDR 1 STORE_INT PUSHSTR 4 4 PUSHADDR 2 STORE_STRING LOAD_STRING 2 PRINT_STR PUSHSTR 8 5 PUSHADDR 2 STORE_STRING LOAD_STRING 2 PRINT_STR PUSH 11 PRINT_INT LOAD 0 INC PRINT_INT LOAD 1 INC PRINT_INT
 
 
 
 
 
 
 
 
 
 










