Jose Luis Montañes Ojados f2e90efc16 Add user-defined functions with call frames
Implement fn/return across the full pipeline:
- Lexer: TOK_FN, TOK_RETURN keywords
- Parser: NODE_FN_DEF, NODE_RETURN AST nodes
- Compiler: FunctionEntry table, inline compilation with jump-over and backpatching
- VM: CallFrame stack with variable snapshot for scoped calls and OP_RETURN
2026-02-18 03:16:54 +01:00
2026-02-15 20:48:01 +01:00
2026-02-15 20:48:01 +01:00
2026-02-15 22:12:19 +01:00

j-lang

Un proto-lenguaje con sintaxis inspirada en Python, implementado desde cero en C. El objetivo es aprender sobre gestion de memoria, tokenizacion, parsing y evaluacion de un lenguaje de programacion.

Estado actual

Las 5 fases del interprete estan implementadas y funcionando:

Codigo fuente (.j)
       |
   [LEXER]      src/frontend/lexer.h
       |
   Tokens
       |
   [PARSER]     src/frontend/parser.h
       |
   AST
       |
   [EVAL]       src/vm/eval.h
       |
   Ejecucion + GC

Que funciona

  • Variables y asignacion: x = 10
  • Aritmetica: +, -, *, / con enteros
  • Comparaciones: <, >
  • Strings: literales, concatenacion con +, len()
  • Control de flujo: if y while con bloques indentados (estilo Python)
  • Funciones built-in: print(), println(), len()
  • Llamadas a funciones con multiples argumentos separados por ,
  • Expresiones con parentesis: 2 * (4 - 2)
  • Numeros negativos: -300
  • Comentarios: // esto es un comentario

Ejemplo

x = 0
while x < 10:
    x = x + 1

if x > 9:
    println("fin")

Estructura del proyecto

src/
  frontend/
    lexer.h        Tokenizador: texto -> tokens
    parser.h       Parser: tokens -> AST
  memory/
    allocator.h    Memory allocator custom (heap simulado)
    gc.h           Garbage collector (mark-and-sweep)
  objects/
    object.h       Modelo de objetos (int, float, string, list)
  vm/
    eval.h         Evaluador: recorre el AST y ejecuta
  main.c           Punto de entrada
projects/            Scripts de ejemplo en .j
docs/
  roadmap.md       Roadmap detallado de implementacion

Memory allocator

Heap simulado sobre un array de bytes con metadatos por bloque (size, in_use, marked). Soporta asignacion, liberacion, reutilizacion de bloques libres (first-fit) y crecimiento automatico cuando se queda sin espacio.

Garbage collector

Mark-and-sweep: marca los objetos alcanzables desde las variables del environment, barre los no marcados y fusiona bloques libres contiguos.

Modelo de objetos

Los valores del lenguaje se representan como Object con tagged union. Tipos soportados: OBJ_INT, OBJ_FLOAT, OBJ_STRING, OBJ_LIST, OBJ_NONE. Los objetos viven en el heap custom y se referencian por offset (no punteros absolutos).

Compilar y ejecutar

gcc src/main.c -o run
./run projects/sum.j

Roadmap: que falta para hacer un juego 2D con JLang

Para poder escribir un juego 2D tipo "mover un personaje por pantalla, disparar, colisiones" con JLang, harian falta estos bloques:

1. Funciones de usuario

Lo mas urgente. Sin funciones no se puede organizar nada.

fn update(dt):
    player_x = player_x + speed * dt

fn draw():
    draw_rect(player_x, player_y, 32, 32)

Implica: nuevo token fn, nodo NODE_FUNC_DEF en el AST, almacenar el cuerpo de la funcion en el environment, y un mecanismo de scopes (variables locales vs globales).

2. Return

Las funciones necesitan devolver valores.

fn distance(x1, y1, x2, y2):
    dx = x1 - x2
    dy = y1 - y2
    return sqrt(dx * dx + dy * dy)

3. Structs o clases

Para representar entidades del juego (jugador, enemigos, balas...).

class Entity:
    x = 0
    y = 0
    w = 32
    h = 32

player = Entity()
player.x = 100
player.y = 200

Implica: acceso a campos con ., constructor, almacenar la definicion de la clase como un objeto mas en el heap.

4. Listas funcionales

Las listas ya existen como tipo (OBJ_LIST) pero no hay sintaxis para usarlas. Se necesitan para manejar colecciones de entidades.

enemies = [Enemy(), Enemy(), Enemy()]
append(enemies, Enemy())
i = 0
while i < len(enemies):
    update(enemies[i])
    i = i + 1

Implica: sintaxis [...], acceso por indice lista[i], append(), len() para listas.

5. Else / elif

Imprescindible para logica de juego.

if key == "left":
    player_x = player_x - speed
elif key == "right":
    player_x = player_x + speed
else:
    speed = 0

6. For loops

Iterar de forma mas limpia que con while.

for enemy in enemies:
    draw_rect(enemy.x, enemy.y, enemy.w, enemy.h)

7. Operadores que faltan

  • % (modulo) - util para animaciones ciclicas, wrapping
  • ==, != (ya tokenizados pero no evaluados completamente)
  • <=, >=
  • and, or, not - operadores logicos
  • +=, -= - azucar sintactico

8. Floats funcionales

El tipo OBJ_FLOAT existe pero no se puede usar desde el lenguaje. Para un juego se necesita aritmetica de punto flotante para posiciones, velocidades, delta time, etc.

player_x = 100.0
speed = 2.5
player_x = player_x + speed * dt

9. Libreria grafica (FFI a C)

El punto critico. JLang necesita poder llamar a una libreria grafica en C como SDL2 o raylib. Hay dos caminos:

Opcion A: Built-in functions (mas facil) Registrar funciones C directamente en el evaluador, como ya se hace con print:

// En el eval, junto a print/println:
if (strcmp(name, "draw_rect") == 0) { SDL_RenderFillRect(...); }
if (strcmp(name, "key_pressed") == 0) { ... }

Opcion B: FFI generico (mas ambicioso) Un sistema para enlazar funciones C arbitrarias desde JLang.

Las funciones minimas para un juego serian:

Funcion Descripcion
create_window(w, h, title) Crear ventana
clear() Limpiar pantalla
draw_rect(x, y, w, h, r, g, b) Dibujar rectangulo
draw_image(path, x, y) Dibujar imagen/sprite
present() Mostrar frame
key_pressed(key) Consultar tecla
get_dt() Delta time entre frames
random(min, max) Numero aleatorio

10. Funciones matematicas

sqrt(), sin(), cos(), abs(), random(). Todas se pueden registrar como built-ins que llamen a math.h.

Orden sugerido de implementacion

 1. Funciones de usuario + return    (sin esto no se puede hacer nada)
 2. Else / elif
 3. Floats funcionales
 4. Operadores que faltan (%, <=, >=, and, or)
 5. Listas con sintaxis ([], indexado, append)
 6. For loops
 7. Structs o clases
 8. Built-ins graficos (SDL2/raylib)
 9. Funciones matematicas
10. Juego 2D funcional

Los pasos 1-7 son trabajo puro de lenguaje (lexer/parser/eval). El paso 8 es donde JLang toca el mundo real: linkear con SDL2 o raylib a la hora de compilar y exponer las funciones como built-ins en el evaluador.

Description
No description provided
Readme 166 KiB
Languages
C 98.9%
Objective-J 1%