Oberon-2 es una extensión del lenguaje de programación Oberon original que agrega programación reflexiva limitada (reflexión) y funciones de programación orientada a objetos , matrices abiertas como tipos de base de puntero, exportación de campos de solo lectura y reintroduce el bucle de Modula-2 .FOR
Fue desarrollado en 1991 en ETH Zurich por Niklaus Wirth y Hanspeter Mössenböck, quien 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 mixins 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 estilo C++ .
En comparación con lenguajes totalmente orientados a objetos como Smalltalk , en Oberon-2, los tipos y clases de datos básicos no son objetos , muchas operaciones no son métodos, no hay transmisión de mensajes (se puede emular en cierto modo mediante reflexión y extensión de mensajes, como se demostró). en ETH Oberon), y el polimorfismo se limita a subclases de una clase común (no se puede escribir 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 utilizar módulos para este propósito.
Reflection en Oberon-2 no utiliza metaobjetos , sino que simplemente lee 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 tanto, podría implementarse casi por completo a nivel de biblioteca, sin cambiar el código del idioma. De hecho, ETH Oberon hace un uso extensivo de las capacidades de reflexión a nivel de lenguaje y de biblioteca.
Oberon-2 proporciona soporte de tiempo de ejecución integrado para la recolección de basura similar a Java y realiza comprobaciones de índices de matrices y límites, etc., que eliminan los posibles problemas de sobrescritura de límites de matrices y pilas y los problemas de gestión manual de memoria inherentes a C y C++. La compilación separada utilizando 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 de lenguaje Pascal [2] es un refinamiento (un superconjunto) de Oberon-2.
El siguiente código Oberon-2 implementa un árbol binario simple:
MÓDULO Árboles ;TIPO Árbol * = PUNTERO AL Nodo ; Nodo * = nombre del REGISTRO - : PUNTERO A ARRAY DE CARACTERÍSTICOS ; izquierda , derecha : FINAL del árbol ; PROCEDIMIENTO ( t : Árbol ) Insertar * ( nombre : ARRAY OF CHAR ); VAR p , padre : Árbol ; COMENZAR p := t ; REPETIR padre := p ; SI nombre = p . nombre ^ ENTONCES VOLVER FIN ; SI nombre < p . nombre ^ ENTONCES p := p . izquierda MÁS p := p . FINAL derecho HASTA p = NIL ; NUEVO ( p ); pag . izquierda := NULO ; pag . derecha := NULO ; NUEVO ( p . nombre , LEN ( nombre ) + 1 ); COPIAR ( nombre , p . nombre ^ ); SI nombre < padre . nombre ^ ENTONCES padre . izquierda := p ELSE padre . derecha := p FIN FIN Insertar ; PROCEDIMIENTO ( t : Árbol ) Buscar * ( nombre : ARRAY OF CHAR ): Árbol ; VAR p : Árbol ; COMENZAR p := t ; MIENTRAS ( p # NIL ) & ( nombre # p . nombre ^ ) DO IF nombre < p . nombre ^ ENTONCES p := p . izquierda MÁS p := p . derecha FINAL FINAL ; VOLVER p FIN Buscar ;PROCEDIMIENTO NewTree * (): Árbol ; VAR t : Árbol ; COMENZAR NUEVO ( t ); NUEVO ( t . nombre , 1 ); t . nombre [ 0 ] := 0 X ; t . izquierda := NULO ; t . derecha := NULO ; RETORNO t FIN NewTree ;FIN Árboles .
Los procedimientos se pueden vincular a un tipo de registro (o puntero). Son equivalentes a métodos de instancia en terminología orientada a objetos.
El uso de variables exportadas y campos de registro se puede restringir al acceso de solo lectura. Esto se muestra con una bandera de visibilidad "-".
Las matrices abiertas que antes solo podían declararse como tipos de parámetros formales ahora pueden declararse como tipos base de puntero.
La FOR
declaración de Pascal y Modula-2 no se implementó en Oberon. Se reintroduce en Oberon-2.
Oberon-2 proporciona varios mecanismos para comprobar el tipo dinámico de un objeto. Por ejemplo, donde un objeto Bird puede ser instanciado como un Duck o un Cuckoo, Oberon-2 permite al programador responder al tipo real del objeto en tiempo de ejecución.
El primer enfoque, el más convencional, es confiar en el sistema de enlace de tipos . El segundo enfoque es utilizar la WITH
declaración , que permite verificar directamente el subtipo dinámico de una variable. En ambos casos, una vez que se ha identificado el subtipo, el programador puede hacer uso de cualquier procedimiento ligado a tipo o variable que sea apropiado para el subtipo. A continuación se muestran ejemplos de estos enfoques.
Tenga en cuenta que la forma de WITH
declaración utilizada en Oberon-2 no está relacionada con la declaración CON de Pascal y Modula-2. Este método de abreviar el acceso a los campos de registro no está implementado en Oberon ni en Oberon-2.
MÓDULO Aves ; TIPO Pájaro * = GRABAR sonido * : ARRAY 10 OF CHAR ; FIN ; FIN Aves . MÓDULO Patos ; IMPORTAR Aves ; TIPO Pato * = REGISTRO ( Aves . Ave ) FIN ; PROCEDIMIENTO SetSound * ( VAR pájaro : Pato ); COMENZAR pájaro . sonido : = "¡Cuac!" FIN Establecer sonido ; FIN Patos . MÓDULO Cucos ; IMPORTAR Aves ; TIPO Cuco * = REGISTRO ( Aves . Pájaro ) FIN ; PROCEDIMIENTO SetSound * ( VAR pájaro : Cuco ); COMENZAR pájaro . sonido : = "¡Cuco!" FIN Establecer sonido ; FIN Cucos .
WITH
declaración Prueba del MÓDULO ; IMPORTAR Fuera , Aves , Cucos , Patos ; TIPO SomeBird * = REGISTRO ( Aves . Pájaro ) FIN ; VAR sb : Algún pájaro ; c : Cucos . cuco ; d : Patos . Pato ; PROCEDIMIENTO SetSound * ( VAR pájaro : Pájaros . Pájaro ); COMIENZA CON pájaro : Cucos . Cuco DO pájaro . sonido : = "¡Cuco!" | pájaro : patos . Pato DO pájaro . sonido : = "¡Cuac!" MÁS pájaro . sonido : = "¡Tweet!" FIN FIN Establecer sonido ; PROCEDIMIENTO MakeSound * ( VAR b : Aves . Pájaro ); COMENZAR Fuera . ln ; Afuera . Cadena ( b . sonido ); Afuera . Ln FIN MakeSound ; COMENZAR Establecer sonido ( c ); Establecer sonido ( d ); Establecer sonido ( algn ); Hacer sonido ( c ); Hacer sonido ( re ); MakeSound ( sb ) Prueba FINAL .
POINTER
MÓDULO PointerBirds ; IMPORTAR Fuera ; TIPO BirdRec * = GRABAR sonido * : ARRAY 10 OF CHAR ; FIN ; DuckRec * = GRABAR ( BirdRec ) FIN ; CuckooRec * = GRABAR ( BirdRec ) FIN ; Pájaro = PUNTERO A BirdRec ; Cuco = PUNTERO A CuckooRec ; Pato = PUNTERO A DuckRec ; VAR pb : Pájaro ; ordenador personal : Cuco ; pd : pato ; PROCEDIMIENTO SetDuckSound * ( pájaro : Pato ); COMENZAR pájaro . sonido : = "¡Cuac!" FINAL SetDuckSound ; PROCEDIMIENTO SetCuckooSound * ( pájaro : Cuco ); COMENZAR pájaro . sonido : = "¡Cuco!" FINALIZAR SetCuckooSound ; PROCEDIMIENTO SetSound * ( pájaro : Pájaro ); EMPEZAR CON pájaro : Cuco DO SetCuckooSound ( pájaro ) | pájaro : Pato DO SetDuckSound ( pájaro ) ELSE pájaro . sonido : = "¡Tweet!" FIN FIN Establecer sonido ; COMENZAR NUEVO ( ordenador personal ); NUEVO ( pd ); SetCuckooSound ( ordenador personal ); SetDuckSound ( pd ); Afuera . ln ; Afuera . Cadena ( pc ^ . sonido ); Afuera . ln ; Afuera . ln ; Afuera . Cadena ( pd ^ . sonido ); Afuera . ln ; Establecer sonido ( ordenador personal ); Establecer sonido ( pd ); Afuera . ln ; Afuera . Cadena ( pc ^ . sonido ); Afuera . ln ; Afuera . ln ; Afuera . Cadena ( pd ^ . sonido ); Afuera . ln ; (* -------------------------------------- *) (* Pasar tipo dinámico al procedimiento * ) pb : = pd ; SetDuckSound ( pb ( Pato )); Afuera . ln ; Afuera . Cadena ( pb ^ . sonido ); Afuera . ln ; pb : = pc ; SetCuckooSound ( pb ( Cuco )); Afuera . ln ; Afuera . Cadena ( pb ^ . sonido ); Afuera . ln ; (* -------------------------------------- *) Establecer sonido ( pb ); Afuera . ln ; Afuera . Cadena ( pb ^ . sonido ); Afuera . ln ; pb : = pd ; Establecer sonido ( pb ); Afuera . ln ; Afuera . Cadena ( pb ^ . sonido ); Afuera . ln ; (* -------------------------------------- *) NUEVO ( pb ); Establecer sonido ( pb ); Afuera . ln ; Afuera . Cadena ( pb ^ . sonido ); Afuera . Ln FINAL PointerBirds .
IS
operadorUn tercer enfoque es posible utilizando el IS
operador . Este es 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 que el programador acceda al subtipo que ha sido detectado.
El desarrollo de la familia lingüística ALGOL → Pascal → Modula-2 → Oberon → Component Pascal está marcado por una reducción en la complejidad de la sintaxis del lenguaje . Se describe todo el lenguaje Oberon-2 ( Mössenböck & Wirth, marzo de 1995 ) utilizando sólo 33 producciones gramaticales en la forma extendida Backus-Naur , como se muestra a continuación.
Módulo = MÓDULO ident ";" [ ImportList ] DeclSeq [ BEGIN StatementSeq ] END ident "." . ImportList = IMPORTAR [ ident ":=" ] ident { "," [ ident ":=" ] ident } ";" . DeclSeq = { CONST { ConstDecl ";" } | TIPO { TypeDecl ";" } | VAR { VarDecl ";" }} { ProcDecl ";" | AdelanteDecl ";" }. ConstDecl = IdentDef "=" ConstExpr . TypeDecl = IdentDef "=" Tipo . VarDecl = ListaIdent ":" Tipo . ProcDecl = PROCEDIMIENTO [ Receptor ] IdentDef [ FormalPars ] ";" DeclSeq [ BEGIN StatementSeq ] FIN ident . ForwardDecl = PROCEDIMIENTO "^" [ Receptor ] IdentDef [ FormalPars ]. FormalPars = "(" [ FPSección { ";" FPSección }] ")" [ ":" Calidente ]. FPSección = [ VAR ] ident { "," ident } ":" Tipo . Receptor = "(" [ VAR ] ident ":" ident ")" . Tipo = Cualidente | ARRAY [ ConstExpr { "," ConstExpr }] OF Tipo | RECORD [ "(" Qualident ")" ] FieldList { ";" FieldList } FIN | PUNTERO AL Tipo | PROCEDIMIENTO [ FormalPars ]. ListaCampos = [ ListaIdentes ":" Tipo ]. StatementSeq = Declaración { ";" Declaración }. Declaración = [ Designador ":=" Expr | Designador [ "(" [ ExprList ] ")" ] | IF Expr ENTONCES StatementSeq { ELSIF Expr THEN StatementSeq } [ ELSE StatementSeq ] FIN | CASO Expr DE Caso { "|" Caso } [ ELSE StatementSeq ] FIN | MIENTRAS Expr DO StatementSeq END | REPETIR StatementSeq HASTA Expr | FOR ident ":=" Expr TO Expr [ BY ConstExpr ] DO StatementSeq END | BUCLE StatementSeq FIN | CON Guardia DO StatementSeq { "|" Guard DO StatementSeq } [ ELSE StatementSeq ] FIN | SALIR | VOLVER [ Expr ] ]. Caso = [ CaseLabels { "," CaseLabels } ":" StatementSeq ]. CaseLabels = ExprConst [ ".." ExprConst ]. Guardia = Cualident ":" Cualident . ExprConst = Expr . Expr = SimpleExpr [ Relación SimpleExpr ]. ExprSimple = [ "+" | "-" ] Término { Término AddOp }. Término = Factor { Factor MulOp }.Factor = Designador [ "(" [ ExprList ] ")" ] | número | personaje | cadena | NULO | Conjunto | "(" Expr ")" | "~" Factor . Establecer = "{" [ Elemento { "," Elemento }] "}" . Elemento = Expr [ ".." Expr ]. Relación = "=" | "#" | "<" | "<=" | ">" | ">=" | EN | ES . AgregarOp = "+" | "-" | O . MulOp = "*" | "/" | DIVI | MODO | "&" . Designador = Cualident { "." identificador | "[" ListaExpr "]" | "^" | "(" Cualidente ")" }. ListaExpr = Expr { "," Expr }. ListaIdent = IdentDef { "," IdentDef }. Cualident = [ ident "." ] ident . IdentDef = ident [ "*" | "-" ].
Los compiladores 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. Es creado y mantenido por Mike Spivey y utiliza la máquina virtual Keiko. [4] [5]
Hay un escáner Oberon-2 Lex y un analizador Yacc de Stephen J. Bevan de la Universidad de Manchester, Reino Unido, basado en el de la referencia de Mössenböck y Wirth. Está en la versión 1.4.
Existe una versión llamada Native Oberon que incluye un sistema operativo y puede iniciarse directamente en hardware de clase PC.
En ETHZ se ha desarrollado una implementación .NET de Oberon con la adición de algunas extensiones menores relacionadas con .NET.
Programmer's Open Workbench (POW!) [6] es un entorno de desarrollo integrado muy simple , que incluye editor, enlazador y compilador Oberon-2. Esto se compila en ejecutables de Windows . Se proporciona el código fuente completo ; el compilador está escrito en Oberon-2.
El compilador Java to Oberon (JOB) fue escrito en la Universidad de Vologda en Rusia. Produce código objeto en forma de archivos de clase Java ( código de bytes ). 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 Optimizing Oberon-2 compila en C, utilizando la cadena de herramientas de la colección de compiladores GNU (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 de optimización para Intel Pentium o traductor "via-C" para el desarrollo de software multiplataforma . Disponible para Windows y Linux. El compilador está escrito en Oberon-2 y se compila solo.
Oberon Revival es un proyecto para llevar Oberon 2 y Component Pascal ( BlackBox Component Builder ) a Linux y Win32. El puerto Linux de BlackBox no estaba disponible antes y originalmente solo se ejecutaba 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 trasladar el sistema Oberon a plataformas disponibles comercialmente. [7]
Oberon-2 puede apuntar a la máquina virtual Keiko. [8] [9] Por ejemplo, al igual que otros compiladores de lenguajes (ver O-code , p-code , etc.), el compilador Oxford Oberon-2 primero compila en un código de bytes intermedio (código de bytes Keiko) que puede interpretarse con un intérprete de código de bytes o utilice la compilación justo a tiempo .
El compilador Oxford Oberon-2 traduce programas fuente en código para una máquina abstracta basada en pila. ... la máquina Keiko.