Ésta es la versión G o o g l e guardada en el caché de la http://wiki.lugmen.org.ar/twiki/view/Main/TyphonLanguage obtenida el 28 Ago 2005 07:43:43 GMT.
La caché de G o o g l e es la instantánea de la página que tomamos cuando exploramos la Web en forma automática.
Es posible que la página haya cambiado desde entonces. Haga clic aquí para ver la página actual sin resaltar.
Esta página guardada en el caché puede hacer referencia a imágenes que ya no están disponibles. Haga clic aquí para obtener únicamente el texto guardado en el caché.
Para vincularse a esta página o para marcarla, utilice el siguiente url: http://www.google.com/search?q=cache:UudIjxQfm7IJ:wiki.lugmen.org.ar/twiki/view/Main/TyphonLanguage+typhonlanguage&hl=es


Google no tiene relación con los autores de esta página ni es responsable de su contenido.
Se han resaltado estos términos de búsqueda: typhonlanguage 

TyphonLanguage < Main < TWiki %HTTP_EQUIV_ON_VIEW%
%BROADCASTMESSAGE%
%WIKILOGOALT% TWiki > Main > TyphonLanguage TWiki webs:
%WIKIWEBLIST%
Main . { Integrantes %SEPB% Proyectos %SEPB% Eventos %SEPB% ACSFDL %SEPB% Índice %SEPB% Cambios }

Contenidos

Qué es Typhon?

Typhon es (o será) un lenguaje de programación basado en C++ y Python. Typhon tendrá sintaxis al estilo Python y será traducido a C++ de forma lo más directa posible.

Por qué C++?

Porque es un lenguaje compilado eficiente y estándar, que provee una biblioteca lo suficientemente completa como para no necesitar mucho más para escribir cualquier programa. Porque dicha biblioteca estándar define ''interfaces'' que, a pesar de no tener soporte en el lenguaje (por eso surge Typhon también), hace que puedan usarse de forma consistente. Porque es extremadamente flexible y poderoso, porque es compatible con C, con todo lo que eso significa (que no es para nada poco).

Bueno, de más está decir que hacer un lenguaje compilado nuevo (sin traducirlo a alguno existente) no sólo es un trabajo excesivamente monstruoso y para el cual, al menos yo (luca) no estoy capacitado, sino que sería un reinventar un poco la rueda.

Por qué Python?

Python es uno de los mejores lenguajes de alto nivel y su sintaxis simple y clara es una de las principales razones. Python se puede leer de una forma muy natural y aún así, no es para nada tedioso de escribir, de hecho es uno de los lenguajes que más rápido puede tipearse. Python además obliga a producir código legible, al hacer checheo de identación, otra característica bastante deseable.

Por último, Python y C++ son parecidos en cuanto a las características que ofrecen, al menos son los únicos 2 lenguajes que conozco que soportan herencia múltiple, por ejemplo.

Qué significa Typhon

Luca un día se despertó cruzado (creo que después de alguna discusión sobre Mono con gazer :) y se preguntó por qué catso no hay ningún lenguaje compilado de relativo alto nivel. Entre otras cosas estuvo jugando con Pyrex (un lenguaje python-like para hacer wrappers de C para Python); entre idas y venidas, se pensó en hacer que Python se traduzca a una serie de clases predefinidas y usar conteo de referencias para el manejo de memoria, etc; todo como para poder compilar Python casi igual a como lo conocemos ahora traduciéndolo a C++. Entre esas ideas, en algún momento alberto dijo "Python con tipos" y de ahí pensé en Typed Python y vi la T y la Y muy cerca y pensé que empezando con Ty (de Typed) podría armar un anagrama de Python. Lo obvio resultó Typhon.

Luego investigando el nombre, Typhon resulta ser una criatura de la mitología griega (un hombre/dragon con mil cabezas) al igual que Python (una especie de serpiente gigante); pero hay más aún.

Tanto Typhon como Python fueron monstruos creados por los viejos dioses para evitar que los dioes del Olimpo tomaran control del bajomundo.

Así que nombre más acertado para este lenguaje, difícilmente exista ;)

Alcance del Lenguaje

