From 74b426e12db7ffbe9ecfdc4fecbdd9a3332bf887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Luis=20Monta=C3=B1es=20Ojados?= Date: Sun, 15 Feb 2026 20:48:01 +0100 Subject: [PATCH] first commit --- build.bat | 1 + docs/roadmap.md | 448 ++++++++++++++++++++++++++++++++++++++++++++++ projects/simple.j | 1 + readme.md | 52 ++++++ run.exe | Bin 0 -> 62989 bytes src/main.c | 3 + 6 files changed, 505 insertions(+) create mode 100644 build.bat create mode 100644 docs/roadmap.md create mode 100644 projects/simple.j create mode 100644 readme.md create mode 100644 run.exe create mode 100644 src/main.c diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..c4d59aa --- /dev/null +++ b/build.bat @@ -0,0 +1 @@ +gcc -o run.exe src\main.c \ No newline at end of file diff --git a/docs/roadmap.md b/docs/roadmap.md new file mode 100644 index 0000000..ddff5b6 --- /dev/null +++ b/docs/roadmap.md @@ -0,0 +1,448 @@ +# j-lang: Roadmap detallado + +Guia de implementacion fase por fase. Cada fase construye sobre la anterior. + +``` +src/ + memory/ -> Fase 1 y 5 + objects/ -> Fase 2 + frontend/ -> Fase 3 + vm/ -> Fase 4 + main.c -> Punto de entrada (une todo) +``` + +--- + +## Fase 1: Gestion de Memoria + +**Objetivo:** Tener un `malloc` y `free` propios que gestionen un heap simulado con metadatos compactos. + +**Archivos:** `src/memory/allocator.h` + +**Estado actual:** Ya existe una implementacion en `mem-heap/src/allocator.h` con: +- `CMA_metadata` (struct con `size` y `in_use`) +- `CMA_CreateAllocator()` - crea un heap de 1KB +- `CMA_malloc()` - asigna bloques (solo append, no reutiliza huecos) +- `CMA_used()` - calcula bytes usados +- `CMA_last_free()` - encuentra el primer bloque libre +- `CMA_visualize()` - dibuja el heap en consola con colores + +### Tareas + +#### 1.1 Copiar allocator al proyecto +- Copiar `mem-heap/src/allocator.h` a `src/memory/allocator.h` +- Verificar que compila desde `main.c` con `#include "memory/allocator.h"` + +#### 1.2 Implementar `CMA_free` +Liberar un bloque marcandolo como no-usado. + +```c +// Firma +void CMA_free(void *allocator, void *ptr); + +// Logica: +// 1. ptr apunta al payload, retroceder sizeof(CMA_metadata) para llegar al header +// 2. Poner header->in_use = 0 +// 3. Opcionalmente: poner a cero los bytes del payload (memset) +``` + +#### 1.3 Reutilizar bloques liberados (first-fit) +Actualmente `CMA_malloc` solo hace append al final. Hay que recorrer el heap buscando bloques libres que quepan. + +```c +// En CMA_malloc, antes de ir al final: +// 1. Recorrer bloques desde el inicio +// 2. Si encuentras uno con in_use == 0 && size >= requested_size -> reutilizarlo +// 3. Si no hay ninguno, seguir con el append actual +``` + +#### 1.4 Compactar la cabecera (opcional, mejora) +El readme menciona compactar Size + Marked + InUse en menos bytes. La idea: +- Usar bitfields o empaquetar en un `uint32_t`: + - Bits 0-29: size (hasta ~1GB) + - Bit 30: marked (para el GC, Fase 5) + - Bit 31: in_use + +```c +typedef struct { + uint32_t header; // size:30 | marked:1 | in_use:1 +} CMA_metadata_compact; + +#define META_SIZE(h) ((h).header >> 2) +#define META_MARKED(h) (((h).header >> 1) & 1) +#define META_INUSE(h) ((h).header & 1) +``` + +### Criterio de terminado +- `CMA_malloc` asigna bloques correctamente +- `CMA_free` libera bloques +- `CMA_malloc` reutiliza bloques liberados +- `CMA_visualize` muestra bloques libres vs ocupados correctamente +- Test: malloc -> free -> malloc reutiliza el mismo espacio + +--- + +## Fase 2: Modelo de Objetos + +**Objetivo:** Definir como se representan los valores del lenguaje (numeros, strings, listas) en memoria C. + +**Archivos:** `src/objects/object.h` + +**Dependencias:** Fase 1 (los objetos se crean con `CMA_malloc`) + +### Tareas + +#### 2.1 Definir los tipos + +```c +typedef enum { + OBJ_INT, + OBJ_FLOAT, + OBJ_STRING, + OBJ_LIST, + OBJ_NONE // equivalente a None/null +} ObjectType; +``` + +#### 2.2 Definir el struct Object + +Enfoque con tagged union: + +```c +typedef struct Object { + ObjectType type; + union { + int int_val; // OBJ_INT + double float_val; // OBJ_FLOAT + struct { // OBJ_STRING + char *chars; + int length; + } string_val; + struct { // OBJ_LIST + struct Object **items; + int count; + int capacity; + } list_val; + } data; +} Object; +``` + +#### 2.3 Funciones constructoras + +Cada tipo necesita una funcion que cree el objeto usando el allocator: + +```c +Object* obj_new_int(void *allocator, int value); +Object* obj_new_string(void *allocator, const char *str); +Object* obj_new_list(void *allocator); +``` + +#### 2.4 Funcion de impresion + +```c +void obj_print(Object *obj); +// OBJ_INT -> printf("%d", obj->data.int_val) +// OBJ_STRING -> printf("%s", obj->data.string_val.chars) +// OBJ_LIST -> printf("["); ...cada elemento...; printf("]") +``` + +### Criterio de terminado +- Se pueden crear objetos de cada tipo con el allocator +- `obj_print` los muestra correctamente +- Test: crear int(42), string("hola"), lista con ambos, imprimir todo + +--- + +## Fase 3: Front-End (Lexer y Parser) + +**Objetivo:** Convertir texto fuente (`.j`) en un AST que la VM pueda ejecutar. + +**Archivos:** `src/frontend/lexer.h`, `src/frontend/parser.h` + +**Dependencias:** Fase 2 (el parser crea nodos AST que referencian tipos de Object) + +### Tareas + +#### 3.1 Lexer (Tokenizador) + +Convierte texto en una lista de tokens. + +```c +typedef enum { + // Literales + TOK_INT, // 42 + TOK_STRING, // "hola" + + // Identificadores y keywords + TOK_ID, // x, foo, mi_var + TOK_PRINT, // print (keyword) + TOK_IF, // if + TOK_WHILE, // while + + // Operadores + TOK_ASSIGN, // = + TOK_PLUS, // + + TOK_MINUS, // - + TOK_STAR, // * + TOK_SLASH, // / + TOK_EQ, // == + TOK_NEQ, // != + TOK_LT, // < + TOK_GT, // > + + // Delimitadores + TOK_LPAREN, // ( + TOK_RPAREN, // ) + TOK_COLON, // : + TOK_NEWLINE, // \n (significativo, como en Python) + TOK_INDENT, // aumento de indentacion + TOK_DEDENT, // reduccion de indentacion + + TOK_EOF +} TokenType; + +typedef struct { + TokenType type; + char *value; // texto literal del token + int line; // linea del fuente (para errores) +} Token; + +// Firma principal +Token* tokenize(const char *source, int *token_count); +``` + +Empezar simple: solo `TOK_INT`, `TOK_ID`, `TOK_ASSIGN`, `TOK_NEWLINE`, `TOK_EOF`. Ir agregando tokens conforme se necesiten. + +#### 3.2 Parser (AST) + +Convierte tokens en un arbol. + +```c +typedef enum { + NODE_INT_LIT, // literal entero: 42 + NODE_STRING_LIT, // literal string: "hola" + NODE_VAR, // referencia a variable: x + NODE_ASSIGN, // asignacion: x = expr + NODE_BINOP, // operacion binaria: a + b + NODE_PRINT, // print(expr) + NODE_IF, // if cond: bloque + NODE_WHILE, // while cond: bloque + NODE_BLOCK, // secuencia de statements +} NodeType; + +typedef struct ASTNode { + NodeType type; + union { + int int_val; // NODE_INT_LIT + char *string_val; // NODE_STRING_LIT, NODE_VAR + struct { char *name; struct ASTNode *value; } assign; // NODE_ASSIGN + struct { char op; struct ASTNode *left; struct ASTNode *right; } binop; // NODE_BINOP + struct { struct ASTNode *expr; } print; // NODE_PRINT + struct { struct ASTNode **stmts; int count; } block; // NODE_BLOCK + } data; +} ASTNode; + +// Firma principal +ASTNode* parse(Token *tokens, int token_count); +``` + +#### 3.3 Gramatica minima inicial + +Empezar con un subconjunto muy pequeno: + +``` +programa = { statement NEWLINE } +statement = ID "=" expr (asignacion) + | "print" expr (impresion) +expr = term { ("+" | "-") term } +term = INT | ID +``` + +Esto permite ejecutar cosas como: +``` +x = 10 +y = 20 +z = x + y +print z +``` + +### Criterio de terminado +- El lexer tokeniza `x = 10\nprint x` correctamente +- El parser genera un AST valido a partir de esos tokens +- Test: tokenizar y parsear `simple.j`, imprimir el arbol resultante + +--- + +## Fase 4: Evaluador / VM + +**Objetivo:** Recorrer el AST y ejecutar las instrucciones. + +**Archivos:** `src/vm/eval.h` + +**Dependencias:** Fase 2 (crea Objects), Fase 3 (recibe un AST) + +### Tareas + +#### 4.1 Tabla de variables (Environment) + +```c +typedef struct { + char *name; + Object *value; +} Variable; + +typedef struct { + Variable vars[256]; // simple, tamanio fijo por ahora + int count; +} Environment; + +// Buscar o crear variable +Object* env_get(Environment *env, const char *name); +void env_set(Environment *env, const char *name, Object *value); +``` + +#### 4.2 Funcion eval recursiva + +```c +Object* eval(ASTNode *node, Environment *env, void *allocator); + +// Logica por tipo de nodo: +// NODE_INT_LIT -> obj_new_int(allocator, node->data.int_val) +// NODE_VAR -> env_get(env, node->data.string_val) +// NODE_ASSIGN -> evaluar valor, env_set(name, resultado) +// NODE_BINOP -> evaluar left y right, operar segun op +// NODE_PRINT -> evaluar expr, obj_print(resultado) +// NODE_BLOCK -> evaluar cada statement en orden +``` + +#### 4.3 Flujo completo en main.c + +```c +int main(int argc, char *argv[]) { + // 1. Leer archivo .j + char *source = read_file(argv[1]); + + // 2. Tokenizar + int token_count; + Token *tokens = tokenize(source, &token_count); + + // 3. Parsear + ASTNode *program = parse(tokens, token_count); + + // 4. Ejecutar + void *allocator = CMA_CreateAllocator(); + Environment env = {0}; + eval(program, &env, allocator); + + return 0; +} +``` + +### Criterio de terminado +- `simple.j` con `x = 1` se ejecuta sin errores +- Un script con `x = 10\ny = 20\nprint x + y` imprime `30` +- Las variables se almacenan y recuperan correctamente + +--- + +## Fase 5: Recolector de Basura (GC) + +**Objetivo:** Liberar automaticamente objetos que ya no son accesibles. + +**Archivos:** `src/memory/gc.h` + +**Dependencias:** Fase 1 (usa `CMA_free`), Fase 2 (recorre Objects), Fase 4 (accede al Environment) + +### Tareas + +#### 5.1 Agregar bit `marked` al metadata + +Si se compacto la cabecera en Fase 1.4, ya esta. Si no, agregar un campo: + +```c +typedef struct { + size_t size; + int in_use; + int marked; // <-- nuevo +} CMA_metadata; +``` + +#### 5.2 Mark (Marcar) + +Recorrer todos los objetos alcanzables desde las variables del Environment y marcarlos. + +```c +void gc_mark_object(Object *obj); +// 1. Obtener el header del objeto (retroceder sizeof(CMA_metadata)) +// 2. Poner marked = 1 +// 3. Si es OBJ_LIST, marcar recursivamente cada elemento +// 4. Si es OBJ_STRING, marcar el buffer de chars + +void gc_mark(Environment *env); +// Para cada variable en env: gc_mark_object(variable.value) +``` + +#### 5.3 Sweep (Barrer) + +Recorrer todo el heap linealmente. Si un bloque tiene `in_use == 1` y `marked == 0`, liberarlo. + +```c +void gc_sweep(void *allocator); +// 1. Empezar desde el inicio del heap +// 2. Para cada bloque: +// - Si in_use && !marked -> CMA_free +// - Si marked -> quitar marked (resetear para el proximo ciclo) +// 3. Avanzar al siguiente bloque con (header + sizeof(CMA_metadata) + size) +``` + +#### 5.4 Integrar con el evaluador + +```c +// En eval(), despues de N asignaciones o cuando quede poca memoria: +void gc_collect(void *allocator, Environment *env) { + gc_mark(env); + gc_sweep(allocator); +} +``` + +### Criterio de terminado +- Crear objetos, perder la referencia, ejecutar GC -> la memoria se libera +- `CMA_visualize` muestra bloques liberados tras el GC +- Test: crear 100 objetos en un loop, verificar que la memoria no crece indefinidamente + +--- + +## Orden de implementacion recomendado + +``` +Fase 1.1 (copiar allocator) + | +Fase 1.2 (CMA_free) + | +Fase 1.3 (reutilizar bloques) + | +Fase 2 (model de objetos) + | +Fase 3.1 (lexer basico) + | +Fase 3.2 (parser basico) + | +Fase 4 (eval + main.c) <- aqui ya puedes ejecutar simple.j + | +Fase 1.4 (compactar cabecera) <- opcional, mejora + | +Fase 5 (GC) +``` + +## Test de integracion final + +Cuando todo este listo, este script deberia funcionar: + +```python +x = 10 +y = 20 +z = x + y +print z +``` + +Salida esperada: `30` diff --git a/projects/simple.j b/projects/simple.j new file mode 100644 index 0000000..3d2b4b1 --- /dev/null +++ b/projects/simple.j @@ -0,0 +1 @@ +x = 1 \ No newline at end of file diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..66587ce --- /dev/null +++ b/readme.md @@ -0,0 +1,52 @@ +# j-lang + +La idea de j-lang es crear un "proto-lenguaje" parecido a python pero implementado desde 0 para validar y aprender más sobre la gestión de memoria. + +Actualmente en `mem-heap\src\allocator.h` ya hay una implementeción de un Memory Allocator casi funcional. + +## 🗺️ Hoja de Ruta: Proyecto Proto-Lenguaje +Esta ruta va desde lo más bajo (la memoria) hasta lo más alto (ejecutar código). + +### Fase 1: El Cimiento (Gestión de Memoria) 🏗️ +Objetivo: Tener un malloc y free propios que gestionen metadatos compactos. + +Estado: ¡Ya estás aquí! + +Tareas clave: +- [ ] Terminar CMA_malloc con la cabecera compactada (Size + Marked + InUse). +- [ ] Implementar una función CMA_free que pueda liberar un bloque específico. + +### Fase 2: El Modelo de Objetos (Object Model) 📦 +Objetivo: Definir cómo se ve un número, una cadena o una lista dentro de tu memoria C. +Conexión: Cada objeto de tu lenguaje será un struct en C que comienza con tu CMA_metadata. + +Tareas clave: +- [ ] Crear un enum para los tipos (ENTERO, STRING, LISTA). +- [ ] Definir el struct Object genérico que envuelve tus datos. + +### Fase 3: El Front-End (Lexer y Parser) 📖 +Objetivo: Convertir el texto del código fuente en algo que C entienda. + +Tareas clave: +- [ ] Lexer (Tokenizador): Romper el texto x = 10 en fichas: [ID:x], [OP:=], [NUM:10]. +- [ ] Parser: Organizar esas fichas en un Árbol de Sintaxis Abstracta (AST). Por ejemplo, un nodo "Asignación" que tiene un hijo "x" y otro "10". + +### Fase 4: El Motor (Evaluador o VM) ⚙️ +Objetivo: Recorrer el árbol y "hacer" lo que dice. + +Tareas clave: +- [ ] Crear una función recursiva eval(nodo) que ejecute la lógica. + +Si es un nodo SUMA, suma los hijos. Si es un nodo IMPRIMIR, muestra en pantalla. + +### Fase 5: El Recolector de Basura (Garbage Collector) 🧹 +Objetivo: Automatizar la limpieza. + +Tareas clave: +- [ ] Implementar Mark (Marcar): Recorrer todos los objetos accesibles desde tus variables y poner el bit Marked a 1. +- [ ] Implementar Sweep (Barrer): Recorrer todo el heap linealmente (usando tu función next_block). Si un bloque tiene Marked == 0 y InUse == 1, llamar a CMA_free. + +## Estructura del proyecto + +- vm: maquina virtual de j-lang +- projects: carpeta con scripts en j-lang \ No newline at end of file diff --git a/run.exe b/run.exe new file mode 100644 index 0000000000000000000000000000000000000000..ec0091b12729805ff3a4a4ea44ffa546900fa913 GIT binary patch literal 62989 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 X57#-AW20!B2x(ZWIakCNE4u!_G)O&{ literal 0 HcmV?d00001 diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..e9cdae1 --- /dev/null +++ b/src/main.c @@ -0,0 +1,3 @@ +int main() { + return 0; +} \ No newline at end of file