Introducción

ILC ha sido diseñado para funcionar bajo el sistema operativo Linux. No obstante, ha sido portado también a otras variantes de UNIX y a Windows. Por lo tanto, la siguiente información y ejemplos se basan en la versión de ILC para Linux.

Sintaxis reconocida

 - Instrucciones básicas (Siendo V una variable, y L una etiqueta)
V++ (Incrementar el valor de V en una unidad)
V-- (Decrementar el valor de V en una unidad)
V== (Sentencia vacía)
IF V != 0 GOTO L (Salto condicional a la línea marcada con la etiqueta (L) )

 - Variables de entrada:
X1, X2, X3, ...

 - Variable de salida:
Y

 - Variables locales:
Z1, Z2, Z3, ...

 - Etiquetas:
A1, A2, A3, ...
B1, B2, B3, ...
C1, C2, C3, ...
D1, D2, D3, ...
S1, S2, S3, ... (etiquetas de finalización)

 - Comentarios: Los comentarios los representamos con una secuencia de palabras en una línea que empieza por el caracter #.
Ejemplo:
# Asigna el valor de V1 a V2
V2 <- V1

Ejemplo:
V2 <- V1 # Asigna el valor de V1 a V2

Macros

ILC contiene soporte para macros, siendo todas estas definidas en un fichero adjunto que es extensible y modificable por parte de los usuarios sin necesidad de recompilar el código fuente. En el propio código fuente tan sólo están definidas las cuatro instrucciones primitivas de lenguaje L (V==, V++, V--, IF V != 0 GOTO L), estando las macros definidas a partir
de su expansión formada únicamente por dichas instrucciones primitivas. Hemos de remarcar que no esta soportado el anidar macros, teniendo que asignar la submacro a una variable y pasando esa variable como parámetro. Las macros que incorpora ILC son las siguientes:

· Salto incondicional a la etiqueta L:
GOTO L
· Asignación:
V1 <- V2
· Asignación nula:
V <- 0
· Asignación de un natural:
V <- N
· Suma:
V1 <- V2 + V3
· Suma con primer operando natural:
V1 <- N + V2
· Suma con segundo operando natural:
V1 <- V2 + N
· Resta:
V1 <- V2 - V3
· Resta con primer operando natural:
V1 <- N - V2
· Resta con segundo operando natural:
V1 <- V2 - N
· Multiplicación:
V1 <- V2 * V3
· Multiplicación con primer operando natural:
V1 <- N * V2
· Multiplicación con segundo operando natural:
V1 <- V2 * N
· División entera:
V1 <- V2 / V3
· División entera con primer operando natural:
V1 <- N / V2
· División entera con segundo operando natural:
V1 <- V2 / N
· Potencia:
V1 <- V2 pow V3
· Potencia con base natural:
V1 <- N pow V2
· Potencia con exponente natural:
V1 <- V2 pow N
· Divisor de:
IF (V1 | V2) GOTO L
· Divisor de con primer operando natural:
IF (N | V1) GOTO L
· Divisor de con segundo operando natural:
IF (V1 | N) GOTO L
· Comparación con 0:
IF (V1 = 0) GOTO L
· Mayor que:
IF (V1 > V2) GOTO L
· Mayor que con primer operando natural:
IF (N > V1) GOTO L
· Mayor que con segundo operando natural:
IF (V1 > N) GOTO L
· Mayor o igual que:
IF (V1 >= V2) GOTO L
· Mayor o igual que con primer operando natural:
IF (N >= V1) GOTO L
· Mayor o igual que con segundo operando natural:
IF (V1 >= N) GOTO L
· Menor que:
IF (V1 < V2) GOTO L
· Menor que con primer operando natural:
IF (N < V1) GOTO L
· Menor que con segundo operando natural:
IF (V1 < N) GOTO L
· Menor o igual que:
IF (V1 <= V2) GOTO L
· Menor o igual que con primer operando natural:
IF (N <= V1) GOTO L
· Menor o igual que con segundo operando natural:
IF (V1 <= N) GOTO L
· Igualdad:
IF (V1 = V2) GOTO L
· Igualdad con primer operando natural:
IF (N = V1) GOTO L
· Igualdad con segundo operando natural:
IF (V1 = N) GOTO L
· Desigualdad:
IF (V1 != V2) GOTO L
· Desigualdad con primer operando natural:
IF (N != V1) GOTO L
· Desigualdad con segundo operando natural:
IF (V1 != N) GOTO L
· Codificación de un par:
V1 <- < V2, V3 >
· Codificación de un número de Gödel:
V1 <- [ V2...Vn ]
· Parte izquierda:
V1 < l(V2)
· Parte derecha:
V1 < r(V2)
· Primo V2-esimo:
V1 <- p(V2)
· Primo N-esimo con:
V1 <- p(N)
· Proyección del elemento V3-ésimo de un número de Gödel:
V1 <- (V2)V3
· Proyección del elemento N-ésimo de un número de Gödel:
V1 <- (V2)N
· Longitud de un número de Gödel:
V1 <- Long(V2)
· Etiq:
V1 <- Etiq(V2, V3)
· Var:
V1 <- Var(V2, V3)
· Instr:
V1 <- Instr(V2, V3)
· Etiq':
V1 <- Etiq'(V2, V3)
· Variable V1-ésima distinta de 0 dentro de un estado de programa:
IF Delta_E(V1, V2) GOTO L
· Variable V1-ésima distinta de 0 dentro de una descripción instántanea:
IF Delta_DI(V1, V2) GOTO L
· Descripción instantánea inicial:
V1 <- Inic(V2...Vn)
· SKIP:
IF SKIP(V1, V2) GOTO L
· INCR:
IF INCR(V1, V2) GOTO L
· DECR:
IF DECR(V1, V2) GOTO L
· SALTO:
IF SALTO(V1, V2) GOTO L
· Siguiente descripción instantánea:
V1 <- Suc(V2, V3)
· Codificación de la descripción instantánea del programa Vn-1 después de Vn pasos:
V1 <- Inst(V2...Vn)
· FINAL:
IF FINAL(V1, V2) GOTO L
· PASOS (cierto si el programa Vn-1 se detiene antes o en Vn pasos):
IF PASOS(V1...Vn) GOTO L
· Funcion universal:
V1 <- Omega( V2...Vn )