El lengueaje pretende dar acceso a un subset de C++ a través de sintaxis Python. Es decir, la traducción a C++ será lo más directa posible evitando así cualquier tipo de necesidad de traducción (bindings) para usar bibliotecas escritas tanto en C como en C++. Sólo se asumen cosas en cuanto a interfaces provistas por la STL, como Forward Containers, Iterators, etc. Para sacar todo el jugo a Typhon los tipos de datos más complejos deben estar escritos siguiendo el estilo de la STL (cosa que ya está pasando actualmente, las mejores bibliotecas en C++ como gtkmm, libxml2++, cgicc, etc interaccionan bien con la STL y proveen interfaces similares).

Sintaxis

En TyphonSyntax? está especificada la sintaxis del lenguaje, en notación EBNF (o algo parecido, está basado en la especificación de Python).

Definiciones

Acá vamos a ir agregando cosas que definamos en cuanto al lenguaje:

Características aún no definidas

Modo de iterar una secuencia

Prioridad: Alta

En C++ tendríamos 2 formas básicas de traducir:


for item_t i in seq_t seq:

por copia y por referencia. A su vez, cada una de estas formas puede ser constante o no, lo que nos da 4 posibilidades:
  1. Que i sea una copia al ítem en seq
  2. Que i sea una copia constante al ítem de seq
  3. Que i sea una referencia al ítem de seq
  4. Que i sea una referencia constante al ítem de seq
Hacer una copia sería costoso en varios casos (de hecho en todo tipo de dato que ocupe más de lo que ocupa un puntero) y una copia constante sería demasiado raro que tenga alguna utilidad práctica. Por lo que nos queda decidir entre referencia o const referencia.

Probablemente lo más intuitivo (aunque no lo más seguro) sea tener una referencia modificable, y es esto lo que debería usarse por omisión según la premisa optimizar para el caso general . A esto se suma que iterar con una referencia constante sería bastante claro con una construcción como:


for const item_t i in seq_t seq:

En el caso inverso no hay ninguna palabra reservada lo suficientemente clara y realmente sería menos intuitivo (aunque menos suceptible a errores, al menos yo tengo la teoría de que todo debería ser constante a menos que se pueda demostrar que necesita ser variable :).

En caso de necesitarse una copia (querer modificar i dentro del cuerpo del for sin que los cambios se reflejen en los ítems de seq), siempre se puede hacer una copia explícita:


for item_t i in seq_t seq:
    item_t copia = i
    copia += 2 * seq.size()
    # etc.

Implementación


for item_t i in seq_t seq:

se traduciría:
for (seq_t::iterator ___i = seq.begin(); ___i != seq.end(); ++___i)
{
    item_t& i = *___i; // Referencia
    // ...
}

Mientras que:
for const item_t i in seq_t seq:

se traduciría:
for (seq_t::const_iterator ___i = seq.begin(); ___i != seq.end(); ++___i)
{
    const item_t& i = *___i; // Referencia constante
    // ...
}

Uso de typeof

Prioridad: Media

typeof() es una extensión de GNU para C/C++, para obtener el tipo de una expresión en tiempo de compilación. El uso de esta extensión simplificaría considerablemente la implementación de la deducción de tipos para el for y otras construcciones, pudiéndose llegar a hacer prácticamente cualquier declaración de una variable con tipo implícito (siempre y cuando se la inicialice en la declaración). Manteniendo una tabla de símbolos y forward declarations podría evitarse el uso de typeof, pero los forward declarations pueden convertirse en algo muy tedioso e inecesario. Como siempre, se puede llegar a un balance. La deducción de tipos siempre será opcional (para poder tener mayor control de las variables), por lo que puede agregarse algún tipo de opción al compilador (me refiero al traductor de Typhon a C++) para hacer uso o no de typeof. Si no se usa typeof el código tendrá que ser inevitablemente más redundante (tendrán que especificarse los tipos de más variables explícitamente y usar forward declarations) pero permitirá generar código ISO C++ que es una alta prioridad en Typhon.

Implementación

El principal uso sería en un bloque for:
for i in seq:

se puede traducir a:
for (typeof(seq.begin()) ___i = seq.begin(); ___i != seq.end(); ++___i)
{
    typeof(*___i)& i = *___i;
    // ...
}

Sin tener absolutamente ninguna información sobre seq, ni sobre el tipo de elemento que contiene.

