Print

Syntax

Translation in progress.


Hormiga Syntax

Table of contents


In this area it will be specified in the most possible clear way which is the language syntax, that is to say, in which way the programs should be written using Hormiga code.

What is an Hormiga program?

An Hormiga program is a simple text file which contains a specific configuration of the engine (or interpreter) in a well defined and structured language. Through this configuration or programming, the interpreter will guide the final user to make the desired calculation.
El lenguaje definido consta de un grupo de palabras reservadas (o tokens) que estrucutran el lenguaje y de identificadores del usuario que le permiten configurar de forma flexible el motor.

Generalidades del lenguaje

El lenguaje Hormiga es insensible a mayusculas/minusculas, lo que significa que VARIABLE y variable se interpretan de igual manera, tanto para las palabras reservadas como para identificadores definidos por el usuario.
Un programa Hormiga se compone de una serie de sentencias, cada una de las cuales termina con la "palabra" (o simbolo) reservado: ;

Estructura de un programa Hormiga

A continuación se muestra la estructura general de un programa Hormiga. Los textos en negrita son palabras reservadas. Los bloques de texto encerrados por los símbolos /* y */ son comentarios, lo que significa que ese bloque de texto no debe ser interpretado por el motor y solo se encuentra allí para claridad de quien programa.

Declaración de programa

Todo programa Hormiga comienza con una sentencia de declaración de progrma, donde además se le da un nombre:
program ProgramaDeEjemplo ;

Así mismo, todo programa termina con una declaración de fin de programa. Podemos notar que es necesario repetir el nombre, para dejar claro que es lo que queremos hacer:
end program ProgramaDeEjemplo ;

Por lo tanto, podemos definir que el Cuerpo del programa es todo lo que queda encerrado entre las dos sentencias anteriores:
program ProgramaDeEjemplo ;
    cuerpo del programa
end program ProgramaDeEjemplo ;

En general, el cuerpo del programa es un conjunto de declaraciones. Mas concretamente, un programa Hormiga tiene la forma:
program ProgramaDeEjemplo ;
    declaracion de magnitudes
    declaracion de constantes
    declaracion de funciones
    declaracion de steps
end program ProgramaDeEjemplo ;

Las secciones que estan en cursiva son opcionales.

Elementos de un programa Hormiga

Declaración de magnitudes

Dado que el lenguaje está orientado al cálculo, generalmente de problemas físicos, es necesario declarar las magnitudes con las cuales se operará. Una magnitud tiene asociada una unidad principal, en la cual el motor realizará los cálculos. A continuación declaramos una magnitud llamada Area y le creamos asociada una unidad llamada m2 (que nos simbolizará metros cuadrados):
declare magnitude Area unit m2 ;

Podemos agregar unidades adicionales (secundarias) asociadas a una magnitud definida previamente. Estas magnitudes adicionales puden ser utilizadas para mejorar la legibilidad del cádigo, evitar posibles errores de tipeo cuando los numeros son muy grandes (o muy pequeños) y codificar más cómodamente. A continuación declaramos una nueva unidad llamada mm2 asociada a la magnitud Area previamente declarada y especificamos que 1 mm2 = 0.000001 m2:
declare unit mm2 for magnitude Area := 0.000001 M2 ;

Las unidades a las que se hace referencia para la conversión (m2 en este ejemplo) deben pertenecer a la misma magnitud para la que se está creando la unidad.

Declaración de constantes

Las constantes permiten declarar valores en un único lugar y luego utilizarlos donde sea necesario. Las constantes tienen como objetivo hacer mas legible el código de los programas y definir un lugar único desde el cual puede controlarse su valor. Como su nombre indica, las constantes no varían su valor durante la ejecución del programa. Cualquier intento de asignar modificar el valor de una constante provocará un error. A continuación se declaran algunas constantes (se supone declarada la magnitud adimencional):
declare constant PI magnitude adimencional := 3.1416 ;
declare constant SupCircRadio2mm magnitude Area := PI * 4 mm ;

Luego podemos usar estas constantes, llamandolas por su nombre, en el resto del programa (o dentro del ambiente en el que fueron declaradas) para hacer referencia a su valor. En el ejemplo anterior puede verse el uso de la constante PI para calcular el valor de SupCircRadio2mm.

Declaración de variables

