Articulo de referencia

IP Pascal

IP Pascal es una implementación del lenguaje de programación Pascal que utiliza la plataforma de portabilidad IP, un sistema de implementación de lenguaje, sistema operativo y m...

IP Pascal es una implementación del lenguaje de programación Pascal que utiliza la plataforma de portabilidad IP, un sistema de implementación de lenguaje, sistema operativo y máquina múltiple. Implementa el lenguaje "Pascaline" (llamado así por la calculadora de Blaise Pascal) y ha superado la prueba Pascal Validation Suite.

Este artículo sigue una versión bastante antigua de Pascaline. Existe una versión más nueva de Pascaline llamada Pascal-P6, parte de la serie Pascal-P. Consulte las referencias a continuación.

Descripción general

IP Pascal implementa el lenguaje "Pascaline" (nombrado así por la calculadora de Blaise Pascal ), que es un superconjunto altamente extendido de ISO 7185 Pascal. Agrega modularidad con control de espacio de nombres , incluido el concepto de monitor de tareas paralelas , matrices dinámicas , sobrecargas y anulaciones, objetos y una serie de otras extensiones menores al lenguaje. IP implementa una plataforma de portabilidad, que incluye un kit de herramientas de widgets , una biblioteca TCP/IP , una biblioteca MIDI y de sonido y otras funciones, que permite que tanto los programas escritos bajo IP Pascal como el propio IP Pascal se muevan a múltiples sistemas operativos y máquinas.

IP Pascal es una de las únicas implementaciones de Pascal que aún existen que ha pasado la Pascal Validation Suite, un gran conjunto de pruebas creadas para verificar el cumplimiento de la norma ISO 7185 Pascal.

Aunque Pascaline extiende la norma ISO 7185 Pascal, no reduce la seguridad de tipos de Pascal (como muchos otros dialectos de Pascal lo han hecho al incluir los llamados "escapes de tipos"). La funcionalidad del lenguaje es similar a la de C# (que implementa un lenguaje similar a C++ pero con las inseguridades de tipos eliminadas), y Pascaline se puede utilizar en cualquier lugar donde se puedan utilizar programas administrados (aunque se basa en un lenguaje 30 años más antiguo que C#).

Idioma

IP Pascal comienza con ISO 7185 Pascal (que estandarizó el lenguaje original de Niklaus Wirth ) y agrega:

Los módulos, incluidos los constructos de tareas paralelas, procesan, monitorean y comparten

módulo mymod(entrada, salida); 
usa extlib; const uno = 1;
tipo cadena = matriz empaquetada de char; procedimiento wrtstr( vista s: cadena); var privada s: cadena; procedimiento wrtstr( vista s: cadena); var i: entero; comienzo para i := 1 a máx(s) hacer write(s[i]) fin ; comienzo { inicializar monitor } fin ; comienzo { apagar monitor } fin .











Los módulos tienen secciones de entrada y salida. Las declaraciones en los módulos forman sus propias especificaciones de interfaz y no es necesario tener secciones de interfaz e implementación. Si se necesita un archivo de declaración de interfaz independiente, se crea quitando el código de un módulo y creando un "esqueleto" del módulo. Esto se hace normalmente solo si el objeto de un módulo se va a enviar sin la fuente.

Los módulos deben ocupar un único archivo y los módulos hacen referencia a otros módulos mediante una declaración uses o joins . Para permitir esto, un módulo debe tener el mismo nombre que su nombre de archivo. La declaración uses indica que las declaraciones globales del módulo al que se hace referencia se fusionarán con las del módulo que lo referencia y cualquier conflicto de nombres que resulte provocará un error. La declaración joins hará que el módulo al que se hace referencia sea accesible a través del módulo que lo referencia, pero no fusiona los espacios de nombres de los dos módulos. En su lugar, el módulo que hace referencia debe utilizar un denominado "identificador calificado":

módulo.identificador

Un programa de la norma ISO 7185 Pascal es directamente análogo a un módulo y, en efecto, es un módulo sin una sección de salida. Debido a que todos los módulos del sistema están "conectados en cadena" de modo que cada uno se ejecuta en orden, un programa asume el "mando" del programa simplemente porque no sale de su inicialización hasta que se completa su función completa, a diferencia de un módulo que sí lo hace. De hecho, es posible tener múltiples secciones de programa, que se ejecutarían en secuencia.

Un módulo de proceso , al igual que un módulo de programa , solo tiene una sección de inicialización y ejecuta su inicio, función completa y finalización en esa sección. Sin embargo, obtiene su propio hilo para la ejecución, además del hilo principal que ejecuta los módulos de programa . Como tal, solo puede llamar a los módulos de monitorización y uso compartido .

