VAX Pascal - Maverick-Shark/retroGuru GitHub Wiki
Source (geocities) https://www.oocities.org/v.iniestra/apuntes/tall_prog/
Es un aparato al cual se le proporcionan datos, los computa y nos da un resultado.
Las computadoras digitales representan los fenómenos a base de dígitos binarios. Dígito binario = binary digit = bit. Puede tomar solo uno de dos valores posibles: 0, 1. A los dígitos binarios se les aplica el álgebra booleana. La computadora usa voltajes para representar cada bit:
0 voltios = 0 = falso
5 voltios = 1 = verdadero
Con un código binario (números binarios) se pueden representar una serie de valores:
0 0 falso Dom
1 1 verdadero Lun
2 10 Mar
3 11 Mie
4 100 Jue
5 101 Vie
6 110 Sab
7 111
8 1000
El código ASCCI (American Standar for Information Interchange) es un código binario que representa todos los caracteres, numerales y códigos de control. Usa 8 bits (0 a 255).
Nibble 4 bits 1/2 Byte
Palabra de 8 bits 8 bits 1 Byte
Word (palabra) 16 bits 2 Bytes
LongWord 32 bits 4 Bytes (DoubleWord)
QuadWord 64 bits 8 Bytes
Cuando el procesador de una computadora es de n bits, se dice que la computadora maneja datos de n bits.
PC 386 16 bits
VAX 32 bits
-
Complemento de 2 (sistema Nibble):
bs b2 b1 b0 Decimal 0 0 0 0 0 0 0 0 1 1 bs es el bit más significativo 0 0 1 0 2 representa el signo. 0 0 1 1 3 0 1 0 0 4 Por definición -1 equivale 0 1 0 1 5 a todos los bits "prendidos" 0 1 1 0 6 en cualquier notación. 0 1 1 1 7 1 0 0 0 -8 1 0 0 1 -7 Nibble complemento a 2: [-8,7] 1 0 1 0 -6 1 0 1 1 -5 1 1 0 0 -4 1 1 0 1 -3 1 1 1 0 -2 1 1 1 1 -1
-
Complemento de 10 (sistema de 4 dígitos):
El complemento 10 de 3564 es: 9999 - 3564 ------ 6435 + 1 = 6436 Así se pueden realizar:
8642 8642
- 3564 == + 6435
------ ------
5078 15078 El primer 1 se pierde porque estamos trabajando en
un sistema de 4 dígitos.
Si se suman dos cantidades del mismo signo y el resultado es de signo contrario, se dice que ha ocurrido un sobre flujo (overflow).
-
Complemento de 2 (sistema Nibble):
1111 - 0110 ------ 1001 + 1 = 1010 Número 6 en base 10 = Número 110 en base 2 Número -6 en base 10 = Número 1010 en complemento 2 Nibble
-
Valores máximos que se pueden representar según los diversos tipos de procesadores:
Tamaño Binario Complemento 2 4 bits Nibble 0..15 -8..7 8 bits Byte 0..255 -128..127 16 bits Word 0..65535 -32768..32767 32 bits LongWord 0..2^32-1 -2^31..2^31-1 64 bits QuadWord 0..2^64-1 -2^63..2^63-1 n bits 0..2^n-1 -2^(n-1)..2^(n-1)-1
- Unidad central de procesamiento (CPU) - Lee, controla y ejecuta las instrucciones que están en memoria.
- Unidad aritmética lógica (ALU) - Realiza las operaciones aritméticas y lógicas
- Unidad de control - Controla todo el funcionamiento de toda la computadora
- Conjunto de registros - Memoria intermedia pequeña temporal de altísima velocidad que guarda el status del procesador, así como resultados potenciales.
Almacén de datos e instrucciones. Su configuración es como un arreglo de localidades, cada celda de memoria es una localidad que almacena un contenido de n dígitos binarios (n es el número de bits que puede manejar el procesador). Una memoria de 64 kilobytes tiene 65536 bytes o 65536 localidades de memoria cada una con n bits.
Un procesador de 16 bits puede direccionar 2^(16-1) = 32768 localidades de memoria, cada una con 16 bits, o sea un total de 524288 bits o 65536 bytes o 64 kb.
Es la parte de la computadora que es la interfase entre ella y los dispositivos periféricos.
- Dispositivos de almacenamiento masivo.
- Dispositivos de entrada de datos
- Dispositivos de salida de datos
Proceso: Programa en ejecución, secuencia de acciones ejecutadas por la computadora de acuerdo a las especificaciones dadas por un programa.
Algoritmo: Conjunto finito de reglas las cuales dan una secuencia de operaciones para resolver un problema:
Programa: Secuencia de instrucciones que indican a la computadora qué hacer.
- Ser finito, siempre debe terminar
- Debe ser definido
- Debe tener entradas, desde 0 hasta un número finito entero
- Debe tener salidas, desde 1 hasta un número finito entero
- Debe ser efectivo, resultados correctos en tiempo finito
-
Calentar una hamburguesa en horno de microondas:
-
Quitar envoltura
-
Poner hamburguesa en plato
-
Abri r la puerta
-
Meter hamburguesa
-
Cerrar la puerta
-
Definir el tiempo
-
Definir potencia
-
Oprimir botón de inicio
-
Esperar
-
Abrir la puerta
-
Sacar hamburguesa
-
Si la hamburguesa está fría ir a 4
-
Cerrar la puerta
Entrada: Hamburguesa fría, tiempo, potencia Salida: Hamburguesa caliente
-
-
Algoritmo de transformación de base 10 a base 2:
- Designar número a convertir
- Dividir enteramente el número entre 2
- Guardar el residuo
- Si el cociente de la división fue 0 ve a 7
- Sustituir el número por el cociente
- Ir a 2
- Escribir números en orden inverso, el primer residuo va hasta la derecha
-
Programa: Es un texto, secuencia de caracteres, que indica una forma precisa y detallada de lo que se va a hacer. Su significado se indica mediante un formulismo que se conoce como lenguaje.
-
Lenguaje de programación: Reglas que indican cómo se deben construir los programas. Existen dos categorías: Lenguajes de bajo nivel (de máquina y ensamblador) y lenguajes de alto nivel.
El lenguaje de máquina baja directamente los códigos de máquina de la memoria al CPU, es particular a cada procesador, es difícil de programar para el programador, solo hay portabilidad entre miembros de la misma familia:
PC's: 8086, 8088, 80286, 80386, 80486, ...
Mac's: 68000, 68010, 68020, 68030, 68040, ...
El lenguaje ensamblador es una equivalencia directa de cada instrucción de máquina, pero en lugar de usar dígitos binarios usa números nemónicos, no hay congruencia entre los diversos ensambladores. Para cada procesador se necesita su ensamblador, no hay portabilidad, el programador necesita conocer algunas características del procesador.
El lenguaje de alto nivel es un formalismo que definen las reglas para escribir un programa en términos más aproximados a un lenguaje escrito, sin depender de una computadora específica. Sus programas son fáciles de escribir y mantener, no pueden ser traducidos y ejecutados por la máquina directamente, deben ser traducidos a código de máquina mediante un compilador o un intérprete.
No se tiene control del como se compila, los programas son más largos que el código de máquina equivalente. Algunos ejemplos: Fortran, Cobol, Basic, Pascal, Modula 2, C, Ada, etc.
Es una técnica de escritura de programas que usa estructuras de datos y estructuras de control. Las estructuras de datos son una representación aproximada de la realidad. Las estructuras de control son secuencias de operaciones con una sola entrada y una sola salida.
Ventajas:
- Secuencias de operaciones fáciles de seguir y de corregir
- Número de estructuras reducidas a un número útil, completas y suficientes
- Terminología que sigue una norma común
- Se pueden constituir fácilmente en módulos
- El código es autodocumentable y fácil de leer
- Se describen fácilmente secuencias de enunciados
Desventajas:
- No todos los lenguajes de alto nivel aceptan las estructuras directamente
- Los programas estructurados generan más código, su ejecución es más lenta y ocupan más memoria
- Limitación de estructuras de control para programas más complejos
- Algunas estructuras son difíciles de entender
- A algunos programadores les parece bastante restrictivo
-
Hardware: Componentes físicos que forman a la computadora. Se suele referir como arquitectura a la estructura interna de la computadora.
-
Software: Programas que hacen funcional a la computadora.
-
Firmware: Software en chips tipo ROM.
En el núcleo se encuentra el Hardware de la computadora, alrededor está la arquitectura de la misma (combinación de Firmware y Hardware). En seguida se encuentra el sistema operativo, es un Software que aísla los componentes de la computadora del resto de los programas. Por último se encuentran los programas de aplicación, son el Software con el que se interactúa normalmente.
Son funciones esenciales para usar el sistema de cómputo; administra la memoria, fija secuencias de corridas de los programas, transferencias de entrada y salida; Se encuentra el BIOS en esta capa (Basic Input Output System) junto con el sistema operativo. Son una interfase entre el Hardware y el Software de aplicación, hace parecer a la computadora como más poderosa.
Algunos sistemas operativos:
- MS-DOS: Deja que las aplicaciones manejen el Hardware lo que está mal.
- Windows NT: No deja al software tocar el hardware, opera en diversas plataformas pero es más lento que el MS-DOS.
- Sistema Macintosh
- OS/2
- DR-Dos
- Unix: Se tiene un Kernel (núcleo) diferente para cada computadora, pero los comandos son similares.
- VM/ESA: Usa memoria del disco como RAM dinámica (Virtual Memory).
- VMS: Evolución del VM/ESA.
- VAX MS: Sólo corre en sistemas VAX.
- OPEN VMS: Corre en sistemas VAX y en otros varios sistemas.
El software de aplicación son los programas que normalmente usa el usuario: editores, hojas de cálculo, etc.
El software de utilerías son programas de extensión del sistema operativo.
La ejecuta y realiza la ingeniería del software:
-
Análisis de requerimientos: Se descubre la necesidad de contar con un sistema y se identifican y documentan sus requerimientos exactos en términos entendibles por el usuario.
-
Especificación: Se desarrolla una descripción formal del sistema tomando en cuenta las limitaciones y los recursos.
-
Diseño arquitectónico: En base a las especificaciones se diseña la estructura del sistema, se definen algoritmos generales y principales así cómo las estructuras de datos.
-
Diseño detallado: Se detallan las partes del diseño arquitectónico, se describen algoritmos y estructuras de datos, se detallan interfases entre las partes.
-
Implantación: Se realiza físicamente el diseño detallado, se integra el sistema de hardware y software completo.
-
Mantenimiento: Localizar y depurar fallas. Se introducen nuevas funciones o se cambian las existentes:
Versión Revisión Revisión menor: 1.0 1.1 1.1.1 2.0 2.1 2.1.1 3.0 3.1 3.1.1
Son programas de aplicación, le sirven al programador para la realización de los programas:
Editores, editores orientados a lenguajes Programas que sirven para la creación o modificación de archivos de texto. Los editores orientados a lenguajes tienen incluida ayuda de sintaxis del lenguaje, inserción abreviada de elementos gramaticales, detección de errores de sintaxis, señalamiento de errores dentro del programa fuente, pueden llamar al compilador, al encadenador, al depurador, etc.
Compilador: Traduce el código de alto nivel al código de máquina, consta de 5 fases:
1. Análisis lexicográfico: Separa cada elemento gramatical del programa y le asigna una secuencia de símbolos que se utilizan por el resto de las fases.
2. Análisis sintáctico: Valida la secuencia de símbolos de acuerdo a la sintaxis del lenguaje.
3. Generación del código intermedio: Se traduce el código fuente a un código binario de bajo nivel independiente de la máquina.
4. Optimización del código: El compilador intenta optimizar el código intermedio quitando código que no se ejecuta y haciendo más eficiente el código repetitivo.
5. Generación del código de máquina: Traduce el código intermedio al código de máquina necesario para la computadora. Su salida es código objeto.
Intérprete: Programa que lee una instrucción, la traduce y la ejecuta. Se realiza instrucción por instrucción, es fácil de programar. Ensamblador: Traduce un programa de lenguaje ensamblador a lenguaje de máquina. Genera OBJ o EXE.
Enlaza un conjunto de módulos compilados o ensamblados separadamente y genera un sólo módulo que puede usar las funciones y los procedimientos de cada módulo, además debe incluir bibliotecas como la del sistema operativo, la de algún lenguaje en particular, las de uso general, y la del usuario.
1. Combina módulos separados en uno solo.
2. Se enlazan los símbolos contenidos en distintos módulos.
3. Incluye rutinas y definiciones de las bibliotecas.
El cargador es el programa que lee un archivo y lo pone en la memoria para su posterior ejecución, le asigna un espacio en la memoria.
Facilita encontrar errores de lógica de los programas. Da funciones como monitoreo de variables al ejecutar los programas bajo su supervisión. Todas estas fases se usan en la implantación y mantenimiento de los sistemas.
------->Escribir programa Editor
| fuente
| |
| |
| Traducir a código Compiladores, Intérpretes,
| de máquina Ensambladores
| |
| |
| Encadenar el archivo Encadenador
| binario
| |
| |
| ¿Funciona? -----------> Si=Fin Cargador
| |
| |
| No=Busca errores Depurador
| |
-----------------
La sintaxis son un conjunto de reglas que definen como construir oraciones en un lenguaje. La semántica es el significado de las oraciones.
La semántica se da como una explicación de lo que hace la oración. La sintaxis se especifica mediante dos métodos: EBNF y diagramas de sintaxis.
Existen dos tipos de símbolos:
- Terminales, encerrados entre comillas, no requieren de mayor definición
- No terminales, requieren de mas definiciones
Los símbolos se separan con limitadores:
( ) : Agrupar con fines de clarificación
[ ] : Parte opcional
| : Seleccionar una opción
{ } : Repetir 0 o más veces
. : Fin de definición
= : Definición
Regla EBNF: símbolo no terminal = definición.
Ejemplos:
Oración = Sujeto Predicado.
Sujeto = nombre_propio | (artículo sustantivo).
Predicado = Verbo Complemento.
nombre_propio = "Pedro" | "Juan" | "María" | "Rosa".
artículo = "El" | "La".
Verbo = "corre " | "hace" | "ladra" | "come".
Sustantivo = "atleta" | "costurera" | "perro" | "jirafa".
Complemento = "velozmente" | "vestidos finos" | "a los rateros" | "hojas de los árboles".
Se pueden crear las siguientes oraciones válidas:
Juan corre velozmente
María come velozmente
el perro hace a los rateros
la jirafa ladra vestidos finos
Todas son sintácticamente correctas, aún cuando no tengan significado semántico. Los errores sintácticos los detecta el compilador. Los errores semánticos son de lógica y se necesita un depurador para encontrarlos.
Otras definiciones:
numero = [signo] entero.
signo = "+" | "-".
entero = digito {digito}.
digito = "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9".
real = [signo] entero "." entero.
Ejemplos:
- PDP-11: Máquina de 16 bits creada por DEC para aplicaciones específicas.
- VAX-11: Módulo de expansión de 32 bits para la PDP-11 (VAX=Virtual Address Extension).
- VAX: De la VAX-11 evolucionó la VAX que ya no es compatible con la PDP-11, es capaz de direccionar 2^31 direcciones de memoria. Fue la primera en usar el esquema de memoria virtual, es decir, en usar una parte de disco como memoria RAM sin que el CPU se de cuenta. Mientras mas memoria tenga el sistema (memoria física RAM, no virtual en disco) será mas rápido.
Utiliza un sistema operativo especial VMS (Virtual Memory System) que es el encargado de asignar la memoria al disco:
- VAX/VMS: Sólo corre en VAX.
- OPEN VMS: Corre en VAX y en ALPHA.
ALPHA: Sustituirá a la VAX ya que es capaz de correr múltiples sistemas operativos: OPEN VMS, Windows NT y OSF/1 (Unix estándar).
- Sistema operativo multiusuario, el número de usuarios está limitado por la licencia y la memoria.
- Multitarea
- Multiprocesador
- Software de red integrado: DEC-NET
Cada módulo es un nodo, los servidores son nodos y las terminales no.
Los "terminal service" también son servidores cuya única función es la de conectar a los nodos:
UserName> Pide el nombre de usuario del "terminal service", usualmente con dar enter es suficiente. Local> Indicativo de que ya estamos "loggeados" en el "terminal service".
Para conectar a un nodo desde el "terminal service":
Local>connect nodo
Ejemplo: Local>connect UIMXC
Pide UserName y Password. Si falla 3 veces te regresa a Local>. Si te equivocas 4 veces seguidas en una cuenta cancela el password de la cuenta.
Si es exitosa responde con UIMX1>> o UIMX2>> (están en clúster por lo que cualquiera puede contestar).
nodo::dispositivo:[directorio.subdir.subdir]archivo.extension;version
Ejemplos: UIMX1::Disco2:[batman.villanos]gatubela.crimenes;65 UIMX2::Disco0: IME01::sys$sysdevice:
El último ejemplo corresponde al disco que contiene el sistema operativo.
El nodo tiene un máximo de 6 caracteres. El dispositivo tiene un máximo de 32.
Normalmente sys$login es el directorio que se asigna como directorio "home" de una cuenta. El archivo Login.com es el equivalente al autoexec.bat del MS-DOS.
F-5: Salir al modo local, es mejor usar Logout.
Ctrl-Z o F-10: Salir de un programa.
Ctrl-C: Cancela la ejecución de un programa.
Ctrl-Y o F-6: Aborta la ejecución de un programa.
$ es el nodo en el que nos encontramos.
Para mostrar el contenido de un archivo:
$Type archivo.lis
Para salir a modo local (Terminal service):
$Logout
Despliega los archivos del directorio:
$Directory
$Dir /size
$Dir *.pas
Despliega el nombre del directorio actual:
$Show default
Cambia al directorio especificado:
$Set default dispositivo:[directorio.subdirectorio...]
Cambia al directorio "raíz": $Set default sys%login
Cambia al subdirectorio que esté debajo del directorio en uso:
$Set default [.subdirectorio]
Mueve al directorio superior:
$Set default [-]
Copia un archivo:
$Copy origen destino
Borra un archivo:
$Delete archivo;version
Borra pidiendo confirmación:
$Delete /query *.*;*
Borra y despliega los nombres de los archivos borrados:
$Delete *.*;* /log
Borra las versiones antiguas de los archivos:
$Purge
Borra y despliega los nombres de las versiones antiguas de los archivos:
$Purge /log
Borra todas excepto las últimas 2 versiones:
$Purge /keep=2
Para llamar al editor:
$eve archivo.pas
La ayuda se invoca con "PGF 2", para salir usar Ctrl-Z
Comandos dentro del Editor:
0 : Busca errores sintácticos (del teclado numérico).
PF1 y luego 0 : Compila el código que esté en el editor (del teclado numérico).
PF1 y luego . : Se encadena el código ya compilado.
. (o ,) : Se corre el programa que ya se encadenó.
PF1 y luego & : Sale del editor sin modificar el archivo.
PF4 : Abre una ventana para ejecutar un comando. Con el comando Spawn se abre una sesión.
PF1 y luego B : Escribe la estructura "Begin ... End". Funciona con otras estructuras.
PF1 y luego 1 : Abre una nueva ventana del editor (del teclado normal).
PF1 y luego 2 : Abre una ventana y se muestra junto con la que ya se tenia.
PF1 y luego 3 : Cambia de pantalla a pantalla.
PF1 y luego alguna flecha : Mueve la ventana del editor sobre la pantalla.
Para llamar al compilador:
$Pascal archivo.pas // Se generará un archivo .obj
Para encadenar:
$Link archivo.obj // Se generará un archivo .exe
Para correrlo:
$RUN archivo.exe
Para el debugger:
$Pascal /nooptimize /debug archivo.pas
$Link /debug archivo.obj
$Run archivo.exe
Tesis de doctorado de Nicklaus Wirth, diseñado para aplicaciones didácticas.
Dos versiones principales: ANSI (American National Standars Institute) e ISO (International Standar Organization).
En lo sucesivo se manejará el Extended Pascal compatible con ANSI y con ISO usando el compilador VAX-Pascal.
Consiste en palabras, oraciones y signos de puntuación conformados por números, letras y caracteres especiales. No reconoce diferencias entre mayúsculas y minúsculas.
-
Palabras (26 letras y dígitos)
-
Cantidades (dígitos)
-
Signos de puntuación (símbolos especiales)
Símbolo especial = "+" | "-" | "*" | "/" | "=" | "<>" | "<" | ">" | "<=" | ">=" | "(" | ")" | "[" | "]" | ":=" | "." | "," | ":" | ";" | ".." | "'" | "^".
Palabras reservadas = "DIV" | "MOD" | "NIL" | "IN" | "OR" | "OR_ELSE" | "AND" | "AND_THEN" | "NOT" | "IF" | "THEN" | "ELSE" | "CASE" | "OF" | "OTHERWISE" | "REPEAT" | "UNTIL" | "WHILE" | "DO" | "FOR" | "TO" | "DOWNTO" | "BEGIN" | "END" | "WITH" | "GOTO" | "CONST" | "VAR" | "VALUE" | "TYPE" | "ARRAY" | "RECORD" | "SET" | "FILE" | "FUNCTION" | "PROCEDURE" | "LABEL" | "PACKED" | "PROGRAM" | "MODULE".
Las palabras reservadas no se pueden redefinir.
Palabras predefinidas: Funciones y procedimientos predefinidas en el lenguaje: ReadLn, WriteLn, Sin, Card; no se pueden redefinir.
Palabras de usuario: Funciones y procedimientos definidas por el programador.
-
Cadena: Cualquier secuencia de caracteres encerrados entre apóstrofes.
-
String=Cadena = "'" {Cualquier_caracter_excepto_apóstrofo | "''"}"'".
-
cadena vacía = ''.
-
McDonald's = 'McDonald''s'.
-
Comentario: Cualquier texto libre encerrado entre llaves.
{Cálculo del impuesto} o (Total de ventas del año). Dentro del comentario no puede haber más signos de comentario. Puede tener saltos de línea.
Un ejemplo de programa:
PROGRAM NoHaceNada(Input, Output);
.
Otro ejemplo:
PROGRAM InutilPeroMasLargo(Input,Output);
BEGIN
;
;;
END.
Integer: va de -MaxInt a MaxInt. En la VAX MaxInt=2^31-1.
Operador Operación
+ Suma
- Resta
* Multiplicación
DIV División entera
MOD Módulo o residuo
El módulo entre un número positivo y otro negativo no está definido.
Funciones:
Abs Valor absoluto
Sqr Cuadrado
Succ Sucesor
Pred Predecesor
Reales válidos: 3.75 -11.64 0.74 5.0 7.14E24 Reales inválidos: 5. .743
Operador Operación
+ Suma
- Resta
* Multiplicación
/ División real
Funciones:
Abs Valor absoluto
Sqr Cuadrado
Ln Logaritmo
Sin Seno
Cos Coseno
Arctan Arcotangente
Funciones de conversión
Trunc(X) Trunca a la parte entera
Round(X) Redondea al entero
Se usará el ASCII de 8 bits con 255 caracteres (no todos son visibles).
Tipo Char 'a' 'b' '5' Dobles comillas representan el caracter comilla: '''' = '
Operador Operación
+ Concatenación
'H' + 'O' + 'L' + 'A' = 'HOLA' Char+Char+Char+Char=String
Funciones:
Chr(n) Convierte un entero a caracter
Ord(c) Convierte un caracter a entero
Pred(c) Predecesor del caracter c
Succ(c) Sucesor del caracter c
Chr(Ord('M')-Ord('A')+Ord('a'))='m'
Operador Operación
= Igualdad
<> Distinto
< Menor
<= Menor o igual
> Mayor
>= Mayor o igual
Funciones:
Ord(False) = 0
Ord(True) = 1
Succ(False) = True
Succ(True) = False
p q p=q p<=q p<>q
F F F T F
F T F T T
T F F F T
T T T F F
Un esquema es un patrón que sirve como base para definir familias de tipos distintos. Una definición de un tipo de esquema contiene uno o más discriminantes formales, que se ponen en lugar de los límites de un subrango o de los rótulos de los selectores de la parte variante de un registro. Cuando los límites de los índices de un tipo arreglo o de los valores posibles de un tipo conjunto contienen discriminantes, el arreglo o el conjunto se convierten a su vez en esquemas.
Al especificarse valores a los límites o a los rótulos de un tipo basado en un esquema, se construye un tipo válido; a estos valores se les conoce como discriminantes reales.
Un esquema se define como sigue:
esquema = identificador-de-esquema "(" lista-de-discriminantes-formales ")" "=" tipo.
lista-de-discriminantes-formales = discriminante-formal {"," discriminante-formal}.
discriminante-formal = lista-de-identificadores ":" tipo-ordinal.
El tipo puede ser subrango, arreglo, registro o conjunto, mientras que el tipo-ordinal puede ser entero, carácter, booleano, enumerado o subrango.
Ejemplos:
TYPE
diasDeLaSemana = (lunes, martes, miercoles, jueves, viernes, sabado, domingo);
rangoDeDias = lunes..domingo;
arregloDeDias (supD: Integer) = ARRAY [1..supD] OF diasDeLaSemana;
arregloDeHorasEnteras (infE, supE: rangoDeDias) =
ARRAY [infE..supE] OF Integer;
matrizDeReales (maxCol, maxRen: Integer) =
ARRAY [1..maxRen, 1..maxCol] OF Real;
conjuntoDeCaracteres (minCar, maxCar: Char) = SET OF
(minCar..maxCar);
Comentarios sobre los ejemplos:
- El tipo "diasDeLaSemana" es un enumerado simple, por lo que no es un esquema.
- El tipo "rangoDeDias" es un subrango simple, por lo que no es un esquema.
- "arregloDeDias" es un esquema consistente en un arreglo del tipo "arregloDeDias", con índices que pueden ir de 1 a "supD", donde este último es un discriminante formal del tipo "Integer".
- "arregloDeHorasEnteras" es un esquema consistente en un arreglo del tipo "Integer", con índices que pueden ir de "infE" a "supD", donde estos últimos dos son discriminantes formales del tipo "rangoDeDias".
- "matrizDeReales" es un esquema consistente en un arreglo bidimensional del tipo "Real", con índices que pueden ir de 1 a "maxRen" para los renglones, y de 1 a "maxCol" para las columnas, donde "maxRen" y "maxCol" son discriminantes formales del tipo "Integer".
- "conjuntoDeCaracteres" es un esquema consistente en un conjunto con elementos posibles entre el carácter "minCar" y "maxCar", donde estos dos últimos son discriminantes formales del tipo "Char".
Las definiciones anteriores no son tipos válidos hasta que no se especifiquen los discriminantes reales que delimiten los índices de los subrangos. A estos esquemas se les conoce como esquemas indiscriminados, ya que sólo contienen discriminantes formales, y no se les ha determinado su tamaño real. Un esquema indiscriminado sólo puede definirse en una parte de definiciones de tipos, y ser referido por un puntero que apunte al esquema, aunque no esté discriminado, o como parámetro formal de un procedimiento o función.
El estándar permite que un tipo esquema discriminado ordinal sea subsecuentemente utilizado como el tipo de un discriminante formal de otro esquema. Por ejemplo:
TYPE
subrango(inf,sup: Integer) = inf..sup;
subDiscriminado = subrango(-maxInt - 1, maxInt);
esquema1(discr: SubDiscriminado) = ARRAY[1..discr] OF Integer;
esquema2(discr: subDiscriminado) = RECORD
CASE discr OF
1 : (num:Integer);
2 : (letra:Char)
END;
VAX Pascal no soporta este tipo de construcción.
El Pascal extendido permite que un archivo tenga componentes esquemáticos indiscriminados. VAX Pascal requiere que el tamaño de los componentes se conozca al tiempo de compilación.
Pascal extendido permite que un discriminante formal se utilice para dar valor inicial a una de las componentes del esquema. Por ejemplo:
TYPE
registro(discr: Integer) = RECORD
num:Integer VALUE discr;
END;
arreglo(discr: Integer) = ARRAY [1..dicr] OF Integer
VALUE [OTHERWISE discr];
VAX Pascal no soporta estos tipos de construcción y requiere que todas las inicializaciones de valor se conozcan al tiempo de compilación.
Los esquemas indiscriminados no tienen mayor utilidad que la de servir de patrón en la definición de tipos, constantes, variables y parámetros, y para esto, los esquemas deben discriminarse proporcionando valores reales a los discriminantes formales, como en los siguientes ejemplos:
VAR
algunosDias: arregloDeDias (12);
horasTrabajadas: arregloDeHorasEnteras (lunes, viernes);
horasDeEntretenimiento: arregloDeHorasEnteras (sabado, domingo);
matriz4x5: matrizDeReales (4,5);
matriz5x4: matrizDeReales (5,4);
Comentarios sobre los ejemplos:
- "algunosDias" es una variable de un tipo equivalente a un ARRAY [1..12] OF diasDeLaSemana. "supD" se discrimina con un valor de 12.
- "horasTrabajadas" es una variable de tipo equivalente a un ARRAY [lunes..viernes] OF Integer. "infE" toma un valor de "lunes" y "supE" toma un valor de "viernes".
- "horasDeEntretenimiento" es una variable de tipo equivalente a un ARRAY [sabado..domingo] OF Integer. "infE" toma un valor de "sabado" y "supE" toma un valor de "domingo".
- "matriz4x5" es una variable de tipo equivalente a un ARRAY [1..4, 1..5] OF Real. "maxRen" toma un valor de 4, y "maxCol" toma un valor de 5.
- "matriz5x4" es una variable de tipo equivalente a un ARRAY [1..5, 1..4] OF Real. "maxRen" toma un valor de 5, y "maxCol" toma un valor de 4.
Las declaraciones anteriores determinan el tamaño de las variables en función a discriminantes reales, por lo que se conocen como esquemas discriminados. Estos esquemas pueden aparecer en la parte de definición de tipos o en la de declaración de variables. El discriminante real puede evaluarse en tiempo de compilación (como en los ejemplos anteriores), o durante la corrida, a partir de una expresión que haya sido o pueda ser evaluada en el momento en que se encuentra la declaración.
Para obtener el tamaño (en número de elementos, no en bytes) de un esquema discriminado, se puede emplear el discriminante formal en forma semejante a los designadores de los campos de un registro, especificando el nombre de la variable, un punto, y el identificador del discriminante, como sigue:
WriteLn ('Las dimensiones de la matriz son: ', matriz4x5.maxRen:4, matriz5x4.maxCol:4);
Un tipo esquema indiscriminado y los tipos discriminados que de él se derivan se conocen como una familia de esquemas. Dos esquemas discriminados que tienen discriminantes iguales y determinados como expresiones constantes se consideran tipos iguales. No se pueden hacer asignaciones entre tipos desiguales, aunque sean de la misma familia de esquemas. Por ejemplo:
TYPE arregloDeEnteros (infE, supE: Integer) = ARRAY [infE..supE] OF Integer; arreglo1 = arregloDeEnteros(5,15); arreglo2 = arregloDeEnteros(1,10); arreglo3 = arregloDeEnteros(5,15);
- "arreglo1", "arreglo2" y "arreglo3" son esquemas discriminados que forman una familia junto con el esquema indiscriminado "arregloDeEnteros". "arreglo1" y "arreglo3" son iguales, por lo que se pueden hacer asignaciones entre ellos.
Como se indicó anteriormente, un esquema indiscriminado puede especificarse como tipo de un parámetro formal de un procedimiento o función, por ejemplo:
PROCEDURE sumaDeMatrices ( matrizA, matrizB: matrizDeReales;
VAR matrizC: matrizDeReales);
VAR
i,j: Integer;
BEGIN {sumaDeMatrices}
FOR i:=1 TO matrizA.maxRen DO
FOR j:=1 TO matrizA.maxCol DO
matrizC [i,j] := matrizA [i,j] + matrizB [i,j]
END {sumaDeMatrices};
Al procedimiento del ejemplo anterior se le pueden pasar como parámetros cualquier tipo derivado de "matrizDeReales", siempre y cuando las tres matrices sean de las mismas dimensiones. El resultado de una función sólo puede ser un esquema discriminado.
Para poder utilizar un procedimiento como el anterior, es necesario pasarle como parámetros variables discriminadas, por ejemplo:
TYPE
matriz2x3 = matriz(2,3);
VAR
matrizA : matriz2x3 VALUE [1: [1:12, 2:3.45, 3:-12.6];
2: [1:6, 2:0; 3:-3.3]];
matrizB : matriz2x3 VALUE [OTHERWISE [OTHERWISE 1]]; {matriz llena de 1}
BEGIN
sumaDeMatrices (matrizA, matrizB, matrizC);
...
En todos los ejemplos de esquemas anteriores, el discriminante se evalúa a partir de constantes, por lo que el tamaño de las variables es determinado durante el tiempo de compilación. Pascal extendido permite, como se indicó previamente, definir el tamaño de las variables hasta el momento en que se ejecute el programa, lo cual se hace generalmente mediante el uso de funciones. Supóngase que se hacen las siguientes declaraciones:
TYPE
matrizDeReales (maxRen, maxCol: Integer) = ARRAY [1..maxRen, 1..maxCol] Of Real;
FUNCTION limiteSuperior (limite: PACKED ARRAY [inf..sup: Integer] OF Char): Integer;
VAR
num: Integer;
BEGIN
Write ('Número máximo de ', limite, '>> ');
Readln(num);
limiteSuperior:=num
END;
VAR
matrizNxM: matrizDeReales (limiteSuperior('columnas'), limiteSuperior('renglones') );
La función "limiteSuperior" solicita el número máximo de renglones o columnas, dependiendo del parámetro "limite", el cual es una cadena de caracteres, y entrega como resultado el número entero ingresado por el usuario. En la declaración de la "matrizNxM", los discriminadores "maxRen" y "MaxCol" no se determinan en función a constantes, sino a llamadas a la función "limiteSuperior", la cual debe entregar el número máximo de renglones y el de columnas según los determine el usuario al momento de ejecutarse el programa, para cada discriminante. Nótese que el estándar de Pascal extendido permite insertar una definición de función antes de una declaración de variables, lo cual es necesario para poder designar discriminantes reales al momento de iniciarse la ejecución del programa.
El tipo de un esquema puede a su vez ser otro esquema, siempre y cuando éste sea discriminado con valores conocidos en el tiempo de compilación. Esto es, es inválido definir un esquema indiscriminado que tenga como base un esquema indiscriminado al tiempo de compilación.
Cuando un discriminante formal se usa como el rótulo de la parte variante de un registro, es ilegal cambiar la variante una vez que la variable se ha creado. Por ejemplo:
TYPE
reg(discr:Integer) = RECORD
CASE discr OF
1: (num: Integer);
2: (letras PACKED ARRAY [1..6] OF Char)
END;
VAR
miReg: reg(1); {se discrimina con la variante 1}
BEGIN
miReg.letras:='ilegal'; {ES ilegal, pues cambia variantes de 1 a 2}
END.
El estándar de Pascal extendido (aún en revisión) soporta inicialización de variables (o de todas las variables pertenecientes a un tipo) de la siguiente manera:
TYPE
diasDeLaSemana = (domingo, lunes, martes, miercoles, jueves, viernes, sabado);
contador = Integer VALUE 1; {el tipo no se inicializa, sino que
las variables que se declaren de este
tipo se inicializan en 1}
VAR
impuesto: Real VALUE 10;
diaLaboral: diasDeLaSemana VALUE lunes;
i, j: contador; {se inicializan en 1}
El compilador VAX Pascal sigue soportando la inicialización con el operador de asignación (i.e., impuesto: Real:=10), pero no se considera estándar. Para dar un valor estructurado a una constante, se requiere conocer el tipo del valor, antes de definir la constante. Esto significa que debe haber una parte de definición de tipos antes de la de constantes. En consecuencia, el Pascal extendido permite romper el rígido esquema original de la parte de declaraciones, pudiéndose escribir las secciones en cualquier orden. Sin embargo, siempre es conveniente seguir el orden tradicional, y añadir subsecuentes secciones de definiciones de constantes estructuradas después de la de tipos, sólo cuando sea necesario.
Para dar un valor inicial a una constante o variable estructurada, es necesario definir un constructor con todos los valores posibles para el tipo.
El constructor de arreglos se define como sigue:
constructor-de-arreglo = [tipo] "["(lista-de-valores ["OTHERWISE" valor]) | ("OTHERWISE" valor) "]".
lista-de-valores = valor-de-componentes{";" valor-de-componentes}.
valor-de-componentes = lista-de-componentes ";" valor.
lista-de-componentes = componente {";" componente}.
componente = indice | (indice ".." indice).
valor = expresion-constante | constructor.
El "tipo" del constructor sólo es necesario en definiciones de constantes (para asignarle un tipo a la constante), y al asignarle a una variable estructurada un constructor dentro de la parte de enunciados. En el caso de dar valor inicial en la declaración de una variable con VALUE, no se debe poner el tipo, dado que ya se proporciona en la misma declaración al designar el tipo de la variable, antes de la palabra VALUE. Cuando se aniden suscriptores (sean de arreglos o de registros), sólo debe ponerse el tipo antes del corchete más externo, pero nunca antes de los descriptores anidados.
El "valor" puede ser una expresión constante o identificador de constante (evaluable en el tiempo de compilación), o si el arreglo es multidimensional o contiene registros o conjuntos, puede ser otro constructor. Si el constructor aparece en la parte de enunciados, el valor puede ser cualquier expresión (evaluable en tiempo de ejecución), siempre y cuando contenga variables que ya tengan un valor asignado.
Los valores pueden darse en cualquier orden, pero deben inicializarse todos. Para ello puede utilizarse la cláusula OTHERWISE (permitida en el estándar de Pascal extendido).
Ejemplos:
CONST
uno = 1;
nombreSuperHeroe = 'Batman';
TYPE
vector = ARRAY [1..5] of Real;
matriz = ARRAY [1..5, 1..5] of Integer;
nombre = PACKED ARRAY [1..10] of Char;
lista = ARRAY ['a'..'d'] of nombre;
CONST {nótese que se permite otra vez}
primeros5Primos = vector [1:1; 2:2; 3:3; 4:5; 5:7];
matrizUnitaria = matriz [1: [1: uno; OTHERWISE 0];
2:[2:uno; OTHERWISE 0];
3:[3:uno; OTHERWISE 0];
4:[4:uno; OTHERWISE 0];
5:[5:uno; OTHERWISE 0]];
VAR
listaDeNombres: lista VALUE ['a':'Ana';
'b':'Benito';
'c': [1: 'C'; 2: 'a'; 3: 'r'; 4:'l';
5: 'o'; 6: 's'; OTHERWISE ' '];
'd': nombreSuperHeroe];
matrizA, matrizB: matriz;
elemento: Integer VALUE 15;
vectorA, vectorB: vector;
BEGIN
vectorA:= primeros5Primos;
vectorB:= vector[1: elemento; 3: elemento / 3; 5: elemento / 5; OTHERWISE 0];
matrizA:= matrizUnitaria; {no se requiere tipo, ya que lo tiene el descriptor}
matrizB:= matriz[1, 3, 5: [1..2:10; 3: 0; 4..5: -10];
OTHERWISE [OTHERWISE 0]];
Una categoría especial de esquemas es "String", la cual está definida como una estructura semejante a la siguiente:
String ( Capacity: Integer ) = RECORD
length: 0..65535;
body: PACKED ARRAY[1..Capacity] OF Char
END;
En el estándar de Pascal extendido, los campos "length" y "body" no son accesibles directamente. Asimismo, "Capacity" es un entero entre 0 y 65,535, que delimita el tamaño máximo de la cadena. Un "String" de capacidad 0 es una cadena vacía ('').
En el caso especial de VAX Pascal, el "String" se define de distinta forma:
String ( Capacity: Integer ) = VARYING [Capacity] of Char;
Por lo que es un superconjunto del tipo no estándar VARYING, el cual a su vez es un superconjunto de un PACKED ARRAY OF Char.
La capacidad de un "String" no necesariamente representa el número de caracteres que contiene. A diferencia de un arreglo empacado de caracteres, cuando a un "String" se le asigna una cadena más corta que su capacidad, no se completa con espacios. El identificador predefinido "Capacity" da la longitud máxima que puede tener un "String", y no el número de caracteres que realmente contiene. Para obtener el número real de caracteres que contiene la cadena, puede usarse la función "Length".
Ejemplos:
TYPE
nombre = String (40);
nulo = String (0);
VAR
elNombre: nombre;
BEGIN
elNombre:='Bruno Diaz';
WriteLn( elNombre.Capacity ); {Escribe un 40}
WriteLn( Length( elNombre ) ) {Escribe un 10}
END.
El estándar de Pascal extendido define los siguientes operadores y funciones para el tipo "String" (y también para el "VARYING"):
Operadores:
+ concatenación 'buen' + 'día' 'buen dia'
= igualdad 'salida' = 'salida' True
<> desigualdad 'salida' <> 'salida' False
< menor que 'ola' < 'olla' True
<= menor o igual 'ola' <= 'arena' False
> mayor 'libro' > 'libro' False
>= mayor o igual 'libro' >= 'libro' True
Funciones:
Eq igual Eq('libro','libro ') False
NE no es igual NE('carta','Carta') True
LT menor que LT('sal','saco') False
LE menor o igual LE('sali','saco') False
GT mayor que GT('sali'.'saco') True
GE mayor o igual GE('salida','saladas') True
El operador de concatenación puede tener como términos de la expresión caracteres, arreglos empacados de caracteres, "Varyings" y "Strings", pero solo puede entregar como resultado un "Varying" o un "String".
Los operadores comparativos pueden utilizarse con cualquier tipo de cadena, tal como se utilizan con los arreglos empacados de caracteres. Si se comparan dos cadenas de longitud distinta, se completa con espacios a la derecha la cadena mas corta. Si las cadenas contienen signos de acentuación o eñes, la comparación se hace respecto a su valor en el código de caracteres que se esté empleando. Por lo general, los caracteres acentuados tienen un valor superior al de los caracteres no acentuados. Por ejemplo:
'almacén' < 'almacenes' genera False
'aorta' >= 'año' genera False
Las funciones de comparación son equivalentes a los operadores, con la diferencia de que son más eficientes al comparar en función de la longitud de la cadena más corta, sin completar con espacios para igualar longitudes. El primer parámetro equivale a la cadena de la izquierda del operador, y el segundo al de la derecha.
Asimismo, si las cadenas contienen signos de acentuación, la comparación se hace respecto a las letras no acentuadas, y si contienen eñes, respecto a su orden en el alfabeto. Por ejemplo:
LT('alamcén','almacenes') genera True
GE('aorta','año') genera True
Otras funciones definidas en el estándar extendido son:
Index(cadena,texto) Index('buen día','día') 6
// Entrega un entero con el índice donde se encuentra un texto en una cadena.
Length(cadena) Length('buen día') 8
// Entrega un entero con el número de caracteres en la cadena.
Substr(cadena, inicio, numCaracteres)
Substr('buen día', 6, 3) 'día'
// Entrega una subcadena a partir de la cadena, desde el carácter de inicio y con una longitud de numCaracteres.
El constructor de registros se define como sigue:
constructor-de-registro = [tipo] "[" (constructor-fijo
{";" constructor-fijo} [";" constructor-variante])
| constructor-variante [";" "OTHERWISE Zero"] "]".
constructor-fijo = valor-de-seccion {";" valor-de-seccion}.
valor-de-seccion = lista-de-identificadores ";" valor.
lista-de-identificadores = identificador {";" identificador}.
constructor-variante = "CASE" [identificador-de-rotulo ":"] valor-de-rotulo
"OF" "[" valor-de-componentes {";" valor-de-componentes} "]".
El "tipo" del constructor sólo es necesario en definiciones de constantes (para darle un tipo a la constante), y al asignarle a una variable estructurada un constructor dentro de la parte de enunciados. En el caso de dar valor inicial en la declaración de una variable con VALUE, no se debe poner el tipo, dado que ya se proporciona en la misma declaración al designar el tipo de la variable, antes de la palabra VALUE. Cuando se aniden descriptores (sean de arreglos o de registros), sólo debe ponerse el tipo antes del corchete más externo, pero nunca antes de los descriptores anidados. El valor-de-seccion de la parte fija puede contener identificadores de la parte variante, siempre y cuando no haya duplicidad entre distintas variantes.
El "valor" puede ser una expresión constante o identificador de constante (evaluable en el tiempo de compilación), o si el registro contiene arreglos, conjuntos u otros registros, puede ser otro constructor. Si el constructor aparee en la parte de enunciados, el valor puede ser cualquier expresión (evaluable en tiempo de ejecución), siempre y cuando contenga variables que ya tengan un valor asignado.
El identificador-de-rotulo sólo es necesario si se incluye uno en la definición de la parte variante del tipo.
El valor-de-rotulo indica cuál de las variantes posibles es la que se va a inicializar.
Los valores pueden darse en cualquier orden, pero deben inicializarse todos. Para ello puede utilizarse la cláusula "OTHERWISE Zero" la cual es propia de VAX Pascal, y no forma parte del estándar de Pascal extendido. La función "Zero", que inicializa variables de casi cualquier tipo a un valor nulo, tampoco está definida en el estándar.
TYPE
mesesDelAno = (enero, febrero, marzo, abril, mayo, junio, julio, agosto, septiembre,
octubre, noviembre, diciembre);
fecha = RECORD
dia: 1..31;
mes: mesesDelAno;
ano: Integer;
END;
nombreDePersona = PACKED ARRAY [1..30] OF Char;
sexo = (masculino, femenino);
calificacionesPorSemestre = PACKED ARRAY [1..12] OF Integer;
registroDeAlumno = RECORD
numCuenta: Integer;
nombre: nombreDePersona;
edad: Integer;
suSexo: sexo;
calificaciones: calificacionesPorSemestre;
CASE primerIngreso: Boolean OF
false: (promedioCarrera: Real);
true: (prepa: PACKED ARRAY [1..20] OF Char;
promedioPrepa: Real)
END;
CONST
descubrimientoDeAmerica = fecha [dia: 12; mes: octubre; ano: 1492];
VAR
alumno: registroDeAlumno;
BEGIN
alumno:= registroDeAlumno[
numCuenta: 54321;
nombre: 'Trinito Tolueno';
edad: 22;
suSexo: masculino;
calificaciones: [1: 10; 2: 9; 3: 8; 4: 8; 5: 9; 6: 5; OTHERWISE -1];
{no cursado aún}
CASE primerIngreso: False OF [promedioCarrera: 8.2]];
Pascal extendido incluye una estructura estándar para la manipulación del tiempo, la cual se define como sigue:
TimeStamp = PACKED RECORD
DateValid, TimeValid: Boolean;
Year: Integer;
Month: 1..12;
Day: 1..31;
Hour: 0..23;
Minute: 0..59;
Second: 0..59
END;
VAX Pascal entiende la estructura anterior como sigue:
TimeStamp = PACKED RECORD
DateValid, TimeValid: Boolean;
Year: Integer;
Month: 1..12;
Day: 1..31;
Hour: 0..23;
Minute: 0..59;
Second: 0..59;
Hundredth: 0..999;
Binary_time[Quad] RECORD L1, L2 : Integer END;
{Tiempo binario VMS de 32 bits}
Day_Of_Week: 1..7; {1 es lunes. 7 es domingo}
END;
El procedimiento "GetTimeStamp(TimeStamp)" entrega el tiempo del sistema, como en el siguiente ejemplo:
VAR
tiempo: TimeStamp;
BEGIN
GetTimeStamp(tiempo);
WITH tiempo DO
WriteLn("La hora es: ", Hour:2, ":":1, Minute:2, ":":1, Second:2)
END.
Pascal extendido también define funciones para la obtención de cadenas que representan el tiempo, y son:
Date Da una cadena con la fecha Date(tiempo) '23-OCT-1992'
Time Da una cadena con la hora Time(tiempo) '14:22:32.95'
El formato de la cadena entregada es específico del sistema operativo (en el ejemplo, de VMS).
El constructor de conjuntos se define como sigue:
constructor-de-conjunto = "[" lista-de-elementos "]".
lista-de-elementos = elemento { "," elemento }.
elemento = valor | (valor ".." valor).
Ejemplos:
TYPE
conjLetras = SET OF Char;
CONST
minusculas = ['a'..'z', 'á'..'ú'];
Manipulación de conjuntos
El estándar de Pascal extendido también permite definir esquemas de conjuntos, como sigue:
TYPE
conjuntoDeCaracteres (infC, SupC: Char) = SET OF InfC..SupC;
mayusculas = conjuntoDeCaracteres ('A', 'B');
minusculas = conjuntoDeCaracteres ('a', 'b');
VAR
vocalesMinusculas : minusculas VALUE {'a', 'e', 'i', 'o', 'u'};
El nuevo estándar también define la función "Card", la cual da cardinalidad (esto es, el número de elementos) que contiene un conjunto. Por ejemplo:
Card(vocalesMinusculas) Entrega un valor de 5
- Álgebra Matricial
- Animales
- Animales 2
- Lee Dia
- Meses
- Mínimos Cuadrados
- Pirámide
- Raíces
- Suma de Matrices
- Trapecio
- Triángulo
- Factorial