Las variables son objetos del lenguaje similares a las constantes. Se diferencian de las últimas en que, como su nombre lo indica, su valor puede variar durante la ejecución del programa. Una veriable nos permite almacenar valores como pueden ser resultados de una cierta operación o cálculo intermedio. A continuación se declara una variable llamada Superficie que representa un Area:
declare variable Superficie magnitude Area ;

Como puede verse, una variable no se declara con un inicial valor asociado. Si bien el motor las inicializará con un valor 0 (cero), es tarea del programador cuidar de no usarlas sin haberles dado un valor previamente.
Para evitar malas prácticas de programación, no se permite declarar variables en el ambito global (ver Ambitos mas adelante) sino que sólo pueden ser declaradas dentro del ámbito de una Función o un Step.

Expresiones aritméticas

Las expresiones aritméticas y booleanas son la base de cualquier cálculo que querramos realizar. El motor del lenguaje es capaz de interpretar y realizar las siguientes operaciones aritméticas:
  • Suma: expresion + expresion
  • Resta: expresion - expresion
  • Multiplicación: expresion * expresion
  • División: expresion / expresion
  • Factorial: expresion !
  • Módulo: expresion mod expresion
donde expresion puede ser un simple número (o constante numérica), un llamado a función o cualquier construcción a partir de las operaciones anteriores; es decir una suma o una división es también una expresión.
La presedencia de los operadores es la habitual y las operaciones pueden asociarse mediante el uso de ( ), por ejemplo:
Valor := ( 3 + 5 ) / ( 3 ! ) ;
Valor := PI * ( 3 + 5 ) / ( 3 ! ) ;

Se aclara que en el contexto del ejemplo anterior, se ve la asignación de una expresion a una variable.

Expresiones booleanas

Las expresiones booleanas serán utilizadas en estructuras de control de flujo. Funcionan de un modo similar a las expresiones aritméticas. Una expresión booleana simple puede ser cualquiera de las siguientes, donde expresion es cualquier forma de expresión aritmética:
  • Igual: expresion = expresion
  • Distinto: expresion <> expresion
  • Mayor estricto: expresion > expresion
  • Mayor o igual: expresion >= expresion
  • Menor estricto: expresion < expresion
  • Menor o igual: expresion <= expresion
Para lograr expresiones mas complejas, podemos convinar las anteriores mediante las operaciones siguientes. Aquí una expresión booleana ( en adelante boolexp ) puede ser una construcción simple (cualquiera de las anteriores) o mas compleja (formada por otras boolexp).
Las operaciones lógicas disponibles son:
  • Negación: NOT boolexp
  • AND lógico: boolexp AND boolexp.
  • NOT lógico: boolexp OR boolexp
El orden de precedencia es el mismo en el que se listaron: NOT, AND, OR.
Ejemplos:
3 > 5 /* falso */
3 <= 5 /* verdadero */
3 <> 5 /* verdadero */
NOT 3 > 5 /* verdadero, es lo mismo que: 3 <= 5 */
( 2 * PI ) <= 3 AND 1 < 5 /* falso */
( 2 * PI ) >= 3 AND 1 < 5 /* verdadero */
( 2 * PI ) > 3 AND 1 >= 5 /* falso */
( 2 * PI ) <= 3 OR 1 < 5 /* verdadero */
( 2 * PI ) >= 3 OR 1 < 5 /* verdadero */
( 2 * PI ) > 3 OR 1 >= 5 /* verdadero */
( 2 * PI ) < 3 OR 1 >= 5 /* falso */
/* Unos ejemplos mas complejos */
2 <= 3 AND 1 < 5 AND 7 > 5 /* verdadero */
2 <= 3 AND 1 < 5 AND 7 <= 5 /* falso */
2 <= 3 OR 1 < 5 AND 7 > 5 /* verdadero */
( 2 <= 3 OR 1 < 5 ) AND 7 > 5 /* falso */

Asignaciones

Las asignaciones permiten, valga la redundancia, asignarle un valor a una variable (perdiendo ésta su valor anterior). En adelante, cuando se utilize la varible en una expresión, tomará el nuevo valor. Para realizar una asignación se escribe el nombre de la variable a la que queremos cambiar su valor, seguida del símbolo reservado := y luego una expresion matemática (o un simple valor) terminada por ;. A continuación se muestran algunos ejemplos:
/* Asignamos una constante a una variable. En adelante ambas valen igual */
Superficie := PI ;
/* Ahora hacemos que Superficie valga '5.3' */
Superficie := 5.3 ;
/* También podríamos calcular la superficie de un círculo de radio 2 m */
Superficie := PI * 4 ;
/* O utilizar la funcion que definiremos a continuación para calcular la misma superficie */
Superficie := SuperficieCirculo( 2 ) ;