Un monitor es un módulo que incluye el bloqueo de tareas en cada llamada a un procedimiento o función accesible externamente , e implementa la comunicación entre tareas mediante semáforos.

Un módulo compartido , debido a que no tiene datos globales en absoluto, puede ser utilizado por cualquier otro módulo en el sistema y se utiliza para colocar código de biblioteca.

Debido a que el sistema de módulos implementa directamente la multitarea/multihilo mediante el concepto de Monitor , resuelve la mayoría de los problemas de acceso a multihilo. Los datos de un módulo están vinculados al código con mutexes o secciones mutuamente excluyentes . Las subtareas/subhilos se inician de forma transparente con el módulo de proceso. Varias subtareas/subhilos pueden acceder a los monitores o compartir módulos. Un módulo compartido es un módulo sin datos, que no necesita los mecanismos de bloqueo de un monitor.

Matrices dinámicas

En IP Pascal, las dinámicas se consideran "contenedores" para matrices estáticas. El resultado es que IP Pascal es quizás el único Pascal donde las matrices dinámicas son totalmente compatibles con las matrices estáticas ISO 7185 del lenguaje original. Una matriz estática se puede pasar a un parámetro de matriz dinámica para un procedimiento o función, o crearse con nuevas

programa test(salida); 
tipo cadena = matriz empaquetada de char; var s: cadena; procedimiento wrtstr( vista s: cadena); var i: entero; comienzo para i := 1 a máx(s) hacer write(s[i]) fin ; comienzo







nuevo(s, 12); s := 'Hola, mundo'; cadena(s^); wrtstr('Eso es todo amigos')
fin .

Estas matrices "contenedoras" pueden tener cualquier número de dimensiones.

Expresiones constantes

Una declaración constante puede contener expresiones de otras constantes

constante b = a+10;

Base para números

$ff, &76, %011000

Etiquetas de acceso alfanuméricas

etiqueta salir;
 ir a salir;

guión bajo en todas las etiquetas

var my_number: entero;

subrayar en números

un := 1234_5678;

El carácter '_' (salto) se puede incluir en cualquier parte de un número, excepto en el primer dígito. Se ignora y solo sirve para separar dígitos del número.

Secuencias de caracteres especiales que se pueden incrustar en cadenas constantes

const str = 'la lluvia en España\cr\lf';

Utilizando mnemotécnicos estándar ISO 8859-1 .

Duplicación de encabezados reenviados

procedimiento x(i: entero); adelante ; 
...
procedimiento x(i: entero);
comienzo
...
fin ;

Esto hace que sea más fácil declarar un reenvío mediante cortar y pegar, y mantiene los parámetros del procedimiento o función en el encabezado real donde pueden verse.

procedimiento de parada

error de procedimiento ( vista s: cadena); 
comenzar
writeln('*** Error: ', s:0); detener { terminar programa }
fin ;

Archivos de encabezado predefinidos especiales

programa myprog(entrada, salida, lista); 
comenzar
writeln(list, 'Inicio del listado:'); ...
programa echo(salida, comando); 
var c: char;
begin
mientras no eoln(comando) do begin
leer(comando, c); escribir(c)
fin ; writeln
fin .
programa newprog(entrada, salida, error); 
comenzar
... writeln(error, 'Parámetro incorrecto'); detener ...

'comando' es un archivo que se conecta a la línea de comando, de modo que pueda leerse mediante operaciones de lectura de archivos normales.

Conexión automática de archivos de encabezado de programa a nombres de línea de comandos

programa copia(origen, destino); 
var origen, destino: texto; c: char;
comenzar
restablecer(fuente); reescribir(destino); mientras no eof(fuente) comience mientras no eoln ( fuente ) comience

leer(fuente, c); escribir(destino, c)
fin ; readln(fuente); writeln(destino)
fin
fin .

Los archivos 'fuente' y 'destino' se conectan automáticamente a los parámetros en la línea de comando del programa.

Operaciones de denominación y manejo de archivos

 programa extfile ( salida ) ; var f : archivo de entero ; begin asignar ( f , 'miarchivo' ) ; { establecer el nombre del archivo externo} actualizar ( f ) ; { mantener el archivo existente y establecer el modo de escritura} posición ( f , longitud ( f )) ; { posición al final del archivo para agregarlo} writeln ( 'El final del archivo es: ' , ubicación ( f )) ; { indicar al usuario la ubicación del nuevo elemento} escribir ( f , 54321 ) ; { escribir el último elemento nuevo} cerrar ( f ) { cerrar el archivo} fin . 
     
 
      
     
      
      
      
     
 

