Skip to content

Lenguaje de Programación ABCode

Minimizando la Torre de Babel del Software.
Especificación del Lenguaje - Versión 1.
© 2021-2025, César Andrés Arcila Buitrago. Todos los derechos reservados.


Tabla de Contenido

  1. Introducción
  2. ¿Qué es ABCode?
  3. Ejemplo esencial
  4. Lenguaje de programación ABCode vs lenguaje natural
  5. Tips esenciales del lenguaje
  6. Tipos de datos básicos
  7. Variables
  8. Funciones
  9. Operadores del lenguaje
  10. Condicional if / when (else)
  11. Bucle for
  12. Excepciones
  13. Sentencias y Operaciones (run, echo...)
  14. Comentarios
  15. Estructuras de datos
  16. Importar bibliotecas de programas
  17. Clases
  18. Servidor web y su mecanismo interno
  19. Patrón de consulta de base de datos
  20. Resumen de palabras reservadas
  21. Palabras reservadas vs otros lenguajes
  22. Diferencias con Python
  23. Sobre YAML
  24. Estado actual

Introducción

En este texto, dirigido a profesionales y entusiastas afines al software ya iniciados en ello, presento mi lenguaje de programación que se ha inspirado en los orígenes y simplicidad del código en base de datos trasladado a nuestros días, en dónde el código se ubica en lo que llamamos "middleware" en una aplicación, arquitectura de micro-servicios, "serverless", y otras. Agregando que ante tantos lenguajes y tecnologías derivadas, es posible lograr un camino unificador para minimizar la Torre de Babel del Software en buena medida.

Imagina también que, en tiempos dónde la IA (Inteligencia Artificial) llegó para quedarse, exista una tecnología que se entienda con tecnologías existentes brindando un nivel más alto y sencillo para la comprensión del código generado.

Antes de hablar de una nueva especificación y lenguaje de programación ABCode, me permitiré contarte una pequeña experiencia...

Notando ciertas habilidades para interactuar con diferentes lenguajes de programación (como si fuera un políglota informático) se me ocurrió buscar una forma de lograr un lenguaje abstracto para el componente que se encarga de lo que sucede en el servidor (backend), acompañando a un gestor de base de datos (OnMind-XDB) que también hice junto con mi propia plataforma OnMind. De modo que decidí crear una especificación de lenguaje que convirtiera el código a otro lenguaje de interés. Finalmente, así nació el lenguaje de programación ABCode.

Efectivamente encontré ideas similares pero requería algo distinto y como he enfatizado: "abstracto". Luego se me ocurrió combinar YAML (un lenguaje de marcado para datos) y algo de Python (con una sintaxis restringida), dónde cada línea comienza con un atributo (distinguido por terminar con dos puntos :) que guarda sangría cada dos espacios (según YAML), el resto de la línea podría ser código (como Javascript). Validé la idea de este lenguaje de programación con un gran amigo y colega, quién le pareció interesante y entusiasta.

Como dato curioso, antes de pensar en YAML, la idea se gestó originalmente en 2020 usando como editor de código una hoja de cálculo y su disposición por columnas (como una sangría), aplicando color a las celdas con sentencias.

Sobre el Autor

Ingeniero de Sistemas apasionado por la Arquitectura y Desarrollo de Software, con conocimientos en Gestión de Proyectos y estudios en Filosofía. Certificaciones en AWS y Scrum Master, he estado certificado en PMP hasta vencimiento hace unos años.

Experiencia por más de 20 años participando en proyectos de software (ERP, CRM, Workflow, API, Microservicios, Integración) con diversas tecnologías en empresas importantes de diferentes sectores, además proyectos en la nube (AWS).

Líder, experto y creativo, con un punto de vista singular y holístico. Podría decir que un políglota informático. He llegado a ser autor de tecnología propia y blog, así como el libro: El Método OnMind (disponible en Amazon).

Portafolio: https://github.com/kaesar

¿Qué es ABCode?

Un lenguaje para muchos entornos y una especificación como puente

Es una especificación y lenguaje de programación interpretado (creado por Cesar Andrés Arcila Buitrago) que combina el estilo de un lenguaje de marcado como YAML con algo de Python y Javascript, bajo la premisa de ser abstracto y con un enfoque inicial en código para servidor, para lograr generar (transpilar) principalmente código Javascript, quizás algún otro lenguaje experimental como un dialecto, variante o sabor, por ejemplo: Kotlin, Java, Python.

Puede pensarse como un Typescript con un estilo peculiar. Transpila a Javascript con un "look" que mezcla aspectos de Python y YAML, orientado a la lógica de negocio (casos de uso o lógica de "core").

La estrategia inicial de ABCode está orientada dónde opera Javascript y WebAssembly (aunque orginalmente se consideró Python), pensando principalmente en el Backend, es decir, en la portabilidad o la legibilidad de la lógica de negocio (casos de uso). Puede verse también como el sustituto para la capa de código que promovían las bases de datos relacionales con procedimientos almacenados (en lenguajes como: PL/SQL o PL/pgSQL), y que actualmente encontramos alguna similitud en nuevas tecnologías (por ejemplo: AWS Lambda Cloudflare Workers, etc.).

Y es que en mis orígenes como profesional en software trabajé mi primera década con tecnologías de Oracle y lo que añoro de entonces era la simplicidad cuando desarrollabas código para Backend (o la base de datos en ese entonces), sin requirir tantas tecnonologías ni conocimientos diversos.

En otras palabras y en principio, puedes asociar a ABCode con...

Lógica más interna (de dominio o "core")
cuyas funciones componen un Backend
de modo embebido y portable (también modo script)
siendo invocado por otro lenguaje o entorno, o por él mismo

Cada línea de código inicia con una palabra reservada o sentencia definida que correspondería a un atributo o clave en YAML con sangría, el resto de la línea podría verse como código cercano a Python, en realidad transpila Javascript.

ABCode supone una capa adicional para interactuar con distintos lenguajes de programación buscando un sentido unificador o conciliador, quizás a futuro con algunos dialectos (hasta 5 adicionales, sumando 6) que comparten la misma raíz, por ejemplo, pensar en Kotlin, Java, Python y a lo mejor Go (ya veremos).