El resto de macros no están predefinidas y tendrán que ser implementadas en el fichero "usr/share/ilc/macros/macros.m" o en cualquier otro definido por el usuario.  En cuanto a la sintaxis de estas macros las variables que utilizaremos serán:
- Variables de referencia: Se usan como parámetros de la macro y son T1,...,Tn
- Variables locales: Al igual que las Z en el codigo primitivo aquí utilizaremos sólo la W acompañada de un subíndice.

Y por lo que respecta a las etiquetas tendremos:
- De finalización: F, indica un salto a la siguiente instrucción a la macro
- Locales: Sólo se utilizarán los símbolos G1, G2, G3, ...

Remarcar que en la definición de las macros, al igual que en la definición de programas de código primitivo, también están permitidos los comentarios como una secuencia de palabras que empieza por el carácter #.

Algo que difiere en el intérprete respecto al lenguaje L teórico es la estructura de la definición de una macro. Distinguiremos dos bloques: la macro o cabezera y la expansión de la macro, ambos delimitados por llaves {...}.
En la cabecera de la macro utilizaremos cuatro identificadores distintos:

$ETIQ[V] ---> Indica que V es una etiqueta
$VAR[V] ---> Indica que V es una variable
$NATURAL[V] ---> Indica que V es un natural
L1...Ln ---> Indica que el parámetro es una lista de n variables

Y en el cuerpo o expansión de la macro utilizaremos las variables, etiquetas y números de la cabecera en conjunto con instrucciones primitivas y otras macros.

Ejemplo:
#
# Igualdad con primer operando natural
#

MACRO { IF ( $NATURAL[T1] = $VAR[T2] ) GOTO $ETIQ[T3] }
EXPANSION
{
        W1 <- T1
        IF (W1 = T2) GOTO T3
}

Otra intrucción que no está presente en el lenguaje L teórico es %MESP_REP( INST ; INC ; REP ).
Esta instrucción es una "macro especial" que tiene el efecto de expandir el código de la instrucción INST en el código de la macro donde aparezca tantas veces como indique REP con un incremento marcado por INC.

Opciones de ejecución

Para ejecutar el intérprete deberá escribir:

ilc [OPCIONES] <fichero> [<valor_X/X1> ... <valor_Xn>]

