HL-ZX FORTH Tambien llamado Forth 79 de Mike Hampson, esta versión es practicamente identica a SPECTRUM FORTH v48k, hecha por el mismo autor para CP Software. Al cargar el programa "SP48" aparece en pantalla el título con el copy-right de Hampson: "*************" "*HL ZX FORTH* "*************" "2nd version © March 83 M Hampson" (2da version Marzo 1983 Mike Hampson) "Please wait" (Espere por favor) - tras lo cual carga de la cinta los archivos "dict&chrs" y 'routines' pasando entonces al mensaje: "You are now in Command Mode." (Esta usted ahora en modo comando) "***>" - es el prompt indicando que forth esta listo y esperando una orden Una vez ingresado un comando de Forth da el mensaje: "Compiling - please wait." (Compilando - espere por favor) En caso de no haber terminado la orden con ';' dara el mensaje: "Continue definition:" - pidiendo que continue la definicion hasta dar ; Si hubiera un error sintactico o un dato no admisible,, respondera con: "Typing error.Continue." (Error en el tipeado, continue) y esperara a que uno de un dato valido. Una vez ingresados los datos correctos respondera con el resultado y: "Stack: xx ---OK" - donde xx = el numero de elementos en la pila Ejemplo: ***> 30 20 ; - devolvera "Stack: 2 ---OK" ***> + . ; - dara 50 y "Stack: 0 ---OK" debido a que la palabra '.' extrae los valores de la pila vaciandola. Comandos directos: Son solamente 4 y todas de un solo caracter: ":" (definir), "s" (salvar), "d" (definir) y "f" (eliminar) que deben ser tipeadas en minusculas. s copia el viejo archivo bajo nuevo nombre en otra cinta o salva un nuevo archivo con las nuevas definiciones añadidas por el usuario. "File Name:" - el sistema solicita nombre de archivo a salvar tras lo cual responde: "© Copying of this program is illegal except for storage of the purchacer's own FORTH words exclusively for his own use." Literalmente: "copiar el programa es ilegal excepto para salvar las palabras Forth de uso exclusivo del comprador" Salvará el nuevo nombre que se le diera pero mantiene sin cambio: 'dict&chrs' y 'routines' Una vez hecho eso, el sistema querrá verificar si se salvó todo correctamente con: "Please play back to verify." (Por favor retroceda la cinta para su verificación) y si no ha habido error de salva en la cinta dará un "Tape OK." (Cinta okey) : permite ingresar nuevas definiciones de palabas a la libreria "Name Word:" - el sistema solicita nombre de nueva palabra a crear Si la palabra ingresada como nombre ya existiese en la libreria del forth, dirá: "Word already used." - es decir que la palabra ya existe y está en uso. "Continue definition:" - daá este mensaje hasta que uno termine la definicion con ';' d entra al modo de edicion de los 21 UDGs del Spectrum. "Give UDG number:" - el sistema solicita un número de UDG, desde cero hasta ¿? (*) "Redefinition of character " ("Redefinicion del caracter "+ el valor ingresado) A partir de aquí pide se ingresen los datos en binario como lineas de 0 al 7 "Character " - al final aparece el mensaje caracter numero indicando el fin de la definicion. * nota: admite incluso valores negativos o mayores de 255 que seran leidos con EMIT. Es posible hacer 1000 EMIT o -1 EMIT para mostar en pantalla estos UDGs. f permite eliminar de la libreria, palabras definidas por el usuario. "Forget " - espera que el usuario ingrese el nombre de la definicion a ser elimidada "Word not found." - en caso de no existir tal palabra responde con "palabra no hallada" "Forgotten:" - si la definicion existe entonces la elimina y contesta que ya fue olvidada y por lo tanto no podra se usada más. PALABRAS RESERVADAS DEL FORTH: En comparacion con la version de 16k de CP Software este es un superset que incluye trabajar con variables de una sola letra, más de 255 UDGs y sonidos con la orden BEEP. Funciones matematicas y lógicas: + (suma) sintaxis: x y + - (resta) sintaxis: x y - * (multiplica) sintaxis: x y * / (divide) sintaxis: x y / = (igual) sintaxis: x y = < > (distinto) sintaxis: x y < > - nota: tener separados los dos signos con un espacio < (menor) sintaxis: x y < > (mayor) sintaxis: x y > NOT sintaxis: x NOT MAX sintaxis: x y MAX deja en la pila el mayor de 2 numeros MIN sintaxis: x y MIN deja en la pila el menor de 2 numeros ABS devuelve el valor absoluto de un número AND sintaxis: y x AND Función lógica bit a bit entre los dos números x e y OR sintaxis: y x OR Función lógica binaria OR de dos números XOR como OR, pero exclusiva. NEGATE vuelve negativo un numero positivo y viceversa. MOD guarda en la pila el resto de la división RND devuelve un valor entero positivo al azar. Ordenes de manejo de pila: . Extrae el valor de la pila y lo imprime en pantalla, vaciando a su vez la pila CR da un retorno de carro SPACE imprime 1 espacio en la línea en curso. ." sintaxis: ."texto" imprime en pantalla el texto contenido entre las comillas SPACES sintaxis: n SPACES imprime n espacios en la línea en curso. Ejemplo: 5 SPACES ."Hola" DUP duplica el valor contenido en el stack para evitar generalmente que se pierda al usar "." ?DUP hace DUP sólo si el valor no es cero DROP borra el valor en el stack sin mostrarlo en pantalla swap sintaxis: x y SWAP intercambia los dos valores que estan en la pila over sintaxis: x y OVER copia el segundo valor (x) y lo pone sobre la pila ROT sintaxis: x y z ROT Como SWAP pero intercambiando los valores primero y tercero de la pila. PICK sintaxis: n PICK copia el enesimo numero en la pila. Sean por ejemplo los números ingresados: 10 20 30 40 3 PICK - añadirá 20 que es el tercero desde el último valor ingresado 2 PICK - es equivalente a OVER Nota: pick debe tener un argumento o alterará el último valor ingresado en la pila ROLL sintaxis: n ROLL pone el enesimo numero en la pila moviendolo de su sitio en vez de copiarlo. Ejemplo: 3 ROLL - en el ejemplo anterior dejará la lista como: 10 30 40 20 Nota: sin parametros roll puede generar efectos imprevistos. DEPTH Cuenta el número de elementos que hay en la pila KEY Espera indefinidamente a que se pulse una tecla y la guarda en la pila INKEY Como KEY pero espera por un breve momento a que se pulse una tecla. EMIT extrae de la pila el valor ingresado ya sea del teclado, posición de memoria, variable o constante. key e inkey dan el codigo ascii, emit muestra en pantalla su caracter correspondiente Ejemplo: : espera KEY EMIT ; ! sintaxis: y x ! Almacena el valor y en la dirección de memoria x (como doble POKE en Basic) ó Da el valor 'y' a la variable 'x' previamente definida, sino se generará un error. Ejemplo: 444 60000 ! @ sintaxis: x @ busca el valor contenido como 2 bytes en la dirección x (doble PEEK) o en la variable 'x'. Ejemplo: 60000 @ . - devolverá 444 o el valor que sea que contenga C! por 'character', es como ! pero guarda el byte menos significativo (POKE simple) C@ como @ para el byte almacenado con C! (PEEK simple) C? equivale a "C@ ." .En Basic sería como hacer "PRINT PEEK". Ejemplo: 150 60000 ! 60000 C? - devolverá el valor almacenado en esa dirección ? equivale a hacer 'Print Double Peek' en Basic. Ejemplo: 60000 ? +! como ! pero sumando Y al valor previamente almacenado en X antes que reemplazarlo. Ejemplo: 100 60000 +! - añadirá 100 más al valor del ejemplo anterior 600000 ? - devolverá 544 en vez de 444 o solo 100 MOVE sintaxis: d1 d2 n MOVE copia n caracteres como texto o numero, desde la dirección d1 a la d2. CMOVE sintaxis: d1 d2 n CMOVE copia n bytes de la dirección d1 a la d2. Ejemplo: 16396 40000 64 CMOVE - moverá 64 bytes desde la posición 16396 a la 40000 Estructura condicional if: sintaxis: c IF lp1 {ELSE {lp2}} THEN {lp3} if inicia la condicion y ejecuta 'lp1' si se cumple 'c' else sino ejecuta siguiente opción 'lp2' then cierra la condición y se prosigue con 'lp3' Ejemplo: : test 2 > IF ."TOO BIG" ELSE THEN ; - para ejecutar hacer por ejemplo: '1 test' Nota: un defecto del programa hace que el uso de THEN genere un error que devuelve el control al Basic. Para evitarlo hay que hacer 'ELSE THEN' como se muestra en el ejemplo. Esto ocurre solo cuando se carga el Forth por primera vez, lo que obliga que la primera definición contenga un 'ELSE THEN', en cambio las proximas definiciones ya pueden tener 'THEN' sin el 'ELSE'. Bucle do - loop: sintaxis: f c DO {I} lp {s +}LOOP donde: f = valor final o el numero de veces que correrá el bucle + 1 c = valor inicial lp = la serie de palabras que se ejecutarán dentro del bucle do inicia el bucle y equivale en Forth al bucle FOR del Basic loop cierra el bucle (como NEXT) +loop sintaxis: s +LOOP equivale a 'STEP s' del Basic >R, R>, R@: además de la pila con la que trabaja normalmente el usuario, existe una segunda pila, en la que se almacenan otros valores para uso generalmente interno como el caso de DO-LOOP, pero es posible manipular estos datos mediante las sigtes ordenes: >R transfiere n de la pila de datos a la pila de retorno R> hace la inversa de >R R@ copia el valor de la pila de retorno en la pila de datos I guarda el índice del bucle do loop. I es equivalente a: 'R> DUP >R'. Ejemplo: : ft 11 1 DO I . CR LOOP ; - imprimirá 10 numeros bucles begin: sintaxis1: BEGIN lp c UNTIL {...} begin inicia el bucle indefinido o condicional until hasta que se cumple 'c'. Si 'c' = 0 o se omite, el bucle se repite indefinidamente Ejemplo: : tt BEGIN KEY EMIT UNTIL ; - una vez ejecutado no hay modo de interrumpirlo : tt BEGIN KEY DUP EMIT 13 = UNTIL ; - termina al pulsar sintaxis2: BEGIN {lp} c WHILE lp2 REPEAT {...} while mientras se cumpla 'c' repeat se repite el bucle - nota: si falta REPEAT o WHILE, genera error y retorna al Basic Ejemplo: : tt BEGIN INKEY DUP 13 < > WHILE EMIT REPEAT ; LEAVE fuerza la salida prematura de un bucle DO LOOP haciendo que el límite 'f' sea igual al índice. Ejemplo: : ft 11 1 DO I DUP 6 = IF LEAVE ELSE THEN . CR LOOP ; se detendrá tras imprimir 6 numeros, en cambio: : ft DO I DUP 6 = IF LEAVE ELSE . CR THEN LOOP ; - se detiene tras mostrar 5 numeros EXIT termina a la fuerza la ejecución de una definición como ';'. No puede usarse dentro de DO LOOP pero si con bucles BEGIN. Ejemplo: : tt BEGIN KEY DUP 13 = IF EXIT ELSE EMIT THEN 0 UNTIL ; termina al pulsar pero dejará el valor 13 en la pila : tt BEGIN KEY DUP 13 = IF DROP EXIT ELSE EMIT THEN 0 UNTIL ; saldrá sin dejar ningun valor en la pila al terminar EXITLP permite salirse de un bucle DO LOOP antes de su cierre normal como LEAVE. Ejemplo: : ft DO I DUP 6 = IF EXITLP ELSE . CR THEN LOOP ; ABORT sale de un programa y borra la pila de datos Ejemplo: : tt BEGIN KEY DUP 13 = IF ABORT ELSE EMIT THEN 0 UNTIL ; - el mismo ejemplo de EXIT QUIT como ABORT pero sin borrar la pila. Tanto ABORT como QUIT pueden usarse dentro de bucles DO LOOP y BEGIN indistintamente, incluso en lugar de LEAVE, EXIT o EXITLP. WAIT espera indefinidamente interrumpiendo el programa hasta que el usuario pulse "Y". VLIST Muestra todas las palabras reservadas del FORTH, incluidas las que añade el usuario. A medida que imprime una linea de la lista espera a que se pulse "Y" para continuar hasta terminar de mostrar todo el diccionario. ( sintaxis: (comentarios) permite añadir notas a las definiciones que serán ignorados en tiempo de compilación. FIND sintaxis: FIND np devuelve la dirección de compilación de una palabra Forth, o error si no existiese. ---- Spectrum equivalentes: son ordenes exclusivas del Forth para ZX Spectrum, inexistentes en Forth estandar. CLS limpia la pantalla y pone el cursor de texto en la esquina superior izquierda. BORDER sintaxis: n BORDER permite elegir el color del borde como en Basic. INK sintaxis: n INK idem para el color de la tinta. PAPER sintaxis: n PAPER idem para el color del papel. FLASH, BRIGHT, INVERS admiten 1 para activar y 0 para desactivar como en Basic. AT sintaxis: y x AT posiciona el cursor de texto para usar con ., U., ó ." Ejemplo: 5 5 AT ." Hola Mundo" PLOT sintaxis: y x PLOT dibuja un punto en el color por defecto en alta resolución. UNPLOT sintaxis: y x UNPLOT borra el punto en coordenadas absolutas. OVRPLT sintaxis: y x OVRPLT sobreimprime los puntos a diferencia de UNPLOT. POINT sintaxis: y x POINT devuelve 0 si no hay ningun punto dibujado en las coord. y x, 1 si lo hay. BEEP sintaxis: y x BEEP toca una nota Y por un tiempo X, sin parametros o con valores negativos, el sistema se cuelga. Y puede llegar a ser desde 0 hasta 65535, X debe ser un valor nada exagerado. ---- Manejo de variables y constantes Otras versiones Forth poseen dos palabras reservadas que son CONSTANT y VARIABLE, inexistentes en HL-zX Forth, el cual aplica un metodo bastante irregular. Para crear constantes numéricas hay que definirlas con ":". Ejemplo: :alfa 120; - crea una constante numerica de valor 120 Para ver los contenidos basta hacer "alfa ." No importa qué, una constante no puede ser modificada más que por ':'. En el caso de textos es posible hacer lo sigte: : cadena ."texto" ; - bastará con tipear 'cadena' para mostrar el 'texto' En el caso de las variables numericas son de una sola letra y están predefinidas: A B C D E F G H J K L M N O P Q R S T U V W X Y Z Nota: La I está reservada exclusivamente para leer el indice de un bucle DO LOOP. Ejemplo: 23 B ! - da a la variable B predefinida el valor 23 B ? - muestra el contenido de la variable. Equivale a "B @ ." Una variable numerica siempre puede ser modificada con ! y examinada con ? o @. QUERY almacena textos en la dirección 65368 hasta pulsar ENTER (incluido como valor 13 al final) WORD lee el texto almacenado con QUERY un caracter a la vez y los pone en la pila de datos >IN Devuelve la dirección 23682 TYPE sintaxis: d s TYPE extrae cadenas de texto de la posición de memoria 'd' con longitud 's'. PAD area tampón donde se almacena texto (dirección 65368) con QUERY más el código 13 de ENTER EXPECT sintaxis: y x EXPECT lee x caracteres desde el teclado y los almacena en la dirección Y. Ejemplo: PAD 5 EXPECT - quedará a la espera de que uno tipee un texto de 5 caracteres PAD 5 TYPE - lee el texto almacenado con EXPECT Z 5 EXPECT - salvará un texto en la variable Z que podrá ser leido con TYPE COUNT devuelve el largo de una cadena de n caracteres si dicho valor existe al comienzo de la misma. Ejemplo: 6 63600 c! - almacena la longitud de la cadena 63601 6 EXPECT - espera a que se tipea la cadena y la almacena 63600 COUNT TYPE - mostrará en pantalla el texto previamente almacenado Nota: debido a que QUERY no salva la longitud, COUNT no puede contar el largo de la cadena. Para ver el contenido del PAD sin preocuparse por el largo máximo de la cadena, definir por ejemplo: : READ PAD 160 + PAD DO WORD DUP 13 = IF DROP LEAVE ELSE EMIT THEN LOOP ; Para probarlo basta hacer: QUERY - tipeamos por ejemplo "ALICIA" READ - mostrará en pantalla el texto "ALICIA" Para contar cuantos caracteres tiene la cadena habría que definir: : LEN PAD 160 + PAD DO WORD DUP 13 = IF DROP I PAD - LEAVE ELSE DROP THEN LOOP ; LEN . ; - devolverá 6 Nota: WORD lee correctamente si se usa QUERY, debido a eso, READ y LEN solo funcionan una vez por cada QUERY, en cualquier otro caso dará otro valor pero nunca la longitud real. Para que las nuevas definiciones funcionen correctamente hay que modificarlas así: : READ PAD 160 + PAD DO I C@ DUP 13 = IF DROP LEAVE ELSE EMIT THEN LOOP ; : LEN PAD 160 + PAD DO I C@ DUP 13 = IF DROP I PAD - LEAVE ELSE DROP THEN LOOP ; ---- Miscelaneas: Otras palabras propias del HL-ZX FORTH y Spectrum Forth 48k ' sintaxis: ' np da la dirección de memoria de una palabra definida 'np' o error si no existiese. Ejemplo: ' alfa . ; - mostrará en pantalla su posición en la RAM en caso de existir alfa DUMP sintaxis: d n DUMP muestra en pantalla un volcado del contenido de la memoria a partir de 'd', n valores de 2 bytes. Ejemplo: 32000 7 DUMP ; - mostrará en pantalla: 32,000 0 - o el valor que se haya depositado en esa posición y un cuadrado parpadeante 32,002 0 - DUMP espera que se pulse 'Y' para continuar línea a línea 32,004 0 - y así sucesivamente hasta dar los 7 numeros Nota: debido a que DUMP toma dos valores de la pila, para evitar que deje la pila en -1: '0 32000 7 DUMP' CDUMP sintaxis: d n CDUMP Igual que DUMP pero un byte a la vez como PEEK. Ejemplo: 32000 7 CDUMP ; - mostrará en pantalla: 32,000 0 32,001 0 - y así sucesivamente hasta completar la lista Nota: sin parámetros, empieza a mostrar toda la memoria sin parar. FIELD tabula la impresión en pantalla primero en 9 espacios y luego cada 8. Ejemplo: FIELD ."A" FIELD ."B" FIELD ."C" FIELD ."D" ; - imprimirá en pantalla: A B C D P! sintaxis: n m P! envía un valor n al puerto numero m. Equivale a OUT m,n del Basic. P@ sintaxis: n P@ lee datos del puerto n al igual que 'IN n'. Ejemplo: : IN BEGIN 31 P@ 5 5 AT DUP . 16 = UNTIL ; - lee respuestas de un joystick Kempston EXECUT sintaxis: n EXECUT fuerza la ejecución de una dirección de diccionario en la dirección de compilado en la pila. HIRES Admite dos argumentos numericos y devuelve un valor. ATTR sintaxis: {y} x ATTR da un valor si se dan los dos argumentos, ninguno si se omite uno de los parametros. STKSWP parece aludir a Stack Swap (intercambio de valores de la pila) admite valores numericos dependiendo de lo cual puede dar error e interrumpirse, provocar un reset total del sistema en Basic del mismo modo que PRINT USR 0, o colgarse. FILL, ERASE y DELETE En otros Forths estas palabras funcionan correctamente, pero aquí cuelgan el sistema cada vez que se utilizan. Pero es posible definirlas del sigte modo: : MFILL 65535 c! OVER + SWAP DO 65535 @ I c! LOOP ; la sintaxis es: d n b MFILL, llena con n bytes de valor b, una area de memoria a partir de la posición d. : ERA OVER + SWAP DO 0 I ! LOOP ; la sintaxis es: d n ERA, elimina n bytes desde la dirección d llenandola con puro ceros. : DEL OVER + SWAP DO 32 I ! LOOP ; la sintaxis es: d n DEL, como ERASE pero llenandola con espacios. Las siguientes palabras reservadas están en minúsculas y deben ser tipeadas así. number no debe ser usado con la pila vacía ya que copia todos los valores que esta contenga. Ejemplo: 123 40 50 ; - si se ingresa esto el sistema respondera con "Stack: 3" number ; - dará el mensaje "Stack: 6" dejando 123 40 50 123 40 50 en la pila Nota: number . ; - da "Stack: 4" sin repetir la serie ni imprimir nada en pantalla, dejando en la pila un valor, generalmente -25139 tras hacer un nuevo '. ;', 0 con '? ;' number . . ; - muestra el valor y deja "Stack: 3" number ? . ; - es similar a hacer number @ . ; flgtst quita el último valor ingresado en la pila de modo similar a DROP, con la diferencia de que number puede recuperarlo. Ejemplo: 10 20 30 40 ; - si se ingresa esto el sistema respondera con "Stack: 4" flgtst ; - dará "Stack: 3" y dejará la pila solo 10 20 y 30 number ; - dará "Stack: 7" y la pila queda 10 20 30 10 20 30 40 flgtst . ; - elimina 2 valores e imprime un resultado prstrg A diferencia de VLIST no espera que se pulse ninguna tecla ni se detiene hasta que acaba solo. wrdsch ¿?