La idea general es: el símbolo ':=' indica una asignación. Del lado izquierdo solo puede haber el nombre de una varible declarada previamente. Del lado derecho puede aparecer cualquier tipo de expresión, tan complicada como sea necesario ;) Más adelante trataremos las expresiones.

Estructuras de control de flujo

Muchas veces, mientras realizamos un cálculo, es necesario realizar una tarea u otra dependiendo de diferentes valores o condiciones que venimos recolectando durante el cálculo. Este camino que venimos trazando con los cálculos realizados (instrucción a instrucción) se llama flujo del programa. Existen diferentes estructuras de control que nos permiten especificar los pasos a seguir de manera completa, utilizando evaluación de condiciones booleanas para decidir que hacer.

Estructura de ejecución condicional: IF

La estructura condicional IF nos permite realizar una tarea (u otra) dependiendo de una condición que declaramos. La instrucción condicional IF tiene (en general) 3 bloques configurables: una condición booleana, un bloque de ejecución cuando la condición se cumple y otro bloque de ejecución en caso contrario. Por ejemplo:
if Superficie <> 0 then
    Altura := Volumen / Superficie ;
else
    Altura := 1 ;
end if ;

En el ejemplo podemos ver:
  • la condición booleana: Superficie <> 0
  • el bloque de ejecución verdadero: Altura := Volumen / Superficie ;
  • el bloque de ejecución falso: Altura := 1 ;
La condición booleana puede ser tan compleja como necesitemos y los bloques de ejecución pueden ser solo una instrucción (como en el ejemplo) o varias seguidas.
La rama falsa es opcional, y no necesita estar presente siempre; otra estructura correcta de IF puede ser:
if Superficie <> 0 then
    Altura := Volumen / Superficie ;
end if ;

Estructura de repetición condicional: WHILE

La estrucutura while es similar (en sintaxis) al if (sin la rama falsa). Posee una condición booleana y un bloque de ejecución. En este caso el bloque de ejecución será ejecutado 0 o más veces mientras la condición se cumpla:
Distancia := 100 ;
while Distancia > 0 do
    Distancia := Distancia / 2 ;
end while ;

En este ejemplo se muestra la sintaxis de la sentencia while. Sin embargo se introdujo un error a drede. Lo que se muestra programado es el problema del conejo que, para llegar a la meta, siempre recorre la mitad de la distancia que le falta para llegar. De esta forma, el primer tramo es recorrido rápidamente pero, si bien se acerca indefinidamente, nunca logra realmente llegar (recordemos que estamos trabajando con números reales). Es necesario tener especial cuidado al escribir sentencias while, ya que podríamos caer en un ciclo infinito como en el ejemplo anterior. Debe verificarse que la ejecución del bloque de código haga que la condición (tarde o temprano) deje de cumplirse.
Por otro lado, si la condición no se cumple al menos la primera vez, el bloque de instrucciones NO se ejecuta.

Estructura de repetición pre-establesida: FOR

Si bien con la sentencia while alcanza para realizar cualquier tipo de ciclo, hay casos en que una determinada tarea debe repetirse un número determinado de veces, o sobre una secuencia determinada de valores. Para ello existe una estructura de repetición llamada for que toma una variable (previamente declarada) y en cada ciclo, le asigna un valor obtenido de una secuencia (cuyo incremento queda determinado por el parámetro Step). En el siguiente ejemplo la variable Valor va tomando los valores: 1, 1.5, 2, 2.5, ... y así hasta lo que valga la variable Maximo (que podría ser el resultado de un cálculo previo) que en nuestro ejemplo la hemos fijado en 5:
Maximo := 5 ;
/* otras líneas de código por acá que quizas hagan algo... */
for Valor := [ 1 .. Maximo step 0.5 ] do
    Producto := Producto * Valor ;
end for ;


Funciones

Funciones Internas

