From 01740d489219fb4707ced7b56d7a02d60fc68bed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Luis=20Monta=C3=B1es=20Ojados?= Date: Mon, 16 Feb 2026 02:08:54 +0100 Subject: [PATCH] Add evaluator with environment and file-based execution Implements recursive AST evaluator with variable environment, reads .j files from command line args, and executes programs end-to-end (lexer -> parser -> eval). --- projects/simple.j | 2 +- projects/sum.j | 4 +++ src/main.c | 48 +++++++++++++------------- src/vm/eval.h | 86 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 116 insertions(+), 24 deletions(-) create mode 100644 projects/sum.j create mode 100644 src/vm/eval.h diff --git a/projects/simple.j b/projects/simple.j index 3d2b4b1..7d4290a 100644 --- a/projects/simple.j +++ b/projects/simple.j @@ -1 +1 @@ -x = 1 \ No newline at end of file +x = 1 diff --git a/projects/sum.j b/projects/sum.j new file mode 100644 index 0000000..c1fec10 --- /dev/null +++ b/projects/sum.j @@ -0,0 +1,4 @@ +x = 10 +y = 5 +z = x + y +print z \ No newline at end of file diff --git a/src/main.c b/src/main.c index 1d1523a..b51a3d5 100644 --- a/src/main.c +++ b/src/main.c @@ -1,38 +1,40 @@ -#include "frontend/parser.h" -#include "objects/object.h" +#include "vm/eval.h" -int main() { +int main(int argc, char **argv) { + if (argc != 2) { + printf("usage: %s \n", argv[0]); + exit(1); + } // Creamos un allocator JLANG_memory_allocator *allocPtr = JLANG_CreateAllocator(); - size_t stringVar1 = obj_new_string(allocPtr, "Hello world!"); - size_t floatVar1 = obj_new_float(allocPtr, 3.14); - size_t listVar1 = obj_new_list(allocPtr, 3); - Object *list = (Object *)JLANG_RESOLVE(allocPtr, listVar1); + // Read file from argv + FILE *fptr = fopen(argv[1], "r"); + if (fptr == NULL) { + printf("error leyendo: %s\n", argv[1]); + exit(1); + } - size_t *items = (size_t *)JLANG_RESOLVE(allocPtr, list->data.list_val.items); - items[0] = floatVar1; - items[1] = stringVar1; - items[2] = listVar1; + fseek(fptr, 0, SEEK_END); // ir al final + long length = ftell(fptr); // cuántos bytes tiene + fseek(fptr, 0, SEEK_SET); // volver al inicio + char *buff = malloc(length + 1); + size_t bytesRead = fread(buff, 1, length, fptr); + buff[bytesRead] = '\0'; - obj_print(allocPtr, listVar1, ""); + fclose(fptr); - obj_free(allocPtr, stringVar1); - - stringVar1 = obj_new_string(allocPtr, "Hola Mundo!"); - items[1] = stringVar1; - items[2] = stringVar1; - - obj_print(allocPtr, listVar1, ""); - - JLANG_visualize(allocPtr); + printf("%s\n", buff); // Lexer test int totalTokens = 0; - Token *tokens = tokenize("x = 10\ny = 5\nz = x + y\nprint z", &totalTokens); + Token *tokens = tokenize(buff, &totalTokens); printf("totalTokens=%d\n", totalTokens); - ASTNode* block = parse(tokens, totalTokens); + ASTNode *block = parse(tokens, totalTokens); ast_debug(block); + + Environment env = {0}; + eval(block, &env, allocPtr); return 0; } \ No newline at end of file diff --git a/src/vm/eval.h b/src/vm/eval.h new file mode 100644 index 0000000..fffdb3c --- /dev/null +++ b/src/vm/eval.h @@ -0,0 +1,86 @@ +#include "../objects/object.h" +#include "../frontend/parser.h" + +typedef struct +{ + char *name; + size_t value; // offset al Object en el allocator +} Variable; + +typedef struct +{ + Variable vars[256]; + int count; +} Environment; + +size_t env_get(Environment *env, const char *name) +{ + for (int i = 0; i < env->count; i++) + { + if (strcmp(env->vars[i].name, name) == 0) + { + return env->vars[i].value; + } + } + + printf("ERROR: variable '%s' no definida\n", name); + exit(1); +} + +void env_set(Environment *env, const char *name, size_t value) +{ + for (int i = 0; i < env->count; i++) + { + if (strcmp(env->vars[i].name, name) == 0) + { + env->vars[i].value = value; + return; + } + } + + // No existe, añadir + env->vars[env->count].name = (char *)name; + env->vars[env->count].value = value; + env->count++; +} + +size_t eval(ASTNode *node, Environment *env, void *allocator) { + switch (node->type) { + case NODE_INT_LIT: + return obj_new_int(allocator, node->data.int_val); + case NODE_VAR: + return env_get(env, node->data.string_val); + case NODE_ASSIGN: { + size_t val = eval(node->data.assign.value, env, allocator); + env_set(env, node->data.assign.name, val); + return val; + } + case NODE_BINOP: { + size_t left = eval(node->data.binop.left, env, allocator); + size_t right = eval(node->data.binop.right, env, allocator); + + // Resolver objects + Object* l = (Object *) JLANG_RESOLVE(allocator, left); + Object* r = (Object *) JLANG_RESOLVE(allocator, right); + + // Operar (ints por ahora) + if (node->data.binop.op == '+'){ + return obj_new_int(allocator, l->data.int_val + r->data.int_val); + } else if (node->data.binop.op == '-') { + return obj_new_int(allocator, l->data.int_val - r->data.int_val); + } + } + case NODE_PRINT: { + size_t val = eval(node->data.print.expr, env, allocator); + obj_print(allocator, val, ""); + printf("\n"); + return val; + } + case NODE_BLOCK: + for (int i=0; i< node->data.block.count; i++) + eval(node->data.block.stmts[i], env, allocator); + return 0; + default: + break; + } +} \ No newline at end of file