3-64 CAPÍTULO 3. MÉTODO ALGEBRAICO DE ESPECIFICACIÓN. 3.6 Introducción a Maude Maude es un lenguaje que permite la ejecución simbólica de especificaciones algebraicas dadas mediante ecuaciones y pertenencias, es modular y admite la definición de módulos parametrizados ası́ como su instanciación. A continuación veremos, de manera sucinta, sus caracterı́sticas sintácticas2 . 3.6.1 Especificación de módulos La especificación de un módulo (funcional) en Maude tiene el aspecto siguiente: fmod <nombre del modulo> is <cuerpo del modulo> endfm y en el cuerpo de un módulo pueden aparecer las siguientes declaraciones con los formatos que se enuncian en los ejemplos: • Declaraciones de universos y de subuniversos (pueden repetirse): sort S . sorts S1 S2 S3 S4 . subsort S1 < S2 . subsorts S1 < S2 < S3 . subsorts S1 < S2 S4 < S3 . En el último caso, los universos S2 y S4 no están relacionados aunque ambos contienen a S1 y están contenidos en S3. • Declaraciones de operaciones: op p : -> S1 . op p : S1 S2 -> S3 . ops p q : S1 S2 -> S3 . Estas declaraciones pueden etiquetarse con [ctor] para indicar que se trata de una operación generadora del tipo del resultado. Las operaciones pueden declararse infijas mediante guiones de subrayado en los lugares donde deban aparecer los argumentos. • Declaraciones de variables: 2 Para una descripción más completa de la sintaxis de Maude véase “Maude: Specification and Programming in Rewriting Logic” y “A Maude Tutorial”, ambos documentos disponibles en la dirección http://maude.cls.sri.com. 3.6. INTRODUCCIÓN A MAUDE 3-65 var X : S . vars X Y : S . • Declaraciones de axiomas: ecuaciones y pertenencias. Ambos tipos pueden aparecer condicionados, pero las condiciones se reducen siempre a un término b de tipo booleano obtenido a partir de expresiones construidas con las operaciones predefinidas _==_ y _=/=_ correspondientes al test de igualdad semántica y su fallo, y con _:_ o test de pertenencia, definidos para todos los universos. Declaraciones de ecuaciones: eq t1 = t2 . ceq t1 = t2 if b . Declaraciones de pertenencias: mb t : S . cmb t : S if b . • Declaraciones de importación de módulos (pueden repetirse): including <nombre de modulo> . protecting <nombre de modulo> . La primera indica una importación sin restricciones semánticas y se utiliza para especificaciones no acabadas en las que se pueden producir ampliaciones o reducciones de los conjuntos de valores. En cambio, la segunda indica que se va a respetar la especificación importada añadiendo, a lo más, alguna función nueva que no afecta a los conjuntos de valores establecidos. Las declaraciones de importación se escriben al principio del cuerpo del módulo, después aparecerán las declaraciones de universos y de subuniversos, las operaciones, las variables y los axiomas (aunque este orden puede alterarse). Todas las variables que se utilicen en los axiomas deben estar declaradas y en las expresiones puede utilizarse cualquier operación declarada en el módulo o importada de otro módulo. 3.6.2 Ejemplos Veamos cómo se escribirı́an en Maude los módulos correspondientes a algunas de las especificaciones que se han estudiado en los apartados anteriores. Un módulo para la especificación del universo de los booleanos quedarı́a: 3-66 CAPÍTULO 3. MÉTODO ALGEBRAICO DE ESPECIFICACIÓN. fmod BOOL is sort Bool . ops true false : -> Bool [ctor] . op not_ : Bool -> Bool . ops _and_ _or_ : Bool Bool -> Bool . var X : bool . eq not true = false . eq not false = true . eq X and true = X . eq X and false = false . eq X or true = true . eq X or false = X . endfm Un módulo como éste (con algunas operaciones más) está predefinido en Maude y se importa de forma automática en cada módulo que se defina, por lo que los valores las operaciones lógicas siempre están disponibles sin que necesaria su importación explı́cita. El módulo para la especificación de números naturales que aparece en el Ejemplo 3.7, con algunas operaciones de ejemplos posteriores, queda fmod NAT is sorts NatNz Nat Nat? . subsorts NatNz < Nat < Nat? . op z : -> Nat [ctor] . op s_ : Nat -> NatNz [ctor] . ops _+_ _*_ : Nat Nat -> Nat . op _-_ : Nat Nat -> Nat? . op _/_ : Nat NatNz -> Nat . op _mod_ : Nat NatNz -> Nat . op mcd : Nat Nat -> Nat? . op raiz : Nat -> Nat . op rz : Nat Nat -> Nat? . *** op. auxiliar *** op _<=_ : Nat Nat -> Bool . op _<_ : Nat Nat -> Bool . vars M N : Nat . var P : NatNz . 3.6. INTRODUCCIÓN A MAUDE 3-67 eq z + N = N . eq (s M) + N = s (M + N) . eq z * N = z . eq (s M) * N = (M * N) + N . cmb M - N : Nat if N <= M . eq M - z = M . eq (s M) - (s N) = M - N . ceq ceq M / P = z if M < P . M / P = s ((M - P) / P) if P <= M . ceq M mod P = M if M < P . ceq M mod P = (M - P) mod P if P <= M . cmb mcd(M, N) : Nat if (M =/= z) or (N =/= z) . eq mcd(P, z) = P . ceq mcd(M, N) = mcd(N, M) if M < N . ceq mcd(M, P) = mcd(M - P, P) if P <= M . eq raiz(N) = cmb rz(N, M) ceq rz(N, M) ceq rz(N, M) rz(N, z) . : Nat if (M * M) <= N . = M if ((M * M) <= N) and (N < ((s M) * (s M))) . = rz(N, s M) if ((s M) * (s M)) <= N . eq z <= N = true . eq (s M) <= z = false . eq (s N) <= (s M) = N <= M . eq M < z = false . eq z < (s N) = true . eq (s M) < (s N) = M < N . endfm donde, por lo que se ha dicho más arriba, ya no es necesario declarar ni importar explı́citamente los valores lógicos. Un módulo para los números enteros, donde se utilizan los subuniversos Pos y Neg correspondientes a los números positivos y a los números negativos, queda fmod ENT is 3-68 CAPÍTULO 3. MÉTODO ALGEBRAICO DE ESPECIFICACIÓN. sorts Ent Nat Pos Neg . subsorts Pos < Nat < Ent . subsort Neg < Ent . op z : -> Nat [ctor] . ops s_ p_ : Ent -> Ent [ctor] . ops _+_ _-_ _*_ : Ent Ent -> Ent . op abs : Ent -> Nat . op _div_ : Nat Pos -> Nat . op mcd : Nat Nat -> Nat . ops _<=_ _<_ : Ent Ent -> Bool . vars E E1 E2 : Ent . var N N1 N2 : Nat . var P : Pos . mb s N : Pos . mb p z : Neg . mb p Q : Neg . eq s (p E) = E . eq p (s E) = E . eq z + E2 = E2 . eq (s E1) + E2 = s (E1 + E2) . eq (p E1) + E2 = p (E1 + E2) . eq E1 - z = E1 . eq E1 - (s E2) = p (E1 - E2) . eq E1 - (p E2) = s (E1 - E2) . eq z * E2 = z . eq (s E1) * E2 = (E1 * E2) + E2 . eq (p E1) * E2 = (E1 * E2) - E2 . eq abs(N) = N . eq abs(Q) = z - Q . ceq N div P = z if N < P . var Q : Neg . 3.6. INTRODUCCIÓN A MAUDE 3-69 ceq N div P = s ((N - P) div P) if P <= N . eq mcd(N, z) = N . ceq mcd(N1, N2) = mcd(N1 - N2, N2) if N2 <= N1 . ceq mcd(N1, N2) = mcd(N2, N1) if N1 < N2 . ceq E1 <= E2 = true if E2 - E1 : Nat . ceq E1 <= E2 = false if E1 - E2 : Pos . ceq E1 < E2 = true if E2 - E1 : Pos . ceq E1 < E2 = false if E1 - E2 : Nat . endfm Y un módulo para los números racionales representados mediante pares formados por un número entero (numerador) y un entero positivo (denominador) queda: fmod RAC is protecting ENT . sorts RacNz Rac . subsort Ent < Rac . subsort Pos Neg < RacNz < Rac . op _/_ : Ent Pos -> Rac [ctor] . op a-ent : Rac -> Rac . ops _+._ _-._ _*._ : Rac Rac -> Rac . op _/._ : Rac RacNz -> Rac . ops _<._ _<=._ : Rac Rac -> Bool . vars e e1 e2 : Ent . vars p p1 p2 : Pos . cmb e / p : RacNz if e =/= z . var n : Neg . *** simplificacion de racionales *** ceq p1 / p = (p1 div mcd(p1, p)) / (p div mcd(p1, p)) if (s z) < mcd(p1, p) . ceq n / p = (z - (abs(n) div mcd(abs(n), p))) / (p div mcd(abs(n), p)) if (s z) < mcd(abs(n), p) . eq z / p = z . eq e1 / s z = e1 . *** operaciones *** 3-70 CAPÍTULO 3. MÉTODO ALGEBRAICO DE ESPECIFICACIÓN. eq eq eq eq e1 +. e2 = e1 + e2 . e +. (e2 / p2) = ((e * p2) + e2) / p2 . (e1 / p1) +. e = (e1 + (e * p1)) / p1 . (e1 / p1) +. (e2 / p2) = ((e1 * p2) + (e2 * p1)) / (p1 * p2) . eq eq eq eq e1 -. e2 = e1 - e2 . e -. (e2 / p2) = ((e * p2) - e2) / p2 . (e1 / p1) -. e = (e1 - (e * p1)) / p1 . (e1 / p1) -. (e2 / p2) = ((e1 * p2) - (e2 * p1)) / (p1 * p2) . eq eq eq eq e1 *. e2 = e1 * e2 . e *. (e2 / p2) = (e * e2) / p2 . (e1 / p1) *. e = (e1 * e) / p1 . (e1 / p1) *. (e2 / p2) = (e1 * e2) / (p1 * p2) . eq eq eq eq eq eq eq eq e /. p = e / p . e /. n = (z - e) / (z - n) . e /. (p1 / p) = (e * p) / p1 . e /. (n / p) = (z - (e * p)) / (z - n) . (e1 / p1) /. p = e1 / (p1 * p) . (e1 / p1) /. n = (z - e1) / (z - (p1 * n)) . (e1 / p1) /. (p / p2) = (e1 * p2) / (p * p1) . (e1 / p1) /. (n / p2) = (z - (e1 * p2)) / (z - (n * p1)) . eq e <. (e1 / p) = (e * p) < e1 . eq (e1 / p) <. e = e1 < (p * e) . eq (e1 / p1) <. (e2 / p2) = (e1 * p2) < (e2 * p1) . eq e <=. (e1 / p) = (e * p) <= e1 . eq (e1 / p) <=. e = e1 <= (p * e) . eq (e1 / p1) <=. (e2 / p2) = (e1 * p2) <= (e2 * p1) . endfm donde los números enteros se consideran parte de los racionales y se establecen ecuaciones de simplificación para las representaciones de racionales que pueden llegar a producir un número entero. 3.6.3 Especificaciones genéricas Las especificaciones genéricas en Maude implican cuatro tipos de construcciones: la especificación de parámetros o teorı́as, la especificación de módulos parametrizados, la 3.6. INTRODUCCIÓN A MAUDE 3-71 instanciación de parámetros o especificación de enfoques de teorı́as y la particularización de módulos parametrizados. • Una especificación de parámetro o teorı́a se enuncia de manera parecida a un módulo, salvo por los delimitadores, fth <nombre del parametro> is <cuerpo> endfth con la única diferencia de que no pueden aparecer operaciones constructoras y las ecuaciones no son necesariamente reglas de reescritura (pueden aparecer variables nuevas a la derecha) y se interpretan como teoremas que deben satisfacerse en los módulos que sustituyan a dicho parámetro. Una especificación de parámetro denota a cualquier álgebra que cumpla sus axiomas (no necesariamente al álgebra inicial) y sirve para fijar los requisitos que debe cumplir un módulo para que pueda sustituir a un parámetro. Algunos ejemplos de teorı́as son: la teorı́a trivial TRIV, fth TRIV is sort Elt . endth que únicamente impone como requisito la existencia de un dominio de valores; la teorı́a ORDTOT, fth ORDTOT is sort Elt . op _<_ : Elt Elt -> Bool . vars E1 E2 E3 : Elt . eq E1 < E1 = false . ceq E1 < E2 = true if E1 < E3 and E3 < E2 . ceq E1 < E2 or E2 < E1 = true if E1 =/= E2 . endth que exige la existencia de un dominio con una relación de orden total; y la teorı́a COTA, fth COTA is protecting NAT . tmax : -> NatNz . endth que impone como requisito la existencia de un valor natural no nulo. 3-72 CAPÍTULO 3. MÉTODO ALGEBRAICO DE ESPECIFICACIÓN. • Un módulo parametrizado se declara de manera parecida a como se declara un módulo con las diferencias siguientes: junto al nombre del módulo debe aparecer una lista con los nombres de los parámetros y sus correspondientes teorı́as, estos parámetros se utilizan como si se tratase de importaciones con la salvedad de que los universos declarados en las teorı́as de los parámetros, cuando se utilicen, deben etiquetarse de manera postfija con los nombres de los parámetros correspondientes (para evitar ambigüedades cuando se empleen varios parámetros caracterizados por la misma teorı́a), y los universos que se definan en el módulo parametrizado deberán aparecer parametrizados en los mismos parámetros que el módulo. fmod <nombre del modulo> [X :: <nombre de teoria>] is protecting <nombre de modulo> . sort S[X] . subsort S.X < S[X] . ... ... endfm • Una instancia o un enfoque de una teorı́a es una forma de ver un módulo concreto como un caso particular de la teorı́a; para fijar dicho enfoque es necesario establecer una serie de identificaciones entre elementos del módulo y sus correspondientes elementos en la teorı́a. Esto se hace en Maude con la construcción siguiente view <nom. enfoque> form <nom. teoria> to <nom. modulo> is sort <sort de la teoria> to <sort del modulo> . ... op <op. de la teoria> to <op. del modulo> . ... endv • Una particularización de un módulo parametrizado se obtiene importando, de forma protegida, dentro de un módulo el nombre del módulo parametrizado con los parámetros sustituidos por enfoques. fmod <nombre instancia> is protecting <nom. modulo parametrizado>[nom enfoque] endfm 3.6. INTRODUCCIÓN A MAUDE 3-73 Ejemplos de especificaciones genéricas o módulos parametrizados, ası́ como de instanciaciones de dichos módulos, se irán viendo en los capı́tulos siguientes donde también se irán introduciendo algunas particularidades sobre la notación.