INDICACION: En el mundo del desarrollo de aplicaciones (web) que usan Internet se designa la palabra Backend para aquello que está destrás de la red (en un servidor), y con la palabra Frontend nos referimos al aspecto visual que ve el usuario, este puede apreciarse en el navegador o en un dispositivo móvil (ejemplo: desarrollo móvil nativo). ABCode comienza con énfasis en el servidor y propone un camino conciliador para el navegador (dominado por el lenguaje Javascript).

Consideraciones del lenguaje

Traducción multi-lenguaje, multi-entorno, multi-plataforma y multi-paradigma.

  • ABCode es sinónimo de la portabilidad de tu código.
  • ABCode se enfoca en principio en código del lado del servidor (backend) combinando YAML con cierto aspecto de Python, en realidad transpila Javascript usando una sintaxis restringida de este lenguaje.
  • ABCode está pensado para ser fácil de aprender siendo cercano a un algoritmo. También puedes hacer una transición ágil cuando vienes de un lenguaje como Python. Por otra parte, YAML es un lenguaje de marcado expresivo y legible al humano, por lo que ABCode también lo es. Puede ser aconsejable revisar la referencia de YAML antes de empezar pero tampoco es requerido.
  • El lenguaje ABCode apoya el Método OnMind y la base de datos OnMind-XDB del mismo autor.
  • ABCode se proyecta para llegar a funcionar alternativamente como una especificación en la que se transpila otro lenguaje (adicional a Javascript). Con esto se buscaría guardar legibilidad aunque la implementación sea específica para un lenguaje en ese caso. Además, se alcanza personalización cuando una tecnología requiere el potencial de un determinado lenguaje de programación.
  • Puede pensarse a futuro como un traductor o puente entre lenguajes de programación, entornos y plataformas, o bien, multi-lenguaje, multi-entorno y mult-plataforma, quizás multi-propósito o multi-paradigma.
  • Modernización e innovación suelen implicar migración de tecnología, proyectos que llegan a tomar años. Con el uso de ABCode el impacto puede ser menor, teniendo el potencial para facilitar el cambio entre tecnologías (en principio, del lado del servidor).
  • Un gran potencial de este lenguaje puede encontrarse en proyectos con tecnologías mixtas, permitiendo agregar una capa abstracta con un sentido unificador. Un caso de aplicación es lo que se conoce como ciudades inteligentes (Smart Cities), así como también para la operación con servidores en la nube (DevOps), o cuando se piensa en incorporar aprendizaje de máquina (Machine Learning) con software de gestión usando una semántica uniforme, o en su defecto, con un estilo semejante para la lectura del equipo de trabajo. Quizás se tienen las bases para explorar a futuro el caso del aspecto visual (frontend).
  • Otros lenguajes estarían en mente y podrán ser introducidos poco a poco de modo experimental, pero el objetivo es mantener principalmente 2 o 3 destinos oficiales (por ejemplo: NodeJS, Deno y WebAssembly) y hasta 5 dialectos adicionales (sumando 6 lenguajes: Javascript, Typescript, Kotlin, Java, Python y a lo mejor Go, ya veremos).

¿Para qué otro lenguaje?

Pensando en la portabilidad del código de la lógica de negocio

Creo que se ha indicado el motivo entre las líneas anteriores, pero podemos enfatizar que se busca mitigar algo... debido a: "la Torre de Babel del Software".

También se comprende que la idea se ha originado al requerir un nivel de abstracción o capa para una tecnología que también usaba componentes con orientación genérica (la base de datos y plataforma de OnMind), además de apoyar el Método OnMind. Seguramente otros pueden identificar una necesidad similar así como el interés de algo multiplataforma, o quizás observe la fatiga de la batalla comercial y comunitaria sobre el mejor lenguaje o tecnología.

Unificar, embeber, portar código, integrar sistemas, conservar cierta simplicidad, aportar en agilismo, persistir con el tiempo la lógica de negocio o casos de uso, reducir la complejidad dando apertura a programadores sin que sean expertos, romper ciertos paradigmas actuales y doctrinas informáticas retornando a los fundamentos, generar el impacto correspondiente donde tenga acogida, son los motivos de que se haya concebido ABCode

En lo personal, tendría que contar otra parte de la historia. La plataforma de la que soy autor se construyó inicialmente con Javascript y Kotlin. Luego identifiqué que si llegara a involucrar Machine Learning, incluso DevOps, sería genial aprender Python. Así que pensé que podía ser útil aprender otros lenguajes y mejorar mis habilitades en ellos aplicando ABCode, mientras lo que estaba codificado en OnMind podía quedar en Javascript y Kotlin respectivamente, siendo la parte de la lógica de negocio introducida con ABCode progresivamente (hasta llegar a sustituir ese aspecto en el Backend)...

Así podría volverse algún día a los orígenes cuando se desarrollaba código en base de datos, es decir, implementar y mantener desarrollos de negocio usando tecnologías específicas y simples, aunque se derive el resultado potencialmente en más tecnologías para orientarse como tecnología multiplaforma.

Es cierto que esto requiere un nuevo esfuerzo y no cualquier menor efuerzo, sin embargo en tanto se avanza con el compilador se estarían sumando esfuerzos de tecnologías a las que se convierte el código, y en ese aspecto se trabajaría también sobre lo construido. Esto sin mencionar que sería más eficiente con la IA (Inteligencia Artificial) usar ABCode como puente para llegar a tener código mantenible en múltiples plataformas. Considero que un código más legible en sintaxis evita distanciamiento entre la comprensión del humano y el mecanismo de la IA en términos de codificación.

¿Cómo se pronuncia?

Las dos primeras letras ("ab") se deletrean con su pronunciación en inglés, cuando llegas a la "c" dices la palabra "code" (en inglés). Y por cierto, se promueve escribirlo con las tres primeras letras en mayúsculas.

Instalación de ABCode

Solo descarga y descomprime segun tu sistema y ejecuta algo como...

bash
./abcodec -s abc/hello.abc

