class MemoryMap: ''' Clase que maneja el mapa de memoria que va a utilizar la Máquina Virtual Contiene la memoria de variables globales, la tabla de funciones, la tabla de constantes y un stack de memoria para manejar memoria local en ejecución''' FALSE_CONSTANT = 0 TRUE_CONSTANT = 1 INT_CONSTANT_BASE = 1000 FLOAT_CONSTANT_BASE = 2000 STRING_CONSTANT_BASE = 3000 INT_BASE = 10000 FLOAT_BASE = 11000 STRING_BASE = 12000 BOOL_BASE = 13000 LOCAL_INT_BASE = 20000 LOCAL_FLOAT_BASE = 21000 LOCAL_STRING_BASE = 22000 LOCAL_BOOL_BASE = 23000 TEMP_INT_BASE = 30000 TEMP_FLOAT_BASE = 31000 TEMP_STRING_BASE = 32000 TEMP_BOOL_BASE = 33000 POINTER_BASE = 40000 # Inicializa el mapa de memoria. Recibe la tabla de constantes y el directorio de funciones # Del directorio de funciones saca las variables del 'main' para poder inicializar un objeto # de la clase Memory con las variables globales. def __init__(self, constant_table, functions): self.log = Logger(False) self.log.write(" //////////////////////// Memory Map init ////////////////////") global_variables = [] for function in functions: if(function['name'] == "main"): global_variables = function['size_dict'] self.functions_table = functions self.memory_stack = [] self.global_memory = Memory(True, global_variables) self.memory_stack.append(self.global_memory) self.constant_table = constant_table self.nested_call_level = 0 self.log.write( "=============== functions dir ==================") self.log.write(self.functions_table) self.log.write( "=============== global memory ==================") self.log.write(self.global_memory.register) self.log.write(self.global_memory.temp_register) self.log.write( "=============== constant memory ==================") self.log.write(self.constant_table.table) # Función que inicializa un objeto de la clase Memoria con las variables # locales de la función que se pasa como argumento. La memoria local se agrega # a la pila de memoria def push_local(self, function_name): for function in self.functions_table: if(function['name'] == function_name): new_local_variables = function['size_dict'] local_memory = Memory(False, new_local_variables) self.memory_stack.append(local_memory) # Se quita una memoria de la pila de memoria def pop_local(self): self.memory_stack.pop() # La función get_value recibe una dirección. A partir de esta dirección, se # decide si es una variable global, local, temporal o constante y de aquí llama # a su método correspondiente def get_value(self, address): if self.nested_call_level <= 0: if address >= MemoryMap.INT_BASE and address < MemoryMap.LOCAL_INT_BASE: return self.get_global_value(address) elif address >= MemoryMap.LOCAL_INT_BASE and address < MemoryMap.TEMP_INT_BASE: return self.get_local_value(address) elif address >= MemoryMap.TEMP_INT_BASE and address < MemoryMap.POINTER_BASE: return self.get_temp_value(address) elif address >= MemoryMap.INT_CONSTANT_BASE and address < MemoryMap.INT_BASE: return self.get_constant_value(address) elif address >= MemoryMap.POINTER_BASE: return self.get_pointer_value(address) elif address == MemoryMap.FALSE_CONSTANT: return False elif address == MemoryMap.TRUE_CONSTANT: return True else: print('Error de ejecucion: Direccion virtual desconocida') exit(1) return None else: return self.get_param_value(address) # La función set_value recibe una dirección y un valor. A partir de esta dirección, se # decide si es una variable global, local, temporal o constante y de aquí llama # a su método correspondiente. Si la dirección es de una variable constante, marca # error por dirección invalida def set_value(self, address, value): if address >= MemoryMap.INT_BASE and address < MemoryMap.LOCAL_INT_BASE: return self.set_global_value(address, value) elif address >= MemoryMap.LOCAL_INT_BASE and address < MemoryMap.TEMP_INT_BASE: return self.set_local_value(address, value) elif address >= MemoryMap.TEMP_INT_BASE and address < MemoryMap.POINTER_BASE: return self.set_temp_value(address, value) elif address >= MemoryMap.INT_CONSTANT_BASE and address < MemoryMap.INT_BASE: print('Error de ejecucion: Direccion virtual no valida') return None elif address >= MemoryMap.POINTER_BASE: return self.set_pointer_value(address, value) elif address == MemoryMap.FALSE_CONSTANT: print('Error de ejecucion: Direccion virtual no valida') return None elif address == MemoryMap.TRUE_CONSTANT: print('Error de ejecucion: Direccion virtual no valida') return None else: print('Error de ejecucion: Direccion virtual no valida') return None # La función get_global_value recibe una dirección. Con esta dirección se checa # si es una dirección de una variable entera, flotante, string o booleana, # y se procede a pedir el valor a la memoria global con ese tipo def get_global_value(self, address): if address >= MemoryMap.INT_BASE and address < MemoryMap.FLOAT_BASE: return self.global_memory.get_int_value(address) elif address >= MemoryMap.FLOAT_BASE and address < MemoryMap.STRING_BASE: return self.global_memory.get_float_value(address) elif address >= MemoryMap.STRING_BASE and address < MemoryMap.BOOL_BASE: return self.global_memory.get_string_value(address) elif address >= MemoryMap.BOOL_BASE and address < MemoryMap.LOCAL_INT_BASE: return self.global_memory.get_bool_value(address) else: print('Error de ejecucion: Direccion virtual global desconocida') return None # La función get_local_value recibe una dirección. Con esta dirección se checa # si es una dirección de una variable entera, flotante, string o booleana, # y se procede a pedir el valor a la memoria local con ese tipo def get_local_value(self, address): if address >= MemoryMap.LOCAL_INT_BASE and address < MemoryMap.LOCAL_FLOAT_BASE: return self.get_local_memory().get_int_value(address) elif address >= MemoryMap.LOCAL_FLOAT_BASE and address < MemoryMap.LOCAL_STRING_BASE: return self.get_local_memory().get_float_value(address) elif address >= MemoryMap.LOCAL_STRING_BASE and address < MemoryMap.LOCAL_BOOL_BASE: return self.get_local_memory().get_string_value(address) elif address >= MemoryMap.LOCAL_BOOL_BASE and address < MemoryMap.TEMP_INT_BASE: return self.get_local_memory().get_bool_value(address) else: print('Error de ejecucion: Direccion virtual local desconocida') return None # La función get_temp_value recibe una dirección. Con esta dirección se checa # si es una dirección de una variable entera, flotante, string o booleana, # y se procede a pedir el valor a la memoria temporal con ese tipo def get_temp_value(self, address): if address >= MemoryMap.TEMP_INT_BASE and address < MemoryMap.TEMP_FLOAT_BASE: return self.get_local_memory().get_temp_int_value(address) elif address >= MemoryMap.TEMP_FLOAT_BASE and address < MemoryMap.TEMP_STRING_BASE: return self.get_local_memory().get_temp_float_value(address) elif address >= MemoryMap.TEMP_STRING_BASE and address < MemoryMap.TEMP_BOOL_BASE: return self.get_local_memory().get_temp_string_value(address) elif address >= MemoryMap.TEMP_BOOL_BASE and address < MemoryMap.POINTER_BASE: return self.get_local_memory().get_temp_bool_value(address) else: print('Error de ejecucion: Direccion virtual temporal desconocida') return None # La función get_constant_value recibe una dirección. Con esta dirección se checa # si es una dirección de una variable entera, flotante, string o booleana, # y se procede a pedir el valor a la tabla de constantes con ese tipo def get_constant_value(self, address): if address >= MemoryMap.INT_CONSTANT_BASE and address < MemoryMap.FLOAT_CONSTANT_BASE: return self.constant_table.get_int_value(address) elif address >= MemoryMap.FLOAT_CONSTANT_BASE and address < MemoryMap.STRING_CONSTANT_BASE: return self.constant_table.get_float_value(address) elif address >= MemoryMap.STRING_CONSTANT_BASE and address < MemoryMap.INT_BASE: return self.constant_table.get_string_value(address) else: print('Error de ejecucion: Direccion virtual constante desconocida') return None # La función get_pointer_value recibe una dirección. Con esta dirección se # obtiene la dirección real en la memoria global y se llama a la función # get_value con esa nueva dirección real def get_pointer_value(self, address): real_address = self.global_memory.get_pointer_value(address) return self.get_value(real_address) # Regresa la direccion del pointer en la memoria global def get_pointer_address(self, address): return self.global_memory.get_pointer_value(address) # La función set_global_value recibe una dirección y un valor. Con esta dirección # se checa si la dirección es de una variable entera, flotante, string o booleana, # y se procede a poner el valor a la memoria global con ese tipo def set_global_value(self, address, value): if address >= MemoryMap.INT_BASE and address < MemoryMap.FLOAT_BASE: return self.global_memory.set_int_value(address, value) elif address >= MemoryMap.FLOAT_BASE and address < MemoryMap.STRING_BASE: return self.global_memory.set_float_value(address, value) elif address >= MemoryMap.STRING_BASE and address < MemoryMap.BOOL_BASE: return self.global_memory.set_string_value(address, value) elif address >= MemoryMap.BOOL_BASE and address < MemoryMap.LOCAL_INT_BASE: return self.global_memory.set_bool_value(address, value) else: print('Error de ejecucion: Direccion virtual global desconocida') return None # La función set_local_value recibe una dirección y un valor. Con esta dirección # se checa si la dirección es de una variable entera, flotante, string o booleana, # y se procede a poner el valor a la memoria local con ese tipo def set_local_value(self, address, value): if address >= MemoryMap.LOCAL_INT_BASE and address < MemoryMap.LOCAL_FLOAT_BASE: return self.get_local_memory().set_int_value(address, value) elif address >= MemoryMap.LOCAL_FLOAT_BASE and address < MemoryMap.LOCAL_STRING_BASE: return self.get_local_memory().set_float_value(address, value) elif address >= MemoryMap.LOCAL_STRING_BASE and address < MemoryMap.LOCAL_BOOL_BASE: return self.get_local_memory().set_string_value(address, value) elif address >= MemoryMap.LOCAL_BOOL_BASE and address < MemoryMap.TEMP_INT_BASE: return self.get_local_memory().set_bool_value(address, value) else: print('Error de ejecucion: Direccion virtual local desconocida') return None # La función set_temp_value recibe una dirección y un valor. Con esta dirección # se checa si la dirección es de una variable entera, flotante, string o booleana, # y se procede a poner el valor a la memoria temporal con ese tipo def set_temp_value(self, address, value): if address >= MemoryMap.TEMP_INT_BASE and address < MemoryMap.TEMP_FLOAT_BASE: return self.get_local_memory().set_temp_int_value(address, value) elif address >= MemoryMap.TEMP_FLOAT_BASE and address < MemoryMap.TEMP_STRING_BASE: return self.get_local_memory().set_temp_float_value(address, value) elif address >= MemoryMap.TEMP_STRING_BASE and address < MemoryMap.TEMP_BOOL_BASE: return self.get_local_memory().set_temp_string_value(address, value) elif address >= MemoryMap.TEMP_BOOL_BASE and address < MemoryMap.POINTER_BASE: return self.get_local_memory().set_temp_bool_value(address, value) else: print('Error de ejecucion: Direccion virtual temporal desconocida') return None # La función set_pointer_value recibe una dirección y un valor. Con esta dirección # se llama a la función set_pointer_value de la memoria global def set_pointer_value(self, address, value): self.global_memory.set_pointer_value(address, value) # La función get_param_value recibe una dirección. Con esta dirección se checa # si es una dirección de una variable entera, flotante, string o booleana global, local, # o temporal, y se procede a pedir el valor a la memoria ese tipo def get_param_value(self, address): if address < MemoryMap.INT_BASE: return self.get_constant_value(address) elif address >= MemoryMap.INT_BASE and address < MemoryMap.LOCAL_INT_BASE: return self.get_global_value(address) elif address >= MemoryMap.LOCAL_INT_BASE and address < MemoryMap.LOCAL_FLOAT_BASE: return self.get_previous_memory().get_int_value(address) elif address >= MemoryMap.LOCAL_FLOAT_BASE and address < MemoryMap.LOCAL_STRING_BASE: return self.get_previous_memory().get_float_value(address) elif address >= MemoryMap.LOCAL_STRING_BASE and address < MemoryMap.LOCAL_BOOL_BASE: return self.get_previous_memory().get_string_value(address) elif address >= MemoryMap.LOCAL_BOOL_BASE and address < MemoryMap.TEMP_INT_BASE: return self.get_previous_memory().get_bool_value(address) elif address >= MemoryMap.TEMP_INT_BASE and address < MemoryMap.POINTER_BASE: return self.get_temp_value(address) elif address >= MemoryMap.POINTER_BASE: return self.get_pointer_value(address) else: print('Error de ejecucion: Direccion virtual local desconocida') return None # Función que regresa la memoria local actual def get_local_memory(self): return self.memory_stack[-1] # Función que regresa la penúltima memoria def get_previous_memory(self): return self.memory_stack[-2] # Función que decide el tipo de input que se va a leer, se divide entre direcciones globales, # locales o temporales que son enteras, flotantes o string. Después de decidir llama a la # función correspondiente de input def read_by_type(self, address): if address >= MemoryMap.INT_BASE and address < MemoryMap.FLOAT_BASE: return self.read_int() elif address >= MemoryMap.FLOAT_BASE and address < MemoryMap.STRING_BASE: return self.read_float() elif address >= MemoryMap.STRING_BASE and address < MemoryMap.BOOL_BASE: return self.read_string() elif address >= MemoryMap.LOCAL_INT_BASE and address < MemoryMap.LOCAL_FLOAT_BASE: return self.read_int() elif address >= MemoryMap.LOCAL_FLOAT_BASE and address < MemoryMap.LOCAL_STRING_BASE: return self.read_float() elif address >= MemoryMap.LOCAL_STRING_BASE and address < MemoryMap.LOCAL_BOOL_BASE: return self.read_string() elif address >= MemoryMap.TEMP_INT_BASE and address < MemoryMap.TEMP_FLOAT_BASE: return self.read_int() elif address >= MemoryMap.TEMP_FLOAT_BASE and address < MemoryMap.TEMP_STRING_BASE: return self.read_float() elif address >= MemoryMap.TEMP_STRING_BASE and address < MemoryMap.TEMP_BOOL_BASE: return self.read_string() else: print('Error de ejecucion: Direccion virtual temporal desconocida o invalida') return None # Lee un input entero def read_int(self): return int(input()) # Lee un input flotante def read_float(self): return float(input()) # Lee un input string def read_string(self): return input()