Esto podría llevarse más lejos y usar tipos implícitos:


int f(): return 5
int main():
    n = f() # n es una declaración implícita, con el tipo de f(), en este caso int
    return 0

esto se traduciría a:
int f()
{
    return 5;
}
int main()
{
    typeof(f()) n = f(); // n tiene el tipo devuelto por f(), gracias al uso de typeof
    return 0;
}

De nuevo, a pesar de que pueda ser conveniente, me parece muy suceptible a errores, ya que cualquier asignación se convertiría en una declaración implícita, haciendo que un typo en el nombre de una variable sea un bug muy difícil de encontrar (problema actual de la mayoría de los lenguajes interpretados).

Palabra reservada auto

Una posible solución a esto, que mantendría un buen equilibrio entre conveniencia y seguridad, sería agregar una palabra reservada como auto para declarar una variable con tipo implícito (de hecho se propuso en comp.lang.c++). El ejemplo anterior en Typhon sería:
int f(): return 5
int main():
    auto n = f() # n es declarada con tipo implícito, obtenido de f(), en este caso int
    return 0

De esta manera se puede distinguir claramente una declaración, pero dejamos en manos del compilador la deducción del tipo. De manera que si alguien tipea mal una variable en una asignación, no se crearía un símbolo nuevo y se convertiría en un error de compilación.

Un ejemplo con más sentido sería el caso en que se queira iterar un contenedor obteniendo una copia de cada ítem:


for i in seq:
    auto copia = i
    copia += 2 * seq.size()
    # etc.

Por supuesto la declaración de una variable de tipo implícito deberá estar acompañada siempre de su inicialización, de otra manera no se puede deducir el tipo. Por lo tanto la expresión auto mi_var (sin una asignación) es un error de compilación.

Literales de strings

Prioridad: Media/Alta

Aún no sabemos que vamos a hacer con los strings largos y strings cortos de Python.

Shortstrings

Prioridad: Alta

En principio los strings cortos deberían poder escribirse sólo con " (comillas dobles) porque las ' (comillas simples) deberían usarse para expresar literales char como en C/C++.

Longstrings

Prioridad: Media

Con respecto a los string largos no sé si valga la pena traducirlos de alguna forma o directamente no soportarlo, aunque creo que soportarlos no traería grandes complicaciones y en ciertas circunstancias pueden ser convenientes.

Prefijos

Prioridad: Media/Alta

También hay que definir si se soportan los prefijos (como r para strings raw, u para unicode, etc). Tener en cuenta que traducirlos podría romper la compatibilidad en ciertos ámbitos.

Strings traducibles
Prioridad: Media

También podría incluirse el prefijo _ introducido por D para marcars strings traducibles. Esto podría integrarse con gettext u otros sistemas de internacionalización. Lo bueno es que la forma de trabajar quedaría en manos del lenguaje y en caso de cambiar de implementación, sólo habría que cambiar el compilador. De hecho podría tener soporte para varios sistemas de internacionalización.

Por otro lado, siguien la hipótesis de optimizar para el caso general, podría tomarse por omisión a todos los strings como traducibles, excepto a los que lleven el prefijo _, ya que por lo general, la mayor parte de los strings en un programa son traducibles.

Todo esto podría manejarse con opciones de línea de comandos a la hora de compilar, por lo que sin ningún problema, y de forma transparente, podría generase código sin ningún tipo de dependencia de un sistema de internacionalización incluso cuando el código esté escrito para ser internacionalizable.

Palabra reservada block

Prioridad: Baja

Serviría para hacer un bloque de código arbitrario. Es útil para técnicas de programación como sentries.

Ejemplo:


include ifstream, string
import ifstream, string, getline from std
void f():
    # Hago cosas ...
    # Quiero obtener en una variable el contenido de un archivo
    string contenido
    block:
        ifstream f("archivo")
        string buffer
        while getline(f, buffer):
            contenido += buffer
    # Listo, acá se destruye tanto f (se cierra el archivo) como buffer
    # Usamos el contenido como más nos guste

Workarround

Esto podría emularse con:
if 1:
    # código del bloque acá

Comentarios

Prioridad: Media

Comentarios multilínea

Prioridad: Media

A Python le falta comentarios multilínea, cosa que me resulta bastante molesto.

Comentarios multilínea anidados

