
¿Y si JSON no fuera solo un formato de datos?
¿Y si fuera un lenguaje de programación?
Construimos un lenguaje Turing completo que es un subconjunto estricto de JSON. Sin sintaxis nueva. Sin analizador propio. Todo programa es JSON válido.
Esto es Almadar.
En 1958, John McCarthy presentó las S-expressions (expresiones simbólicas) en Lisp:
(+ 1 2)
(if (> x 10) "big" "small")Las S-expressions son listas anidadas en las que el primer elemento es el operador.
Los arrays de JSON son listas anidadas.
["+", 1, 2]
["if", [">", "x", 10], "big", "small"]Eso es todo.
Las S-expressions ya encajan perfectamente dentro de los arrays de JSON. En lugar de inventar una sintaxis nueva, interpretamos lo que JSON ya expresa.
Un programa de Almadar se compone de Orbitals, los bloques básicos del sistema.
Cada Orbital encapsula tres elementos centrales:
La Entity define la estructura de los datos. Declara campos, tipos y restricciones.
Es:
Contiene los datos sobre los que opera el sistema.
Un Trait define el comportamiento.
Técnicamente, un Trait es una máquina de estados reutilizable vinculada a una Entity.
Contiene:
set, emit, etc.)Los Traits encapsulan la lógica y pueden reutilizarse entre orbitals. Son el núcleo computacional del sistema.
Una Page define la interfaz de usuario.
Describe:
Las Pages reaccionan al estado de la Entity y envían eventos que mueven los Traits.
{
"name": "ApprovalWorkflow",
"orbitals": [{
"entity": {
"name": "Request",
"fields": [
{ "name": "amount", "type": "number" },
{ "name": "status", "type": "enum", "values": ["pending", "approved", "rejected"] }
]
},
"traits": [{
"name": "ApprovalTrait",
"linkedEntity": "Request",
"stateMachine": {
"states": [
{ "name": "Pending", "isInitial": true },
{ "name": "Approved" },
{ "name": "Rejected" }
],
"transitions": [{
"from": "Pending",
"to": "Approved",
"event": "APPROVE",
"guard": ["and",
[">=", "@user.roleLevel", 3],
["<", "@entity.amount", 10000]
],
"effects": [
["set", "@entity.status", "approved"],
["emit", "REQUEST_APPROVED"]
]
}]
}
}]
}]
}La estructura es JSON. La lógica son arrays de JSON. La ejecución es determinista y recursiva.
Un guard es una expresión condicional que determina si se permite ejecutar una transición de estado.
Una transición solo se dispara si su guard se evalúa como true.
Si el guard se evalúa como false, la transición queda bloqueada.
Los guards son expresiones puras: no tienen efectos secundarios.
{
"from": "Pending",
"to": "Approved",
"event": "APPROVE",
"guard": ["and",
[">=", "@user.roleLevel", 3],
["<", "@entity.amount", 10000]
],
"effects": [
["set", "@entity.status", "approved"]
]
}Esta transición se ejecuta solo si:
Si alguna de las dos condiciones falla, la transición no hace nada.
Los guards se evalúan de forma recursiva:
["and",
[">=", "@user.roleLevel", 3],
["<", "@entity.amount", 10000]
]Pasos de la evaluación:
@user.roleLevel, @entity.amount)El resultado debe ser un booleano.
Los guards pueden usar:
and, or, not=, !=, <, >, <=, >=@entity, @user o @payloadConceptualmente, un guard equivale a una condición if para una transición.
Almadar es Turing completo porque ofrece:
set, emit)Una autotransición con un guard y actualizaciones de estado equivale a un bucle while:
{
"from": "Computing",
"to": "Computing",
"event": "TICK",
"guard": [">", "@entity.counter", 0],
"effects": [
["set", "@entity.counter", ["-", "@entity.counter", 1]],
["emit", "TICK"]
]
}Estado = memoria. Transiciones = flujo de control. Expresiones = cómputo.
Eso es un modelo computacional completo.
Almadar propone un cambio sencillo:
Sin gramática nueva. Sin reglas de sintaxis nuevas. Solo cómputo estructurado dentro del formato de datos más universal del mundo.
JSON ya ganó.
Ahora puede pensar.