# processors/symbol_manager.py import sympy import re class SymbolManager: def __init__(self): # plc_name -> py_id (e.g., '"DB".Var' -> 'v0_') self.plc_to_py_id = {} # py_id -> Symbol object (e.g., 'v0_' -> sympy.Symbol('v0_')) self.py_id_to_symbol = {} # py_id -> plc_name (e.g., 'v0_' -> '"DB".Var') - Inverse mapping self.py_id_to_plc = {} self.counter = 0 # Pre-define common keywords/constants to avoid mapping them self.reserved_names = {"TRUE", "FALSE"} # Add others if needed def _generate_py_id(self): py_id = f"v{self.counter}_" self.counter += 1 # Extremely unlikely collision, but check anyway while py_id in self.py_id_to_symbol: py_id = f"v{self.counter}_" self.counter += 1 return py_id def get_symbol(self, plc_var_name): """Gets/Creates a SymPy Symbol for a PLC variable name.""" if plc_var_name is None: print("Warning: Attempted to get symbol for None PLC name.") return None # Or handle error appropriately if plc_var_name.upper() in self.reserved_names: print(f"Warning: Attempted to create symbol for reserved name: {plc_var_name}") return None # Or handle differently (e.g., return sympy.true/false?) if plc_var_name not in self.plc_to_py_id: py_id = self._generate_py_id() self.plc_to_py_id[plc_var_name] = py_id self.py_id_to_plc[py_id] = plc_var_name self.py_id_to_symbol[py_id] = sympy.symbols(py_id) # print(f"DEBUG SymbolManager: Created {py_id} -> {plc_var_name}") # Debug else: py_id = self.plc_to_py_id[plc_var_name] return self.py_id_to_symbol.get(py_id) def get_plc_name(self, py_id): """Gets the original PLC name from a py_id.""" return self.py_id_to_plc.get(py_id) def get_inverse_map(self): """Returns the map needed for postprocessing (py_id -> plc_name).""" return self.py_id_to_plc.copy() # Helper function to extract PLC variable name from JSON operand info def extract_plc_variable_name(operand_info): if operand_info and operand_info.get("type") == "variable": return operand_info.get("name") return None # Not a variable or info missing