Declaraciones fijas que declaran tipos constantes estructurados

tabla fija : matriz [1..5] del  registro a: entero; matriz empaquetada  [1..10] del carácter fin = matriz registro 1, 'data1 ' fin ,
                    registro 2, 'data2 ' fin ,
                    registro 3, 'data3 ' fin ,
                    registro 4, 'data4 ' fin ,
                    registro 5, 'data5 ' fin fin ;

                

Operadores de bits booleanos

prueba
 de programa ; var a, b: entero;
 comienza 
   a := a y b;
   b := b o $a5;
   a := no b;
   b := a xor b
 fin .

Variables de rango extendido

prueba del programa ;
 var a: lintero;
    b: cardenal;
    c: lcardinal;
    d: 1..maxint*2;
...

Las especificaciones de rango extendido proporcionan reglas para los escalares que se encuentran fuera del rango de -maxint..maxint. Depende de cada implementación qué tan grande es posible que sea un número, pero Pascaline define una serie de tipos estándar que aprovechan los rangos extendidos, incluidos linteger para enteros de rango doble, cardinal para enteros sin signo y lcardinal para enteros de rango doble sin signo. Pascaline también define nuevos límites para estos tipos, como maxlint, maxcrd y maxlcrd.

Semáforos

prueba de monitor ; 
var notempty, notfull: semáforo; procedimiento entrar en cola; comenzar mientras nodata hacer esperar(notempty); ... señaluno(no llena) fin ; ... empezar fin .

Los semáforos implementan la puesta en cola de eventos de tareas directamente en el lenguaje, utilizando los métodos clásicos descritos por Per Brinch Hansen .

Anulaciones

módulo test1;
 procedimiento virtual  x;
 comenzar
   ...
fin ;
programa prueba;
 se une a test1;
 anula  el procedimiento x;
 comienza 
   heredado x
 fin ;
 comienza 
fin .

La sustitución de un procedimiento o una función en otro módulo "engancha" efectivamente esa rutina, reemplazando la definición para todos los que la llaman, pero hace que la definición original esté disponible para el módulo que la sustituye. Esto permite que el módulo que la sustituye agregue una nueva funcionalidad al procedimiento o la función antiguos. Esto se puede implementar con cualquier profundidad.

Sobrecargas

procedimiento x;
 comienzo 
fin ;
 sobrecarga  procedimiento x(i: entero);
 comienzo 
fin ;
 sobrecarga  función x: entero;
 comienzo
   xx:= 1
fin ;

Los "grupos" de sobrecarga permiten colocar una serie de procedimientos y/o funciones bajo el mismo nombre y acceder a ellos por su parámetro formal o "firma" de uso. A diferencia de otros lenguajes que implementan el concepto, Pascaline no aceptará sobrecargas como pertenecientes al mismo grupo a menos que no sean ambiguas entre sí. Esto significa que no hay "prioridad" de sobrecargas, ni ninguna duda sobre qué rutina de un grupo de sobrecarga se ejecutará para una referencia real dada.

Objetos

prueba
 de programa ; usa clase base;
 clase alpha;
 extiende beta;
 tipo alpha_ref = referencia  a alpha;
 var a, b: entero;
          siguiente: alpha_ref;
 procedimiento virtual x(d: entero);
 comenzar
   aa:= d;
   selfl:= siguiente
fin ;
 var privada
 q: entero;
 empezar fin .
 var r: alfa_ref;
 comenzar

   nuevo(r);
   ...
   si r es alfa entonces ra := 1;
   rx(5);
   ...
fin .

En Pascaline, las clases son una instancia dinámica de un módulo (y los módulos son una instancia estática de una clase). Las clases son una construcción de código (no un tipo) que existe entre módulos y procedimientos y funciones. Debido a que una clase es un módulo, puede definir cualquier construcción de código, como constantes, tipos, variables, procedimientos y funciones fijos (que se convierten en "métodos"), y hacerlos públicos para los clientes de la clase u ocultarlos con la palabra clave "private". Dado que una clase es un módulo, se puede acceder a ella mediante un identificador calificado.