Prioridad: Media

D tiene comentarios anidados, cosa muy conveniente para comentar un bloque de código grande que a su vez pueda tener comentarios adentro. Me parecería piola que Typhon tenga algo similar.

Compilación condicional

Prioridad: Media

Meter cosas del precompilador en Typhon me parece poco conveniente, pero hay cosas necesarias como la compilación condicional. D lo soluciona con palabras clave version, que es básicamente lo mismo que un #ifdef ... #endif del precompilador. Creo que Typhon podría proveer algo similar. Por ejemplo:


version DEBUG:
    void debug(string msg):
        cerr << "debug: " << msg << "\n"

int main():
    version DEBUG:
        debug("entrando al main\n");
    # Mas cosas
    version LINUX:
         # algo específico de Linux.

Luego para compilar podría haber un flag: tyc -V DEBUG archivo.ty

Podrían definirse versiones estándar como en D, como LINUX, WIN32, MACOS, etc que se activen automáticamente dependiendo de la plataforma en la que corra el compilador.

Todo esto puede traducirse de forma bastante inmediata y sin mayores inconvenientes a directivas del precompilador.

class vs. struct

Prioridad: Alta

En C++ una clase y una estructura son exactamente igual, sólo que la clase tiene visibilidad privada por omisión y el struct pública. Ninguna de las dos hace virtuales sus métodos a menos que sea especificado explícitamente.

Las clases en la mayoría de los lenguajes de alto nivel son completamente virtuales, sin posibilidad siquiera de que sea de otra forma. Incluso en C++ el struct suele utilizarse para tipos de datos más simples y concretos, que muy difícilmente tengan algún método virtual (aunque no hay ninguna razón técnica que lo impida).

Siguendo esta línea y la premisa de optimizar para el caso general probablemente sea una buena idea que las clases tengan todos sus métodos virtuales por omisión y las estructuras no.

El problema de esto es que debería haber alguna palabra clave para hacer un método no virtual, para tener una mayor flexibilidad y no tener que caer en un struct con muchos métodos virtuales declarados explícitamente porque se necesita que un método particular no sea virtual.

Visibilidad

Con respecto a la visibilidad por omisión, creo que es indiscutible que las estructuras deben tener visibilidad pública, pero con las clases no es tan claro. En los lenguajes interpretados, las clases suelen tener visibilidad pública por omisión y los lenguajes más serios suelen tener visibilidad privada. Que tenga visibilidad privada no tiene muchas más ventajas que dejar contento a los abanderados de la orientación a objetos estricta (al menos para mí :), por lo que probablemente lo más conveniente es que tanto las clases como estructuras tengan visibilidad pública por omisión.

Lo mismo para la visibilidad en la herencia, en este caso creo que es mucho más claro que lo más natural es que la herencia sea pública por omisión.

Herencia virtual

Es un caso muy poco frecuente y no creo que haya una mejor manera de manejarlo que la de C++, así que creo que debería mantenerse la herencia como no virtual por omisión pero permitir que lo sea si se lo especifica explícitamente.

Ejemplo


class C:
    C(): cout << "Constructor de C\n"
    int hacer_algo(double i) const: return i/2
    ~C(): cout << "Destructor de C\n"

Se traduciría como:
struct C
{
    C();
    virtual int hacer_algo(double i) const;
    virtual ~C();
};
C::C()
{
    cout << "Constructor de C\n";
}
int C::hacer_algo(double i) const
{
    return i/2;
}
C::~C()
{
    cout << "Destructor de C\n";
}

Mientras que:
struct C:
    C(): cout << "Constructor de C\n"
    int hacer_algo(double i) const: return i/2
    ~C(): cout << "Destructor de C\n"

Se traduciría como:
struct C
{
    C();
    int hacer_algo(double i) const;
    ~C();
};
// ídem anterior

Nota: La declaración de C++ estaría en un .h y la definición en un .cpp.

Ejemplos

Los ejemplos se mudaron a TyphonExamples porque eran demasiado extensos.

Links


Topic TyphonLanguage . { Edit | Attach | Ref-By | Printable | Diffs | r1.2 | > | r1.1 | More }
Revision r1.2 - 08 Oct 2004 - 02:33 - LeandroLucarella

%WEBCOPYRIGHT%