Una vez que corrieron las 4 pasadas tenemos en memoria:
- Todo el codigo fuente necesario para compilar el programa
- Todo el codigo tokenizado
- La indicacion de los bloques
- El diccionario lleno con el total de definiciones e informacion adicional de cada palabra.
La generacion del codigo se divide en dos partes, la definicion de datos y la compilacion de codigo:
La definicion de datos:
Fuente:
Este palabra recorre dos veces el diccionario:
primero todas las palabras que son codigo y que tienen llamadas (que son usadas), se buscan los string constantes y se les asigna un numero consecutivo
por ejemplo:
:decirhola "hola" print ;
Si esta palabra es usada, el string "hola" sera generado en la definicion de datos como
Como el recorrido en la generacion de codigo es unico, el valor asignado sera el correcto cuando se compile,en, por ejemplo:
Una vez que se generaron todos los strings, se procede al segundo recorrido del diccionario.
Tomando solamente las variables que tengan llamadas y que no sean constantes (se haya usado su direccion)
por ejemplo
genera la siguiente definicion
Notar aqui que las palabras son reemplazadas por W+nro de palabra, esto evita los caracteres ilegales para el ensamblador, en este caso el FASM.
Aqui esta construida la logica de las difirentes formas de generar datos, por ejemplo el * que reserva lugares
genera
Esta etapa no es especialmente complicada, y la mayoria de los compiladores construidos para r4 utilizan casi el mismo codigo.
Hago una especial indicacion que esta familia de lenguajes recomienda utilizar el mapa de memoria que se genera en el codigo y por lo tanto no modifica la posicion de las variables, con esto es posible saber que una direccion de variable puede ser limite de otra y cosas por el estilo.
Por lo tanto no se alinea la memoria entre variables ni se reordena.