Las clases como módulos tienen acceso automático a su espacio de nombres, como en C# y C++, ya que no requieren ninguna calificación. Fuera de la clase, se puede acceder a todos los miembros de la clase mediante un identificador calificado o una referencia. Una referencia es un puntero al objeto que se crea según la clase. Se puede crear cualquier cantidad de instancias de una clase, conocidas como "objetos", con la declaración new() y eliminarlas con la declaración dispose(). Se debe acceder a los miembros de la clase que tienen datos de instancia asociados a ellos, como variables (o campos) y métodos, a través de una referencia. Una referencia es un tipo y se parece a un puntero, incluida la capacidad de tener el valor nulo y verificar la igualdad con otros tipos de referencia. No es necesario calificar el acceso al puntero con "^".

Pascaline implementa el concepto de "gracia de referencia" para permitir que una referencia acceda a cualquier parte del objeto independientemente de si es por instancia o no. Esta característica permite que los miembros de la clase sean "promovidos", es decir, que pasen de ser constantes a variables y luego a "propiedades" (que son campos de la clase cuyo acceso de lectura y escritura se proporciona mediante los métodos "get" y "set").

Se proporcionan tanto sobrecargas como anulaciones para los métodos de un objeto. Un método que se va a anular debe indicarse como virtual.

Los métodos de objeto pueden cambiar la referencia utilizada para acceder a ellos con la selfpalabra clave.

Sólo se implementa la herencia única.

Manejo estructurado de excepciones

intentar

   ...

excepto ...
 de lo contrario ...;

tirar

La instrucción "try" puede proteger una serie de instrucciones y cualquier excepción marcada dentro del código se envía a la instrucción después de "except". La instrucción try también incluye una cláusula else que permite ejecutar una instrucción al finalizar normalmente el bloque try.

Las excepciones se generan en el código a través del procedimiento throw(). Las instrucciones try permiten que el programa salga de cualquier bloque anidado y sirven como un mejor reemplazo para los gotos intraprocedimiento (que aún son compatibles con Pascaline). Dado que las excepciones no controladas generan errores de forma predeterminada, el procedimiento throw() puede servir como un sistema de señalización de errores de propósito general.

Afirmaciones

afirmar(expresión);

El procedimiento del sistema assert hace que el programa finalice si el valor probado es falso. Normalmente está asociado a un volcado o diagnóstico en tiempo de ejecución y se puede eliminar mediante una opción del compilador.

Unicode

IP Pascal puede generar programas en modo ISO 8859-1 (caracteres de 8 bits) o en modo Unicode con un simple cambio en tiempo de compilación (a diferencia de muchos otros lenguajes, no hay diferencia de origen entre programas Unicode y no Unicode). El formato UTF-8 compatible con ASCII se utiliza en archivos de texto, y estos archivos se leen hacia y desde caracteres de 8 o 16 bits internos al programa (los 128 caracteres superiores de ISO 8859-1 se convierten hacia y desde formato UTF-8 en archivos de texto incluso en un programa codificado con caracteres de 8 bits).

Constante para límite alto de caracteres

De manera similar a maxint, Pascaline tiene un maxchr, que es el carácter máximo que existe en el conjunto de caracteres (y puede que no tenga una representación gráfica). El rango del tipo char se define entonces como 0..maxchr. Esta es una adición importante para trabajar con tipos como "conjunto de char", y ayuda cuando se trabaja con diferentes opciones de conjuntos de caracteres (como ISO 8859-1 o Unicode).

Estructura modular

IP Pascal utiliza un concepto de apilamiento exclusivo para los módulos. Cada módulo se apila uno sobre otro en la memoria y se ejecuta en la parte inferior. El módulo inferior llama al módulo que está al lado, y este llama al módulo siguiente, y así sucesivamente.

envoltura
serlib
programa
tapa

El módulo de tapa (a veces llamado "celda" en la terminología de IP Pascal, en honor a un concepto de diseño de circuitos integrados ) termina la pila y comienza un proceso de retorno que se extiende hacia abajo hasta que el programa termina. Cada módulo tiene su sección de inicio o entrada que se realiza en el camino hacia arriba de la pila, y su sección de finalización o salida que se realiza en el camino de regreso hacia abajo.

Esto coincide con las dependencias naturales de un programa. Los módulos más primitivos, como el soporte de E/S básico en "serlib", realizan su inicialización primero y su finalización por último, antes y después de los módulos de nivel superior en la pila.

Plataforma de portabilidad

IP Pascal tiene una serie de módulos (o "bibliotecas") que forman una "plataforma de portabilidad" llamada Petit-Ami (que en francés significa "pequeño amigo"). Estas bibliotecas presentan una API idealizada para cada función que se aplica, como archivos y funciones extendidas del sistema operativo, gráficos, midi y sonido, etc. La colección completa forma la base para una implementación en cada sistema operativo y máquina en la que aparece IP Pascal.

