Category:Amazing Hopper: Difference between revisions

Content added Content deleted
Line 5,063: Line 5,063:




=== DIRECTIVA \ ===
=== DIRECTIVA "\" ===


No es una directiva propiamente tal, dado que puede ser usada a lo largo de todo el programa; no obstante, se incluye aquí por razones de apoyo a la definición de directivas.
No es una directiva propiamente tal, dado que puede ser usada a lo largo de todo el programa; no obstante, se incluye aquí por razones de apoyo a la definición de directivas.
Line 5,071: Line 5,071:
Ejemplo:
Ejemplo:


#defn uniformrand(_MU_,_FVAR_,*) #RAND,_V_#RNDV=0,{*}randarray(_V_#RNDV),\
#defn uniformrand(_MU_,_FVAR_,*) #RAND,_V_#RNDV=0,{*}randarray(_V_#RNDV),\
{_V_#RNDV}mulby(2),minus(1),mulby(_FVAR_),\
{_V_#RNDV}mulby(2),minus(1),mulby(_FVAR_),\
plus(1),mulby(_MU_),clear(_V_#RNDV)
plus(1),mulby(_MU_),clear(_V_#RNDV)


Dentro del código principal de programación, se puede esar para aquellas macros que se anidan, por ejemplo:
Dentro del código principal de programación, se puede esar para aquellas macros que se anidan, por ejemplo:


#include <stdio.hh>
#include <hopper.h>
main:
main:
true(i)
true(i)
iif(false,{"Es verdad\n"},\
iif(false,{"Es verdad\n"},\
iif(true,{"Es verdad por 2 intento\n"},{"Es falso"})), println
iif(true,{"Es verdad por 2 intento\n"},{"Es falso"})), println
return(0)
exit(0)


En el ejemplo, la macro IIF, ubicada dentro de STDIO.HH, anidada, extiende la programación; en este caso, es muy útil "\".
En el ejemplo, la macro IIF, ubicada dentro de STDIO.HH, anidada, extiende la programación; en este caso, es muy útil "\".




=== DIRECTIVA * ===
=== DIRECTIVA "*" ===


Es un comodín, que será reemplazado por cualquier cosa que encuentre en el argumento. Este comodín es FINAL, es decir, debe colocarse como último argumento de la macro.
Es un comodín, que será reemplazado por cualquier cosa que encuentre en el argumento. Este comodín es FINAL, es decir, debe colocarse como último argumento de la macro.
Line 5,106: Line 5,106:




=== DIRECTIVA ; ===
=== DIRECTIVA ";" ===


El semicolon es útil para forzar que el preprocesador de macros de HOPPER lea una expresión, como un único argumento. Dicho caracter puede ser usado en el código de programa, en la invocación de macros.
El semicolon es útil para forzar que el preprocesador de macros de HOPPER lea una expresión, como un único argumento. Dicho caracter puede ser usado en el código de programa, en la invocación de macros.
Line 5,133: Line 5,133:
Este número reemplazará todas las instancias de #RNDV dentro de la actual expansión. Se coloca al principio del desarrollo de la macro, y desaparece en la expansión. Ejemplo:
Este número reemplazará todas las instancias de #RNDV dentro de la actual expansión. Se coloca al principio del desarrollo de la macro, y desaparece en la expansión. Ejemplo:


#defn uniformrand(_MU_,_FVAR_,*) #RAND,_V_#RNDV=0,{*}randarray(_V_#RNDV),\
#defn uniformrand(_MU_,_FVAR_,*) #RAND,_V_#RNDV=0,{*}randarray(_V_#RNDV),\
{_V_#RNDV}mulby(2),minus(1),mulby(_FVAR_),\
{_V_#RNDV}mulby(2),minus(1),mulby(_FVAR_),\
plus(1),mulby(_MU_),clear(_V_#RNDV)
plus(1),mulby(_MU_),clear(_V_#RNDV)


En el ejemplo, se crea un número pseudo-aleatorio, y éste reemplaza a todas las instancias #RNDV, creándose variables intermedias. Por ejemplo, si #RAND libera 28973, todas las instancias _V_#RNDV se convierten en _V_28973.
En el ejemplo, se crea un número pseudo-aleatorio, y éste reemplaza a todas las instancias #RNDV, creándose variables intermedias. Por ejemplo, si #RAND libera 28973, todas las instancias _V_#RNDV se convierten en _V_28973.
Line 5,145: Line 5,145:
Ejemplo:
Ejemplo:


#defn rnd #RAND, {#RNDV}divby(1000000)
#defn rnd #RAND, {#RNDV}divby(1000000)


Esta macro generará un número aleatorio entre 0 y 1, igual que la instrucción RAND:
Esta macro generará un número aleatorio entre 0 y 1, igual que la instrucción RAND:
Line 5,161: Line 5,161:
La macro ADDTO espera que exista un valor en el stack. Si el argumento _X_ es un número o una variable, reemplazará a #ATOM y lo colocará entre "{}", o sea, declarará un PUSH de ese dato; si es una expresión compleja (una operación), reemplazará #CMPLX, pero omitirá el uso de "{}". Es decir:
La macro ADDTO espera que exista un valor en el stack. Si el argumento _X_ es un número o una variable, reemplazará a #ATOM y lo colocará entre "{}", o sea, declarará un PUSH de ese dato; si es una expresión compleja (una operación), reemplazará #CMPLX, pero omitirá el uso de "{}". Es decir:


{100},add to (5) ==> expande: {100}{5};add
{100},add to (5) ==> expande: {100}{5};add
{100},add to ({x}minus(1)) ==> expande: {100}{x}minus(1);add

{100},add to ({x}minus(1)) ==> expande: {100}{x}minus(1);add


RESTRICCION. Cada combinación #ATOM#CMPLX reemplaza a un solo argumento de la macro, en la posición señalada. Por ejemplo:
RESTRICCION. Cada combinación #ATOM#CMPLX reemplaza a un solo argumento de la macro, en la posición señalada. Por ejemplo:
Line 5,178: Line 5,177:
Permite al preprocesador de HOPPER la toma de decisiones dentro de una macro particular. Ejemplo:
Permite al preprocesador de HOPPER la toma de decisiones dentro de una macro particular. Ejemplo:


/* sobrecarga de instrucciones aritmeticas naturales: MINUS */
/* sobrecarga de instrucciones aritmeticas naturales: MINUS */
#defn minus(_X_) #IF minus(#ATOMF) #ELSE #CMPLX;postfix;sub;postfix #EIF
#defn minus(_X_) #IF minus(#ATOMF) #ELSE #CMPLX;postfix;sub;postfix #EIF


Line 5,187: Line 5,186:


Recordar que POSTFIX activa/desactiva el cálculo en notación polaca. Para el ejemplo, calculará 5 - x*10; sin POSTFIX, HOPPER calcularía x*10-5, y no cumpliría con el sentido de la operación MINUS.
Recordar que POSTFIX activa/desactiva el cálculo en notación polaca. Para el ejemplo, calculará 5 - x*10; sin POSTFIX, HOPPER calcularía x*10-5, y no cumpliría con el sentido de la operación MINUS.


$$END Directivas inline para #defn
$$BEGIN Directivas de estructuras




Line 5,203: Line 5,198:
Ejemplo:
Ejemplo:


#defn while(*) &( ) #LOOP:,*,jnt(#ENDLOOP)
#defn while(*) &( ) #LOOP:,*,jnt(#ENDLOOP)
#defn for(_X_,_Y_,_Z_) &(_Z_) _X_, #LOOP:, _Y_, jnt(#ENDLOOP)
#defn for(_X_,_Y_,_Z_) &(_Z_) _X_, #LOOP:, _Y_, jnt(#ENDLOOP)

#defn wend %&, jmp(%LOOP), %ENDLOOP:
#defn wend %&, jmp(%LOOP), %ENDLOOP:
#synon wend next
#synon wend next


%LOOP y %ENDLOOP sacan la etiqueta del stack de estructuras.
Las directivas %LOOP y %ENDLOOP sacan la etiqueta del stack de estructuras.




Line 5,237: Line 5,232:
---v--- ------------v------------- -------------v------------
---v--- ------------v------------- -------------v------------
_Z_ %LOOP %ENDLOOP
_Z_ %LOOP %ENDLOOP





Line 5,250: Line 5,244:
Ejemplo:
Ejemplo:


#defn continue %%&, jmp(%%LOOP)
#defn continue %%&, jmp(%%LOOP)
#defn break jmp(%%ENDLOOP)
#defn break jmp(%%ENDLOOP)


Si en el ejemplo del ciclo FOR anterior, existiese un CONTINUE, éste expandiría así:
Si en el ejemplo del ciclo FOR anterior, existiese un CONTINUE, éste expandiría así:
Line 5,270: Line 5,264:
Ejemplo:
Ejemplo:


#defn foreachline(_Y_,_X_,_V_) #RAND, ##ENDLOOP\
#defn foreachline(_Y_,_X_,_V_) #RAND, ##ENDLOOP\
&(++_V_;{_V_#RNDV,_V_},jgt(%%ENDLOOP)),\
&(++_V_;{_V_#RNDV,_V_},jgt(%%ENDLOOP)),\
_Y_="", _V_=1, _V_#RNDV=0, {"\n"}toksep,\
_Y_="", _V_=1, _V_#RNDV=0, {"\n"}toksep,\
totaltoken(_X_), cpy( _V_#RNDV ), \
totaltoken(_X_), cpy( _V_#RNDV ), \
jz(%%ENDLOOP), #LOOP:,{_V_},$(_X_),mov(_Y_)
jz(%%ENDLOOP), #LOOP:,{_V_},$(_X_),mov(_Y_)


Ejemplo:
Ejemplo:
#include <stdio.hh>
#include <stdio.hh>
main:
main:
s="Juanito juega a la pelota\nMaría tenía un corderito\nPablito clavó un clavito"
s="Juanito juega a la pelota\nMaría tenía un corderito\nPablito clavó un clavito"
v="",indice=0
v="",indice=0
for each line(v, s, indice)
for each line(v, s, indice)
prnlutf8(v)
prnlutf8(v)
next
next
return(0)
return(0)
Line 5,299: Line 5,293:
Ejemplo (stdio.hh):
Ejemplo (stdio.hh):


#defn try swtrap( #CATCH )
#defn try swtrap( #CATCH )
#defn raise(_ERR_,_M_) {_M_}, throw(_ERR_)
#defn raise(_ERR_,_M_) {_M_}, throw(_ERR_)
#defn catch(_X_) jmp(#ENDCATCH), %CATCH:,\
#defn catch(_X_) jmp(#ENDCATCH), %CATCH:,\
clearstack,_X_=0,gettry(_X_)
clearstack,_X_=0,gettry(_X_)
#defn finish %ENDCATCH:, popcatch
#defn finish %ENDCATCH:, popcatch


#CATCH y #ENDCATCH son almacenadas en el stack de estructuras, por lo que también permiten anidamiento.
Las directivas #CATCH y #ENDCATCH son almacenadas en el stack de estructuras, por lo que también permiten anidamiento.




Line 5,312: Line 5,306:
Estas directivas se diseñaron para simular estructuras de BIFURCACION, aunque no necesariamente se remiten a IF/ELSE. Con ellas, es posible dar vida a la estructura IF/ELSEIF/ELSE/ENDIF, y a otras, como se mostrará a continuación.
Estas directivas se diseñaron para simular estructuras de BIFURCACION, aunque no necesariamente se remiten a IF/ELSE. Con ellas, es posible dar vida a la estructura IF/ELSEIF/ELSE/ENDIF, y a otras, como se mostrará a continuación.


Ejemplo (stdio.hh):
Ejemplo (stdio.hh y hopper.h):


#defn elseif(*) jmp(%%CODEIF), %ENDIF:, *, jnt(#ENDIF)
#defn elseif(*) jmp(%%CODEIF), %ENDIF:, *, jnt(#ENDIF)
#defn if(*) ##CODEIF, *, jnt(#ENDIF)
#defn if(*) ##CODEIF, *, jnt(#ENDIF)
#defn else jmp(%%CODEIF), %ENDIF:, true,jnt(#ENDIF)
#defn else jmp(%%CODEIF), %ENDIF:, true,jnt(#ENDIF)
#defn endif %CODEIF:, %ENDIF:
#defn endif %CODEIF:, %ENDIF:


NOTA: se coloca ELSEIF antes de IF, porque el preprocesador se confunde si están al revés.
NOTA: se coloca ELSEIF antes de IF, porque el preprocesador se confunde si están al revés.


##CODEIF crea una etiqueta aleatoria, y la guarda en el stack de bifurcación. #ENDIF creará una única etiqueta aleatoria, que será consumida por ELSEIF o por ELSE, asegurando el funcionamiento de la estructura. ELSEIF o ELSE, consumen la etiqueta (%ENDIF), y a continuación, crean una nueva con #ENDIF.
La directiva ##CODEIF crea una etiqueta aleatoria, y la guarda en el stack de bifurcación. #ENDIF creará una única etiqueta aleatoria, que será consumida por ELSEIF o por ELSE, asegurando el funcionamiento de la estructura. ELSEIF o ELSE, consumen la etiqueta (%ENDIF), y a continuación, crean una nueva con #ENDIF.


La lógica de "%%" es la misma vista en las directivas anteriores.
La lógica de "%%" es la misma vista en las directivas anteriores.
Line 5,327: Line 5,321:
Un ejemplo de una bifurcación natural, se muestra a continuación, donde se espera que exista un dato en el stack, y que sea TRUE o similar:
Un ejemplo de una bifurcación natural, se muestra a continuación, donde se espera que exista un dato en el stack, y que sea TRUE o similar:


#defn segúnloanteriorhazesto ##CODEIF,jnt(#ENDIF)
#defn segúnloanteriorhazesto ##CODEIF,jnt(#ENDIF)
#defn hastaaquí %CODEIF:,%ENDIF:
#defn hastaaquí %CODEIF:,%ENDIF:




Line 5,337: Line 5,331:
Ejemplo (hopper.h):
Ejemplo (hopper.h):


#defn iif(_X_,_Y_,_Z_) #ATOMF#CMPLX, jnt(#ENDIIF),\
#defn iif(_X_,_Y_,_Z_) #ATOMF#CMPLX, jnt(#ENDIIF),\
#ATOMF#CMPLX, jmp(#ENDIF),\
#ATOMF#CMPLX, jmp(#ENDIF),\
%ENDIIF:, #ATOMF#CMPLX, %ENDIF:
%ENDIIF:, #ATOMF#CMPLX, %ENDIF:


La macro IIF requiere de #ENDIF, que la usa para reservar una etiqueta de salto, si la expresión _X_ es TRUE.
La macro IIF requiere de #ENDIF, que la usa para reservar una etiqueta de salto, si la expresión _X_ es TRUE.
Line 5,347: Line 5,341:
Ejemplo:
Ejemplo:


#include <hopper.h>
#include <hopper.h>
main:
main:
false(i)
false(i)
iif(i, {"Es verdad\n"},\
iif(i, {"Es verdad\n"},\
iif(true,{"Es verdad por 2do intento\n"},{"Es falso"}))
iif(true,{"Es verdad por 2do intento\n"},{"Es falso"}))
println
println
return(0)
exit(0)


imprimirá: "Es verdad por 2do intento"
imprimirá: "Es verdad por 2do intento"