Add while loops, GC mark-and-sweep, and malloc block reuse
- Lexer: add INDENT/DEDENT tokens, <, >, : operators, while keyword,
closing DEDENT emission, include guards
- Parser: add NODE_WHILE with while_loop union, parse while/cond/body
blocks, include guards
- Eval: add while loop evaluation, GC integration with roots from env,
debug and gc flags, <, > comparison operators
- GC: implement mark-and-sweep collector with 3 stages (mark roots,
sweep unmarked, join free blocks)
- Allocator: block reuse via first-fit search with splitting, exponential
heap growth, NULL check on malloc, include guards, marked field in metadata
- Object: add include guards, fix include to use allocator.h
2026-02-16 04:55:52 +01:00
|
|
|
#ifndef JLANG_ALLOCATOR_H
|
|
|
|
|
#define JLANG_ALLOCATOR_H
|
|
|
|
|
|
2026-02-15 20:57:19 +01:00
|
|
|
#include <stdio.h>
|
2026-02-15 22:12:19 +01:00
|
|
|
#include <stdlib.h>
|
2026-02-15 20:57:19 +01:00
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Custom Memory Allocator
|
|
|
|
|
|
2026-02-15 22:12:19 +01:00
|
|
|
Implementacion custom de un memory allocator que opera sobre un array de
|
|
|
|
|
bytes usandolo como "heap"
|
2026-02-15 20:57:19 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#define JLANG_OK 0
|
|
|
|
|
#define JLANG_ERR 1
|
|
|
|
|
#define JLANG_FREE 0
|
|
|
|
|
#define JLANG_HEADER 1
|
|
|
|
|
#define JLANG_PAYLOAD 2
|
2026-02-16 00:33:02 +01:00
|
|
|
#define JLANG_NOT_USE 3
|
2026-02-15 20:57:19 +01:00
|
|
|
|
|
|
|
|
/*
|
2026-02-15 22:12:19 +01:00
|
|
|
La estructura de Metadata se encarga de almacenar el tamaño del bloque y si
|
|
|
|
|
está en uso. Se añadirá al principio de cada bloque [BLOCK_METADATA] +
|
|
|
|
|
[BLOCK_BYTES]
|
2026-02-15 20:57:19 +01:00
|
|
|
*/
|
2026-02-15 22:12:19 +01:00
|
|
|
typedef struct {
|
|
|
|
|
size_t size; // 8 bytes
|
|
|
|
|
int in_use; // 4 bytes
|
Add while loops, GC mark-and-sweep, and malloc block reuse
- Lexer: add INDENT/DEDENT tokens, <, >, : operators, while keyword,
closing DEDENT emission, include guards
- Parser: add NODE_WHILE with while_loop union, parse while/cond/body
blocks, include guards
- Eval: add while loop evaluation, GC integration with roots from env,
debug and gc flags, <, > comparison operators
- GC: implement mark-and-sweep collector with 3 stages (mark roots,
sweep unmarked, join free blocks)
- Allocator: block reuse via first-fit search with splitting, exponential
heap growth, NULL check on malloc, include guards, marked field in metadata
- Object: add include guards, fix include to use allocator.h
2026-02-16 04:55:52 +01:00
|
|
|
int marked; // 4 bytes
|
2026-02-15 20:57:19 +01:00
|
|
|
} JLANG_metadata;
|
|
|
|
|
|
|
|
|
|
/*
|
2026-02-15 22:12:19 +01:00
|
|
|
La estructura de Memory Allocator se encarga de almancenar el array de
|
|
|
|
|
memoria y el tamaño de esta.
|
2026-02-15 20:57:19 +01:00
|
|
|
*/
|
2026-02-15 22:12:19 +01:00
|
|
|
typedef struct {
|
|
|
|
|
char *memory; // 8 bytes
|
|
|
|
|
size_t size; // 8 bytes
|
2026-02-15 20:57:19 +01:00
|
|
|
} JLANG_memory_allocator;
|
|
|
|
|
|
2026-02-15 22:12:19 +01:00
|
|
|
void *JLANG_CreateAllocator() {
|
|
|
|
|
// Allocate memory in heap for JLANG_memory_allocator
|
|
|
|
|
JLANG_memory_allocator *allocator =
|
|
|
|
|
(JLANG_memory_allocator *)malloc(sizeof(JLANG_memory_allocator));
|
2026-02-15 20:57:19 +01:00
|
|
|
|
2026-02-15 22:12:19 +01:00
|
|
|
// Assign default free bytes
|
|
|
|
|
allocator->memory = (char *)malloc(1 * 1024);
|
|
|
|
|
allocator->size = 1 * 1024;
|
2026-02-15 20:57:19 +01:00
|
|
|
|
2026-02-15 22:12:19 +01:00
|
|
|
// ensure all memory is zero
|
2026-02-16 05:16:41 +01:00
|
|
|
memset(allocator->memory, 0, 1024);
|
2026-02-15 20:57:19 +01:00
|
|
|
|
2026-02-15 22:12:19 +01:00
|
|
|
return allocator;
|
2026-02-15 20:57:19 +01:00
|
|
|
}
|
|
|
|
|
|
2026-02-15 22:12:19 +01:00
|
|
|
size_t JLANG_used(void *ptr) {
|
|
|
|
|
JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr;
|
2026-02-15 20:57:19 +01:00
|
|
|
|
2026-02-15 22:12:19 +01:00
|
|
|
// Iterate memory parsing only metadata
|
|
|
|
|
JLANG_metadata *currentHeader = (JLANG_metadata *)allocPtr->memory;
|
|
|
|
|
size_t used = 0;
|
2026-02-15 23:16:45 +01:00
|
|
|
while (currentHeader->size != 0 && used < allocPtr->size) {
|
2026-02-15 22:12:19 +01:00
|
|
|
used += sizeof(JLANG_metadata) + currentHeader->size;
|
2026-02-15 20:57:19 +01:00
|
|
|
|
2026-02-15 22:12:19 +01:00
|
|
|
// Current block is in_use, jump to next block
|
|
|
|
|
currentHeader =
|
|
|
|
|
(JLANG_metadata *)((char *)currentHeader + sizeof(JLANG_metadata) +
|
|
|
|
|
currentHeader->size);
|
|
|
|
|
}
|
2026-02-15 20:57:19 +01:00
|
|
|
|
2026-02-15 22:12:19 +01:00
|
|
|
return used;
|
2026-02-15 20:57:19 +01:00
|
|
|
}
|
|
|
|
|
|
2026-02-15 22:12:19 +01:00
|
|
|
void *JLANG_last_free(void *ptr) {
|
|
|
|
|
JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr;
|
2026-02-15 20:57:19 +01:00
|
|
|
|
2026-02-15 22:12:19 +01:00
|
|
|
// Iterate memory parsing only metadata
|
|
|
|
|
JLANG_metadata *currentHeader = (JLANG_metadata *)allocPtr->memory;
|
|
|
|
|
size_t used = 0;
|
2026-02-15 23:16:45 +01:00
|
|
|
while (currentHeader->size != 0 && used < allocPtr->size) {
|
2026-02-15 22:12:19 +01:00
|
|
|
used += sizeof(JLANG_metadata) + currentHeader->size;
|
2026-02-15 20:57:19 +01:00
|
|
|
|
2026-02-15 22:12:19 +01:00
|
|
|
// Current block is in_use, jump to next block
|
|
|
|
|
currentHeader =
|
|
|
|
|
(JLANG_metadata *)((char *)currentHeader + sizeof(JLANG_metadata) +
|
|
|
|
|
currentHeader->size);
|
|
|
|
|
}
|
2026-02-15 20:57:19 +01:00
|
|
|
|
2026-02-15 22:12:19 +01:00
|
|
|
return currentHeader;
|
2026-02-15 20:57:19 +01:00
|
|
|
}
|
|
|
|
|
|
2026-02-15 23:16:45 +01:00
|
|
|
// JLANG_malloc devuelve un offset a la memoria del heap. No un absoluto a la
|
|
|
|
|
// memoria del proceso
|
|
|
|
|
size_t JLANG_malloc(void *ptr, size_t size) {
|
2026-02-15 22:12:19 +01:00
|
|
|
JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr;
|
2026-02-15 20:57:19 +01:00
|
|
|
|
Add while loops, GC mark-and-sweep, and malloc block reuse
- Lexer: add INDENT/DEDENT tokens, <, >, : operators, while keyword,
closing DEDENT emission, include guards
- Parser: add NODE_WHILE with while_loop union, parse while/cond/body
blocks, include guards
- Eval: add while loop evaluation, GC integration with roots from env,
debug and gc flags, <, > comparison operators
- GC: implement mark-and-sweep collector with 3 stages (mark roots,
sweep unmarked, join free blocks)
- Allocator: block reuse via first-fit search with splitting, exponential
heap growth, NULL check on malloc, include guards, marked field in metadata
- Object: add include guards, fix include to use allocator.h
2026-02-16 04:55:52 +01:00
|
|
|
// Recorrer memoria hasta encontrar un hueco libre
|
|
|
|
|
JLANG_metadata *currentHead = (JLANG_metadata *)allocPtr->memory;
|
|
|
|
|
size_t used = 0;
|
|
|
|
|
while (1) {
|
|
|
|
|
used += currentHead->size;
|
2026-02-15 20:57:19 +01:00
|
|
|
|
Add while loops, GC mark-and-sweep, and malloc block reuse
- Lexer: add INDENT/DEDENT tokens, <, >, : operators, while keyword,
closing DEDENT emission, include guards
- Parser: add NODE_WHILE with while_loop union, parse while/cond/body
blocks, include guards
- Eval: add while loop evaluation, GC integration with roots from env,
debug and gc flags, <, > comparison operators
- GC: implement mark-and-sweep collector with 3 stages (mark roots,
sweep unmarked, join free blocks)
- Allocator: block reuse via first-fit search with splitting, exponential
heap growth, NULL check on malloc, include guards, marked field in metadata
- Object: add include guards, fix include to use allocator.h
2026-02-16 04:55:52 +01:00
|
|
|
if (currentHead->in_use == 0 && currentHead->size >= size) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
2026-02-15 20:57:19 +01:00
|
|
|
|
Add while loops, GC mark-and-sweep, and malloc block reuse
- Lexer: add INDENT/DEDENT tokens, <, >, : operators, while keyword,
closing DEDENT emission, include guards
- Parser: add NODE_WHILE with while_loop union, parse while/cond/body
blocks, include guards
- Eval: add while loop evaluation, GC integration with roots from env,
debug and gc flags, <, > comparison operators
- GC: implement mark-and-sweep collector with 3 stages (mark roots,
sweep unmarked, join free blocks)
- Allocator: block reuse via first-fit search with splitting, exponential
heap growth, NULL check on malloc, include guards, marked field in metadata
- Object: add include guards, fix include to use allocator.h
2026-02-16 04:55:52 +01:00
|
|
|
if (currentHead->size == 0) {
|
|
|
|
|
size_t offset = (char *)currentHead - allocPtr->memory;
|
|
|
|
|
if (offset + sizeof(JLANG_metadata) + size > allocPtr->size) {
|
|
|
|
|
// No cabe, grow
|
|
|
|
|
size_t newSize = allocPtr->size * 2;
|
|
|
|
|
// asegurar que quepa la peticion
|
|
|
|
|
while (newSize < offset + sizeof(JLANG_metadata) + size) {
|
|
|
|
|
newSize *= 2;
|
|
|
|
|
}
|
2026-02-15 23:16:45 +01:00
|
|
|
|
Add while loops, GC mark-and-sweep, and malloc block reuse
- Lexer: add INDENT/DEDENT tokens, <, >, : operators, while keyword,
closing DEDENT emission, include guards
- Parser: add NODE_WHILE with while_loop union, parse while/cond/body
blocks, include guards
- Eval: add while loop evaluation, GC integration with roots from env,
debug and gc flags, <, > comparison operators
- GC: implement mark-and-sweep collector with 3 stages (mark roots,
sweep unmarked, join free blocks)
- Allocator: block reuse via first-fit search with splitting, exponential
heap growth, NULL check on malloc, include guards, marked field in metadata
- Object: add include guards, fix include to use allocator.h
2026-02-16 04:55:52 +01:00
|
|
|
char *newBuffer = (char *)malloc(newSize); // pedir newSize bytes
|
|
|
|
|
if (newBuffer == NULL) {
|
|
|
|
|
printf("ERROR: out of memory\n");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
memset(newBuffer, 0, newSize);
|
|
|
|
|
memcpy(newBuffer, allocPtr->memory,
|
|
|
|
|
allocPtr->size); // Copiamos al nuevo buffer
|
|
|
|
|
|
|
|
|
|
allocPtr->size = newSize;
|
|
|
|
|
|
|
|
|
|
free(allocPtr->memory); // Liberamos el buffer antiguo
|
|
|
|
|
allocPtr->memory = newBuffer; // Seteamos el nuevo buffer
|
|
|
|
|
|
|
|
|
|
JLANG_metadata *freeHeader =
|
|
|
|
|
(JLANG_metadata *)(allocPtr->memory + offset);
|
|
|
|
|
freeHeader->size = size;
|
|
|
|
|
freeHeader->in_use = 1;
|
|
|
|
|
|
|
|
|
|
void *payloadPtr = (char *)freeHeader + sizeof(JLANG_metadata);
|
|
|
|
|
return (char *)payloadPtr - allocPtr->memory;
|
|
|
|
|
}
|
|
|
|
|
// Fin del heap, asignar aqui
|
|
|
|
|
currentHead->size = size;
|
|
|
|
|
currentHead->in_use = 1;
|
|
|
|
|
return (char *)currentHead - allocPtr->memory + sizeof(JLANG_metadata);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Go next
|
|
|
|
|
currentHead =
|
|
|
|
|
(JLANG_metadata *)((char *)currentHead + sizeof(JLANG_metadata) +
|
|
|
|
|
currentHead->size);
|
2026-02-15 22:12:19 +01:00
|
|
|
}
|
2026-02-15 20:57:19 +01:00
|
|
|
|
Add while loops, GC mark-and-sweep, and malloc block reuse
- Lexer: add INDENT/DEDENT tokens, <, >, : operators, while keyword,
closing DEDENT emission, include guards
- Parser: add NODE_WHILE with while_loop union, parse while/cond/body
blocks, include guards
- Eval: add while loop evaluation, GC integration with roots from env,
debug and gc flags, <, > comparison operators
- GC: implement mark-and-sweep collector with 3 stages (mark roots,
sweep unmarked, join free blocks)
- Allocator: block reuse via first-fit search with splitting, exponential
heap growth, NULL check on malloc, include guards, marked field in metadata
- Object: add include guards, fix include to use allocator.h
2026-02-16 04:55:52 +01:00
|
|
|
// currentHead tiene sitio para nosotros, particionamos y usamos
|
|
|
|
|
currentHead->in_use = 1;
|
|
|
|
|
size_t oldSize = currentHead->size;
|
|
|
|
|
currentHead->size = size;
|
|
|
|
|
|
|
|
|
|
if (oldSize > size + sizeof(JLANG_metadata)) {
|
|
|
|
|
// creamos un bloque vacio con los bytes que sobran
|
|
|
|
|
JLANG_metadata *emptyBlock =
|
|
|
|
|
(JLANG_metadata *)((char *)currentHead + sizeof(JLANG_metadata) + size);
|
|
|
|
|
emptyBlock->size = oldSize - size - sizeof(JLANG_metadata);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (char *)currentHead - allocPtr->memory + sizeof(JLANG_metadata);
|
|
|
|
|
|
2026-02-15 23:16:45 +01:00
|
|
|
/*
|
Add while loops, GC mark-and-sweep, and malloc block reuse
- Lexer: add INDENT/DEDENT tokens, <, >, : operators, while keyword,
closing DEDENT emission, include guards
- Parser: add NODE_WHILE with while_loop union, parse while/cond/body
blocks, include guards
- Eval: add while loop evaluation, GC integration with roots from env,
debug and gc flags, <, > comparison operators
- GC: implement mark-and-sweep collector with 3 stages (mark roots,
sweep unmarked, join free blocks)
- Allocator: block reuse via first-fit search with splitting, exponential
heap growth, NULL check on malloc, include guards, marked field in metadata
- Object: add include guards, fix include to use allocator.h
2026-02-16 04:55:52 +01:00
|
|
|
// 1. Hay bloques disponibles??
|
|
|
|
|
size_t used = JLANG_used(ptr);
|
|
|
|
|
size_t available = allocPtr->size - used;
|
|
|
|
|
|
|
|
|
|
// chequear si hay suficiente espacio libre
|
|
|
|
|
if (available > size + sizeof(JLANG_metadata)) {
|
|
|
|
|
JLANG_metadata *freeHeader = (JLANG_metadata *)JLANG_last_free(ptr);
|
|
|
|
|
freeHeader->size = size;
|
|
|
|
|
freeHeader->in_use = 1;
|
|
|
|
|
|
|
|
|
|
void *payloadPtr = (char *)freeHeader + sizeof(JLANG_metadata);
|
|
|
|
|
|
|
|
|
|
return (char *)payloadPtr - allocPtr->memory;
|
|
|
|
|
}
|
2026-02-15 23:16:45 +01:00
|
|
|
|
Add while loops, GC mark-and-sweep, and malloc block reuse
- Lexer: add INDENT/DEDENT tokens, <, >, : operators, while keyword,
closing DEDENT emission, include guards
- Parser: add NODE_WHILE with while_loop union, parse while/cond/body
blocks, include guards
- Eval: add while loop evaluation, GC integration with roots from env,
debug and gc flags, <, > comparison operators
- GC: implement mark-and-sweep collector with 3 stages (mark roots,
sweep unmarked, join free blocks)
- Allocator: block reuse via first-fit search with splitting, exponential
heap growth, NULL check on malloc, include guards, marked field in metadata
- Object: add include guards, fix include to use allocator.h
2026-02-16 04:55:52 +01:00
|
|
|
// Se necesita más espacio..
|
2026-02-15 23:16:45 +01:00
|
|
|
|
Add while loops, GC mark-and-sweep, and malloc block reuse
- Lexer: add INDENT/DEDENT tokens, <, >, : operators, while keyword,
closing DEDENT emission, include guards
- Parser: add NODE_WHILE with while_loop union, parse while/cond/body
blocks, include guards
- Eval: add while loop evaluation, GC integration with roots from env,
debug and gc flags, <, > comparison operators
- GC: implement mark-and-sweep collector with 3 stages (mark roots,
sweep unmarked, join free blocks)
- Allocator: block reuse via first-fit search with splitting, exponential
heap growth, NULL check on malloc, include guards, marked field in metadata
- Object: add include guards, fix include to use allocator.h
2026-02-16 04:55:52 +01:00
|
|
|
int newSize = allocPtr->size + 1024;
|
|
|
|
|
char *newBuffer = (char *)malloc(newSize); // Otro 1KB
|
|
|
|
|
memset(newBuffer, 0, newSize);
|
|
|
|
|
memcpy(newBuffer, allocPtr->memory,
|
|
|
|
|
allocPtr->size); // Copiamos al nuevo buffer
|
2026-02-15 23:16:45 +01:00
|
|
|
|
Add while loops, GC mark-and-sweep, and malloc block reuse
- Lexer: add INDENT/DEDENT tokens, <, >, : operators, while keyword,
closing DEDENT emission, include guards
- Parser: add NODE_WHILE with while_loop union, parse while/cond/body
blocks, include guards
- Eval: add while loop evaluation, GC integration with roots from env,
debug and gc flags, <, > comparison operators
- GC: implement mark-and-sweep collector with 3 stages (mark roots,
sweep unmarked, join free blocks)
- Allocator: block reuse via first-fit search with splitting, exponential
heap growth, NULL check on malloc, include guards, marked field in metadata
- Object: add include guards, fix include to use allocator.h
2026-02-16 04:55:52 +01:00
|
|
|
allocPtr->size = newSize;
|
2026-02-15 23:16:45 +01:00
|
|
|
|
Add while loops, GC mark-and-sweep, and malloc block reuse
- Lexer: add INDENT/DEDENT tokens, <, >, : operators, while keyword,
closing DEDENT emission, include guards
- Parser: add NODE_WHILE with while_loop union, parse while/cond/body
blocks, include guards
- Eval: add while loop evaluation, GC integration with roots from env,
debug and gc flags, <, > comparison operators
- GC: implement mark-and-sweep collector with 3 stages (mark roots,
sweep unmarked, join free blocks)
- Allocator: block reuse via first-fit search with splitting, exponential
heap growth, NULL check on malloc, include guards, marked field in metadata
- Object: add include guards, fix include to use allocator.h
2026-02-16 04:55:52 +01:00
|
|
|
free(allocPtr->memory); // Liberamos el buffer antiguo
|
|
|
|
|
allocPtr->memory = newBuffer; // Seteamos el nuevo buffer
|
2026-02-15 23:16:45 +01:00
|
|
|
|
Add while loops, GC mark-and-sweep, and malloc block reuse
- Lexer: add INDENT/DEDENT tokens, <, >, : operators, while keyword,
closing DEDENT emission, include guards
- Parser: add NODE_WHILE with while_loop union, parse while/cond/body
blocks, include guards
- Eval: add while loop evaluation, GC integration with roots from env,
debug and gc flags, <, > comparison operators
- GC: implement mark-and-sweep collector with 3 stages (mark roots,
sweep unmarked, join free blocks)
- Allocator: block reuse via first-fit search with splitting, exponential
heap growth, NULL check on malloc, include guards, marked field in metadata
- Object: add include guards, fix include to use allocator.h
2026-02-16 04:55:52 +01:00
|
|
|
JLANG_metadata *freeHeader = (JLANG_metadata *)JLANG_last_free(ptr);
|
|
|
|
|
freeHeader->size = size;
|
|
|
|
|
freeHeader->in_use = 1;
|
|
|
|
|
|
|
|
|
|
void *payloadPtr = (char *)freeHeader + sizeof(JLANG_metadata);
|
|
|
|
|
return (char *)payloadPtr - allocPtr->memory;
|
|
|
|
|
*/
|
2026-02-15 22:12:19 +01:00
|
|
|
}
|
|
|
|
|
|
2026-02-15 23:16:45 +01:00
|
|
|
void JLANG_free(void *ptr, size_t blockOffset) {
|
2026-02-15 22:12:19 +01:00
|
|
|
JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr;
|
|
|
|
|
|
|
|
|
|
// Get block header
|
2026-02-15 23:16:45 +01:00
|
|
|
void *blockPtr = allocPtr->memory + blockOffset;
|
|
|
|
|
|
2026-02-15 22:12:19 +01:00
|
|
|
JLANG_metadata *blockHeader =
|
|
|
|
|
(JLANG_metadata *)((char *)blockPtr - sizeof(JLANG_metadata));
|
|
|
|
|
|
|
|
|
|
// Set block as not_used
|
|
|
|
|
blockHeader->in_use = 0;
|
2026-02-16 00:33:02 +01:00
|
|
|
|
|
|
|
|
// Set to 0 payload
|
|
|
|
|
memset(blockPtr, 0, blockHeader->size);
|
2026-02-15 20:57:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Debug Visualization
|
|
|
|
|
|
|
|
|
|
[FF FF FF FF FF FF FF ]
|
|
|
|
|
*/
|
|
|
|
|
|
2026-02-15 22:12:19 +01:00
|
|
|
int _ceil(float v) {
|
|
|
|
|
int n = (int)v;
|
|
|
|
|
float r = v - n;
|
2026-02-15 20:57:19 +01:00
|
|
|
|
2026-02-15 22:12:19 +01:00
|
|
|
if (r > 0) {
|
|
|
|
|
return n + 1;
|
|
|
|
|
}
|
|
|
|
|
return n;
|
2026-02-15 20:57:19 +01:00
|
|
|
}
|
|
|
|
|
|
2026-02-15 22:12:19 +01:00
|
|
|
void JLANG_visualize(void *ptr) {
|
|
|
|
|
JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr;
|
|
|
|
|
|
|
|
|
|
// Step 1. Get byte type
|
|
|
|
|
char *byteMapPtr = (char *)malloc(allocPtr->size);
|
|
|
|
|
memset(byteMapPtr, 0, allocPtr->size);
|
|
|
|
|
|
|
|
|
|
JLANG_metadata *currentHeader = (JLANG_metadata *)allocPtr->memory;
|
|
|
|
|
long used = 0;
|
|
|
|
|
while (used < allocPtr->size) {
|
|
|
|
|
long blockIndex = (char *)currentHeader - (char *)allocPtr->memory;
|
|
|
|
|
used += sizeof(JLANG_metadata) + currentHeader->size;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
HEADER
|
|
|
|
|
blockIndex + sizeof(JLANG_metadata)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (currentHeader->size > 0) {
|
2026-02-16 00:33:02 +01:00
|
|
|
if (currentHeader->in_use == 1) {
|
|
|
|
|
byteMapPtr[blockIndex] = JLANG_HEADER;
|
|
|
|
|
for (int i = 0; i < sizeof(JLANG_metadata); i++) {
|
|
|
|
|
byteMapPtr[blockIndex + i] = JLANG_HEADER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
PAYLOAD
|
|
|
|
|
*/
|
|
|
|
|
for (int i = 0; i < currentHeader->size; i++) {
|
|
|
|
|
byteMapPtr[blockIndex + sizeof(JLANG_metadata) + i] = JLANG_PAYLOAD;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Mark all block as JLANG_NOT_USE
|
2026-02-16 02:24:37 +01:00
|
|
|
memset(byteMapPtr + blockIndex, JLANG_NOT_USE,
|
|
|
|
|
sizeof(JLANG_metadata) + currentHeader->size);
|
2026-02-15 22:12:19 +01:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
break;
|
2026-02-15 20:57:19 +01:00
|
|
|
}
|
|
|
|
|
|
2026-02-15 22:12:19 +01:00
|
|
|
// Jump to next block
|
|
|
|
|
currentHeader =
|
|
|
|
|
(JLANG_metadata *)((char *)currentHeader + sizeof(JLANG_metadata) +
|
|
|
|
|
currentHeader->size);
|
|
|
|
|
}
|
2026-02-15 20:57:19 +01:00
|
|
|
|
2026-02-15 22:12:19 +01:00
|
|
|
// Step 2. Draw
|
2026-02-15 20:57:19 +01:00
|
|
|
|
2026-02-15 22:12:19 +01:00
|
|
|
int bytePerRow = 40;
|
|
|
|
|
int totalRows = _ceil(allocPtr->size / bytePerRow);
|
2026-02-15 20:57:19 +01:00
|
|
|
|
2026-02-15 22:12:19 +01:00
|
|
|
char *currentMemPtr = allocPtr->memory;
|
2026-02-15 20:57:19 +01:00
|
|
|
|
2026-02-15 22:12:19 +01:00
|
|
|
for (int i = 0; i < totalRows; i++) {
|
|
|
|
|
printf("[");
|
|
|
|
|
for (int n = 0; n < bytePerRow; n++) {
|
2026-02-15 20:57:19 +01:00
|
|
|
|
2026-02-15 22:12:19 +01:00
|
|
|
int index = n + i * bytePerRow;
|
2026-02-15 20:57:19 +01:00
|
|
|
|
2026-02-15 22:12:19 +01:00
|
|
|
switch (byteMapPtr[index]) {
|
|
|
|
|
case JLANG_HEADER:
|
|
|
|
|
printf("\033[46m");
|
|
|
|
|
break;
|
|
|
|
|
case JLANG_FREE:
|
|
|
|
|
printf("\033[32m");
|
|
|
|
|
break;
|
2026-02-16 00:33:02 +01:00
|
|
|
case JLANG_NOT_USE:
|
|
|
|
|
printf("\033[47;5;224m");
|
|
|
|
|
break;
|
2026-02-15 22:12:19 +01:00
|
|
|
default:
|
|
|
|
|
printf("\033[41m");
|
|
|
|
|
break;
|
|
|
|
|
}
|
2026-02-15 20:57:19 +01:00
|
|
|
|
2026-02-15 22:12:19 +01:00
|
|
|
printf("%.2x", (unsigned char)*(currentMemPtr + (n + i * bytePerRow)));
|
2026-02-15 20:57:19 +01:00
|
|
|
|
2026-02-16 02:24:37 +01:00
|
|
|
/*
|
|
|
|
|
if (n < bytePerRow - 1) {
|
|
|
|
|
printf(" ");
|
|
|
|
|
}
|
|
|
|
|
*/
|
2026-02-15 20:57:19 +01:00
|
|
|
|
2026-02-15 22:12:19 +01:00
|
|
|
printf("\033[0m");
|
2026-02-15 20:57:19 +01:00
|
|
|
}
|
2026-02-15 22:12:19 +01:00
|
|
|
|
|
|
|
|
printf("]\n");
|
|
|
|
|
}
|
2026-02-15 20:57:19 +01:00
|
|
|
}
|
Add while loops, GC mark-and-sweep, and malloc block reuse
- Lexer: add INDENT/DEDENT tokens, <, >, : operators, while keyword,
closing DEDENT emission, include guards
- Parser: add NODE_WHILE with while_loop union, parse while/cond/body
blocks, include guards
- Eval: add while loop evaluation, GC integration with roots from env,
debug and gc flags, <, > comparison operators
- GC: implement mark-and-sweep collector with 3 stages (mark roots,
sweep unmarked, join free blocks)
- Allocator: block reuse via first-fit search with splitting, exponential
heap growth, NULL check on malloc, include guards, marked field in metadata
- Object: add include guards, fix include to use allocator.h
2026-02-16 04:55:52 +01:00
|
|
|
|
|
|
|
|
#endif
|