Las dos diferencias importantes entre IP Pascal y muchos otros lenguajes que simplemente se han combinado con bibliotecas de gráficos portátiles son las siguientes:

  1. IP Pascal utiliza su propia plataforma de portabilidad para su propio código de bajo nivel, de modo que una vez que se crea la plataforma para un sistema operativo y una máquina en particular, tanto el sistema IP como los programas que compila pueden ejecutarse en él. Esto es similar a la forma en que funcionan los sistemas Java y UCSD Pascal , pero con código compilado de alta optimización real, no código interpretado o código compilado "justo a tiempo".
  2. Dado que los módulos pueden anular funciones de nivel inferior, como la declaración "write" de Pascal, los programas Pascal ISO 7185 normales y sin modificar también pueden utilizar aspectos avanzados de la plataforma de portabilidad. Esto es diferente a muchas o la mayoría de las bibliotecas de gráficos portables que obligan al usuario a utilizar una metodología de E/S completamente diferente para acceder a un sistema de gráficos en ventanas, por ejemplo, C, otros Pascal y Visual Basic .

También se pueden crear módulos IP que sean independientes del sistema y dependan únicamente de los módulos de la plataforma de portabilidad. El resultado es que IP Pascal es altamente portable.


Ejemplo: El programa estándar "hola mundo" está acoplado para mostrarse en una ventana gráfica.

programa HolaMundo(salida);
 comenzar
    writeln('¡Hola, mundo!')
fin .


Ejemplo: "hola mundo" con comandos gráficos añadidos. Tenga en cuenta que todavía se utilizan las instrucciones de salida estándar de Pascal.

 programa hola ( entrada , salida ) ; usa gralib ; var er : evtrec ; begin bcolor ( salida , verde ) ; curvis ( salida , falso ) ; auto ( salida , falso ) ; page ( salida ) ; fcolor ( salida , rojo ) ; frect ( salida , 50 , 50 , maxxg ( salida ) - 50 , maxyg ( salida ) - 50 ) ; fcolorg ( salida , maxint , maxint - ( maxint div 3 ) , maxint - maxint div 3 ) ; frect ( salida , 50 , 50 , 53 , maxyg ( salida ) - 50 ) ; frect ( salida , 50 , 50 , maxxg ( salida ) - 50 , 53 ) ; fcolorg ( salida , maxint div 2 , 0 , 0 ) ; frect ( salida , 52 , maxyg ( salida ) -53 , maxxg ( salida ) -50 , maxyg ( salida ) -50 ) ; frect ( salida , maxxg ( salida ) -53 , 52 , maxxg ( salida ) -50 , maxyg  
  
   
 
     
     
     
    
     
        
           
        
        
         
        
        ( salida ) - 50 ) ; 
font ( salida , font_sign ) ; fontsiz ( salida , 100 ) ; binvis ( salida ) ; fcolor ( salida , cian ) ; cursorg ( salida , maxxg ( salida ) div 2 - strsiz ( salida , 'hola, mundo' ) div 2 + 3 , maxyg ( salida ) div 2 - 100 div 2 + 3 ) ; writeln ( 'hola, mundo' ) ; fcolor ( salida , azul ) ; cursorg ( salida , maxxg ( salida ) div 2 - strsiz ( salida , 'hola, mundo' ) div 2 , maxyg ( salida ) div 2 - 100 div 2 ) ; writeln ( 'hola, mundo' ) ; repita el evento ( entrada , er ) hasta er . etype = eterm fin .     
     
    
     
          
                        
    
     
          
                        
    
          
  
Ejemplo: Juego de ruptura.
Ejemplo: Reloj gráfico en una ventana de tamaño considerable.

Debido a que los módulos IP Pascal pueden "anularse" entre sí, un módulo de extensión gráfica (o cualquier otro tipo de módulo) puede anular las llamadas de E/S estándar implementadas en un módulo inferior. Por lo tanto, paslib implementa instrucciones estándar de Pascal, como lectura, escritura y otros servicios de soporte. gralib anula estos servicios y redirige todas las E/S estándar de Pascal a ventanas gráficas.

La diferencia entre esta y otras bibliotecas similares en otras implementaciones es que normalmente hay que dejar de usar las instrucciones de E/S estándar y cambiar a un conjunto de llamadas y paradigmas completamente diferente. Esto significa que no se pueden "transferir" programas implementados con el paradigma de E/S serial a sistemas gráficos.

