Oberon-2 es una extensión del lenguaje de programación Oberon original que agrega programación reflexiva limitada (reflexión) y facilidades de programación orientada a objetos , matrices abiertas como tipos base de puntero, exportación de campos de solo lectura y reintroduce el bucle de Modula-2 .
FOR
Fue desarrollado en 1991 en la ETH de Zúrich por Niklaus Wirth y Hanspeter Mössenböck, que ahora trabaja en el Institut für Systemsoftware (SSW) de la Universidad de Linz , Austria. Oberon-2 es un superconjunto de Oberon, es totalmente compatible con él y fue un rediseño de Object Oberon .
Oberon-2 heredó la reflexión limitada y la herencia única ("extensión de tipo") sin las interfaces o combinaciones de Oberon, pero agregó métodos virtuales eficientes ("procedimientos vinculados a tipo"). Las llamadas a métodos se resolvieron en tiempo de ejecución utilizando tablas de métodos virtuales de estilo C++ .
En comparación con lenguajes totalmente orientados a objetos como Smalltalk , en Oberon-2, los tipos de datos básicos y las clases no son objetos , muchas operaciones no son métodos, no hay paso de mensajes (se puede emular de alguna manera por reflexión y a través de la extensión de mensajes, como se demuestra en ETH Oberon), y el polimorfismo está limitado a subclases de una clase común (no hay tipado de pato como en Python , [1] y no es posible definir interfaces como en Java ). Oberon-2 no admite la encapsulación a nivel de objeto o clase, pero se pueden usar módulos para este propósito.
La reflexión en Oberon-2 no utiliza metaobjetos , sino que simplemente lee los descriptores de tipo compilados en los binarios ejecutables y expuestos en los módulos que definen los tipos y/o procedimientos. Si el formato de estas estructuras se expone a nivel de lenguaje (como es el caso de ETH Oberon, por ejemplo), la reflexión podría implementarse a nivel de biblioteca . Por lo tanto, podría implementarse casi en su totalidad a nivel de biblioteca, sin cambiar el código de lenguaje. De hecho, ETH Oberon hace un uso extensivo de las capacidades de reflexión a nivel de lenguaje y de biblioteca.
Oberon-2 ofrece compatibilidad integrada en tiempo de ejecución para la recolección de basura similar a Java y realiza comprobaciones de límites e índices de matriz, etc., que eliminan los posibles problemas de sobrescritura de límites de matriz y pila y los problemas de administración manual de memoria inherentes a C y C++. La compilación separada mediante archivos de símbolos y espacios de nombres a través de la arquitectura del módulo garantiza reconstrucciones rápidas ya que solo es necesario volver a compilar los módulos con interfaces modificadas.
El componente del lenguaje Pascal [2] es un refinamiento (un superconjunto) de Oberon-2.
Código de ejemplo
El siguiente código Oberon-2 implementa un árbol binario simple:
MÓDULO Árboles ;
TIPO
Árbol * = PUNTERO A Nodo ;
Nodo * = REGISTRO
nombre - : PUNTERO A MATRIZ DE CHAR ;
izquierda , derecha : Árbol
FIN ;
PROCEDIMIENTO ( t : Árbol ) Insertar * ( nombre : MATRIZ DE CHAR );
VAR p , padre : Árbol ;
COMIENZO p := t ;
REPETIR padre := p ;
SI nombre = p . nombre ^ ENTONCES RETORNO FIN ;
SI nombre < p . nombre ^ ENTONCES p := p . izquierda SI NO p := p . derecha FIN
HASTA p = NULO ;
NUEVO ( p ); p . izquierda := NULO ; p . derecha := NULO ; NUEVO ( p . nombre , LEN ( nombre ) + 1 ); COPIA ( nombre , p . nombre ^ );
SI nombre < padre . nombre ^ ENTONCES padre . izquierda := p SI NO padre . derecha := p FIN
FIN Insertar ;
PROCEDIMIENTO ( t : Árbol ) Buscar * ( nombre : MATRIZ DE CHAR ): Árbol ;
VAR p : Árbol ;
COMIENZO p := t ;
MIENTRAS ( p # NIL ) & ( nombre # p . nombre ^ ) HACER
SI nombre < p . nombre ^ ENTONCES p := p . izquierda SINO p := p . derecha FIN
FIN ;
RETORNO p
FIN Buscar ;
PROCEDIMIENTO NewTree * (): Árbol ;
VAR t : Árbol ;
BEGIN NEW ( t ); NEW ( t . nombre , 1 ); t . nombre [ 0 ] := 0 X ; t . izquierda := NIL ; t . derecha := NIL ; RETURN t
END NewTree ;
FIN Árboles .
Extensiones de Oberon-2 para Oberon[3]
Procedimientos ligados a tipos
Los procedimientos pueden vincularse a un tipo de registro (o puntero). Son equivalentes a los métodos de instancia en la terminología orientada a objetos.
Exportación de solo lectura
El uso de variables exportadas y campos de registros se puede restringir a acceso de solo lectura. Esto se muestra con un indicador de visibilidad "-".
Matrices abiertas
Las matrices abiertas que antes solo podían declararse como tipos de parámetros formales ahora pueden declararse como tipos base de puntero.
Declaración FOR
La FORdeclaración de Pascal y Modula-2 no se implementó en Oberon. Se reintrodujo en Oberon-2.
Comprobación de tipos en tiempo de ejecución
Oberon-2 ofrece varios mecanismos para comprobar el tipo dinámico de un objeto. Por ejemplo, si bien un objeto Pájaro puede instanciarse como Pato o Cuco, Oberon-2 permite al programador responder al tipo real del objeto en tiempo de ejecución.
El primer enfoque, el más convencional, consiste en confiar en el sistema de vinculación de tipos . El segundo enfoque consiste en utilizar la WITHsentencia , que permite comprobar directamente el subtipo dinámico de una variable. En ambos casos, una vez identificado el subtipo, el programador puede utilizar cualquier procedimiento o variable de vinculación de tipos que sea adecuado para el subtipo. A continuación se muestran ejemplos de estos enfoques.
Tenga en cuenta que la forma de WITHla declaración utilizada en Oberon-2 no está relacionada con la declaración WITH de Pascal y Modula-2. Este método de abreviación del acceso a los campos de registro no está implementado en Oberon ni en Oberon-2.
Enlace de tipo
MÓDULO Pájaros ;
TIPO
Pájaro * = GRABAR
sonido * : MATRIZ 10 DE CARACTERES ;
FIN ;
FIN Pájaros .
MÓDULO Patos ;
IMPORTACIÓN Aves ;
TIPO
Pato * = REGISTRO ( Pájaros . Pájaro ) FIN ;
PROCEDIMIENTO SetSound * ( VAR bird : Duck );
BEGIN
bird . sound : = "¡Cuac!"
END SetSound ;
END Ducks .
MÓDULO Cucos ;
IMPORTACIÓN Pájaros ;
TIPO
Cuco * = REGISTRO ( Pájaros.Pájaro ) FIN ;
PROCEDIMIENTO SetSound * ( VAR bird : Cuckoo );
BEGIN
bird . sound : = "¡Cuckoo!"
END SetSound ;
END Cuckoos .
WITHdeclaración
MÓDULO Prueba ;
IMPORTAR Salida , Pájaros , Cucos , Patos ;
TIPO
SomeBird * = RECORD ( Birds . Bird ) FIN ;
VAR
sb : SomeBird ;
c : Cucos . Cuco ;
d : Patos . Pato ;
PROCEDIMIENTO SetSound * ( VAR bird : Birds . Bird );
BEGIN
WITH bird : Cuckoos . Cuckoo DO
bird . sound : = "¡Cuco!"
| bird : Ducks . Duck DO
bird . sound : = "¡Cuac!"
ELSE
bird . sound : = "¡Pío!"
END
END SetSound ;
PROCEDIMIENTO MakeSound * ( VAR b : Birds . Bird );
BEGIN
Out . Ln ;
Out . String ( b . sound );
Out . Ln
FIN MakeSound ;
COMIENZA
EstablecerSonido ( c );
EstablecerSonido ( d );
EstablecerSonido ( sb );
MakeSound ( c );
MakeSound ( d );
MakeSound ( algn )
FIN Prueba .
POINTER
MÓDULO PointerBirds ;
IMPORTAR Salida ;
TIPO
BirdRec * = GRABAR
sonido * : MATRIZ 10 DE CHAR ;
FIN ;
DuckRec * = GRABAR ( BirdRec ) FIN ;
CuckooRec * = GRABAR ( BirdRec ) FIN ;
Pájaro = PUNTERO A BirdRec ;
Cuco = PUNTERO A CucoRec ;
Pato = PUNTERO A DuckRec ;
VAR
pb : Pájaro ;
pc : Cuco ;
pd : Pato ;
PROCEDIMIENTO SetDuckSound * ( pájaro : Pato );
INICIO
pájaro . sonido : = "¡Cuac!"
FIN SetDuckSound ;
PROCEDIMIENTO SetCuckooSound * ( pájaro : Cuco );
INICIO
pájaro . sonido : = "¡Cuco!"
FIN SetCuckooSound ;
PROCEDIMIENTO SetSound * ( pájaro : Pájaro );
COMIENZA
CON pájaro : Cuco HACER
SetCuckooSound ( pájaro )
| pájaro : Pato HACER
SetDuckSound ( pájaro )
SINO
pájaro . sonido : = "¡Pío!"
FIN
FIN SetSound ;
COMENZAR
NUEVO ( pc );
NUEVO ( pd );
EstablecerSonidoDeCuco ( pc );
EstablecerSonidoDePato ( pd );
Fuera . Ln ; Fuera . Cadena ( pc ^ . sonido ); Fuera . Ln ;
Fuera . Ln ; Fuera . Cadena ( pd ^ . sonido ); Fuera . Ln ;
EstablecerSonido ( pc );
EstablecerSonido ( pd );
Fuera . Ln ; Fuera . Cadena ( pc ^ . sonido ); Fuera . Ln ;
Fuera . Ln ; Fuera . Cadena ( pd ^ . sonido ); Fuera . Ln ;
(* -------------------------------------- *)
(* Pasar tipo dinámico al procedimiento *)
pb : = pd ;
SetDuckSound ( pb ( Duck ));
Salida . Ln ; Salida . String ( pb ^ . sound ); Salida . Ln ;
pb : = pc ;
SetCuckooSound ( pb ( Cuckoo )
) ; Salida.Ln ; Salida.String ( pb ^ .sound ) ; Salida.Ln ;
(* -------------------------------------- *)
SetSound ( pb )
; Salida.Ln ; Salida.Cadena ( pb ^ .sound ) ; Salida.Ln ;
pb : = pd ;
SetSound ( pb )
; Salida.Ln ; Salida.Cadena ( pb ^ .sound ) ; Salida.Ln ;
(* -------------------------------------- *)
NUEVO ( pb );
SetSound ( pb ) ;
Salida.Ln ; Salida.String ( pb ^ .sound ) ; Salida.Ln FIN PointerBirds .
ISoperador
Existe un tercer enfoque posible mediante el ISoperador . Se trata de un operador de relación con la misma precedencia que igual ( =), mayor ( >), etc., pero que prueba el tipo dinámico. Sin embargo, a diferencia de los otros dos enfoques, no permite al programador acceder al subtipo que se ha detectado.
Sintaxis
El desarrollo de la familia de lenguajes ALGOL → Pascal → Modula-2 → Oberon → Component Pascal se caracteriza por una reducción de la complejidad de la sintaxis del lenguaje . Se describe el lenguaje Oberon-2 completo ( Mössenböck & Wirth, marzo de 1995 ) utilizando solo 33 producciones gramaticales en la forma extendida Backus–Naur , como se muestra a continuación.
Módulo = MÓDULO ident ";" [ ListaImportar ] DeclSeq [ BEGIN SecuenciaInstrucciones ] FIN ident "." .
ListaImportar = IMPORTAR [ ident ":=" ] ident { "," [ ident ":=" ] ident } ";" .
DeclSeq = { CONST { ConstDecl ";" } | TIPO { TypeDecl ";" } | VAR { VarDecl ";" }} { ProcDecl ";" | ForwardDecl ";" }.
ConstDecl = IdentDef "=" ConstExpr .
TypeDecl = IdentDef "=" Tipo .
VarDecl = IdentList : " Tipo .
ProcDecl = PROCEDURE [ Receptor ] IdentDef [ ParsFormales ] ";" DeclSeq [ BEGIN SecuenciaInstrucciones ] FIN ident .
ForwardDecl = PROCEDURE "^" [ Receptor ] IdentDef [ FormalPars ].
FormalPars = "(" [ FPSection { ";" FPSection }] ")" [ ":" Qualident ].
FPSection = [ VAR ] ident { "," ident } ": " Tipo .
Receptor = "(" [ VAR ] ident ": " ident ")" .
Tipo = Qualident
| ARRAY [ ConstExpr { "," ConstExpr }] OF Tipo
| REGISTRO [ "(" Qualident ")" ] FieldList { ";" FieldList } FIN
| PUNTERO A Tipo
| PROCEDIMIENTO [ FormalPars ].
FieldList = [ IdentList : " Tipo ].
StatementSeq = Statement { ";" Statement }.
Statement = [ Designator ":=" Expr
| Designator [ "(" [ ExprList ] ")" ]
| IF Expr THEN StatementSeq { ELSIF Expr THEN StatementSeq } [ ELSE StatementSeq ] FIN
| CASE Expr OF Case { "|" Case } [ ELSE StatementSeq ] FIN
| WHILE Expr DO StatementSeq FIN
| REPEAT StatementSeq UNTIL Expr
| FOR ident ":=" Expr TO Expr [ BY ConstExpr ] DO StatementSeq FIN
| LOOP StatementSeq FIN
| WITH Guard DO StatementSeq { "|" Guard DO StatementSeq } [ ELSE StatementSeq ] FIN
| EXIT
| RETURN [ Expr ]
].
Caso = [ CaseLabels { "," CaseLabels } ":" StatementSeq ].
CaseLabels = ConstExpr [ ".." ConstExpr ].
Guardia = Qualident ":" Qualident .
ConstExpr = Expr .
Expr = SimpleExpr [ Relación SimpleExpr ].
SimpleExpr = [ "+" | "-" ] Término { Término AddOp }.
Término = Factor { Factor MulOp }.
Factor = Designador [ "(" [ ExprList ] ")" ] | número | carácter | cadena | NIL | Conjunto | "(" Expr ")" | "~" Factor .
Conjunto = "{" [ Elemento { "," Elemento }] "}" .
Elemento = Expr [ ".." Expr ].
Relación = "=" | "#" | "<" | "<=" | ">" | ">=" | EN | ES .
AddOp = "+" | "-" | O .
MulOp = "*" | "/" | DIV | MOD | "&" .
Designador = Qualident { "." ident | "[" ExprList "]" | "^" | "(" Qualident ")" }.
ExprList = Expr { "," Expr }.
IdentList = IdentDef { "," IdentDef }.
Qualident = [ ident "." ] ident .
IdentDef = ident [ "*" | "-" ].
Implementaciones
Los compiladores de Oberon-2 mantenidos por ETH incluyen versiones para Windows , Linux , Solaris y macOS .
El compilador Oxford Oberon-2 compila en código de máquina nativo y puede usar un JIT en Windows, Linux y macOS. Fue creado y mantenido por Mike Spivey y utiliza la máquina virtual Keiko. [4] [5]
Existe un escáner Oberon-2 Lex y un analizador sintáctico Yacc creado por Stephen J. Bevan de la Universidad de Manchester, Reino Unido, basado en el de la referencia de Mössenböck y Wirth. Se encuentra en la versión 1.4.
Hay una versión llamada Native Oberon que incluye un sistema operativo y puede arrancar directamente en hardware de PC.
En ETHZ se ha desarrollado una implementación .NET de Oberon con la incorporación de algunas extensiones menores relacionadas con .NET.
Programmer's Open Workbench (POW!) [6] es un entorno de desarrollo integrado muy simple , que se proporciona con editor, enlazador y compilador Oberon-2. Este compilador genera ejecutables de Windows . Se proporciona el código fuente completo ; el compilador está escrito en Oberon-2.
El compilador de Java a Oberon (JOB) fue escrito en la Universidad de Vologda en Rusia. Produce código objeto en forma de archivos de clase Java ( bytecode ). Se proporcionan algunas clases específicas de JOB que son compatibles con Java, pero que utilizan una jerarquía de componentes más parecida a la de Oberon.
El compilador optimizador Oberon-2 compila a C, utilizando la cadena de herramientas GNU Compiler Collection (GCC) para la generación de programas.
Oberon Script es un compilador que traduce el lenguaje Oberon completo a JavaScript . El compilador está escrito en JavaScript y, por lo tanto, se puede llamar desde páginas web para procesar scripts escritos en Oberon.
XDS Modula2/Oberon2 es un sistema de desarrollo de Excelsior LLC, Novosibirsk, Rusia. Contiene un compilador optimizador para Intel Pentium o un traductor "via-C" para el desarrollo de software multiplataforma . Disponible para Windows y Linux. El compilador está escrito en Oberon-2 y se compila a sí mismo.
Oberon Revival es un proyecto para llevar Oberon 2 y Component Pascal ( BlackBox Component Builder ) a Linux y Win32. La versión Linux de BlackBox no estaba disponible antes y originalmente solo funcionaba en Microsoft Windows.
XOberon es un sistema operativo en tiempo real para PowerPC , escrito en Oberon-2.
El compilador portátil Oberon-2 (OP2) fue desarrollado para portar el sistema Oberon a plataformas disponibles comercialmente. [7]
Código de bytes de Keiko
Oberon-2 puede apuntar a la máquina virtual Keiko. [8] [9] Por ejemplo, al igual que otros compiladores de lenguaje (ver O-code , p-code , etc.), el compilador Oxford Oberon-2 primero compila a un bytecode intermedio (bytecode Keiko) que puede interpretarse con un intérprete de bytecode o usar compilación just-in-time .
Véase también
Referencias
- ^ "Lectura relacionada". Dr. Dobb's .
- ^ Pfister, Cuno (2001). "Novedades en Component Pascal (cambios de Oberon-2 a CP)" (PDF) . Oberon microsystems . Archivado desde el original (PDF) el 15 de mayo de 2011 . Consultado el 10 de enero de 2007 .
- ^ Diferencias entre Oberon y Oberon-2, Mössenböck y Wirth (1993)
- ^ Spivey, Michael (2014). Especificación de Keiko. Spivey's Corner (Informe). Oriel College, Universidad de Oxford. Archivado desde el original el 4 de marzo de 2016. Consultado el 9 de julio de 2023 .
- ^ Spivey, Michael (30 de septiembre de 2020). Descripción general del diseño de OBC: la máquina abstracta Keiko. Spivey's Corner (informe). Oriel College, Universidad de Oxford . Consultado el 9 de julio de 2023.
El compilador Oxford Oberon-2 traduce los programas fuente en código para una máquina abstracta basada en pila. ... la máquina Keiko.
- ^ Collingbourne, H. (febrero de 2000). "Lo que hizo a continuación el inventor de Pascal". PC Plus . N.º 160.
- ^ Crelier, Régis (1994). Compilación separada y extensión de módulos (PhD). ETH Zurich. doi :10.3929/ethz-a-000945227. hdl :20.500.11850/141604 . Consultado el 18 de noviembre de 2018 .
- ^ Dr. Michael Spivey. "Especificación de Keiko".
- ^ Dr. Michael Spivey. "Descripción general del diseño para OBC: la máquina abstracta Keiko". cita: "El compilador Oxford Oberon--2 traduce los programas fuente en código para una máquina abstracta basada en pila... la máquina Keiko"
Lectura adicional
- " Árbol genealógico de la lengua Oberon " mantenido en ETHZ
- "Segunda Conferencia Internacional Modula-2", septiembre de 1991.
- De Modula a Oberon Wirth (1990)
- Programación en Oberon - Un derivado de Programación en Modula-2 Wirth (1982)
- El lenguaje de programación Oberon Wirth (1990)
- Informe de Oberon 2
- El lenguaje de programación Oberon-2 H. Mössenböck, N. Wirth, Institut für Computersysteme, ETH Zurich , enero de 1992 y Programación estructurada (1991) 12(4): 179-195.
- Varias referencias, incluidas versiones electrónicas en línea
- Programación orientada a objetos en Oberon-2 Hanspeter Mössenböck (1994). (Disponible en formato PDF en la Universidad Johannes Kepler con el amable permiso de Springer-Verlag)
- Patrones de diseño en Oberon-2 y Component Pascal
- Proyecto Oberón. El diseño de un sistema operativo y compilador Niklaus Wirth & Jürg Gutknecht (2005)
- Proyecto Oberón. El diseño de un sistema operativo y compilador Niklaus Wirth & Jürg Gutknecht (2013)
Enlaces externos
- Sitio web oficial de la ETH de Zúrich
- Página de referencia de Oberon en la ETH de Zúrich
- Oberon en SSW, Linz
- Tutorial de Pow (en rumano), por Dan Popa
- ftp://ftp.inf.ethz.ch/pub/Oberon/
- El modelo de reflexión de Oberon-2 y sus aplicaciones
