IP Pascal es una implementación del lenguaje de programación Pascal que utiliza la plataforma de portabilidad IP, una máquina múltiple, un sistema operativo y un sistema de implementación de lenguaje.
Descripción general
IP Pascal implementa el lenguaje "Pascaline" (llamado así por la calculadora de Blaise Pascal ), que es un superconjunto muy extendido de ISO 7185 Pascal. Agrega modularidad con control del 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 del lenguaje. IP implementa una plataforma de transferencia, que incluye un kit de herramientas de widgets , biblioteca TCP / IP , 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 todavía existen y que ha superado Pascal Validation Suite, un gran conjunto de pruebas creadas para verificar el cumplimiento de ISO 7185 Pascal.
Aunque Pascaline extiende ISO 7185 Pascal, no reduce la seguridad de tipos de Pascal (como muchos otros dialectos de Pascal tienen 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 tipo eliminadas), y Pascaline se puede usar en cualquier lugar donde se puedan usar programas administrados (aunque se basa en un lenguaje 30 años más antiguo). que C #).
Estado abierto o cerrado
El autor de Pascaline the language ha declarado que no hay ningún deseo de que siga siendo un lenguaje propietario. IP Pascal se vende como una implementación de Pascaline, pero el lenguaje en sí puede y debe ser abierto y debe tener implementaciones de calidad.
Con ese fin, la especificación completa de Pascaline se publicará en línea, y la intención a largo plazo es crear una versión del compilador-intérprete P5 de código abierto (una versión ISO 7185 del compilador-intérprete P4 de Wirth) que implemente el cumplimiento de Pascaline. Esto se conocerá como el compilador P6 y también se publicará y distribuirá abiertamente.
El valor de IP Pascal como producto comercial se basará en el IDE y los recursos del codificador-compilador de ese sistema.
Este artículo sigue una versión bastante antigua de Pascaline. Existe una versión más reciente de Pascaline como Pascal-P6, parte de la serie Pascal-P. Consulte las referencias a continuación.
Idioma
IP Pascal comienza con ISO 7185 Pascal (que estandarizó el idioma original de Niklaus Wirth ) y agrega:
módulo mymod (entrada, salida);
usa extlib;constante uno = 1;
tipo cadena = matriz empaquetada de caracteres ; procedimiento wrtstr ( vista s: cadena); var privado s: cadena; procedimiento wrtstr ( vista s: cadena); var i: número entero; comenzar para i: = 1 a max (s) hacen de escritura (s [i]) final ; begin {initialize monitor} end ; begin {shutdown monitor} end .
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 y de implementación. Si se necesita un archivo de declaración de interfaz separado, se crea eliminando el código de un módulo y creando un "esqueleto" del módulo. Por lo general, esto se hace solo si el objeto de un módulo se enviará sin la fuente.
Los módulos deben ocupar un solo archivo y los módulos hacen referencia a otros módulos a través de una declaración de usos o combinaciones . Para permitir esto, un módulo debe tener el mismo nombre que su nombre de archivo. La declaración de usos indica que el módulo referenciado tendrá sus declaraciones globales fusionadas con el módulo de referencia, y cualquier conflicto de nombre que resulte provocará un error. La declaración joins hará que el módulo referenciado sea accesible a través del módulo de referencia, pero no fusionará los espacios de nombres de los dos módulos. En su lugar, el módulo de referencia debe utilizar un "identificador calificado":
module.identifier
Un programa de ISO 7185 Pascal es directamente análogo a un módulo y es efectivamente un módulo sin una sección de salida. Debido a que todos los módulos del sistema están "encadenados" de manera que cada uno se ejecuta en orden, un programa asume el "comando" 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 lo hace. De hecho, es posible tener varias secciones del programa, que se ejecutarían en secuencia.
Un módulo de proceso , como un módulo de programa , tiene solo 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 del programa . Como tal, solo puede llamar a monitorear y compartir módulos.
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 las tareas mediante semáforos.
Un módulo compartido , debido a que no tiene ningún dato global, puede ser utilizado por cualquier otro módulo del sistema y se utiliza para colocar el código de la biblioteca en formato.
Debido a que el sistema de módulos implementa directamente la multitarea / subprocesos múltiples utilizando el concepto de Monitor , resuelve la mayoría de los problemas de acceso de subprocesos múltiples . Los datos de un módulo están vinculados al código con exclusiones mutuas o secciones mutuamente excluyentes . Las subtareas / subprocesos se inician de forma transparente con el módulo de proceso. Varias subtareas / subprocesos 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 idioma original. Una matriz estática se puede pasar a un parámetro de matriz dinámica a un procedimiento o función, o crearse con nuevos
prueba de programa (salida);
tipo cadena = matriz empaquetada de caracteres ; var s: cadena; procedimiento wrtstr ( vista s: cadena); var i: número entero; comenzar para i: = 1 a max (s) hacen de escritura (s [i]) final ; empezar
nuevo (s, 12); s: = 'Hola, mundo'; wrtstr (s ^); wrtstr ('Eso es todo amigos')
final .
Tales matrices de "contenedores" pueden tener cualquier número de dimensiones.
Expresiones constantes
Una declaración constante puede contener expresiones de otras constantes
const b = a + 10;
Radix para números
$ ff, & 76,% 011000
Ir a etiquetas alfanuméricas
salida de etiqueta ;ir a salir;
subrayado en todas las etiquetas
var my_number: integer;
subrayado en números
a: = 1234_5678;
El carácter '_' (ruptura) se puede incluir en cualquier lugar de un número excepto en el primer dígito. Se ignora y solo sirve para separar dígitos en el número.
Secuencias de caracteres especiales que se pueden incrustar en cadenas constantes
const str = 'la lluvia en España \ cr \ lf';
Utilizando nemotécnicos estándar ISO 8859-1 .
Duplicación de encabezados reenviados
procedimiento x (i: entero); adelante ;
...
procedimiento x (i: entero);
comenzar
...
terminar ;
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 se pueden ver.
detener el procedimiento
error de procedimiento ( ver s: cadena);
empezar
Writeln ('*** Error:', s: 0); detener {terminar el programa}
fin ;
Archivos de encabezado especiales predefinidos
programa myprog (entrada, salida, lista);
empezar
Writeln (lista, 'Inicio de la lista:'); ...
eco del programa (salida, comando);
var c: char;
comenzar
mientras no EOLN (comando) no comienzan
leer (comando, c); escribir (c)
final ;
final escrito .
programa newprog (entrada, salida, error);
empezar
... Writeln (error, 'Parámetro incorrecto'); detener ...
'comando' es un archivo que se conecta a la línea de comando, por lo que se puede leer usando las operaciones normales de lectura de archivos.
Conexión automática de archivos de encabezado de programa a nombres de línea de comando
copia de programa (origen, destino);
var origen, destino: texto; c: char;
empezar
reset (fuente); reescribir (destino); mientras que no eof (fuente) no comenzará
mientras no EOLN (fuente) no comenzará
leer (fuente, c); escribir (destino, c)
final ; readln (fuente); Writeln (destino)
end
end .
Los archivos 'origen' y 'destino' se conectan automáticamente a los parámetros en la línea de comando del programa.
Operaciones de nomenclatura y manejo de archivos
programa extfile ( salida ) ; var f : archivo de entero ; comenzar asignar ( f , 'miarchivo' ) ; {establecer el nombre del archivo externo} actualización ( f ) ; {mantener el archivo existente y ponerlo en 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} write ( f , 54321 ) ; {escribir nuevo último elemento} cerrar ( f ) {cerrar el archivo} final .
declaraciones fijas que declaran tipos constantes estructurados
tabla fija : matriz [1..5] del registro a: entero; matriz empaquetada [1..10] de char end = matriz registro 1, 'data1' end , record 2, 'data2' end , record 3, 'data3' end , record 4, 'data4' end , record 5, 'data5 ' fin fin ;
Operadores de bits booleanos
prueba de programa ;var a, b: número entero;comenzar a: = a y b; b: = b o $ a5; a: = no b; b: = a xor b final .
Variables de rango extendido
prueba de programa ;var a: linteger; b: cardenal; c: lcardinal; d: 1..maxint * 2;...
Las especificaciones de rango extendido dan reglas para escalares que se encuentran fuera del rango de -maxint..maxint. Es específico de la implementación en cuanto a cuán grande es posible un número, pero Pascaline define una serie de tipos estándar que explotan los rangos extendidos, incluyendo linteger para enteros de doble rango, cardinal para enteros sin signo e lcardinal para enteros de doble rango 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 enterqueue;comenzará mientras nodata hacen esperar (NotEmpty); ... signalone (no completo)terminar ;...comenzar fin .
Los semáforos implementan la 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;empezar ...terminar ;
prueba de programa ;se une a test1;anular el procedimiento x;comenzar heredado x final ;comenzar fin .
Reemplazar un procedimiento o función en otro módulo efectivamente "engancha" 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 de enganche. Esto permite que el módulo primordial agregue una nueva funcionalidad al procedimiento o función anterior. Esto se puede implementar a cualquier profundidad.
Sobrecargas
procedimiento x;comenzar fin ;procedimiento de sobrecarga x (i: entero);comenzar fin ;función de sobrecarga x: entero;empezar xx: = 1terminar ;
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 pregunta sobre qué rutina de un grupo de sobrecarga se ejecutará para cualquier referencia real dada.
Objetos
prueba de programa ;usa clase base;clase alfa;extiende beta;tipo alpha_ref = referencia a alfa;var a, b: número entero; siguiente: alpha_ref; procedimiento virtual x (d: entero);empezar aa: = d; selfl: = siguienteterminar ;var q privado : entero;comenzar fin .var r: alpha_ref;empezar nuevo (r); ... si r es alfa, entonces ra: = 1; rx (5); ...final .
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. Como una clase es un módulo, puede definir cualquier construcción de código, como constantes, tipos, variables, fijos, procedimientos y funciones (que se convierten en "métodos"), y hacerlos públicos para los clientes de la clase, u ocultarlos con el palabra clave "privada". 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 se encuentra en C # y C ++ en el sentido de 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 mediante una referencia. Una referencia es un puntero al objeto que se crea según la clase. Se puede crear cualquier número de instancias de una clase, conocidas como "objetos" con la instrucción new () y eliminar con la instrucción dispose (). Los miembros de la clase que tienen datos de instancia asociados con ellos, como variables (o campos) y métodos, deben ser accedidos a través de una referencia. Una referencia es un tipo y se parece a un puntero, incluida la capacidad de tener el valor nil y comprobar 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 "promocionados", que se muevan de constantes a variables, y luego a "propiedades" (que son campos de clase cuyo acceso de lectura y escritura son proporcionados por los métodos "get" y "set").
Se proporcionan tanto sobrecargas como anulaciones para los métodos del objeto. Un método que se anulará debe indicarse como virtual.
Los métodos de objeto pueden cambiar la referencia utilizada para acceder a ellos con la self
palabra clave.
Solo se implementa la herencia única.
Manejo estructurado de excepciones
intentar ...excepto ... más ...;lanzar
La declaración "try" puede proteger una serie de declaraciones, y cualquier excepción marcada dentro del código se enruta a la declaración después de "except". La instrucción try también incluye una cláusula else que permite ejecutar una instrucción en la terminación normal del bloque try.
Las excepciones se generan en el código mediante el procedimiento throw (). Las sentencias de prueba permiten que el programa salga de cualquier bloque anidado y sirven como un mejor reemplazo para los gotos dentro del procedimiento (que todavía 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);
La afirmación del procedimiento del sistema hace que el programa finalice si el valor probado es falso. Por lo general, está acoplado a un volcado o diagnóstico en tiempo de ejecución y se puede eliminar mediante la opción del compilador.
Unicode
IP Pascal puede generar programas en modo ISO 8859-1 (caracteres de 8 bits) o programas en modo Unicode con un simple interruptor 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 versiones posteriores de ASCII se usa en archivos de texto, y estos archivos se leen hacia y desde caracteres de 8 o 16 bits internos del programa (los 128 caracteres superiores de ISO 8859-1 se convierten hacia y desde UTF -8 en archivos de texto, incluso en un programa con codificación de caracteres de 8 bits).
Constante para el límite alto de caracteres
Similar a maxint, Pascaline tiene un maxchr, que es el carácter máximo que existe en el conjunto de caracteres (y de hecho 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 tratar con tipos como "conjunto de caracteres" y ayuda cuando se trata de diferentes opciones de conjuntos de caracteres (como ISO 8859-1 o Unicode).
Estructura modular
IP Pascal utiliza un concepto de apilamiento único para módulos. Cada módulo se apila uno encima del otro en la memoria y se ejecuta en la parte inferior. El módulo inferior llama al módulo siguiente, y ese módulo llama al módulo siguiente, y así sucesivamente.
envolturaserlibprogramagorra
El módulo de tapa (a veces llamado "celda" en la terminología de IP Pascal, después de un concepto en el diseño de circuitos integrados ) termina la pila y comienza un proceso de retorno que se repite hasta que el programa termina. Cada módulo tiene su sección de inicio o entrada realizada en el camino hacia arriba en la pila, y su sección de finalización o salida realizada en el camino de regreso.
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 al final, 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". Estas bibliotecas presentan una API idealizada para cada función que aplica, como archivos y funciones extendidas del sistema operativo, gráficos, midi y sonido, etc. Toda la colección 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 acoplado con bibliotecas de gráficos portátiles son las siguientes:
- IP Pascal utiliza su propia plataforma de transferencia 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 eso. Esto es similar a la forma en que funcionan los sistemas Java y UCSD Pascal , pero con verdadero código compilado de alta optimización, no código interpretado o código compilado "justo a tiempo".
- Dado que los módulos pueden anular funciones de nivel inferior, como la declaración de "escritura" de Pascal, los programas ISO 7185 Pascal normales y no modificados también pueden utilizar aspectos avanzados de la plataforma de migración. Esto es diferente a muchas o la mayoría de las bibliotecas de gráficos portátiles que obligan al usuario a utilizar una metodología de E / S completamente diferente para acceder a un sistema de gráficos con ventanas, por ejemplo, C, otros Pascal y Visual Basic .
También se pueden crear módulos IP que sean independientes del sistema y se basen solo en los módulos de la plataforma de transferencia. El resultado es que IP Pascal es muy portátil.
Ejemplo: el programa estándar "hola mundo" está acoplado a la salida en una ventana gráfica.
programa HelloWorld (salida);empezar Writeln ('¡Hola, mundo!')final .
Ejemplo: "hola mundo" con comandos gráficos agregados. Tenga en cuenta que todavía se utilizan declaraciones 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 ) ; página ( 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' ) ; repetir evento ( entrada , er ) hasta er . etype = etterm end .
Debido a que los módulos IP Pascal pueden "anularse" entre sí, un módulo de extensión gráfico (o cualquier otro tipo de módulo) puede anular las llamadas de E / S estándar implementadas en un módulo debajo de él. Por lo tanto, paslib implementa declaraciones estándar de Pascal como lectura, escritura y otros servicios de soporte. gralib anula estos servicios y redirige todas las E / S Pascal estándar a ventanas gráficas.
La diferencia entre esta y otras bibliotecas en otras implementaciones es que, por lo general, debe dejar de usar las declaraciones de E / S estándar y cambiar a un conjunto de llamadas y paradigmas completamente diferente. Esto significa que no puede "adelantar" programas implementados con el paradigma de E / S en serie a sistemas gráficos.
Otra diferencia importante con IP Pascal es que utiliza métodos de lenguaje de procedimiento para acceder a la biblioteca de gráficos en ventana. La mayoría de los juegos de herramientas de gráficos obligan al juego de herramientas a utilizar métodos de programación orientados a objetos . Una razón de esto es que la orientación a objetos es una buena combinació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 operador. system, 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 para el código de manejo de eventos, cada uno de los cuales sería una devolución de llamada individual.
La orientación a objetos es un buen método de programación, pero IP Pascal lo convierte 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 de acantilado " para los programas más antiguos. No es necesario reescribirlos solo para aprovechar los entornos de programación modernos.
Otra característica interesante de la plataforma de portabilidad IP es que 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, y programas que solo usan llamadas en modo de caracteres (que funcionarían en cualquier terminal o conexión telnet) funcionan en entornos gráficos de forma automática.
Historia
La implementación de Z80
El compilador comenzó en 1980 en Micropolis Disk Operating System, pero se movió rápidamente a CP / M ejecutándose en el Z80. El sistema original estaba codificado en lenguaje ensamblador Z80 y generaba código de máquina directo para el Z80 . Era un compilador de un solo paso sin un enlazador, incluía su biblioteca de soporte del sistema dentro del compilador, y lo reubicaba y lo enviaba al 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 mostraba que las tablas del enlazador serían un problema en el Z80 limitado de 64 kb, por lo que el enlazador debía ser lo más pequeño posible. Esto se usó luego para mover el código fuente del compilador y enlazador Z80 del ensamblador Micropolis (que era un ensamblador sin enlazador que creaba un binario de salida única) al nuevo sistema enlazador del ensamblador.
Después de esto, el compilador se modificó para generar el formato del vinculador, y la biblioteca de soporte se movió a un archivo separado y se vinculó.
En 1981, el compilador se rehizo ampliamente para agregar optimización, como asignación de registros, booleano para saltar, código muerto, plegado constante y otras optimizaciones. Esto creó una implementación de Pascal que se comparó mejor que cualquier compilador Z80 existente, así como la mayoría de los compiladores 8086. Desafortunadamente, a 46kb, también era difícil de usar, pudiendo compilar solo 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 se pudo utilizar principalmente debido a la decisión de crear un enlazador compacto que permitió construir grandes sistemas a partir de estos pequeños archivos de objetos.
A pesar de esto, la implementación original de IP Pascal se ejecutó hasta 1987 como un compilador de propósito general. En esta fase, IP Pascal fue como C en su diseño modular. Cada archivo fuente era una unidad y consistía en una 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 pueden estar fuera de cualquier bloque y en cualquier orden. Los procedimientos, funciones y variables en otros archivos fueron referenciados por declaraciones 'externas', y los procedimientos, funciones y variables en el archivo actual fueron declarados 'globales'. Cada archivo se compiló en un archivo de objeto y luego se vinculó. No hubo verificación de tipos en los archivos de objetos.
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 en serie (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 pasadas con intermedio, que fue diseñado para resolver los problemas de memoria asociados con el primer compilador. La interfaz del compilador se creó y se probó sin capacidades intermedias de generación de código (solo análisis).
En 1987, el sistema Z80 utilizado para IP se cambió por un 80386 IBM-PC y se detuvo el trabajo. A partir de ese momento, se utilizaron varios otros compiladores estándar ISO 7185, que terminaron con el compilador SVS Pascal, una implementación basada en el extensor DPMI de 32 bits .
La implementación 80386
En 1993, los compiladores compatibles con ISO 7185 que proporcionaban código de 32 bits de alta calidad estaban desapareciendo. En este punto, la elección fue dejar de usar Pascal o revivir el antiguo proyecto IP Pascal y modernizarlo como un compilador 80386. En este punto, todo lo que existía era un analizador Pascal y un ensamblador (para Z80) que se podían utilizar en IBM-PC. De 1993 a 1994, el ensamblador se hizo modular para apuntar a múltiples CPU, incluido el 80386, se creó un enlazador para reemplazar el enlazador en lenguaje ensamblador Z80 y se terminó una interfaz del compilador Pascal para generar un 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" de ISO 7185 IP Pascal para incluir características tales como matrices dinámicas.
En 1995, se creó un "codificador de verificación" para apuntar al código de máquina 80386, y se creó un programa de conversión para tomar los archivos de objeto de salida y crear un archivo "ejecutable portátil" para Windows. La biblioteca de soporte del sistema se creó para IP Pascal, en sí misma en IP Pascal. Este fue un paso inusual que se tomó para evitar tener que volver a codificar la biblioteca desde ensamblado 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 e IP Pascal se volvió completamente operativo como un compilador 80386 en Windows. El sistema se arrancó a sí mismo y el código Pascal restante se transfirió de SVS Pascal a IP Pascal para completar el arranque. Este proceso fue ayudado considerablemente por la capacidad del SVS Pascal basado en DPMI para ejecutarse bajo Windows 95, lo que significó que se eliminó la necesidad de arrancar entre DOS y Windows 95.
La implementación de Linux
En 2000, se creó una versión de Linux (Red Hat) solo para modo texto. Esta implementación usa directamente las llamadas al sistema y evita el uso de glibc , y por lo tanto crea binarios más delgados que si se usara el sistema de soporte completo necesario para C, a costa de la portabilidad binaria.
El plan es crear una versión de la biblioteca de texto que use información termcap y la biblioteca gráfica bajo X11.
Pasos para "escribir una vez, ejecutar en cualquier lugar"
En 1997, una versión de la biblioteca de terminales del IP Pascal original de 1980 se transfirió a Windows 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 hizo irrelevante en gran medida por los aumentos en 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 archivos de encabezado C a archivos de encabezado Pascal. Esto estaba destinado a reemplazar el método manual de crear interfaces de sistema operativo para IP Pascal.
En 2003, se creó un módulo independiente del sistema operativo totalmente gráfico para IP Pascal.
En 2005, se agregó el kit de administración y widgets de Windows.
Lecciones
En retrospectiva, el mayor error en la versión Z80 fue su estructura de una sola pasada. No había ninguna razón real para ello; El compilador (básico) anterior del autor era de paso múltiple con almacenamiento intermedio. El único argumento a favor era que se suponía que la compilación de un solo paso era más rápida. Sin embargo, la compilación de un solo paso resulta ser una mala combinación para las máquinas pequeñas y no es probable que ayude a las optimizaciones avanzadas comunes en las máquinas grandes.
Además, el aspecto de un solo paso ralentizó o impidió que el compilador arrancara del lenguaje ensamblador Z80 y lo llevara al propio Pascal. Dado que el compilador era monolítico, la conversión a Pascal no se podía realizar de una sección a la vez, sino que debía realizarse 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 de dos pasadas dio 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 del mismo tamaño se emparejan íntimamente, la complejidad no es aditiva, sino multiplicativa, porque las conexiones entre las mitades del programa se multiplican sin control.
Otra lección de los días de Z80, que se corrigió en el compilador 80386, fue escribir la mayor cantidad de código posible en el propio Pascal, incluso en la biblioteca de soporte. Tener el código de soporte 80386 todo escrito en Pascal lo ha hecho tan modular y portátil que la mayor parte se movió fuera del área específica del sistema operativo y en 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" solo necesita modificaciones ligeramente de implementación a implementación. El resultado es una gran cantidad de trabajo de implementación que se ahorra durante la migración del sistema.
Finalmente, fue un error entrar en una segunda ronda de optimización antes de iniciar el compilador. Aunque la mejora del código de salida fue considerable, el aumento resultante en la complejidad del compilador causó problemas con el espacio de direcciones limitado. En ese momento, se consideró que un código mejor optimizado era un habilitador para iniciar el código en Pascal. En retrospectiva, las secciones restantes escritas de la asamblea FUERON el problema, y debían eliminarse, cuanto antes, mejor. Otra forma de decir esto es que los problemas de espacio pueden ser transitorios, pero tener secciones importantes del programa escritas en ensamblado es un problema serio y duradero.
Otras lecturas
- 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
- ^ Supcik, Jacques (5 de diciembre de 1997). "PASCAL - Manual de usuario e informe" . ETH Zürich: Departamento de Ciencias de la Computación. Archivado desde el original el 14 de marzo de 2005 . Consultado el 23 de junio de 2005 .
- ^ Moore, Scott A. "ANSIISO PASCAL" . Moorecad.com . Consultado el 21 de febrero de 2017 .
enlaces externos
- Página web oficial
- El estándar, sitio web ISO 7185 Pascal
- Repositorio Pascal-P6