Otra diferencia importante con IP Pascal es que utiliza métodos de lenguaje procedimental para acceder a la biblioteca de gráficos Windowed. La mayoría de los kits de herramientas de gráficos fuerzan el uso de métodos de programación orientada a objetos en el kit de herramientas. Una razón para esto es que la programación orientada a objetos es una buena opción para los gráficos, pero también ocurre porque los sistemas comunes como Windows fuerzan al programa de aplicación a aparecer como un programa de servicio para el sistema operativo, apareciendo como una colección de funciones llamadas por el sistema operativo, en lugar de que el programa controle su propia ejecución y llame al sistema operativo. Esto se conoce comúnmente como diseño de devolución de llamada . El código orientado a objetos a menudo funciona mejor con devoluciones de llamada porque permite que los métodos de un objeto se llamen como devoluciones de llamada, en lugar de que un programador tenga que registrar varios punteros a funciones en el código de manejo de eventos, cada uno de los cuales sería una devolución de llamada individual.

IP Pascal convierte la programación orientada a objetos en una metodología opcional, no obligatoria, para escribir programas. La capacidad de IP Pascal de utilizar métodos procedimentales para acceder a todas las funciones gráficas significa que no existe un " efecto acantilado " para los programas más antiguos. No es necesario reescribirlos solo para aprovechar los entornos de programación modernos.

La plataforma de portabilidad IP admite un modo de caracteres, incluso en entornos gráficos, al proporcionar una "cuadrícula de caracteres" que se superpone a la cuadrícula de píxeles. Los programas que utilizan únicamente llamadas al modo de caracteres (que funcionarían en cualquier terminal o conexión telnet) funcionan en entornos gráficos automáticamente.

Historia

La implementación del Z80

El compilador comenzó a funcionar en 1980 en el sistema operativo de disco Micropolis , pero rápidamente se trasladó a CP/M que se ejecutaba en el Z80. El sistema original estaba codificado en lenguaje ensamblador del Z80 y generaba código de máquina directo para el Z80 . Era un compilador de una sola pasada sin enlazador, incluía su biblioteca de soporte del sistema dentro del compilador y la reubicaba y generaba la salida en el código generado en el archivo de disco ejecutable.

Después de que el compilador estuvo operativo, casi exactamente en el nuevo año de 1980, se escribió un ensamblador complementario para el compilador, en Pascal, seguido de un enlazador, en lenguaje ensamblador Z80. Esta extraña combinación se debió a un cálculo que mostró que las tablas de enlazadores serían un problema en el Z80 limitado a 64 kb, por lo que el enlazador debía ser lo más pequeño posible. Esto se utilizó luego para mover el código fuente del compilador y enlazador Z80 del ensamblador Micropolis (que era un ensamblador sin enlazador que creaba un único binario de salida) al nuevo sistema de enlazadores de ensamblador.

Después de esto, se rediseñó el compilador para generar la salida en el formato del enlazador y la biblioteca de soporte se trasladó a un archivo separado y se vinculó.

En 1981, el compilador fue rediseñado en gran medida para agregarle optimización, como asignación de registros, saltos de booleanos, código muerto, plegado de constantes y otras optimizaciones. Esto creó una implementación de Pascal que se evaluó mejor que cualquier compilador Z80 existente, así como la mayoría de los compiladores 8086. Desafortunadamente, con 46 kb, también era difícil de usar, ya que solo podía compilar unas pocas páginas de código fuente antes de desbordar sus tablas (este era un problema común con la mayoría de las implementaciones de Pascal en procesadores de direcciones pequeños). El sistema pudo usarse principalmente debido a la decisión de crear un enlazador compacto que permitiera construir sistemas grandes a partir de estos pequeños archivos de objetos.

A pesar de esto, la implementación original de IP Pascal funcionó hasta 1987 como un compilador de propósito general. En esta fase, IP Pascal era como C en su diseño modular. Cada archivo fuente era una unidad y consistía en alguna combinación de un módulo de "programa", tipos, constantes, variables, procedimientos o funciones. Estos estaban en "formato libre". Los procedimientos, funciones, tipos, constantes y variables podían estar fuera de cualquier bloque y en cualquier orden. Los procedimientos, funciones y variables en otros archivos eran referenciados por declaraciones "externas", y los procedimientos, funciones y variables en el archivo actual eran declarados "globales". Cada archivo se compilaba en un archivo objeto y luego se vinculaba entre sí. No había comprobación de tipos en los archivos objeto.

Como parte del compilador original, se creó un módulo de E/S de terminal independiente del dispositivo para permitir el uso de cualquier terminal serial (similar a la unidad CRT de Turbo Pascal ), que permanece hasta el día de hoy.

