c programming-languages stackless compiler-design

¿El uso de C para implementar otros lenguajes ha restringido sus diseños de alguna manera?



programming-languages stackless (9)

Parece que la mayoría de los nuevos lenguajes de programación que han aparecido en los últimos 20 años han sido escritos en C. Esto tiene mucho sentido, ya que C puede verse como una especie de lenguaje ensamblador portátil. Pero lo que me interesa es si esto ha limitado el diseño de los idiomas de alguna manera. Lo que motivó mi pregunta fue pensar cómo se usa la pila de C directamente en Python para llamar a las funciones. Obviamente, el diseñador del lenguaje de programación puede hacer lo que quiera en el idioma que quiera, pero me parece que el lenguaje en el que elige escribir su nuevo lenguaje lo pone en cierta forma de pensar y le brinda ciertos atajos que son difíciles de ignorar. ¿Existen otras características de estos idiomas que vienen de estar escritas en ese idioma (buenas o malas)?


Implementar un compilador / intérprete en C no tiene ninguna limitación importante. Por otro lado, la implementación de un lenguaje X a C es el compilador. Por ejemplo, de acuerdo con el artículo de Wikipedia en C--, al compilar un lenguaje de nivel superior a C no se puede hacer una recolección de basura precisa, un manejo eficiente de excepciones o la optimización de la recursión de la cola. Este es el tipo de problema que C-- pretendía resolver.


Incluso con una implementación de C, eres sorprendentemente libre en términos de implementación. Por ejemplo, el esquema de pollo usa C como intermedio, pero aún así logra usar la pila como una generación de viveros en su recolector de basura.

Dicho esto, hay algunos casos donde hay restricciones. Caso en cuestión: el compilador haskell de GHC tiene un script en perl llamado Evil Mangler para alterar el código de ensamblado generado por GCC para implementar algunas optimizaciones importantes. Se han estado moviendo al ensamblado generado internamente y LLVM parcialmente por ese motivo. Dicho esto, esto no ha limitado el diseño del idioma, solo la elección del compilador de las optimizaciones disponibles.


La única limitación que viene a la mente es la extensibilidad y el alojamiento del compilador. Consideremos el caso de C #. El compilador está escrito en C / C ++ y es un código completamente nativo. Esto hace que sea muy difícil de usar en el proceso con una aplicación C #.

Esto tiene amplias implicaciones para la cadena de herramientas de C #. Cualquier código que desee aprovechar el analizador C # real o el motor de enlace debe tener al menos un componente escrito en código nativo. Con el tiempo, esto hace que la mayoría de la cadena de herramientas para el lenguaje C # se escriba en C ++, que es un poco hacia atrás para un idioma.

Esto no limita el lenguaje por voz, pero definitivamente tiene un efecto en la experiencia en torno al idioma.


La pila C es solo la pila del sistema, y ​​este concepto es anterior a C bastante. Si estudias la teoría de la computación, verás que usar una pila es muy poderoso.

El uso de C para implementar lenguajes probablemente ha tenido muy poco efecto en esos lenguajes, aunque la familiaridad con C (y otros lenguajes similares a C) de las personas que diseñan e implementan lenguajes probablemente ha influido mucho en su diseño. Es muy difícil no dejarse influenciar por las cosas que has visto antes, incluso cuando no estás copiando activamente los mejores fragmentos de otro idioma.

Sin embargo, muchos idiomas usan C como el pegamento entre ellos y otras cosas. Parte de esto es que muchos sistemas operativos proporcionan una API de C, por lo que para acceder es fácil de usar C. Además, C es tan común y simple que muchos otros idiomas tienen algún tipo de manera de interactuar con él. Si desea pegar dos módulos juntos que están escritos en diferentes idiomas, entonces usar C como intermediario es probablemente la solución más fácil.

Donde la implementación de un lenguaje en C probablemente ha influido más en otros idiomas, es probable que las cosas como la forma de escape se realicen en cadenas, lo que probablemente no sea tan limitante.


Lo único que ha limitado el diseño lingüístico es la imaginación y la habilidad técnica de los diseñadores lingüísticos. Como usted dijo, se puede considerar a C como un "lenguaje ensamblador portátil". Si eso es cierto, entonces preguntar si C ha restringido un diseño es similar a preguntar si el ensamblaje tiene un diseño de lenguaje limitado. Dado que todos los códigos escritos en cualquier idioma se ejecutan finalmente como ensamblajes, todos los idiomas sufrirán las mismas restricciones. Por lo tanto, el lenguaje C en sí no impone restricciones que puedan superarse utilizando un lenguaje diferente.