Entre las opciones disponibles podemos encontrar:

-a, --acerca-de: Muestra los créditos de ILC


-c, --codificar: Codifica un programa en L primitivo (sin macros) leido desde el archivo indicado en un número de Godel
Ejemplo:
$ cat prueba.l
(A) IF X != 0 GOTO S
Y++
$ ilc -c prueba.l
#P = [1533,2] - 1



-d, --descodificar: Descodifica un numero de Godel en un programa en L, mostrando este último por pantalla. Tenemos dos opciones en cuando a la representación del número de Gödel: en forma de tupla [1,2,3] y como un natural.
Ejemplo:
$ ilc -d [1,2,3]
(A1) Y==
Y++
(B1) Y==
$ ilc -d 2249
(A1) Y==
Y++
(B1) Y==



-e, --expandir-macros: Expande las macros de un programa y muestra el codigo en L primitivo (sin macros)
Ejemplo:
$ cat prueba.l
(A) IF X1 != 0 GOTO S
GOTO A
$ ilc -e prueba.l
(A) IF X1 != 0 GOTO S
Z1++
IF Z1 != 0 GOTO A



-h, --help: Muestra información sobre todas las opciones y uso de ILC.


-i, --imprimir-macros: Muestra las macros definidas en los ficheros de macros.


-m, --macros-adicionales: Establece el fichero con macros adicionales definidas por el usuario.
Ejemplo:
$ ilc -m ./macros_add.m prueba.l ---> Haría que el interprete buscase definiciones de macros también en el archivo "./macros.add.m" además de en "usr/share/ilc/macros/macros.m"


-n, --no-gui: Desactiva el modo gráfico.


-p, --pasos: Cuenta el número de pasos de ejecución hasta la finalización del programa en L.
Ejemplo:
$ cat prueba.l
(A) IF X1 != 0 GOTO S

GOTO A
$ ilc -p prueba.l 2
ILC (Intérprete de funciones L-Computables)

Variable de salida: 0
Pasos de ejecucion: 1



-s, --sintaxis: Comprueba la sintaxis del programa en L pasado como argumento sin ejecutarlo.
Ejemplo:
$ cat prueba.l
(A) IF H1 != 0 GOTO S
GOTO A
$ ilc -p prueba.l 2
ERROR: el codigo contiene una macro que no esta definida '(A) IF H1 != 0 GOTO S'


Ejemplo:
$ cat prueba.l
(A) IF X1 != 0 GOTO S
GOTO A
$ ilc -p prueba.l 2
La sintaxis es correcta



-t, --traza: Activa la ejecución del programa paso a paso mediante el depurador con el fin de hacer una traza del programa y corregir posibles errores de semántica
Ejemplo:
$ cat prueba.l
Y++
Z1--
X1++
Y--
$ ilc -t prueba.l 2
ILC (Intérprete de funciones L-Computables)

Instruccion: Y++
Descripcion: (1, (X1 = 2, Y1 = 0, Z1 = 0))
$

Instruccion: Z1--
Descripcion: (2, (X1 = 2, Y1 = 1, Z1 = 0))
$

Instruccion: X1++
Descripcion: (3, (X1 = 2, Y1 = 1, Z1 = 0))
$

Instruccion: Y--
Descripcion: (4, (X1 = 3, Y1 = 1, Z1 = 0))
$

Descripcion: (5, (X1 = 3, Y1 = 0, Z1 = 0))

Variable de salida: 0



-v, --version: Nos informa del número de versión del intérprete

Depurador

ILC posee un depurador que permite seguir paso a paso la ejecución de un programa con el fin de hacer más llevadera la corrección de errores. Para ello, se debe de ejecutar con la opcion -t o --trace. A continuación apareceran dos filas. En la primera de ellas aparece la línea de código que se está ejecutando, y en la segunda la descripción instantánea. Dentro del depurador se pueden ejecutar las siguientes ordenes:

 - p <variable>: imprime el valor de la variable <variable>
 - l o line: imprime el número de línea de la instrucción en ejecución.
 - f o finish: finaliza la ejecución del programa, ejecutando las instrucciones restantes y mostrando el valor de la variable de salida.
 - q o quit: finaliza la ejecución del programa sin ejecutar las restantes instrucciones.

Para pasar a la siguiente instrucción se deberá pulsar la tecla INTRO.