En 1985, se inició un esfuerzo para reescribir el compilador en Pascal. El nuevo compilador sería de dos pasos con intermedios, lo que fue diseñado para resolver los problemas de memoria asociados con el primer compilador. La parte frontal del compilador fue creada y probada sin capacidades de generación de código intermedio (solo análisis).

En 1987, el sistema Z80 utilizado para IP se cambió por un IBM-PC 80386 y se detuvo el trabajo en él. A partir de ese momento, se utilizaron varios otros compiladores estándar ISO 7185, hasta llegar al compilador SVS Pascal, una implementación basada en un extensor DPMI de 32 bits .

La implementación del 80386

En 1993, los compiladores compatibles con ISO 7185 que ofrecían código de 32 bits de alta calidad estaban desapareciendo. En ese momento, la opción era dejar de usar Pascal o revivir el antiguo proyecto IP Pascal y modernizarlo como un compilador 80386. En ese momento, lo único que existía y que se podía usar en el IBM-PC era un analizador sintáctico y un ensamblador (para Z80). Entre 1993 y 1994, el ensamblador se hizo modular para que pudiera usarse en varias CPU, incluida la 80386, se creó un enlazador para reemplazar al enlazador de lenguaje ensamblador de Z80 y se terminó una interfaz de compilador Pascal para generar código intermedio. Finalmente, se construyó un simulador de código intermedio, en Pascal, para probar el sistema.

En 1994, el simulador se utilizó para ampliar el lenguaje central IP Pascal ISO 7185 para incluir características como matrices dinámicas.

En 1995, se creó un "codificador de verificación" para el código de máquina 80386 y un programa de conversión para tomar los archivos de objetos de salida y crear un archivo "ejecutable portátil" para Windows. Se creó la biblioteca de soporte del sistema para IP Pascal, que a su vez estaba en IP Pascal. Esta fue una medida inusual que se tomó para evitar tener que recodificar posteriormente la biblioteca desde el ensamblador u otro Pascal a IP Pascal, pero con el problema de que tanto el generador de código 80386 como la biblioteca tendrían que depurarse juntos.

A principios de 1996, el objetivo original de Windows NT se cambió a Windows 95, y IP Pascal pasó a ser plenamente operativo como compilador 80386 en Windows. El sistema se autoarrancó y el código Pascal restante se trasladó de SVS Pascal a IP Pascal para completar el arranque. Este proceso se vio facilitado considerablemente por la capacidad de SVS Pascal basado en DPMI para ejecutarse en Windows 95, lo que supuso que se eliminara la necesidad de arrancar de DOS a Windows 95 una y otra vez.

La implementación de Linux

En el año 2000 se creó una versión para Linux (Red Hat) que sólo permitía el modo texto. Esta implementación utiliza directamente las llamadas del sistema y evita el uso de glibc , creando así binarios más delgados que si se utilizara el sistema de soporte completo necesario para C, a costa de la portabilidad de los binarios.

El plan es crear una versión de la biblioteca de texto que utilice información de termcap y la biblioteca gráfica bajo X11.

Pasos para “escribir una vez, ejecutar en cualquier lugar”

En 1997, se trasladó a Windows una versión de la biblioteca de terminales del IP Pascal original de 1980 y se inició un codificador final para el 80386. Sin embargo, la razón principal para necesitar un codificador mejorado, la velocidad de ejecución, se volvió irrelevante en gran medida debido a los aumentos en la velocidad del procesador en el IBM-PC. Como resultado, el nuevo codificador no se terminó hasta 2003.

En 2001, se creó un programa complementario de IP Pascal para traducir los archivos de encabezado de C a archivos de encabezado de Pascal. El objetivo era reemplazar el método manual de creación de interfaces de sistema operativo para IP Pascal.

En 2003, se creó un módulo totalmente gráfico e independiente del sistema operativo para IP Pascal.

En 2005 se añadió el kit de gestión de ventanas y widgets.

Pascalina

En 2015 aproximadamente se recopiló y amplió la especificación del lenguaje para IP Pascal. El resultado fue un lenguaje llamado "Pascaline". Gran parte de la especificación de Pascaline se implementó en IP Pascal. Sin embargo, se tomó la decisión de incorporar primero la mayor parte del lenguaje en la base de código del compilador Pascal-P6. La serie Pascal-P es el compilador original de la ETH de Zúrich creado por los estudiantes de Wirth allí y existe hoy como Pascal-P4 (el nombre elegido por Niklaus Wirth). Se convirtió a ISO 7185 Pascal en Pascal-P5 y se está actualizando al lenguaje Pascaline en Pascal-P6. Al mismo tiempo, Pascal-P6 se ​​está adaptando como un compilador completo, comenzando con la generación de código para el modelo de procesador AMD64, con el objetivo de extenderlo a otros procesadores como ARM y RISC-V. El objetivo es llegar a Pascal-P6 1.0 cuando la especificación Pascaline esté completamente implementada.