Dicho esto, hay algunas cosas que son más fáciles de hacer en un idioma en comparación con otro. Muchos diseñadores de idiomas tienen esto en cuenta. Si el lenguaje se está diseñando para que sea, digamos, poderoso en el procesamiento de cadenas pero el rendimiento no es una preocupación, entonces usar un lenguaje con mejores instalaciones de procesamiento de cadenas (como C ++) podría ser más óptimo.

Muchos desarrolladores eligen C por varias razones. Primero, C es un lenguaje muy común. En particular, los proyectos de código abierto son más fáciles de encontrar que un desarrollador con experiencia en lenguaje C que encontrar un desarrollador con habilidades equivalentes en otros idiomas. En segundo lugar, C normalmente se presta a la microoptimización. Al escribir un analizador para un lenguaje con script, la eficiencia del analizador tiene un gran impacto en el rendimiento general de los scripts escritos en ese idioma. Para los lenguajes compilados, un compilador más eficiente puede reducir los tiempos de compilación. Muchos compiladores de C son muy buenos para generar código extremadamente optimizado (que también es parte de la razón por la cual muchos sistemas embebidos están programados en C), y el código crítico para el rendimiento se puede escribir en el ensamblaje en línea. Además, C está estandarizado y generalmente es un objetivo estático. El código puede escribirse según el estándar ANSI / C89 y no tiene que preocuparse de que sea incompatible con una versión futura de C. Las revisiones realizadas en el estándar C99 agregan funcionalidad pero no rompen el código existente. Finalmente, C es extremadamente portátil. Si al menos un compilador existe para una plataforma dada, es muy probable que sea un compilador de C. El uso de un lenguaje altamente portátil como C hace que sea más fácil maximizar la cantidad de plataformas que pueden usar el nuevo idioma.


No, en definitiva. La realidad es que, a su alrededor, los idiomas que están escritos en C. Lua, por ejemplo, están tan lejos de C como puede obtener sin convertirse en Perl. Tiene funciones de primera clase, gestión de memoria totalmente automatizada, etc.

Es inusual que los lenguajes nuevos se vean afectados por su lenguaje de implementación, a menos que dicho lenguaje contenga serias limitaciones. Si bien definitivamente desapruebo la C, no es un lenguaje limitado, solo es muy propenso a errores y lento de programar en comparación con los lenguajes más modernos. Oh, excepto en el CRT. Por ejemplo, Lua no contiene la funcionalidad de directorio, porque no es parte de la CRT, por lo que no pueden implementarla de manera portátil en el estándar C. Esa es una forma en la que C es limitado. Pero en términos de características del lenguaje, no está limitado.

Si desea construir un argumento que diga que los lenguajes implementados en C tienen limitaciones o características XYZ, tendría que demostrar que hacer las cosas de otra manera es imposible en C.


Recolección de basura. Las implementaciones de lenguaje en la parte superior de Java o .NET utilizan el GC de la máquina virtual. Los que están encima de C tienden a usar el conteo de referencias.


Tiendo a estar en desacuerdo

No creo que sea tanto que el compilador o intérprete de un lenguaje se implementa en C; después de todo, puede implementar una máquina virtual con C que sea completamente diferente a su entorno de host, lo que significa que puede alejarse de una C / near- mentalidad del lenguaje ensamblador.

Sin embargo, es más difícil afirmar que el lenguaje C en no tuvo ninguna influencia en el diseño de idiomas posteriores. Tomemos, por ejemplo, el uso de llaves { } para agrupar las declaraciones en bloques, la noción de que el espacio en blanco y la sangría no son importantes, los nombres de los tipos nativos ( int , char , etc.) y otras palabras clave, o la forma en que se definen las variables (es decir, Escriba primero la declaración, seguida del nombre de la variable, inicialización opcional). Muchos de los lenguajes populares y extendidos de hoy en día (C ++, Java, C # y estoy seguro de que hay aún más) comparten estos conceptos con C. (Estos probablemente no eran completamente nuevos con C, pero AFAIK C llegó a eso). mezcla particular de sintaxis de lenguaje.)


Una cosa en la que puedo pensar es que las funciones no son necesariamente miembros de primera clase en el lenguaje, y esto no se puede atribuir solo a C (no estoy hablando de pasar un indicador de función, aunque se puede argumentar que C le ofrece con esa característica).

Si uno escribiera un DSL en groovy (/ scheme / lisp / haskell / lua / javascript / y algunos más de los que no estoy seguro), las funciones pueden convertirse en miembros de primera clase. Hacer funciones de miembros de primera clase y permitir funciones anónimas permite escribir código conciso y más legible para los humanos (como lo demuestra LINQ).

Sí, eventualmente todos estos se ejecutan bajo C (o ensamblaje si desea llegar a ese nivel), pero en términos de proporcionar al usuario del idioma la capacidad de expresarse mejor, estas abstracciones hacen un trabajo maravilloso.