abcodec es el compilador y abc/hello.abc representa tu código fuente con ABCode.
Los fuentes liberados parcialmente se encuentran en mi repositorio en GitHub: https://github.com/kaesar/abcode

Ejemplo esencial

yml
echo: "Hello World!"

Este programa en ABCode imprime un saludo en la pantalla usando echo:.
Ten presente que, en principio, cada instrucción de lógica en ABCode correspondería a una línea de código.

Una variación más completa sería por ejemplo:

yml
fun: hello()
  echo: "Hello World!"

run: hello()

Nótese que en este caso echo: se deriva o pertenece a fun: (que veremos avanzando) y por esto se dejan dos espacios como sangría.

Lenguaje de programación ABCode vs lenguaje natural

En un sentido general y espontáneo, un lenguaje natural puede verse como un acuerdo que llega a tener acogida para comunicar, expresar o indicar algo. ABCode suele usar palabras en inglés de 3 o 4 letras. Conocer su significado puede darnos una comprensión de éste lenguaje, es decir, aquello que se le estaría indicando a un computador que haga. Veamos que significan cada una de las palabras reservadas para ABCode.

  • root: raíz
  • fun: algo divertido
  • set: conjunto (sustantivo) o establecer (verbo)
  • var: abreviatura de variable
  • val: abreviatura de valor (inmutable)
  • run: correr
  • pass: pasar
  • if: si... (expresa una condición)
  • when: cuando... (expresa otra condición o al no cumplir)
  • else: sino... (de lo contrario)
  • for: para... (por cada uno)
  • do: hacer
  • try: intentar
  • fail: fallo
  • use: usar
  • type: clase
  • echo: eco
  • goal: objetivo
  • like: semejante a...

Tips esenciales del lenguaje

Para quien tenga habilidades, experticia en programación y/o requiera agilidad en conceptos técnicos, pueden resumirse los siguientes tips esenciales del lenguaje:

  1. Tipos de datos básicos: int, float, boolean, string, array, object, any. Las variables se definen iniciando con el atributo var:, el nombre de la variable, dos puntos de nuevo (:), el tipo de datos y puede asignarse un valor. Puede omitirse la indicación del tipo de dato cuando se trata de uno básico o genérico.
  2. Las funciones se definen o comienzan con el atributo fun: al nombre de la función, luego los parámetros van entre paréntesis (...), continuando con el nombre del parámetro, el caracter : que separa el tipo de datos posteriormente (y separando los parámetros con coma ,). El tipo de datos a retornar va también después de :. Además, se usa pass: para retornar un valor. La función principal de un programa se denomina main (fun: main()).
  3. Para el bloque de la función o el flujo de control se usa la sangría de YAML y cada línea de un bloque corresponde a una sentencia con un atributo, es decir, las líneas inician con un atributo YAML que corresponda a la especificación del lenguaje. No aplican los corchetes de otros lenguajes ni el punto y coma, por lo que la indentación del código toma mayor importancia para legibilidad e incidencia del mismo.
  4. El flujo de control varía respecto a lenguajes como C, Java, Javascript, Kotlin, pero encuentras una forma equivalente para el uso de if y for, incluso para el manejo de excepciones (try), cuyas palabras clave deben llevar a continuación el caracter :.
  5. El constructor de una clase se expresa con el atributo fun: y el valor new (fun: new()) y la clase se define con el atributo type:.
  6. Las estructuras de datos se definen con el atributo set: seguido por el nombre y aplicando YAML en los atributos asociados. No obstante, al usar YAML y Python, el uso de JSON es prácticamente nativo, comprendiendo que no es un tipo o estructura natural del lenguaje.

La declaración de variables y funciones presenta una variación respecto a Python. ABCode maneja tipos de datos genéricos para guardar compatibilidad con otros lenguajes, por lo que es un lenguaje tipado. Sin embargo, puede omitirse la indicación del tipo de dato en la declaración de la variable cuando se inicializa un valor con un tipo básico o genérico.

Tipos de datos básicos

Dado que la programación se asocia con información, los datos se tipifican para identifcar si se trata de un texto, número u otro tipo. Se pueden citar los siguientes tipos de datos.

  • string - Cadena de caracteres o texto
  • int - Números enteros
  • float - Número flotante (con decimales)
  • boolean - Booleano (True/False)
  • array - Arreglo o vector, se representa como corchetes []
  • object - Objeto, se representa como llaves {}
  • any - Para casos en donde puede aplicar varios tipos (dinámico)
  • void - Vacío (para métodos o funciones)

Varios de estos tipos de datos se inspiran en Typescript, salvo que se usa int y float para números y no existe number.

Variables

Recordando que la variable es como un dato a tener en cuenta (en memoria), se puede expresar una variable asignándo un valor con el operador igual (=). Cada vez que se mencione o use posteriormente la variable, esta debe aparecer con el mismo nombre original (respetando mayúsculas y minúsculas). Sin embargo, la convención para declarar variables inicia la línea con var: o val: (este último para valores constantes o inmutables), el nombre de la variable, dos puntos de nuevo (:) el tipo de datos, luego puede asignarse un valor (con =). Puede omitirse la indicación del tipo de dato en la declaración de la variable cuando se trata de uno básico o genérico.

Ejemplo:

yml
  var: variable = "Ana"
  var: i = 0
  val: list = [10, 20, 30]
  echo: variable

echo: es una sentencia que viene en el lenguaje para mostrar algo en pantalla (en este caso imprime el valor de la variable). En un lenguaje como Python se usaría print()

En programación de computadoras las variables tienen un tipo de dato que indica la naturaleza del contenido, por ejemplo, si una variable contiene un texto (string) o si es un número entero (int) o flotante (float), incluso si se trata de un valor verdadero o falso (boolean) o una lista (array). Veamos el ejemplo indicando el tipo de datos.

yml
  var: variable:string = "Ana"
  var: i:int = 0
  val: list:array = [10, 20, 30]

Funciones