El intérprete provee un conjunto de funciones de utilidad general. Una función interna es una herramienta provista que realiza una funcionalidad bien definida. Las funciones se invocan con uno o mas parámetros y retornan un valor específico (al igual que cualquier función matemática).
Puede ver el listado de funciones internas disponibles en la página de "Funciones internas"

Utilización de funciones

Una función se utiliza llamándola por su nombre seguido, entre paréntesis, de uno o más parámetros (según la funcón haya sido refinida); es decir una función concebida para recibir 2 parámetros debe ser invocada con exactamente 2 parámetros, del mismo tipo y en el mismo orden. Por ejemplo, el motor cuenta con una función interna llamada 'pow' que calcula una potenciación. Esta función recibe por parámetro 2 números: base y exponente (en ese orden). Cada uno de ellos puede ser un simple número (o constante) o una expresión. En el siguiente ejemplo se muestra un posible uso de la función pow. Supongamos que calculemos el volumen de un cilindor (PI*r2) de radio 3 y altura 5:
Superficie := PI * pow( 3 , 2 ) * 5 ;
/* O si tenemos el radio y la altura en una variable llamada radio y altura respectivamente... */
Superficie := PI * pow( radio , 2 ) * altura ;
/* Contando con la función sqrt que calcula la raiz cuadrada de su parámetro, podemos hacer algo (ridículo) como... */
Superficie := sqrt( pow( radio , 2 ) ) ;

En el último ejemplo la variable Superficie deberia valer simplemente radio, ya que estamos calculando la raíz cuadrada del resultado de haber hecho radio al cuadrado. Esta no parece ser una operación muy útil; solo se buscaba mostrar que es posible dar por parámetro a una función el llamado a otra función (que podría ser eventualmente la misma).

Declaración de funciones del usuario

Una función definida por el usuario nos permite crear un módulo de código reutilizable que tiene una funcionalidad bien definida. Generalmente una función recibe uno o mas parámetros, elavoran un único resultado asociado a sus parámetros y lo retornan. El usuario puede definir sus propias funciones en la medida que le sean necesarias y utilizarlas luego de la misma manera que cualquier otra función interna. A continuación se declara la función SuperficieCirculo encargada de calcular la superficie de un círculo a partir de su radio; para ello recibe un único parámetro, el radio del círculo (asociado a una magnitud previamente declarada llamada distancia) que queremos calcular, y retorna una magnitud Area:
declare function SuperficieCirculo ( Radio magnitude Distancia ) magnitude Area ;
    SuperficieCirculo := PI * Radio * Radio ;
end function SuperficieCirculo ;

Como podemos ver, los parámetros de una función se encierran entre paréntesis. En caso de requerir más de un parámetro, se los declara de igual manera separados por coma.
Para indicarle a una función cual es el valor que debe retornar, se realiza una asignación a una variable que lleva el mismo nombre que la función (como muestra la línea central). A continuación se muestra un ejemplo de una función que recibe 2 parámetros (superficie y altura) y calcula el volumen de un cuerpo (simple). Una vez más, suponemos que las magnitudes aquí invovadas fueron previamente declaradas:
declare function VolumenSimple ( Altura magnitude Distancia , Superficie magnitude Area ) magnitude Volumen ;
    VolumenSimple := Superficie * Altura ;
end function VolumenSimple ;

Destacamos que los parámetros declarados de una función son Variables Implisitamente Declaradas. Por ello es posible usarlas para obtener su valor, como así también para asignarles uno nuevo. En este último caso el cambio tiene vigencia solo dentro del ámbito de la función (lo que se llama pasaje de parametros por copia).
Por otro lado, una función definida por el usuario se ejecuta más lentamente que una función interna. Por ello es deseable que en lo posible se utilizen las funciones internas antes de definir una nueva función que realice lo mismo.

Cálculo de integrales definidas

Es posible obtener el resultado de integrar una función en un rango definido. El cálculo de la integral se realiza por cálculo iterativo; es decir que la integral se convierte a una sumatoria por cada dimensión integrada. Por ejemplo podemos integrar la función sqrt (que solo recibe un parámetro) en el intérvalo 4..9 utilizando un diferencial de ancho 0.01 (suponiendo declarada una variable llamada resultado):
resultado := sqrt( [ 4 .. 9 step 0.01 ] ) ;

