Mario de Lama
malar@arrakis.es
http://www.arrakis.es/~malar
>Hola, seguí tu recomendacion y estoy programando en USER antes que
>en SYS, pero tengo una preguntica.
>He visto algunos programas en USER y he encontrado dentro del programa la
>palabra Code ( creo que eso es un programa que está "como comprimido",
>perdona mi ignorancia en esa palabra, ya que segun los argumentos que
>esten en la pila, cuando se ejecuta esa parte del programa ( Code ) este
>devuelve un resultado a la pila.
Al final de mi pasado mail te comento de pasada que los programas en System aparecen en la pila como External y los que están desarrollados en ML (Machine Language) aparecen como Code. Por tanto no están comprimidos sino que son programas creados en lenguaje máquina (bastante más complicado, peligroso y rápido que el System)
>Conozco un programa llamado CODER que toma un programa y lo "mete" en esa
>palabra ( espero que me entiendas ).
CODER es un programa de Simone Rapisarda & James Cloos que codifica una cadena (GD 5). Creo que te refieres a CODE, de Richard Steventon & Joe Horn que, efectivamente, "transforma" cualquier objeto del nivel 1 en un Code (puedes encontrarlo en el GD 11).
>Mi pregunta es ¿Cómo puedo colocar un programa que este "metido" en Code
>como un subprograma de uno principal? Ejemplo
>
>IF 8 9 == THEN Code END
>
>Como te dije anteriormente Code es un programa dentro del programa mayor y
>no un nombre de variable local que va a ser llamado.
>
>Algo similar encontre como te lo muestro en el siguiente ejemplo,
>
>IF 8 9 == THEN "BZ A-"*+..." Code END ( es solo un ejemplo )
>
>Ves que "BZ A-"*+..." es algo comprimido con BZ4 y que luego Code lo
>descomprime.
>
>?????? COMO HACEN ESO ????????
Tampoco sería difícil si el comando LIST-> (o el OBJ->) funcionara con un programa igual que con una lista. Desharíamos el programa, colocaríamos en el nivel 1 el objeto que deseáramos y luego iríamos en la pila hasta el lugar deseado, presionaríamos ROLLD y ya con el objeto en su lugar sólo deberíamos modificar el número que LIST-> nos devuelve en 1: (según hayamos añadido o quitado elementos del programa). Finalmente la cosa fallaría ya que no tenemos tampoco el comando User equivalente a ->LIST que nos transforma la pila en un programa, pero bueno, son detalles :-)
En User no podemos hacer esto porque OBJ-> no funciona con programas, pero en System existe "INNERCOMP" (al que podemos llamar con #054AFh SYSEVAL)
Su uso: Ponemos un programa en el nivel 1, por ejemplo << 1 2 3 >>, y ejecutamos #054AFh SYSEVAL, como resultado tendremos el programa deshecho en la pila y en el nivel 1 un binary integer (el equivalente al clásico tipo de dato integer de cualquier lenguaje de programación) que nos indica el número de elementos:
6: <<
5: 1
4: 2
3: 3
2: >>
1: <5d> @ o <5h> si tenemos elegida la base hexadecimal
Esta pila es lo que se conoce por metaobjeto.
Estos binary integers no pueden manipularse con User. Ahora sólo queda poner el Code o External deseado en la pila y llevarlo a su lugar con ROLLD, luego aumentamos el binary a <6d> y ya está. Bueno, nos queda volver a transformar el metaobjeto en programa con la palabra de System "::N", o llamando a su dirección de memoria con #05445h SYSEVAL.
Como es un rollo hacer todo esto (también habría que modificar los binary integers con SYSEVAL), hay gente que ya ha pensado en ello y ha creado programas que además de funcionar bien hacen chequeos de datos para impedir que se nos borre la memoria. Si usas la librería <-LIB-> v2.3 (18k) que te envío puedes, además de hacer y deshacer librerías y muchas otras cosas, usar OB-> para deshacer cualquier cosa y ->PRG para rehacerla (son comandos de la librería).
A pesar de todo, la cosa no te será fácil del todo ya que si cogemos tu ejemplo << IF 8 9 == THEN "BZ A-"*+..." Code END >> y lo deshacemos en la pila con OB-> tendremos:
10: <<
9: IF
8: 8
7: 9
6: ==
5: THEN
4: "BZ A-"*+..." Code
3: END
2: >>
1: 9
Esta vez en vez de un integer tenemos un real, que ya si podemos manipular.
Según esto, todo lo que hay entre THEN y END es un sólo objeto, quiere esto decir que si quieres meter otra cosa en esta cláusula has de tomar "BZ A-"*+..." Code del nivel 4: y deshacerlo con OB->, poner lo que quieras en el lugar deseado y volver a rehacerlo con PRG-> (no hay que poner delimitadores << >>), luego llevarlo hasta el nivel 4: y volver a rehacerlo todo. Si la cláusula IF estuviese dentro de, por ejemplo, un bucle START NEXT, te quedaría en la pila:
n: <<
....
i: START
i-1: ...... THEN "BZ A-"*+..." Code END .........
i-2: NEXT
...
1: n+1
Tendrías que deshacer unos cuantos objetos, manipularlos, colocarlos en el lugar debido y rehacerlos. Es un poco lioso pero ...
Finalmente, otra forma de hacerlo sería descompilar con JAZZ nuestro programa y el Code o External, tendremos dos cadenas de caracteres que uniremos sumándolas. Las editamos con ED (viene con JAZZ) o con String Writer (ya que puede haber caracteres nulos) y sólo tenemos que cortar y pegar donde deseemos el código descompilado del Code o External. Finalmente lo volvemos a compilar todo y ya está.
>Gracias por tu atencion.
>pta : el curso de USER que tienes en tu pagina es muy bueno.
Gracias, tú si sabes apreciar lo bueno :-)
Si tienes más dudas ya sabes dónde estoy, un saludo
Soy humano, también me gustan los halagos (N. del T., vamos, mía :-)