Las funciones realizan algo o definen una serie de instrucciones que cumplen un propósito, es decir, se relacionan con lógica en bloques bien definidos según se organicen. Para el caso de ABCode se antepone fun: al nombre de la función, luego los parámetros van entre paréntesis (...), continuando con el nombre del parámetro, el caracter : que separa el tipo de datos posteriormente (y separando los parámetros con coma ,). El tipo de dato a retornar va también después de :. Veamos a continuación un ejemplo.

yml
fun: hello()
  echo: "Hello World!"

run: hello()

Quién conoce Python puede observar que se omite la palabra reservada def siendo innecesaria al usar fun:. Además, en este caso no requiere retornar un tipo de datos (aunque podría usarse :void al final de la declaración de la función).
run: se usa para invocar operaciones, funciones o sentencias. En la mayoría de lenguajes no se antepone algo como run: para operaciones o sentencias, siendo éstas las líneas comunes, pero aquí se requiere un atributo para conservar el estilo YAML.

Veamos otro ejemplo.

yml
fun: sayMyName(name:string):string
  pass: name

echo: sayMyName("Andrey")

En este caso se usa pass para devolver el valor contenido en la variable (que en otros lenguajes suele ser return).

Si estás comenzando con la programación de computadores, quizás no convenga distinguir cierto aspecto de las funciones. Pero si ya tienes algún conocimiento, es bueno aclarar que las fuciones en ABCode son de naturaleza pública. Para indicar que una función es privada, en el contexto de una clase dada, se debe anteponer el signo @ al nombre, por ejemplo: @sayMyName.

Operadores del lenguaje

Principalmente, los operadores son aquellos que nos permiten realizar operaciones, aunque también se encuentran aquellos que nos permiten evaluar algo (basados en tautología o tabla de la verdad). Con los operadores se pueden sumar dos expresiones o números, así como las demás operaciones matemáticas. Esto se asocia también al algebra esencial que se refiere a funciones y variables. Por otra parte, en los operadores que permiten evaluar algo, se puede comparar o determinar si dos valores son diferentes, o definir condiciones complejas (y, o, no).

Veamos a continuación los operadores del lenguaje.

  • =: igual (asignación)
  • +: suma
  • -: resta
  • *: multiplicación
  • /: división
  • %: módulo de una división
  • +=: incremento
  • -=: decremento
  • ==: comparación exacta (igual a)
  • !=: comparación de diferencia (diferente de)
  • >: mayor que
  • <: menor que
  • >=: mayor o igual que
  • <=: menor o igual que
  • &&: y
  • ||: o
  • !: no, negación
  • @: sustituto de self o this para uso de propiedades de clases en otros lenguajes

Recordando tablas de verdad con operadores

Los operadores de inclusión && y de opción || tienen incidenca en la evaluación de una condición en un programa. Partimos de la siguiente tabla, dónde p es la primera variable y la segunda es q, además se usa True y False para indicar si es verdadero o falso (respectivamente).

pqp and qp or q
TrueTrueTrueTrue
TrueFalseFalseTrue
FalseTrueFalseTrue
FalseFalseFalseFalse

Si una variable o expresión se niega con ! entonces se invierte su valor: si es verdadera se interpreta como falsa y si es falsa se interpreta como verdadera.

Condicional if / when (else)

Las condiciones permiten determinar los puntos de validación en la lógica que se plantee. Por ejemplo, imagina que vas a comprar una bebida para alguien que te la encargó y llevas planteados unas posibles escenarios en caso de que no se encuentre la bebida originalmente solicitada.

Se usa if: para establecer un punto de validación con una condición y when: no, o simplemente else:, cuando no cumple algo. Veamos un ejemplo.

yml
  var: i = 1
  if: i == 1
    echo: "coffee"
  when: no
    echo: "tea"

when: no o else: corresponden a lo que ocurriría cuando no se cumple una condición y debe dejarse siempre como última condición, queriendo indicar lo que sucede en caso contrario.

Se usa when: con una condición (que sería como else if en otros lenguajes) para evaluar otras condiciones determinadas. Veamos el siguiente ejemplo.

yml
  var: i = 3
  if: i == 1
    echo: "coffee"
  when: i == 2
    echo: "tea"
  else:
    echo: "aha"

Nótese que se usa doble igual (==) como operador de comparación, distinguiéndose de la asignación que usa de modo natural un signo de igual (=). En ese orden de ideas, para evaluar valores diferentes (comparación negativa) se usaría el signo de admiración y un igual (!=).

Pueden existir escenarios en los que no se evalúe alternativa, es decir, una condición simple (if:). Por ejemplo:

yml
  var: i = 2
  if: i == 1
    echo: "coffee"

Bucle for

Los ciclos se refieren a instrucciones que se repiten o en donde se da lugar a ciertas iteraciones. Ten presente que la línea del for: suele incluir in, veamos a continuación.

yml
  var: names = ["Ana", "Alex", "Janeth"]
  for: x in names
    echo: x
    if: x == "Alex"
      run: break

Nótese que la variable names es una lista de valores de texto (también conocida con el nombre de arreglos) cuya convención usa corchetes [] separando cada valor por una coma. Cuando se usa break se interrumpe el ciclo, dado que está bajo una condición se imprimirían los nombres hasta que se de lugar a la condición (por tanto no se imprimiría Janeth).

Se puede usar la función range para recorrer un rango, incluso combinarla con len que obtiene el tamaño de un arreglo. Veamos un par de ejemplos:

yml
  for: i in range(10)
    echo: i

  var: n = [10, 20, 30, 40] 
  for: i in range(len(n))
    echo: n[i]

En estos casos se termina el ciclo cuando se alcanza el tope (restando 1). range puede usarse también dos parámetros indicando el primero el inicio y el segundo el tope. Su tercera manera de llamarse es con un tercer parámetro que indicaría un incremento (en caso de ser distinto de 1).

Una tercera variación sería incluyendo una condición y evitando el uso de in, es decir, sin in se interpretaría como while en otros lenguajes. Veamos el ejemplo:

yml
  var: i = 0
  for: i < 10
    run: i += 1
    echo: i

Nótese que for: recibe en este caso una condición y no lleva in.

Una variación adicional consistiría en entrar en un ciclo e interrumpirlo (usando: break) cuando cumpla una condición determminada. Veamos el ejemplo:

yml
  var: i = 0
  for: True
    run: i += 1
    echo: i
    if: i < 10
      run: break

Quién ya tiene conocimiento en programación puede asociar esto con la sentencia do...while de otros lenguajes, siendo el modo de emularla.

Excepciones

Las excepciones se originan cuando se interrumpe la lógica esperada debido a un error en medio de la ejecución del programa de modo que podríamos gestionarlas, en otras palabras, son útiles para manejo de errores generalmente de caracter técnico.

yml
  try:
    echo: n
  fail:
    echo: "error"

try: indica que se inicia un bloque de código controlado y que en caso de una excepción se pasa al bloque correspondiente a fail:.

Sentencias y Operaciones (run, echo...)

run: se usa para invocar operaciones, funciones o sentencias. En la mayoría de lenguajes no se antepone algo como run: siendo las operaciones o sentencias las líneas comunes, pero aquí se requiere un atributo para conservar el estilo YAML. También se usa para invocar break, continue, incrementos. Veamos a continuación un par de aclaraciones sobre este punto.

Operaciones vs Declaraciones

En ABCode se usa var: para declarar variables y se pueden inicializar allí mismo. Por otra parte, cuando se trata de operaciones posteriores se usa run:, por lo que es posible encontrar código semejante en ambos casos, pero en uno cumple una función de inicialización y otro correspondería al flujo común (posterior a la definición). Veamos el ejemplo:

yml
  var: i = 0
  echo: i
  run: i = 1
  echo: i

No se ha mencionado val:, que se usa para variables inmutables o constantes, puesto que no debe admitirse una asignación con run: sobre variables inmutables.

Sentencias complementarias y macros

En teoría, las líneas que no corresponden a atributos como fun:, pass:, if:, when:, for:, try:, fail:, type:, corresponderían a una sentencia que utiliza run:. Sin embargo, pueden existir variaciones para casos específicos que es apropiado que el lenguaje distinga.

Tal es el caso de echo: que se usa para imprimir algo en pantalla. Pensando en implementación a futuro, se tendrían también las palabras reservadas file:, read, web:, dbc:, ask:, sql:, page:, jsx:, html:, css:, code: como sentencias complementarias a run:, conocidas también como macros.

De hecho, echo: permite formatear la salida como en los siguientes ejemplos:

yml
echo: "Hello, {name}! Tienes {age} years."
echo: "Name: {name:10} | Age: {age:3}"  # Alignment with spaces

Para decimales se podría usar: echo: "The prices is {price:.2f}"

Para gestión de archivos se usaría file:, considerando cuatro métodos básicos que son: @open, @write, @read, @close. Por ejemplo:

yml
file: @open = "file.txt"
file: @write = "file.txt", "Hello world!"

Para conexión a base de datos se usaría dbc:. Por ejemplo:

yml
use: @mongodb
dbc: @link = "mongodb://localhost:27017/"
dbc: mydb := "test"
echo: "Database connected!"

dbc: @link = establece internamente una variable dbc para gestionar la conexión a la base de datos. Nótese que se reporta una dirección con controlador de base de datos, dominio (o servidor) y el puerto: "mongodb://localhost:27017/"

Luego dbc: mydb := "test" apunta al nombre de la base de datos específica (test) asignándola a una variable (mydb) con :=.

Comentarios

Los comentarios ofrecen indicaciones para legibilidad y comprensión del código pero no tienen efecto en la ejecución del programa, es decir, van dirigidos a la documentación del código o al equipo.

yml
# Esto es un comentario

