86 lines
2.4 KiB
C
86 lines
2.4 KiB
C
|
|
#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;
|
||
|
|
}
|
||
|
|
}
|