En caso que la función reciba más de un parámetro, podemos integrarla sobre todos o un conjunto cualquiera de ellos. Por ejemplo:
/* Sobre ambos parámetros... */
resultado := pow( [ 4 .. 9 step 0.001 ] , [ 5 .. 7 step 0.01 ] ) ;
/* Sobre solo uno de ellos, dejamos el otro fijo... */
resultado := pow( [ 4 .. 9 step 0.001 ] , 8 ) ;

La función a integrar puede ser cualquiera de las disponibles para uso general, ya sea interna o definida por el usuario. El intérprete realizará una integración simpre que al menos uno de los parámetros sea una construcción pura de tipo secuencia (como las mostradas en los ejemplos anteriores). Ver El operador Secuencia para mas detalles.

Steps

Un step es una unidad funcional de cálculo, en la cual es dividido el problema. En general un step queda delimitado por la necesidad de interacción con el usuario final; como ser, pedirle que ingrese un valor o mostrarle un cierto resultado (final o intermedio). La estructura general de un Step es:
declare step StepDeEjemplo ;
    declaracion bloque de dependencias
    declaracion de magnitudes
    declaracion de constantes
    declaracion de variables
    declaracion de capturas
    declaracion de reportes
    declaracion de bloque de salida
    declaracion de bloque de ejecucion
    declaracion de post-condicion de step
end program ProgramaDeEjemplo ;

Las secciones escritas en cursiva son opcionales.
Los bloques de dependencias, bloques de salida, capturas y reportes son elementos exclusivos de los Steps.

Declaración de capturas

Las capturas permiten que el programa hormiga interactúe con el usuario final. Por medio de estas es posible solicitar, en medio de la ejecución, que el usuario cargue un valor (que será alojado en una variable declarada) que es parámetro para el programa, necesario para resolver el cálculo específico. Una captura se declara (generalmente) asociada a una variable, especificandose en que forma se quiere el ingreso del valor. Es posible controlar que el número ingresado cumpla con siertas condiciones y que por defecto se inicie con un valor específico. A continuación se muestra la declaración de una captura asociada a una varible (supuestamente definida previamente) llamada altura, la cual debe ser cargada con un valor positivo y que por defecto vale 5:
declare capture for variable entrada type ctxt label "Ingrese el valor de altura"
          postcondition altura > 0 default := 5 ;

El texto que sigue a la palabra reservada label encerrado entre comillas será mostrado en la interfaz gráfica, para guiar al usuario y darle a conocer que valor está configurando.
Las capturas se realizan antes de ejecutar el Step (su bolque de ejecución).
Existen otros tipos de captura adicionales como podemos ver a continuación:
Captura numérica controlada gráficamente
Esta captura es muy similar a la anterior, pero el valor se elije gráficamente dentro de un rango acotado. Su sintaxis es como sigue:
declare capture for variable entrada type cgui label "Elija el valor de altura"
          range [ 0.05 .. 10 step 0.005 ] default := 5 ;

Captura de selección
Esta captura presenta al usuario una lista de opciones entre las cuales puede elejir solo una. Las opciones son representadas por una lista de cadenas separadas por coma (,) Cada una de las opciones es mapeada a un numero segun orden comenzando a contar desde 0 (cero). Asi la primer opción siempre es retornada como 0 y es la opción que el sistema entendera como pre-seleccionada; la segunda opción sera retornada como 1 y así sucesivamente.
declare capture for variable entrada type cselect label "Seleccione el perfil:"
          options "Hierro cuadrado" , "Hierro T" , "Hierro L" ;

Mostrar una imagen durante las capturas
Puede mostrarse una imagen durante las capturas para complementar informacion al usuario o hacer la vista mas bonita ;) . Para esto se debe colocar un archivo con la imagen a mostrar dentro del rango de busqueda de modulos. Las imagenes no tienen límite de tamaño pero se aconseja no colocar imágenes pesadas. Para asegurar la visión de estas, el sistema escalará las imagenes que superen los 800x600 pixeles a esta medida (manteniendo el aspecto). Los formatos soportados son los comunes: png, gif, jpg, bmp,...
declare capture from file "table.png" type cimg label "Tabla de valores" ;