Pequeño Amigo

En 2019, la biblioteca de soporte para IP Pascal se reprogramó en C. La idea era doble: primero, hacer que la biblioteca fuera útil para todos los lenguajes, no solo para Pascal, y segundo, hacer que la codificación y la depuración en nuevas plataformas sean más fáciles y rápidas. Petit-Ami ahora está disponible para Windows, Linux y una implementación parcial en Mac OS y BSD Unix.

Lecciones

En retrospectiva, el mayor error de la versión Z80 fue su estructura de una sola pasada. No había ninguna razón real para ello; el compilador anterior del autor (Basic) era de varias pasadas con almacenamiento intermedio. El único argumento a favor era que se suponía que la compilación de una sola pasada era más rápida. Sin embargo, la compilación de una sola pasada resulta ser una mala opción para máquinas pequeñas y no es probable que ayude a las optimizaciones avanzadas comunes en máquinas grandes.

Además, el aspecto de una sola pasada ralentizó o impidió que el compilador se pusiera en marcha desde el lenguaje ensamblador Z80 hasta el propio Pascal. Dado que el compilador era monolítico, la conversión a Pascal no se podía hacer sección por sección, sino que tenía que proceder como un reemplazo total. Cuando se inició el reemplazo, el proyecto duró más que la máquina. La mayor ayuda que la compilación en dos pasadas proporcionó a la implementación de I80386 fue el mantenimiento de un libro estándar de instrucciones intermedias que se comunicaban entre los extremos frontal y posterior del compilador. Esta "etapa" de compilación bien entendida redujo la complejidad general. Intuitivamente, cuando dos programas de igual tamaño se acoplan íntimamente, la complejidad no es aditiva, sino multiplicativa, porque las conexiones entre las mitades del programa se multiplican sin control.

Otra lección de la época del Z80, que se corrigió en el compilador 80386, fue escribir la mayor cantidad posible de código en Pascal, incluso la biblioteca de soporte. El hecho de que el código de soporte del 80386 esté escrito en Pascal lo ha hecho tan modular y portátil que la mayor parte se trasladó del área específica del sistema operativo a la sección de la biblioteca de "código común", una sección reservada para el código que nunca cambia para cada máquina y sistema operativo. Incluso el código "específico del sistema" necesita sólo una ligera modificación de una implementación a otra. El resultado es un gran ahorro de trabajo de implementación al trasladar el sistema.

Finalmente, fue un error entrar en una segunda ronda de optimización antes de arrancar el compilador. Aunque la mejora del código de salida fue considerable, el aumento resultante en la complejidad del compilador causó problemas con el limitado espacio de direcciones. En ese momento, se consideró que un código mejor optimizado era un facilitador para arrancar el código en Pascal. En retrospectiva, las secciones restantes escritas en ensamblador ERAN el problema y necesitaban ser eliminadas, cuanto antes mejor. Otra forma de decir esto es que los problemas de espacio podrían ser transitorios, pero tener secciones significativas del programa escritas en ensamblador es un problema serio y duradero.

Lectura adicional

  • Kathleen Jansen y Niklaus Wirth : PASCAL - Manual de usuario e informe . Springer-Verlag, 1974, 1985, 1991, ISBN  0-387-97649-3 , ISBN 0-387-90144-2 y ISBN 3-540-90144-2 [1]  
  • Niklaus Wirth: "El lenguaje de programación Pascal". Acta Informatica , 1, (junio de 1971) 35–63
  • ISO/IEC 7185: Lenguajes de programación - PASCAL . [2]

Referencias

  1. ^ Supcik, Jacques (5 de diciembre de 1997). «PASCAL - Manual de usuario e informe». ETH Zürich: Departamento de Informática. Archivado desde el original el 14 de marzo de 2005. Consultado el 23 de junio de 2005 .
  2. ^ Moore, Scott A. "ANSIISO PASCAL". Moorecad.com . Consultado el 21 de febrero de 2017 .
  • Sitio web oficial
  • El sitio web de la norma ISO 7185 Pascal
  • Repositorio principal de Pascal-P6
  • Repositorio espejo de Pascal-P6
Retrieved from "https://en.wikipedia.org/w/index.php?title=IP_Pascal&oldid=1259369094"