Quien tiene conocimientos en YAML o Python debe saber que el uso de la almoadilla (#) para comentarios coincide con ABCode.
A diferencia de YAML, ABCode admite comentarios de línea completa, es decir, no se interpreta al final de línea salvo excepción de comentario especial del lenguaje (ej. #in:).

Directivas y etiquetas especiales

Si estás comenzando con la programación de computadores, quizás comprendas mejor este tópico avanzando en la codificación de programas. ABCode introduce ciertas etiquetas y comentarios especiales (directivas) que en realidad son más que comentarios, puesto que ofrecen una orientación en el lenguaje. Veamos:

  • goal: indica el modo o el lenguaje destino (any, cli, api, fun, dbs o un entorno de lenguaje: deno, wasm, kotlin, java, python)
  • like: indica que una sentencia anterior, distinta de like: (por ejemplo con run:, echo:, use: o pass:), se expresa en otro lenguaje, el cual se define en #@in: (por ejemplo #@in: java). De este modo, se transpila literalmente cuando el destino corresponde a ese lenguaje. No aplica (ni tiene efecto) cuando el destino definido en goal: es un lenguaje específico
  • #in: comentario usado al final de la sentencia like:, que indica lenguaje literal expresado para esa línea y que sustituye una línea de código anterior cuando se transpila a ese destino
  • #[...] usado para anotaciones del lenguajes como Java (inspirado en Rust)

goal: no es un comentario pero es una etiqueta (o atributo) que no opera como una sentencia. Por ejemplo, goal: fun se usa para las funciones más internas o scripts embebidos, y goal: dbs es como fun para bases de datos con sql.

Ejemplo de las anteriores directivas:

yml
goal: any

val: name = "Andrey"
echo: "Hello, ${name}"
like: "Hello" + name   #in: java
like: "Hello, $name"   #in: kotlin

Este ejemplo es sólo ilustrativo y es posible que echo: no necesite acompañarse con like: al permitir un formato más estándar: echo: "Hello, {name}"

Revisemos lo siguiente:

  • goal: determina el lenguaje que se expresa en el código y se omite cuando se usa la sintáxis estricta de ABCode. Por defecto: Javascript (core).
  • goal: actualmente admitiría valores como any y cli (ABCode para programas planos), más los lenguajes o entorno deno, wasm, kotlin, java, python y nodejs/bun, es decir, un par de entornos y al menos 5 lenguajes o dialectos. Adicionalmente, api para indicar destinos compatibles con librería web para servidor. Quizás a futuro se introduzca pwa para indicar destino compatible con el aspecto visual (Javascript en el navegador).
  • goal: any se usa para programas planos (POJO) en los que no se requieren dependencias (librerías), motivo por el cual se piensa preparar el uso de goal: cli y goal: api para soportar una librería compatible con destinos oficiales. goal: fun se usa para indicar que el contenido corresponde a funciones más internos o scripts (ej. Lua). goal: dbs es como fun para bases de datos con sql (es decir, código para repositorio y persitencia de datos).
  • goal: puede ser usado para reportar un destino distinto a any, cli, api, fun o dbs (incluso pwa en un futuro), así se debe entender como una modalidad de puente para otro lenguaje. De esta manera se conserva la estructura expresiva (YAML) y la parte de código se orienta para traducción a un lenguaje en particular. Esto es útil para implementar soluciones específicas en un lenguaje o entorno determinado.
  • like: combinado con el comentario #in: es útil cuando se desea traducir una línea de código con un lenguaje en particular (por ejemplo, debido a diferencias en librerías), refiriéndose siempre a la anterior línea (distinta de like:), es decir, aplicando una traducción literal. Lo anterior sugiere que si se usa goal: con un destino distinto de any, cli, api, fun o dbs, no se requiere usar like:, siendo en ese caso excluyentes.
  • Pueden existir restricciones para el uso de like: con #in: en algunas sentencias, por ejemplo, fun:, if:, for:, do:, try:, y fail: deben acoger la propuesta de ABCode (sin traducción).

Para evitar ambigüedad o disminuir posible conflicto entre goal: y el argumento del compilador en la línea de comandos en donde se usa -t para indicar como destinos los lenguajes o entornos, la interpretación es la siguiente:

El compilador abcodec en principio traduce ciertos dialectos, siendo nativo el lenguaje Javascript (nodejs/bun), y el dialeto destino se indica con el argumento -t. En el compilador se revisará si existe la etiqueta goal: (en las primeras líneas del archivo o primera aparición) y en el caso de indicar de encontrarse con un valor para un lenguaje distinto se reportará la advertencia y se evitará la transpilación. Por supuesto, si el valor no corresponde a lenguajes o entornos (por ejemplo: any, cli, api, fun, dbs) el argumento aplica para traducir al código destino.

Estructuras de datos

Las estructuras de datos representan un modelo o tuplas, y pueden definirse bajo el atributo set: de la siguiente manera:

yml
set: Person
  name: string
  age: int

Se usa la misma disposición de YAML indicando los tipos de datos de cada atributo.

Importar bibliotecas de programas

Las librerías o bibliotecas de programas permiten organizar y usar código que se encuentra en otro archivo. Se usa la palabra reservada use: para indicar la librería que se importa y dónde se encuentra (ruta), o en su defecto una incorporada en el sistema. Esto es semejante a lo que se conoce en otros lenguajes como import.

yml
use: @sys

A modo de ejemplo, @sys, @api, @mongodb serían directivas para resolver algunas librerías dinámicamente.
A la fecha de esta publicación, use: está pendiente por definir otros detalles adicionales para su modo de uso (mientras se implementan funciones incorporadas o librerías esenciales para el lenguaje).

Clases

Las clases permiten un paradigma que se conoce como programación orientada a objetos, buscando representar todo como un objeto. Si conoces Python, cuando se manejan clases esto debe reinterpretarse conforme a ABCode, encontrándose variaciones o diferencias en este aspecto.

yml
type: Circle
  var: @radious

  fun: new(radious)
    run: @radious = radious

  fun: print()
    echo: @radious

new es el nombre de la funcion con la que se inicializa la clase, es decir, el constructor de la clase se expresa como: fun: new(). Esto difiere de Python y se inspira en Rust.
@ se usa para dar referencia a una propiedad directa de la clase, distinguiédose de una variable común. Esto difiere de Python que usa self u otros que usan this, y se inspira en Ruby, pero debe declararse usando var:.

Otros aspectos

Para indicar que una función es privada, en el contexto de una clase dada, se debe anteponer el signo _ al nombre, por ejemplo: _printer().

En lenguajes como C# o Java (incluso PHP y Kotlin), las clases se organizan o agrupan, bien sea con namespace o package (respectivamente). En ABCode encuentras la palabra reservada root: para estos casos y suele ubicarse en las primeras líneas del programa, antes de definir una clase. Por ejemplo:

yml
root: awesome

type: Circle
...

cast: es reservada para otro concepto conocido como interfaces.

yml
root: awesome

cast: Area
...

Estos criterios se definen como parte de la especificación del lenguaje, aunque en primeras versiones del compilador es posible que aún no estén disponibles.

Servidor web y su mecanismo interno

La sentencia web: usa métodos para la Web implementando código para cada lenguaje (según librería usada internamente). web: tiene métodos basicos que son: @server, @listen, @handle (incluso @fetch). Veamos un ejemplo...

yml
use: @api

web: @server = app

do: get("/") = index
  web: @handle = "Hi there!"

fun: main()
  val: port:int = 8000
  echo: port
  web: @listen = port

run: main()

Nótese que web: @server = establece variable del servidor, luego web: @handle = asigna un gestor de peticiones, que en este caso devuelve un texto, y web: @listen = inicia el servicio en el puerto indicado.

Por otra parte, en lugar de fun: se usa do: get(...) = ... para definir las funciones asociadas a una petición web según la ruta. De este modo, podría ser get, post, put o delete.

Estos criterios se definen como parte de la especificación del lenguaje, aunque en primeras versiones del compilador es posible que aún no estén disponibles

Patrón de consulta de base de datos

En tanto se implemente ask: (palabra reservada para gestión con base de datos), se buscaría una estructura de consulta declarativa para interactuar con una base datos y que internamente se traduzca a SQL (Structured Query Language) conservando el estilo YAML y un patrón, usando la base de datos OnMind-XDB. Por ejemplo:

yml
  ask:
    what: find
    some: persons
    with: name = 'peter'
    how: order age

Con ask: se usarían los atributos what:, some:, with:, puts:, show: o how: para establecer un patrón en la consulta. to: para la colección o tabla, what: para la acción (find, insert, update, delete), with: para el criterio de búsqueda o filtro, y how: para indicaciones complementarias (por ejemplo: order, limit). show: cuando encuentras algo and puts: podría incluirse para operaciones de insercción o actualización. Veamos otros ejemplos:

yml
  ask:
    what: find
    some: persons
    with: name = 'peter'
    show: name,age

Para find se usa show: separando con ,, y with: usa un modo cercano a SQL.
En lugar de usar LIKE dentro de with: se usaría la función begins_with(field, value) o contains(field, value) (reportando campo y valor)

yml
  ask:
    what: insert
    some: persons
    puts: {name:'peter',age:25}

Para insert se usa puts: con {} (JSON).

yml
  ask:
    what: update
    some: persons
    with: name = 'peter'
    puts: {age:20}

En este caso, puts: establece age = 20, y with: usa el modo SQL.

yml
  ask:
    what: delete
    some: persons
    with: name = 'peter'

Adicionalmente, dbc: para indicar la conexión específica, keys: para establecer parámetros nombrados que corresponden a una lista clave-valor ({}), call: para invocar funciones, user: y auth: para reportar usuario y token de sesión. También from: cuando se refiere a un respositorio orientado con el Método OnMind.

Estos criterios se definen como parte de la especificación del lenguaje, aunque en primeras versiones del compilador es posible que aún no estén disponibles

Resumen de palabras reservadas

De modo esencial podemos citar las siguientes palabras reservadas o tipo de sentencia.

  • root: paquete o módulo de programa (referido por compatibilidad, por ejemplo con package o namespace)
  • fun: establece una función o método (rutina que cumple una función)
  • set: establece estructura de datos (modelo)
  • var: declaración de variable (incluye asignación inicial)
  • val: declaración para fijar inmutables (incluye asignación)
  • run: sentencia, operación o asignación (también para break, continue)
  • pass: retorna o concluye una función con un valor (si aplica)
  • if: condición establecida o inicio de validación
  • when: condición adicional (else if). when: no o simplemente else: cuando no cumple algo
  • for: ciclo convencional (el codigo respectivo puede incluir in)
  • do: bloque de código, para derivarse como subrutina (o función lambda)
  • try: inicia bloque para excepciones
  • fail: indica evento generado para el control de excepción
  • use: importa librería (funciones de otro archivo de programas, import)
  • type: define una clase, como constructor de la clase se usa fun: new()
  • echo: imprime o registra salida de consola (con parámetros usa: {param})
  • file: gestiona archivos locales (@open, @write, @read, @close)
  • goal: sugiere el destino
  • like: reemplaza una línea de código anterior tal como se indica (combinando #in: y el lenguaje destino)

A la fecha de esta publicación, no se implementan la sentencia read: quedando reservada como especificación del lenguaje para incorporar en futuras versiones.

Palabras reservadas vs otros lenguajes

Para quién tenga conocimientos en otro lenguaje, una manera ágil de comprender ABCode consiste en citar el siguiente paralelo o lista comparativa:

  • root: ~ package, namespace
  • fun: ~ function, func, def, proc
  • set: ~ struct, type, data class
  • var: ~ let, var, let mut
  • val: ~ const, val, let
  • pass: ~ return
  • if: ~ if
  • when: ~ else if, elif, elsif, else
  • for: ~ for, while
  • do: ~ do
  • try: ~ try
  • fail: ~ catch, exception, rescue
  • use: ~ import, include, using, require
  • type: ~ class
  • echo: ~ print, echo, puts, console
  • # ~ // (comentarios de línea)

run: no suele tener paralelo y por esto no se encuentra en la tabla anterior. En la mayoría de lenguajes no se antepone algo como run: para operaciones o sentencias, siendo éstas las líneas comunes, pero aquí se requiere un atributo para conservar el estilo YAML.

Diferencias con Python

Se ha hablado de Python por ser un lenguaje cuya sintaxis fue inspiradora para mi propio lenguaje. Aunque ABCode es mas cercano a Javascript se guardan algunos aspectos de Python. Para quién tenga conocimientos en Python, y sin hablar de la incidencia de YAML, se indica a continuación las principales diferencias:

  1. Las funciones en ABCode inician con fun: (inspirado en Kotlin) y se omite la palabra reservada def de Python.
  2. Las funciones pueden especificar el tipo de datos a retornar, agregando dos puntos (:) al final y el tipo de datos respectivo.
  3. Se omite la palabra reservada return del lenguaje Python cuando se usa pass:.
  4. Las variables pueden especificar el tipo de datos al definirlas, agregando dos puntos (:) después del nombre y el tipo de datos respectivo, antes de asignar un valor (antes de =).
  5. Se simplifican algunas palabras reservadas respecto a Python u otros lenguajes. Tal es el caso de while que no existe y se usa for: (inspirado en Go), o switch...case que tampoco existen y se debe usar if: y when:. En principio, tampoco se piensa en implementar finally que correspondería a try:, con el fin de guardar simplicidad y compatibilidad con ciertos lenguajes.
  6. Las clases llevan el nombre después de iniciar con type:, sustituyendo la palabra reservada class de Python, y el constructor de la clase se debe llamar new (inspirado en Rust).
  7. En las clases se usa el caracter @ (inspirado en Ruby) en lugar de la palabra reservada self de Python, que en otros lenguajes sería this. Esto se verá reflejado en sentencias como run: cuando se usa una propiedad, es decir, que cuando se manejan clases esto debe reinterpretarse conforme a ABCode, el cual presenta variaciones en este tema respecto a Python.
  8. Python incorpora print() mientras ABCode usa echo: para mostrar algo en pantalla (inspirado en PHP).
  9. En lugar de los operadores lógicos and, or y not de Python, ABCode promueve el uso de &&, || y ! en favor de varios lenguajes.

Sobre YAML

Hasta ahora no se mencionan variaciones respecto a YAML dado que en un sentido práctico se respeta su estilo. Se puede apreciar, por ejemplo, que la palabra reservada run: se introduce debido al estilo YAML, puesto que no existe en otros lenguajes este concepto en el caso de sentencias u operaciones.

Por otra parte, es posible que en futuras versiones se llegue a introducir la notación YAML para textos largos usando el caracter >, por ejemplo, en el caso de la sentencia echo: o pass:.

yml
  echo: >
    This text
    is wrapped
    as a paragraph

Estos criterios se definen como parte de la especificación del lenguaje, aunque en primeras versiones del compilador es posible que aún no estén disponibles

Estado actual

Especificación lista (este libro), trabajo en progreso, el auspicio es bienvenido

El presente texto ya es una especificación del lenguaje de programación ABCode creada y elaborada por César Andrés Arcila Buitrago en el año 2021, si bien fue ideada con un prototipo rústico en 2020. En los inicios del año 2022, al interior de la plataforma OnMind se logró un transpilador (traductor de lenguaje fuente a otro fuente) como prueba de concepto que permitía ejecutar programas sencillos que no requieren dependencias, para algunos lenguajes o entornos (Deno, NodeJS).

Recuerda que el enfoque inicial de este nuevo lenguaje es la lógica de negocio que se aborda desde el Backend. Por ello no se ve una necesidad urgente de que el compilador convierta múltiples archivos y en su lugar se debe procesar archivo por archivo, aunque seguramente se puede considerar más adelante esto.

Para escribir con ABCode no se necesita una nueva aplicación, es decir, se usa un editor (como VSCode, Sublime u otro que puedes descargar de Internet) asociando el formato YAML con archivos de extensión .abc. Alternativamente, el formato puede asociarse a Lua (solo debes evitar aplicar sus comentarios). Sin embargo, se ha llegado a pensar en preparar un editor para una mejor integración con el compilador/transpilador.

Los fuentes liberados parcialmente se encuentran en mi repositorio en GitHub: https://github.com/kaesar/abcode

Sobre la intención de soporte

Si hablamos de una tecnología que tendría versión Open Source (de código abierto), ya se estaría pensando en cierto soporte pero no impositivo, debido precisamente al tipo de licencia. Considero que para distinguir los lenguajes objetivos y su nivel de soporte lo más coherente es hablar de un nivel de intención de soporte por lenguaje destino o prioridad, dónde cinco (5) es una posibilidad remota. Es verdad que suele usarse la palabra experimental para características no prioritarias y pueden no ser atendidas.

Por ahora, los destinos se orientan al backend, si bien existen tecnologías que promueven el desarrollo FullStack desde el back. A continuación veamos la propuesta de intención del nivel de soporte, dado el contexto, no vinculante para ningún nivel (incluso el 1).

Destinos principales

Característica de interés o estrategia:

  1. NodeJS - Nivel 1 - Servidor Web y Microservicios, AWS Lambda, CDK
  2. Deno - Nivel 2 - Multiplataforma, Typescript
  3. AssemblyScript - Nivel 2 - WebAssembly basado en Typescript (wasm)

Bun podría usarse como sustituto de NodeJS debido a su compatibilidad.

Destinos complementarios de alta experimentación a futuro

Característica de interés o estrategia:

  1. Kotlin - Nivel 3 - Multiplataforma, Servidor Web y Microservicios
  2. Java - Nivel 3 - Bases de Datos, Servidor Web y Microservicios (SpringBoot)
  3. Python - Nivel 4 - Scripts y Ciencia de Datos
  4. Go - Nivel 5 - WebAssembly, Servidor Web y Microservicios

4 podría corresponder a Kotlin (JVM), luego Java, quizás Python y Go (ya se verá después).

Origenes que cuentan tanto como los destinos

Dado que otra estrategia de ABCode consiste en operar como lenguaje portable y embebido en otro lenguaje (ej. usando quickjs) o en un entorno destacado para Backend, debe entenderse que potencialmente se podría llegar a usar desde PHP, NodeJS, Java, C, Python, Ruby, Dart, Deno, Rust, Go, Swift, Kotlin, C#, Pascal, PostgreSQL y quizás más por medio de entorno de ejecución.

No se trataría sólo de pensar en el destino sino también de las posibilidades de lenguajes y entornos que integran wasm (WebAssembly) o quickjs, incluso Lua con el proyecto TypescriptToLua (TSTL).

¿Por qué no PHP u otros lenguajes?

En cuanto a otros lenguajes, se considera que la estrategia tiene un alcance más que suficiente y bien amplio, con lenguajes "Top". En el caso de PHP se identifica mayor dificultad para traducir el código, por ejemplo, por el uso del signo $ en las variables y consideraciones semejantes que sería impedimento para obtener un destino claro. También puede ser sustituido usando Python, o el proyecto py2php, así como ts2php. Aunque, se podría pensar a futuro en una capa web ligera en PHP (un "Runtime") que invoque funciones en wasm, gracias a wasmer-php.

Más detalles sobre el avance técnico

Como detalle técnico, no se requiere ningún gestor de paquetes (al dejar esto a cada lenguaje destino) y tampoco requiere librería estándar o SDK (hasta ahora). Sin embargo, se ha empezado a revisar algún programa esencial con alguna librería sencilla y ligera muy específica. Se consideran aplicaciones web para alguna API de modo clásico o plano (sin requerir librería), es decir, un controlador principal (endpoint) sin enrutamiento de url (se haría mediante POST con parámetro que indique la función a invocar y un token para la seguridad), por lo que puede implementarse de modo estandard.

Recuerda que ABCode finalmente convierte código a Javascript, en su enfoque prioritario, tomando las partes de la línea que son los valores en YAML. Esto ya está disponible en el compilador sujeto a mantenimiento y al refuerzo de reglas para disminuir errores potenciales en su uso.

Invitación final

Si has llegado hasta aquí me queda agradecer la acogida respectiva e invitarte a ver mi portafolio de proyectos, aunque algunos estén congelados o sean privados y mi ocupación pueda estar a tope, he publicado software gratuito que puedes encontrar entre mis obras y tengo previsto preparar algún anexo a este texto que ha planteado los fundamentos...

Portafolio: https://github.com/kaesar
ABCode (Compilador): https://github.com/kaesar/abcode
https://onmind.co

Fe de erratas

El formato digital de eBook puede tener variaciones respecto al proyectado originalmente dónde se respeta un estilo, colores, sangría y algún otro aspecto.