Mostrar el gráfico de una función de 2D
Puede mostrarse el gráfico de una función, ya sea interna o declarada por el usuario, al momento de las capturas de un step. La función puede tener cualquier cantidad de parámetros (al menos 1), pero solo uno de ellos puede ser invocado con una secuencia, sobre la cual se graficará. Dicho parámetro será tomado como el eje X de gráfico y la evaluación de la función ( f(x) ) como eje Y. El resto de los parámetros, si los hubiese, deben ser expresiones simples: variables, constantes o una combinación algebráica de éstas incluyendo también el invocación de funciones; es decir cualquier otra cosa que no sea una simple secuencia.
declare capture type cplot label "Gráfico de sen(x) entre 0 y 2PI" function sin( [0 .. 6.29 step 0.1] ) ;
declare capture type cplot label "Gráfico de log5(x) entre 5 y 23" function log( 5 , [5 .. 23 step 0.1] ) ;

Como siempre, el parámetro step regula la definición del gráfico; es decir, qué tan preciso es. Un valor muy grande hará que al gráfico le falten puntos, haciéndolo cuadrado; por el contrario, un valor execivamente pequeño provocará que consuma mayor cantidad de memoria y tome más tiempo realizarlo. Queda en el programador, quien conoce la naturaleza y características de la función que grafica, ajustar el step debidamente.
Considere que, como se explicaba en el párrafo anterior, realizar el gráfico de una función puede consumir muchos recursos; por lo tanto, en caso que el gráfico de la función sea siempre el mismo (no varía de una ejecución a otra, ni depende de parámetros) seguramente sea conveniente que tome una imagen del mismo y la coloque usando una captura de tipo CIMG.
Notará que la sintaxis de invocación de la función es idéntica a un cálculo de integración; no se preocupe, el intérprete sabrá que hacer.

Declaración de reportes

Los reportes son la contrapartida de las capturas, y sirven para mostrar un resultado. Tienen un formato similar al de la captura correspondiente, pero ya que son solo informativos no necesitan de las condiciones de control ni el valor por defecto. A continuación se muestra una declaración de reporte asociada a una variable (supuestamente definida previamente) llamada resultado:
declare report for variable resultado type ctxt label "Resultado del calculo" ;

Los reportes se muestran al finalizar el bloque de ejecución del Step.
Existen otros tipos de captura adicionales como podemos ver a continuación:
Reporte numérico con escala
Este reporte es similar al anterior pero muetra el valor dentro de una escala pre-establesida.
declare report for variable entrada type cgui label "Altura:"
          range [ 10.5 .. 50 step 0.1 ] ;

Reporte de selección
Este reporte, como contrapartida a la captura de igual nombre, permite mostrar uno texto de los textos de la lista de opciones, según sea el valor de la variable asociada.
declare report for variable entrada type cselect label "Perfil calculado:"
          options "Hierro cuadrado" , "Hierro T" , "Hierro L" ;

Mostrar una imagen durante los reportes
Al igual que durante las capturas, es posible mostrar imagenes durante los reportes. Puede ver a continuación un ejemplo de uso. Para mas información vea el mas arriba Mostrar una imagen durante las capturas.
declare report from file "table.png" type cimg label "Tabla de valores" ;

Mostrar el gráfico de una función de 2D
Puede mostrarse el gráfico de una función, ya sea interna o declarada por el usuario, al momento de los reportes de un step. Vea el mismo apartado para las capturas para mas información.
declare report type cplot label "Gráfico de sen(x) entre 0 y 2PI" function sin( [0 .. 6.29 step 0.1] ) ;

Exportación de datos

Un Step puede exportar valores calculados para que estén disponibles para otros Steps. Esta tarea se realiza agregando las variables de interés en el bloque de salida. Las variables a exportar deben habar sido declaradas dentro del mismo step que la exporta. A continuación se muestra un ejemplo de bloque de salida que exporta una variable llamada resultadoStep1:
begin export ;
    variable resultadoStep1 ;
end export ;

En adelante, los Steps declarados después de este, podrán acceder al dato calculado.

Dependencias entre Steps

Cuando un Step necesita que otro se haya ejecutado previamente por que utiliza un valor que este último genera (calcula), estamos ante la precencia de una dependencia. Una dependencia se declara agregando el nombre de la variable que necesitamos utilizar (que es exportada por el Step que la genera) en el bloque de dependencias. A continuación se muestra un bloque de dependencias de un step que depende del supuesto Step1:
begin needs ;
    variable resultadoStep1 ;
end needs ;

Opcionalmente, aunque no es recomendado su uso, se puede declarar la dependencia de un step, suponiendo que el step que exporta la variable anterior es llamado Step1:
begin needs ;
    step Step1 ;
