Último mensaje de la página anterior:
Elurdio escribió:···El número se ha de dar en el momento de la compilación, de ahí el uso de los corchetes. No se puede usar ningún número que estuviera en la pila antes de empezar la definición de una palabra, pues el JA usa un sistema de comprobación que no lo permite (el JA comprueba que la pila queda igual al final de la compilación que antes, si no es así, da error #5)···
Explico en detalle las comprobaciones que hace el JA si usamos palabras compilantes "primitivas" (DO/LOOP, BEGIN/UNTIL, etc.) cuando definimos una nueva palabra:
Veámoslo con un ejemplo:
Supongamos que queremos definir esto:
Código: Seleccionar todo
: BUCLE 5 0 DO I . LOOP ;
¿Que hace el JA durante la compilación de esta palabra tras pulsar el ENTER?
Para verlo sin que se altere la definición, lo haremos así:
Código: Seleccionar todo
: BUCLE [ .S ] 5 0 DO [ .S ] I . LOOP [ .S ] ;
.S es una palabra que nos muestra el contenido de la pila sin modificarla (ver manual del JA pág 143). Tras pulsar ENTER nos saldrá en pantalla (con VIS activado):
Código: Seleccionar todo
: bucle [ .s 10 ] 5 0 do [ .s 10 21313 3 ] i . loop [ .s 10 ] ;
Así vemos que (haciendo esto con la pila vacía y comprobando que sigue vacía después del ENTER) :
- ":" planta un 10 en la pila
- "DO" planta el valor de HERE (*) y un 3
- "LOOP" usa el valor del HERE tras DO y quita el 3 que plantó DO
- ";" quita el 10 que plantó ":"
Deducimos que el JA comprueba que:
- El 10 que planta al principio de la definición sigue estando al final de la misma.
- Cuando se compila el LOOP tiene que haber un 3 en la pila.
Para otras palabras compilantes como :BEGIN, IF/ELSE y WHILE los códigos son 1, 2 y 4 respectivamente.
Todo esto permite al JA comprobar que las compilantes están pareadas (no hay DOs sin LOOPs, etc) y bien anidadas.
Para qué nos sirve saber esto:
- Si al programar ULOOP hubiera seguido este protocolo entonces el JA se encargaría de comprobar que está todo bien (pareado/anidado).
- Podría usar ULOOP con DO (no necesitaría el UDO)
- Podemos engañar al JA para que nuestras compilantes puedan tomar números de la pila (**).
- Etc.
(*) Que 21313 es el valor del HERE en ese momento, se comprueba de esta manera:
Código: Seleccionar todo
: bucle [ .s ] 5 0 [ here .s drop ] do [ here .s drop ] i . loop [ .s ] ;
que dará este resultado
: bucle [ .s 10 ] 5 0 [ here .s 10 21311 drop ] do [ here .s 10 21313 3 21313 drop ] i . loop [ .s 10 ] ;
(**) Podemos, por ejemplo, utilizar números de la pila (que estaban antes de empezar la definición) siempre y cuando nos aseguremos que antes que se compile el ";" haya un 10 en la pila... etc.
NOTA: Al preparar este post me he dado cuenta que LEAVE no se comprueba, por lo que ULEAVE no es es necesaria. Se puede usar LEAVE en un bucle UDO/ULOOP.
-------------------------------------------------------------------
He aquí una modificación de ULOOP que se ajusta a lo expuesto. Esta versión funciona con DO sin problemas.
Código: Seleccionar todo
2 COMPILER ULOOP
3 =
IF
HERE - ,
ELSE
5 ERROR
THEN
RUNS>
ULOOPMC
;
ERROR toma un número n de la pila, imprime ERROR n en pantalla y realiza un ABORT.