Skip to content

Navigation Menu

Sign in
Sign up

Latest commit

History

17 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

JAJAJA

"El chiste no se cuenta, se reescribe."

Un esolang de reescritura de cadenas cuyo alfabeto son repeticiones del token ja. Cuántas veces se ríe el programa en cada punto es el símbolo.

El resultado: un sistema de reescritura formal, Turing completo, cuyo código fuente lo lee cualquier hispanohablante.

jaja::=~Hello, world!
j::=~ 
::=
jaja j
$ python check_bootstrap.py
Jajaja_COMPILE_OK status=HALTED steps=2 signature='JAJAJA-OK\n'

Sin dependencias. Python 3 y nada más.


Runtime

JAJAJA tiene dos runtimes con la MISMA semántica:

runtime ejecutor papel
src/jajaja.lol (armado desde src/parts/*.lol) un runtime LOLCODE externo (lci) implementación en LOLCODE
jajaja_interpreter.py Python oráculo de referencia y herramientas

Además de correr programas, el repo ya incluye en LOLCODE los generadores que lo construyen: src/proofs_lol/tm_compile.lol compila màquinas de Turing a JAJAJA (byte-idéntico al generador Python, verificado por tools/compare_tm_compile.py) y src/proofs_lol/ja_encoding.lol hace la versión en risas puras (verificado con tools/compare_ja_compile.py y tools/compare_ja_run.py). La suite nativa tests/runtime_tests.lol corre 22 aserciones dentro de lci vía test_lolcode_native.py.

Guía operativa (en español, con salidas reales): docs/GUIA_LOLCODE.md.

Para correr sobre LOLCODE (requiere un intérprete lci disponible; ver backends/lolcode/README.md):

python tools/run_jajaja_lol.py examples/hola.jaja
python tools/run_jajaja_lol.py examples/echo.jaja --input "hello"

Paridad demostrada: python tools/parity_check.py corre un corpus y compara (output, steps, status) entre ambos runtimes. python tools/turing_parity_lol.py verifica que los fixtures de Turing producidos por proofs/tm_to_jajaja.py dan el mismo resultado en ambos runtimes. Evidencia en evidence/lolcode_port/. El rol de Python: ver docs/PYTHON_ORACLE_AND_LOLCODE.md.

Correr

python check_bootstrap.py # smoke test canónico
python run_examples.py # todos los examples/*.jaja
python test_jajaja.py # 49 tests del intérprete
python test_host.py # 51 tests del host runtime
python proofs/tm_to_jajaja.py # simula máquinas de Turing (7 casos)
python proofs/ja_encoding.py # ¿el alfabeto de risas alcanza?
# Host runtime
python host.py examples/calculator.jaja --input "ADD 1 2"
python host.py examples/echo.jaja --input "hello" --allow stdin,stdout
python host.py examples/calculator.jaja --input "MUL 3 3" --trace
from jajaja_interpreter import run, Jajaja
# Básico
output, steps, status = run(source, max_steps=200000)
# Runtime input (COMPILE_ONCE_TEST_MANY)
output, steps, status = run(source, stdin_data="hello")
# Con trace (no afecta output)
j = Jajaja(source, trace=True)
output, steps, status = j.run(stdin_data="hello")
for snapshot in j.trace:
 print(snapshot.step, snapshot.base)

El lenguaje

Especificación completa en JAJAJA_LANG.md . Lo mínimo:

Estado una cadena (base) más un buffer de salida
Regla lhs::=rhs — reemplaza la primera ocurrencia de lhs por rhs
Salida lhs::=~texto emite texto y borra el match; ::=~ solo emite newline
Evaluación primera regla que matchea, ocurrencia más a la izquierda
Input stdin_data se inyecta como prefijo de la base
Fin HALTED cuando ninguna regla matchea; MAX_STEPS al agotar presupuesto

El alfabeto ja+ es una convención estilística, no una restricción: el motor acepta tokens arbitrarios.

Runtime input

El mismo archivo .jaja responde a diferentes inputs en runtime:

# command.jaja
bye::=~BYE
hello::=~HELLO
::=
from jajaja_interpreter import Jajaja
src = open("examples/command.jaja").read()
Jajaja(src).run(stdin_data="hello") # → ("HELLO", 1, "HALTED")
Jajaja(src).run(stdin_data="bye") # → ("BYE", 1, "HALTED")
Jajaja(src).run(stdin_data="") # → ("", 0, "HALTED")

Mismo SHA256, diferentes inputs, diferentes outputs. Python no calcula nada — las reglas JAJAJA procesan el input directamente.

Host runtime

host.py ejecuta programas JAJAJA con un protocolo de capabilities:

python host.py program.jaja --input "data" --allow stdin,stdout,kv
python host.py program.jaja --allow fs-read,fs-write --root ./sandbox

JAJAJA genera peticiones EFFECT via reglas de output. host.py las ejecuta, inyecta los RESULT de vuelta en la base, y JAJAJA continúa computando.

JAJAJA → EFFECT stdout {"text":"hello"}
host.py → ejecuta, inyecta RESULT OK ""
JAJAJA → continua...

Capabilities disponibles

Capability Grupo Descripción
stdin io Lee del input buffer
stdout io Escribe a stdout
kv-get kv Lee del key-value store
kv-set kv Escribe al key-value store
fs-read filesystem Lee archivo (sandboxed)
fs-write filesystem Escribe archivo (sandboxed)
clock Timestamp actual
http-get http GET request (fixture mode)

Sandbox

El filesystem está sandboxed — path traversal bloqueado:

python host.py app.jaja --allow fs-read,fs-write --root ./sandbox
# app.jaja NO puede leer fuera de ./sandbox

¿Es Turing completo?

Sí. Y la prueba se corre, no se cree: proofs/TURING.md .

Resumen:

  • JAJAJA es un algoritmo normal de Markov, no un sistema Thue. Lista ordenada de reglas, primera aplicable, ocurrencia más a la izquierda, parar cuando ninguna aplica. Ese modelo es Turing completo desde 1951.
  • Traducción mecánica MT → JAJAJA, uniforme: compile_tm toma una máquina de Turing arbitraria como datos. Verificada contra un simulador independiente en 7 casos, 0 fallos.
  • El alfabeto de risas también alcanza — pero con delimitador. Sin él la codificación unaria es ambigua: jaja es substring de jajaja, y el símbolo 2 concatenado con el 3 es indistinguible del 5. Medido: una regla del símbolo 2 se dispara dentro del símbolo 3.
$ python proofs/ja_encoding.py
OK binary_increment('1011') esperado '1100' -> en risas '1100'
OK bit_flip('1011') esperado '0100' -> en risas '0100'
 alfabeto de reglas y cinta: ['a', 'j']

Una máquina de Turing corriendo en risas puras: reglas, cinta y estados, sólo j y a.

Ejemplos

Archivo Qué hace
hola.jaja Hello, world!
amplificacion.jaja Amplificación de risa por etapas
eco.jaja Emite dos copias
loop.jaja Bucle infinito (MAX_STEPS)
calculator.jaja ADD 1 23 (JAJAJA computa, Python imprime)
echo.jaja Mismo archivo, 5 inputs diferentes → 5 outputs diferentes
command.jaja Router de comandos (hello→HELLO, bye→BYE)
structured.jaja Compute en base, emit al final

La trampa que vas a pisar

Si el rhs de una regla contiene su propio lhs, esa regla se dispara sobre su propio resultado para siempre:

jaja::=jajajaja # jajajaja CONTIENE jaja -> bucle infinito
jajajaja::=~jajajaja! # nunca se alcanza

Poné antes las reglas de lhs más largo. La §5.3 de la spec lo documenta con los dos casos, y el suite fija los dos como test — incluido el anti-ejemplo.

Backend LOLCODE (demo de composición)

JAJAJA puede targetear otros lenguajes. Demo: Python como único frontend, JAJAJA componiendo la petición, y LOLCODE (un lenguaje de bajo uso soportado por GitHub Linguist) como backend ejecutando la semántica con un runtime externo real (lci).

python demo_lolcode.py "ADD 2 3" # 5 (SUM OF lo calcula LOLCODE)
python demo_lolcode.py "MAX 9 4" # 9 (BIGGR OF + O RLY? branch)
python demo_lolcode.py "ECHO hola" # hola (string real)
python demo_lolcode.py "COUNT 3" # 3 2 1 0 (loop IM IN YR)

Why this backend? Para demostrar que la arquitectura no depende de un backend convencional, esta demo conecta el frontend Python con a low-usage language supported by GitHub Linguist: LOLCODE (19,904 archivos .lol indexados vs ~360 millones de .py, medido 2026年09月03日 vía GitHub Search API; ver evidence/lolcode_backend/LINGUIST_AUDIT.md). No afirmamos que sea "el menos usado de GitHub" — no existe ranking oficial y nuestra medición encontró lenguajes con menos archivos (Befunge, 228). El punto es la composición, no el récord.

Firma de honestidad del diseño:

  • La regla de route.jaja que matchea decide qué op corre. Sin esa reescritura no hay llamada al backend (prueba: "DIV 1 2" no emite nada).
  • Python nunca calcula el resultado: transporta y presenta.
  • Sin runtime externo instalado, el sistema falla ruidosamente — no hay fallback secreto que calcule en Python.
  • Docs y requisitos del runtime: backends/lolcode/README.md.

Tests

130 tests, sin framework:

python test_jajaja.py # 49 tests: intérprete + examples + runtime input + trace
python test_host.py # 51 tests: data model + host ABI + calculator + UI IR + FS
python test_backend_lolcode.py # 30 tests: backend LOLCODE (e2e requiere runtime externo; sin él se omite el e2e y se prueba el fallo limpio)

Cubren el intérprete, los ejemplos, CRLF, tolerancia del separador, runtime input, trace equivalence, structured output, host capabilities, filesystem sandbox, y UI IR. Los ejemplos de la spec se ejecutan y verifican contra el .md — si alguien edita un ejemplo sin actualizar su salida documentada, el suite se pone en rojo.

Arquitectura

JAJAJA Program (.jaja)
 ↓
Jajaja (Markov rewriter)
 ↓ rules produce EFFECT lines
Host IR (EFFECT/RESULT protocol)
 ↓
host.py (capability dispatcher)
 ↓
Capability adapters (stdin, stdout, kv, fs, http)
 ↓
RESULT injected back into base
 ↓
JAJAJA continues computing

JAJAJA decide qué effects requestear. host.py los ejecuta. Python no calcula la lógica de aplicación.

Licencia

MIT.

About

Esolang de reescritura de cadenas cuyo alfabeto son repeticiones del token 'ja'. Turing completo, con prueba ejecutable.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

AltStyle によって変換されたページ (->オリジナル) /