end needs ;

Bloque de ejecución

Los steps cuentan con un bloque de ejecución, que son la razon de ser de un Step. Un paso de cálculo debe tener al menos eso... un cálculo. Los bloques de ejecución de los step tienen una forma similar a:
begin execution ;
    miVariable := resultadoStep1 * PI ;
end execution ;

Declaración de Post-Condiciones de Step

Finalmente, los Steps pueden especificar una lista de Post-Condiciones compuestas por una condición booleana y un texto a mostrarse en caso que la evaluación de la condición falle (sea falsa). Estas condiciones se evalúan al finalizar la ejecución del step en cuestión, y en caso de fallar alguna evita que los Steps que dependen de éste se habiliten para ejecución, ya que supone un estado no aceptable del presente Step.
postcondition miVariable > 0 or show "El resultado es Negativo" ;
postcondition variable1 <> variable2 or show "Los valores son distintos" ;

Como siempre, la expresión booleana puede ser tan compleja como sea necesario, y el alcance de la misma es igual al del cuerpo del Step.

Modulos

El uso de modulos permite reutilizar partes de codigo en varios programas. Cada modulo es un archivo con un formato particular (similar al de un programa) que contiene una coleccion de elementos de programa Hormiga: declaracion de magnitudes, unidades, constantes, funciones y steps como asi tambien declaraciones de uso de otros modulos.

Declaracion de uso

Las declaraciones de uso de modulo se colocan inmediatamente despues de la sentencia de declaración de programa o modulo y significa literalmente que esa sentencia sera reemplazada por el contenido del modulo invocado. En caso que este ultimo necesite mas modulos, estos seran tambien incluidos de forma automatica. A continuacion se da un ejemplo de declaracion de uso de modulo:
program ProgramaDeEjemplo ;
    needs module "sistemas/simela.hrm" ;
    needs module "otro_modulo.hrm" ;
    ...

Cada declaracion de uso hace referencia a un archivo ubicado en un directorio definido por el sistema, o eventualmente en algun subdirectorio del mismo. Por esta razon, nunca se debe hacer referencia a un modulo utilizando una ruta absoluta. En el ejemplo anterior se declara el uso de 2 modulos; el primero se encuntra en un archivo llamado simela.hrm el cual esta alojado dentro de un subdirectorio llamado sistemas; el segundo hace referencia a un modulo cuyo archivo es llamado otro_modulo.hrm. Ambas direcciones de archivo son relativas al directorio de modulos Hormiga.
Cabe aclarar que para separar de directorios debe usarse la barra a derecha (/) para asegurar la portabilidad de los programas y modulos Hormiga.

Directorio de modulos Hormiga

El directorio de modulos hormiga es el lugar a partir del cual lo modulos son buscados. Este directorio depende de la arquitectura sobre la cual el interprete es ejecutado (Windows, Linux, Mac, etc):
  • En Windows: C:\hormiga\modules\
  • En Linux: /usr/lib/hormiga/modules/
  • En Mac OSX: /usr/lib/hormiga/modules/
Esta configuracion puede ser sobre escrita utilizando la clave Core/Modules_Path en la configuracion de Hormiga (por ahora solo usuarios avanzados).

Estructura de un modulo

Cada modulo debe ser declarado en archivos independientes y cada uno de ellos contiene solo un tipo de declaracion. Un archivo que declara modulos posee un formato como el siguiente:
module funciones_simela ;
  needs module "sistemas/simela.hrm" ;
  declare function Area ( b magnitude longitud, h magnitude longitud ) magnitude area ;
    A := b * h  ;
  end function Area ;
end module funciones_simela ;

Un buen nombre para el archivo que contenga este modulo podria ser funciones_simela.hrm eventualmente alojado en algun subdirectorio como podria ser funciones. Este modulo usa otro modulo (que esta en el archivo sistemas/simela.hrm en el directorio de modulos) y declara una funcion llamada Area. Luego cualquier programa Hormiga podria usar esta funcion (o cualquier otro elemento declarado dentro de ese modulo o incluida por el) con solo declarar el uso de este modulo.

El operador Secuencia

Ambitos de las declaraciones



Calendar


March 2012 - March 2012
S M T W T F S
26 27 28 29 01 02 03
04 05 06 07 08 09 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

Upcoming events

Last blog posts

No records to display