int nodo_analizar(lat_vm *vm, ast *node, lat_bytecode *bcode, int i) { int temp[8] = {0}; lat_bytecode *funcion_bcode = NULL; int fi = 0; switch (node->tipo) { case NODO_BLOQUE: { if (node->r) { pn(vm, node->r); } if (node->l) { pn(vm, node->l); } } break; case NODO_IDENTIFICADOR: /*GET*/ { dbc(OP_LOCALNS, 1, 0, NULL); lat_objeto *ret = lat_cadena_nueva(vm, node->valor->v.s); dbc(OP_STORESTR, 2, 0, ret); dbc(OP_GET, 2, 1, NULL); dbc(OP_MOV, 255, 2, NULL); } break; case NODO_ASIGNACION: /*SET*/ { pn(vm, node->l); dbc(OP_PUSH, 255, 0, NULL); lat_objeto *ret = lat_cadena_nueva(vm, node->r->valor->v.s); if (ret->num_declared < 0) { ret->num_declared = 0; } ret->es_constante = node->r->valor->es_constante; ret->num_declared++; if (ret->es_constante && ret->num_declared > 1) { lat_registrar_error("Linea %d: %s", (node->r->valor->num_linea + 1), "Intento de asignar un nuevo valor a una constante "); } dbc(OP_LOCALNS, 1, 0, NULL); dbc(OP_POP, 255, 0, NULL); dbc(OP_SET, 255, 1, ret); } break; case NODO_INCREMENTO: { pn(vm, node->l); dbc(OP_INC, 255, 0, NULL); } break; case NODO_DECREMENTO: { pn(vm, node->l); dbc(OP_DEC, 255, 0, NULL); } break; case NODO_LITERAL: { lat_objeto *ret = lat_literal_nuevo(vm, node->valor->v.c); dbc(OP_STORECHAR, 255, 0, ret); } break; case NODO_ENTERO: { lat_objeto *ret = lat_entero_nuevo(vm, node->valor->v.i); dbc(OP_STOREINT, 255, 0, ret); } break; case NODO_DECIMAL: { lat_objeto *ret = lat_decimal_nuevo(vm, node->valor->v.d); dbc(OP_STOREDOUBLE, 255, 0, ret); } break; case NODO_CADENA: { lat_objeto *ret = lat_cadena_nueva(vm, node->valor->v.s); dbc(OP_STORESTR, 255, 0, ret); } break; case NODO_LOGICO: { lat_objeto *ret = node->valor->v.b ? vm->true_object : vm->false_object; dbc(OP_STOREBOOL, 255, 0, ret); } break; case NODO_SI: { nodo_si *nIf = ((nodo_si *)node); pn(vm, nIf->cond); dbc(OP_MOV, 2, 255, NULL); dbc(OP_MOV, 3, 255, NULL); dbc(OP_NOT, 2, 0, NULL); temp[0] = i; dbc(OP_NOP, 0, 0, NULL); pn(vm, nIf->th); bcode[temp[0]] = lat_bc(OP_JMPIF, i, 2, NULL); if (nIf->el) { temp[1] = i; dbc(OP_NOP, 0, 0, NULL); pn(vm, nIf->el); bcode[temp[1]] = lat_bc(OP_JMPIF, i, 3, NULL); } } break; case NODO_MIENTRAS: { temp[0] = i; pn(vm, node->l); dbc(OP_MOV, 2, 255, NULL); dbc(OP_NOT, 2, 0, NULL); temp[1] = i; dbc(OP_NOP, 0, 0, NULL); pn(vm, node->r); dbc(OP_JMP, temp[0], 0, NULL); bcode[temp[1]] = lat_bc(OP_JMPIF, i, 2, NULL); } break; case NODO_HACER: { pn(vm, node->r); temp[0] = i; pn(vm, node->l); dbc(OP_MOV, 2, 255, NULL); dbc(OP_NOT, 2, 0, NULL); temp[1] = i; dbc(OP_NOP, 0, 0, NULL); pn(vm, node->r); dbc(OP_JMP, temp[0], 0, NULL); bcode[temp[1]] = lat_bc(OP_JMPIF, i, 2, NULL); } break; case NODO_FUNCION_LLAMADA: { if (node->r) { pn(vm, node->r); } pn(vm, node->l); dbc(OP_CALL, 255, 0, NULL); } break; case NODO_RETORNO: { pn(vm, node->l); dbc(OP_END, 0, 0, NULL); } break; case NODO_FUNCION_ARGUMENTOS: { if (node->l) { pn(vm, node->l); dbc(OP_PUSH, 255, 0, NULL); } if (node->r) { pn(vm, node->r); //Soporte para recursion NODO_FUNCION_LLAMADA if (node->r->valor || node->r->tipo == NODO_FUNCION_LLAMADA) { dbc(OP_PUSH, 255, 0, NULL); } } } break; case NODO_LISTA_PARAMETROS: { if (node->l) { dbc(OP_LOCALNS, 1, 0, NULL); dbc(OP_POP, 2, 0, NULL); lat_objeto *ret = lat_clonar_objeto(vm, lat_cadena_nueva(vm, node->l->valor->v.s)); dbc(OP_SET, 2, 1, ret); } if (node->r) { pn(vm, node->r); } } break; case NODO_FUNCION_USUARIO: { funcion_bcode = (lat_bytecode *)lat_asignar_memoria(sizeof(lat_bytecode) * MAX_BYTECODE_FUNCTION); fi = 0; if (node->l) { fpn(vm, node->l); } fpn(vm, node->r); dbc(OP_FN, 255, 0, funcion_bcode); funcion_bcode = NULL; fi = 0; } break; case NODO_LISTA: { nested++; dbc(OP_STORELIST, nested, 0, NULL); if (node->l) { pn(vm, node->l); } dbc(OP_MOV, 255, nested, NULL); nested--; } break; case NODO_LISTA_ASIGNAR_ELEMENTO: { nodo_lista_elem *nElem = ((nodo_lista_elem *)node); /*if (node->l) { pn(vm, node->l); dbc(OP_PUSHLIST, nested, 255, NULL); } if (node->r) { pn(vm, node->r); }*/ } break; case NODO_LISTA_OBTENER_ELEMENTO:{ if (node->l){ pn(vm, node->l); dbc(OP_POPLIST, nested, 255, NULL); } if (node->r){ pn(vm, node->r); dbc(OP_LISTGETITEM, nested, 255, NULL); } } break; case NODO_DICCIONARIO: { nested++; dbc(OP_STOREDICT, nested, 0, NULL); if (node->l) { pn(vm, node->l); } dbc(OP_MOV, 255, nested, NULL); nested--; } break; case NODO_DICCIONARIO_ELEMENTOS: { if (node->l) { pn(vm, node->l); dbc(OP_PUSHDICT, nested, 255, NULL); } if (node->r) { pn(vm, node->r); } } break; case NODO_DICCIONARIO_ELEMENTO:{ pn(vm, node->l); dbc(OP_PUSH, 255, 0, NULL); lat_objeto *ret = lat_cadena_nueva(vm, node->r->valor->v.s); if (ret->num_declared < 0) { ret->num_declared = 0; } ret->es_constante = node->r->valor->es_constante; ret->num_declared++; if (ret->es_constante && ret->num_declared > 1) { lat_registrar_error("Linea %d: %s", (node->r->valor->num_linea + 1), "Intento de asignar un nuevo valor a una constante "); } dbc(OP_LOCALNS, 1, 0, NULL); dbc(OP_POP, 255, 0, NULL); dbc(OP_SET, 255, 1, ret); }break; /*case NS: { dbc(OP_NS, 255, 0, NULL); pn(node->l); dbc(OP_ENDNS, 255, 0, NULL); } break;*/ default: printf("nodo_tipo:%i\n", node->tipo); return 0; } // printf("i = %i\n", i); return i; }
int nodo_analizar(lat_vm *vm, ast *node, lat_bytecode *bcode, int i) { int temp[8] = {0}; lat_bytecode *funcion_bcode = NULL; int fi = 0; switch (node->tipo) { case NODO_INCLUIR: { //TODO: Incluir rutas con punto ej. incluir "lib.modulos.myModulo" char* archivo = node->l->valor->v.s; lat_objeto* mod = lat_cadena_nueva(vm, archivo); if(!find_list(vm->modulos, (void*)mod)) { //encontrar el modulo en la ruta actual char dir_actual[MAX_PATH_LENGTH]; ldirectorio_actual(dir_actual, sizeof(dir_actual)); strcat(dir_actual, PATH_SEP); strcat(dir_actual, archivo); if(!endsWith(dir_actual, ".lat")) { strcat(dir_actual, ".lat"); } if(legible(dir_actual)) { insert_list(vm->modulos, mod); pn(vm, lat_analizar_archivo(vm, dir_actual)); } else { //sino existe buscar en el path_home de latino/lib char* latino_lib = getenv("LATINO_LIB"); if(latino_lib != NULL) { strcat(latino_lib, PATH_SEP); strcat(latino_lib, archivo); if(!endsWith(latino_lib, ".lat")) { strcat(latino_lib, ".lat"); } if(legible(latino_lib)) { insert_list(vm->modulos, mod); pn(vm, lat_analizar_archivo(vm, latino_lib)); } } } } //return NULL; } break; case NODO_BLOQUE: { if (node->r) { pn(vm, node->r); } if (node->l) { pn(vm, node->l); } } break; case NODO_IDENTIFICADOR: /*GET*/ { dbc(OP_LOCALNS, 1, 0, NULL); lat_objeto *ret = lat_cadena_nueva(vm, node->valor->v.s); dbc(OP_STORESTR, 2, 0, ret); dbc(OP_GET, 2, 1, NULL); dbc(OP_MOV, 255, 2, NULL); #if DEBUG_VM printf("LOCALNS R1\n"); printf("STORESTR R2 %s\n", ret->data.str); printf("GET R2 R1\n"); printf("MOV R255 R2\n"); #endif } break; case NODO_ASIGNACION: /*SET*/ { pn(vm, node->l); dbc(OP_PUSH, 255, 0, NULL); lat_objeto *ret = lat_cadena_nueva(vm, node->r->valor->v.s); if (ret->num_declared < 0) { ret->num_declared = 0; } ret->es_constante = node->r->valor->es_constante; ret->num_declared++; if (ret->es_constante && ret->num_declared > 1) { lat_registrar_error("Linea %d: %s", (node->r->valor->num_linea + 1), "Intento de asignar un nuevo valor a una constante "); } dbc(OP_LOCALNS, 1, 0, NULL); dbc(OP_POP, 255, 0, NULL); dbc(OP_SET, 255, 1, ret); #if DEBUG_VM printf("PUSH R255 R0\n"); printf("LOCALNS R1 R0\n"); printf("POP R255 R0\n"); printf("SET R255 R1\n"); #endif } break; case NODO_INCREMENTO: { pn(vm, node->l); dbc(OP_INC, 255, 0, NULL); #if DEBUG_VM printf("INC R255 R0\n"); #endif } break; case NODO_DECREMENTO: { pn(vm, node->l); dbc(OP_DEC, 255, 0, NULL); #if DEBUG_VM printf("DEC R255 R0\n"); #endif } break; case NODO_LITERAL: { lat_objeto *ret = lat_literal_nuevo(vm, node->valor->v.c); dbc(OP_STORELIT, 255, 0, ret); #if DEBUG_VM printf("STORECHAR R255 %s\n", ret->data.str); #endif } break; case NODO_ENTERO: { lat_objeto *ret = lat_entero_nuevo(vm, node->valor->v.i); dbc(OP_STOREINT, 255, 0, ret); #if DEBUG_VM printf("STOREINT R255 %ld\n", ret->data.i); #endif } break; case NODO_DECIMAL: { lat_objeto *ret = lat_decimal_nuevo(vm, node->valor->v.d); dbc(OP_STOREDOUBLE, 255, 0, ret); #if DEBUG_VM printf("OP_STOREDOUBLE R255 %.14g\n", ret->data.d); #endif } break; case NODO_CADENA: { lat_objeto *ret = lat_cadena_nueva(vm, node->valor->v.s); dbc(OP_STORESTR, 255, 0, ret); #if DEBUG_VM printf("STORESTR R255 %s\n", ret->data.str); #endif } break; case NODO_LOGICO: { lat_objeto *ret = node->valor->v.b ? vm->true_object : vm->false_object; dbc(OP_STOREBOOL, 255, 0, ret); #if DEBUG_VM printf("STOREBOOL R255 %i\n", ret->data.b); #endif } break; case NODO_SI: { nodo_si *nIf = ((nodo_si *)node); pn(vm, nIf->cond); dbc(OP_MOV, 2, 255, NULL); dbc(OP_MOV, 3, 255, NULL); dbc(OP_NOT, 2, 0, NULL); temp[0] = i; dbc(OP_NOP, 0, 0, NULL); pn(vm, nIf->th); bcode[temp[0]] = lat_bc(OP_JMPIF, i, 2, NULL); #if DEBUG_VM printf("MOV R2 R255\n"); printf("MOV R3 R255\n"); printf("NOT\n"); printf("NOP R0 R0\n"); printf("JMPIF R%i R2\n", i); #endif if (nIf->el) { temp[1] = i; dbc(OP_NOP, 0, 0, NULL); pn(vm, nIf->el); bcode[temp[1]] = lat_bc(OP_JMPIF, i, 3, NULL); #if DEBUG_VM printf("NOP\n"); printf("MOV R3 R255\n"); printf("JMPIF R%i R3\n", i); #endif } } break; case NODO_MIENTRAS: { temp[0] = i; pn(vm, node->l); dbc(OP_MOV, 2, 255, NULL); dbc(OP_NOT, 2, 0, NULL); temp[1] = i; dbc(OP_NOP, 0, 0, NULL); pn(vm, node->r); dbc(OP_JMP, temp[0], 0, NULL); bcode[temp[1]] = lat_bc(OP_JMPIF, i, 2, NULL); #if DEBUG_VM printf("MOV R2 R255\n"); printf("NOT R2 R0\n"); printf("NOP\n"); printf("JMP R%i\n", temp[0]); printf("JMPIF R%i R2\n", i); #endif } break; case NODO_HACER: { pn(vm, node->r); temp[0] = i; pn(vm, node->l); dbc(OP_MOV, 2, 255, NULL); dbc(OP_NOT, 2, 0, NULL); temp[1] = i; dbc(OP_NOP, 0, 0, NULL); pn(vm, node->r); dbc(OP_JMP, temp[0], 0, NULL); bcode[temp[1]] = lat_bc(OP_JMPIF, i, 2, NULL); #if DEBUG_VM printf("MOV R2 R255\n"); printf("NOT R2 R0\n"); printf("NOP\n"); printf("JMP R%i\n", temp[0]); printf("JMPIF R%i R2\n", i); #endif } break; case NODO_FUNCION_LLAMADA: { if (node->r) { pn(vm, node->r); } pn(vm, node->l); dbc(OP_CALL, 255, 0, NULL); #if DEBUG_VM printf("CALL R255\n"); #endif } break; case NODO_RETORNO: { pn(vm, node->l); dbc(OP_END, 0, 0, NULL); #if DEBUG_VM printf("END R255\n"); #endif } break; case NODO_FUNCION_ARGUMENTOS: { if (node->l) { pn(vm, node->l); dbc(OP_PUSH, 255, 0, NULL); #if DEBUG_VM printf("PUSH R255\n"); #endif } if (node->r) { pn(vm, node->r); //Soporte para recursion NODO_FUNCION_LLAMADA if (node->r->valor || node->r->tipo == NODO_FUNCION_LLAMADA) { dbc(OP_PUSH, 255, 0, NULL); #if DEBUG_VM printf("PUSH R255\n"); #endif } } } break; case NODO_LISTA_PARAMETROS: { if (node->l) { dbc(OP_LOCALNS, 1, 0, NULL); dbc(OP_POP, 2, 0, NULL); lat_objeto *ret = lat_clonar_objeto(vm, lat_cadena_nueva(vm, node->l->valor->v.s)); dbc(OP_SET, 2, 1, ret); #if DEBUG_VM printf("LOCALNS R1\n"); printf("POP R2\n"); printf("SET R2 R1 %s\n", ret->data.str); #endif } if (node->r) { pn(vm, node->r); } } break; case NODO_FUNCION_USUARIO: { funcion_bcode = (lat_bytecode *)lat_asignar_memoria(sizeof(lat_bytecode) * MAX_BYTECODE_FUNCTION); fi = 0; if (node->l) { fpn(vm, node->l); } fpn(vm, node->r); dbc(OP_FN, 255, 0, funcion_bcode); #if DEBUG_VM printf("FN R255\n"); #endif funcion_bcode = NULL; fi = 0; } break; case NODO_LISTA: { nested++; dbc(OP_STORELIST, nested, 0, NULL); #if DEBUG_VM printf("STORELIST R%i\n", nested); #endif if (node->l) { pn(vm, node->l); dbc(OP_MOV, 255, nested, NULL); #if DEBUG_VM printf("MOV R255 R%i\n", nested); #endif } nested--; } break; case NODO_LISTA_AGREGAR_ELEMENTO: { if (node->l) { pn(vm, node->l); dbc(OP_PUSHLIST, nested, 255, NULL); #if DEBUG_VM printf("PUSHLIST R%i R255\n", nested); #endif } if (node->r) { pn(vm, node->r); } } break; case NODO_LISTA_ASIGNAR_ELEMENTO: { nodo_lista_elem *elem = ((nodo_lista_elem *)node); if (elem->exp) { pn(vm, elem->exp); dbc(OP_MOV, 3, 255, NULL); #if DEBUG_VM printf("MOV R3 R255\n"); #endif } if(elem->id) { pn(vm, elem->pos); dbc(OP_MOV, 4, 255, NULL); #if DEBUG_VM printf("MOV R4 R255\n"); #endif pn(vm, elem->id); dbc(OP_LISTSETITEM, 255, 3, (void*)4); #if DEBUG_VM printf("LISTSETITEM R255 R3\n"); #endif } } break; case NODO_LISTA_OBTENER_ELEMENTO: { if (node->l) { pn(vm, node->l); dbc(OP_MOV, 3, 255, NULL); #if DEBUG_VM printf("MOV R3 R255\n"); #endif } if (node->r) { pn(vm, node->r); dbc(OP_LISTGETITEM, 255, 3, NULL); #if DEBUG_VM printf("LISTGETITEM R55 R3\n"); #endif } } break; case NODO_DICCIONARIO: { nested++; dbc(OP_STOREDICT, nested, 0, NULL); #if DEBUG_VM printf("STOREDICT R%i\n", nested); #endif if (node->l) { pn(vm, node->l); dbc(OP_MOV, 255, nested, NULL); #if DEBUG_VM printf("MOV R255 R%i\n", nested); #endif } nested--; } break; case NODO_DICC_AGREGAR_ELEMENTO: { if(node->l) { pn(vm, node->l); dbc(OP_PUSHDICT, nested, 255, NULL); #if DEBUG_VM printf("PUSHDICT R%i R255\n", nested); #endif } if(node->r) { pn(vm, node->r); } } break; case NODO_DICC_ELEMENTO: { if(node->l){ pn(vm, node->l); dbc(OP_PUSH, 255, 0, NULL); #if DEBUG_VM printf("PUSH R255\n"); #endif } if(node->r){ pn(vm, node->r); dbc(OP_PUSH, 255, 0, NULL); #if DEBUG_VM printf("PUSH R255\n"); #endif } dbc(OP_PUSHDICTELEM, 0, 0, NULL); #if DEBUG_VM printf("OP_PUSHDICTELEM\n"); #endif } break; case NODO_DICC_ASIGNAR_ELEMENTO: { nodo_dicc_elem *elem = ((nodo_dicc_elem *)node); if(elem->exp) { pn(vm, elem->exp); dbc(OP_MOV, 3, 255, NULL); #if DEBUG_VM printf("MOV R3 R255\n"); #endif } if(elem->id) { pn(vm, elem->llave); dbc(OP_MOV, 4, 255, NULL); #if DEBUG_VM printf("MOV R4 R255\n"); #endif pn(vm, elem->id); dbc(OP_DICTSETITEM, 255, 3, (void*)4); #if DEBUG_VM printf("DICTITEM R255 R3\n"); #endif } } break; case NODO_DICC_OBTENER_ELEMENTO: { if(node->l){ pn(vm, node->l); dbc(OP_MOV, 3, 255, NULL); #if DEBUG_VM printf("MOV R3 R255\n"); #endif } if(node->r){ pn(vm, node->r); dbc(OP_DICTGETITEM, 255, 3, NULL); #if DEBUG_VM printf("MOV R255 R3\n"); #endif } }break; /*case NS: { dbc(OP_NS, 255, 0, NULL); pn(node->l); dbc(OP_ENDNS, 255, 0, NULL); } break;*/ default: printf("nodo_tipo:%i\n", node->tipo); return 0; } // printf("i = %i\n", i); return i; }