Agregado de los parametros de las FC
This commit is contained in:
parent
66c5a076ab
commit
0e68e32b8a
|
@ -11,14 +11,17 @@ SCL_SUFFIX = "_sympy_processed"
|
|||
|
||||
def process_call(instruction, network_id, sympy_map, symbol_manager: SymbolManager, data):
|
||||
instr_uid = instruction["instruction_uid"]
|
||||
instr_type_original = instruction.get("type", "") # Tipo antes de añadir sufijo
|
||||
if instr_type_original.endswith(SCL_SUFFIX) or "_error" in instr_type_original:
|
||||
return False
|
||||
|
||||
# Get original type before potential suffix/error was added by x1 or previous passes
|
||||
# This requires storing the original type perhaps, or removing known suffixes
|
||||
# Let's assume 'block_type' (FC/FB) and 'block_name' are correct from x1
|
||||
block_name = instruction.get("block_name", f"UnknownCall_{instr_uid}")
|
||||
block_type = instruction.get("block_type") # FC, FB
|
||||
instance_db = instruction.get("instance_db") # Nombre del DB de instancia (para FB)
|
||||
|
||||
# Check if already processed
|
||||
if instruction.get("type", "").endswith(SCL_SUFFIX) or "_error" in instruction.get("type", ""):
|
||||
return False
|
||||
|
||||
# Formatear nombres SCL (para la llamada final)
|
||||
block_name_scl = format_variable_name(block_name)
|
||||
instance_db_scl = format_variable_name(instance_db) if instance_db else None
|
||||
|
@ -33,91 +36,140 @@ def process_call(instruction, network_id, sympy_map, symbol_manager: SymbolManag
|
|||
|
||||
# --- Procesar Parámetros de Entrada ---
|
||||
scl_call_params = []
|
||||
processed_inputs = {"en"}
|
||||
processed_inputs = {"en"} # Track processed pins to avoid duplicates if 'en' is also listed elsewhere
|
||||
dependencies_resolved = True
|
||||
|
||||
# Ordenar para consistencia
|
||||
# Iterar sobre las entradas que x1 debería haber poblado
|
||||
# Ordenar por nombre de pin para consistencia en la llamada SCL
|
||||
input_pin_names = sorted(instruction.get("inputs", {}).keys())
|
||||
|
||||
for pin_name in input_pin_names:
|
||||
if pin_name not in processed_inputs:
|
||||
if pin_name not in processed_inputs: # Skip 'en' if already handled
|
||||
source_info = instruction["inputs"][pin_name]
|
||||
# Obtener la representación de la fuente (puede ser SymPy o Constante/String)
|
||||
|
||||
# Get the representation of the source (SymPy, constant, or SCL string)
|
||||
source_sympy_or_const = get_sympy_representation(source_info, network_id, sympy_map, symbol_manager)
|
||||
|
||||
if source_sympy_or_const is None:
|
||||
# print(f"DEBUG Call {instr_uid}: Input param '{pin_name}' dependency not ready.")
|
||||
dependencies_resolved = False
|
||||
break # Salir si una dependencia no está lista
|
||||
break # Exit if one dependency is not ready
|
||||
|
||||
# Convertir la expresión/constante a SCL para la llamada
|
||||
# Simplificar ANTES de convertir? Probablemente no necesario para parámetros de entrada
|
||||
# a menos que queramos optimizar el valor pasado. Por ahora, convertir directo.
|
||||
# Convert the expression/constant to SCL for the call
|
||||
# Simplification of inputs is generally not needed here, convert directly
|
||||
param_scl_value = sympy_expr_to_scl(source_sympy_or_const, symbol_manager)
|
||||
|
||||
# El nombre del pin SÍ necesita formateo
|
||||
# Parameter pin name needs formatting for SCL
|
||||
pin_name_scl = format_variable_name(pin_name)
|
||||
|
||||
# Special check for DB_ANY or ANY_POINTER - pass name directly without :=
|
||||
# We need the original parameter type info for this, which is not in the simplified JSON.
|
||||
# WORKAROUND: Check if param_scl_value looks like a DB name ("DB_NAME")
|
||||
# This is heuristic and might be wrong. Ideally, x1 should pass type info.
|
||||
# For now, we assume standard 'Param := Value' syntax.
|
||||
# if param_scl_value.startswith('"') and param_scl_value.endswith('"') and block_type == "FC": # Heuristic for DB_ANY?
|
||||
# scl_call_params.append(f"{pin_name_scl} := {param_scl_value}") # Still use := for clarity? TIA might infer
|
||||
# else:
|
||||
scl_call_params.append(f"{pin_name_scl} := {param_scl_value}")
|
||||
|
||||
processed_inputs.add(pin_name)
|
||||
|
||||
if not dependencies_resolved:
|
||||
return False
|
||||
|
||||
# --- Construcción de la Llamada SCL (similar a antes) ---
|
||||
# --- Construcción de la Llamada SCL (con parámetros) ---
|
||||
scl_call_body = ""
|
||||
param_string = ", ".join(scl_call_params)
|
||||
param_string = ", ".join(scl_call_params) # Join parameters with commas
|
||||
|
||||
if block_type == "FB":
|
||||
if not instance_db_scl:
|
||||
print(f"Error: Call FB '{block_name_scl}' (UID {instr_uid}) sin instancia.")
|
||||
instruction["scl"] = f"// ERROR: FB Call {block_name_scl} sin instancia"
|
||||
instruction["type"] = f"Call_FB_error"
|
||||
return True
|
||||
instruction["type"] = f"Call_FB_error" # Mark with error
|
||||
return True # Processed (with error)
|
||||
# FB Call: InstanceName(Param1 := Value1, Param2 := Value2);
|
||||
scl_call_body = f"{instance_db_scl}({param_string});"
|
||||
elif block_type == "FC":
|
||||
# FC Call: BlockName(Param1 := Value1, Param2 := Value2);
|
||||
scl_call_body = f"{block_name_scl}({param_string});"
|
||||
else:
|
||||
print(f"Advertencia: Tipo de bloque no soportado para Call UID {instr_uid}: {block_type}")
|
||||
scl_call_body = f"// ERROR: Call a bloque tipo '{block_type}' no soportado: {block_name_scl}"
|
||||
instruction["type"] = f"Call_{block_type}_error" # Marcar como error
|
||||
# Mark instruction type with error
|
||||
instruction["type"] = f"Call_{block_type or 'Unknown'}_error" # Add specific type if known
|
||||
|
||||
|
||||
# --- Aplicar Condición EN (usando la expresión SymPy EN) ---
|
||||
scl_final = ""
|
||||
if sympy_en_expr != sympy.true:
|
||||
# Simplificar la condición EN ANTES de convertirla a SCL
|
||||
# Simplify the EN condition before converting to SCL
|
||||
try:
|
||||
#simplified_en_expr = sympy.simplify_logic(sympy_en_expr, force=True)
|
||||
simplified_en_expr = sympy.logic.boolalg.to_dnf(sympy_en_expr, simplify=True)
|
||||
except Exception as e:
|
||||
print(f"Error simplifying EN for Call {instr_uid}: {e}")
|
||||
print(f"Error simplifying EN for Call {instr_uid} ({block_name_scl}): {e}")
|
||||
simplified_en_expr = sympy_en_expr # Fallback
|
||||
en_condition_scl = sympy_expr_to_scl(simplified_en_expr, symbol_manager)
|
||||
|
||||
indented_call = "\n".join([f" {line}" for line in scl_call_body.splitlines()])
|
||||
scl_final = f"IF {en_condition_scl} THEN\n{indented_call}\nEND_IF;"
|
||||
# Avoid IF TRUE/FALSE blocks
|
||||
if en_condition_scl == "TRUE":
|
||||
scl_final = scl_call_body
|
||||
elif en_condition_scl == "FALSE":
|
||||
scl_final = f"// Call {block_name_scl} (UID {instr_uid}) condition simplified to FALSE."
|
||||
# Also update type to avoid further processing?
|
||||
# instruction["type"] = f"Call_{block_type}{SCL_SUFFIX}_Optimized"
|
||||
else:
|
||||
# Indent the call body within the IF block
|
||||
indented_call = "\n".join([f" {line}" for line in scl_call_body.splitlines()])
|
||||
scl_final = f"IF {en_condition_scl} THEN\n{indented_call}\nEND_IF;"
|
||||
else:
|
||||
# No IF needed if EN is always TRUE
|
||||
scl_final = scl_call_body
|
||||
|
||||
# --- Actualizar Instrucción y Mapa SymPy ---
|
||||
instruction["scl"] = scl_final # Guardar el SCL final generado
|
||||
instruction["type"] = (f"Call_{block_type}{SCL_SUFFIX}" if "_error" not in instruction["type"] else instruction["type"])
|
||||
|
||||
# Actualizar sympy_map con el estado ENO (es la expresión SymPy de EN)
|
||||
# Update instruction type to mark as processed (unless already marked as error)
|
||||
if "_error" not in instruction.get("type", ""):
|
||||
instruction["type"] = f"Call_{block_type}{SCL_SUFFIX}"
|
||||
|
||||
# Propagar el estado ENO (es la expresión SymPy de EN)
|
||||
map_key_eno = (network_id, instr_uid, "eno")
|
||||
sympy_map[map_key_eno] = sympy_en_expr # Guardar la expresión SymPy para ENO
|
||||
|
||||
# Propagar valores de salida (requiere info de interfaz o heurística)
|
||||
# Si se sabe que hay una salida 'MyOutput', se podría añadir su SCL al mapa
|
||||
# Ejemplo MUY simplificado:
|
||||
# --- Propagar Valores de Salida (Importante pero complejo) ---
|
||||
# Esto requiere conocer la interfaz del bloque llamado (que no tenemos aquí directamente)
|
||||
# O asumir convenciones estándar (ej. FCs tienen Ret_Val, FBs tienen outputs en su instancia)
|
||||
|
||||
# Heurística simple: Si es un FC, intentar propagar Ret_Val si existe en outputs
|
||||
# Si es un FB, las salidas se acceden a través de la instancia (e.g., "MyInstance".Output1)
|
||||
# Por ahora, dejaremos la propagación de salidas más avanzada para una mejora futura
|
||||
# o requerirá pasar información de la interfaz del bloque llamado.
|
||||
|
||||
# Ejemplo básico (necesita mejorar):
|
||||
# for pin_name, dest_list in instruction.get("outputs", {}).items():
|
||||
# if pin_name != 'eno' and dest_list: # Asumir que hay un destino
|
||||
# map_key_out = (network_id, instr_uid, pin_name)
|
||||
# pin_name_scl = format_variable_name(pin_name)
|
||||
# if block_type == "FB" and instance_db_scl:
|
||||
# sympy_map[map_key_out] = f"{instance_db_scl}.{format_variable_name(pin_name)}" # Guardar el *string* de acceso SCL
|
||||
# # Para FCs es más complejo, necesitaría asignación explícita a temp
|
||||
# # else: # FC output -> necesita temp var
|
||||
# # temp_var = generate_temp_var_name(...)
|
||||
# # sympy_map[map_key_out] = temp_var
|
||||
# # Salida de FB: "Instancia".NombrePin
|
||||
# output_scl_access = f"{instance_db_scl}.{pin_name_scl}"
|
||||
# # Podríamos guardar el string SCL o crear/obtener un Symbol
|
||||
# sympy_out_symbol = symbol_manager.get_symbol(output_scl_access)
|
||||
# sympy_map[map_key_out] = sympy_out_symbol if sympy_out_symbol else output_scl_access # Prefiere Symbol
|
||||
# elif block_type == "FC":
|
||||
# # Salida de FC: Requiere asignar a una variable (temporal o de interfaz)
|
||||
# # Esto se complica porque el destino está en 'dest_list'
|
||||
# if len(dest_list) == 1 and dest_list[0].get("type") == "variable":
|
||||
# target_var_name = format_variable_name(dest_list[0].get("name"))
|
||||
# # Guardar el nombre del destino SCL que contendrá el valor
|
||||
# sympy_map[map_key_out] = target_var_name
|
||||
# # Necesitaríamos modificar scl_final para incluir la asignación:
|
||||
# # target_var_name := FC_Call(...); (requiere reestructurar la generación SCL)
|
||||
# else:
|
||||
# # Múltiples destinos o destino no variable es complejo para FC outputs
|
||||
# sympy_map[map_key_out] = f"/* TODO: Assign FC output {pin_name_scl} */"
|
||||
|
||||
|
||||
return True
|
||||
|
||||
|
@ -125,7 +177,8 @@ def process_call(instruction, network_id, sympy_map, symbol_manager: SymbolManag
|
|||
# --- Processor Information Function ---
|
||||
def get_processor_info():
|
||||
"""Devuelve la información para las llamadas a FC y FB."""
|
||||
# Asegurarse que los type_name coincidan con los usados en x1 y x2
|
||||
return [
|
||||
{'type_name': 'call_fc', 'processor_func': process_call, 'priority': 6},
|
||||
{'type_name': 'call_fb', 'processor_func': process_call, 'priority': 6}
|
||||
{'type_name': 'call_fc', 'processor_func': process_call, 'priority': 6}, # Prioridad alta
|
||||
{'type_name': 'call_fb', 'processor_func': process_call, 'priority': 6} # Prioridad alta
|
||||
]
|
184
paste.py
184
paste.py
|
@ -0,0 +1,184 @@
|
|||
# processors/process_call.py
|
||||
# -*- coding: utf-8 -*-
|
||||
import sympy
|
||||
import traceback
|
||||
# Asumiendo que estas funciones ahora existen y están adaptadas
|
||||
from .processor_utils import get_sympy_representation, sympy_expr_to_scl, format_variable_name, get_target_scl_name
|
||||
from .symbol_manager import SymbolManager # Necesitamos pasar el symbol_manager
|
||||
|
||||
# Definir sufijo globalmente o importar
|
||||
SCL_SUFFIX = "_sympy_processed"
|
||||
|
||||
def process_call(instruction, network_id, sympy_map, symbol_manager: SymbolManager, data):
|
||||
instr_uid = instruction["instruction_uid"]
|
||||
# Get original type before potential suffix/error was added by x1 or previous passes
|
||||
# This requires storing the original type perhaps, or removing known suffixes
|
||||
# Let's assume 'block_type' (FC/FB) and 'block_name' are correct from x1
|
||||
block_name = instruction.get("block_name", f"UnknownCall_{instr_uid}")
|
||||
block_type = instruction.get("block_type") # FC, FB
|
||||
instance_db = instruction.get("instance_db") # Nombre del DB de instancia (para FB)
|
||||
|
||||
# Check if already processed
|
||||
if instruction.get("type", "").endswith(SCL_SUFFIX) or "_error" in instruction.get("type", ""):
|
||||
return False
|
||||
|
||||
# Formatear nombres SCL (para la llamada final)
|
||||
block_name_scl = format_variable_name(block_name)
|
||||
instance_db_scl = format_variable_name(instance_db) if instance_db else None
|
||||
|
||||
# --- Manejo de EN ---
|
||||
en_input = instruction["inputs"].get("en")
|
||||
sympy_en_expr = get_sympy_representation(en_input, network_id, sympy_map, symbol_manager) if en_input else sympy.true
|
||||
|
||||
if sympy_en_expr is None:
|
||||
# print(f"DEBUG Call {instr_uid}: EN dependency not ready.")
|
||||
return False # Dependencia EN no resuelta
|
||||
|
||||
# --- Procesar Parámetros de Entrada ---
|
||||
scl_call_params = []
|
||||
processed_inputs = {"en"} # Track processed pins to avoid duplicates if 'en' is also listed elsewhere
|
||||
dependencies_resolved = True
|
||||
|
||||
# Iterar sobre las entradas que x1 debería haber poblado
|
||||
# Ordenar por nombre de pin para consistencia en la llamada SCL
|
||||
input_pin_names = sorted(instruction.get("inputs", {}).keys())
|
||||
|
||||
for pin_name in input_pin_names:
|
||||
if pin_name not in processed_inputs: # Skip 'en' if already handled
|
||||
source_info = instruction["inputs"][pin_name]
|
||||
|
||||
# Get the representation of the source (SymPy, constant, or SCL string)
|
||||
source_sympy_or_const = get_sympy_representation(source_info, network_id, sympy_map, symbol_manager)
|
||||
|
||||
if source_sympy_or_const is None:
|
||||
# print(f"DEBUG Call {instr_uid}: Input param '{pin_name}' dependency not ready.")
|
||||
dependencies_resolved = False
|
||||
break # Exit if one dependency is not ready
|
||||
|
||||
# Convert the expression/constant to SCL for the call
|
||||
# Simplification of inputs is generally not needed here, convert directly
|
||||
param_scl_value = sympy_expr_to_scl(source_sympy_or_const, symbol_manager)
|
||||
|
||||
# Parameter pin name needs formatting for SCL
|
||||
pin_name_scl = format_variable_name(pin_name)
|
||||
|
||||
# Special check for DB_ANY or ANY_POINTER - pass name directly without :=
|
||||
# We need the original parameter type info for this, which is not in the simplified JSON.
|
||||
# WORKAROUND: Check if param_scl_value looks like a DB name ("DB_NAME")
|
||||
# This is heuristic and might be wrong. Ideally, x1 should pass type info.
|
||||
# For now, we assume standard 'Param := Value' syntax.
|
||||
# if param_scl_value.startswith('"') and param_scl_value.endswith('"') and block_type == "FC": # Heuristic for DB_ANY?
|
||||
# scl_call_params.append(f"{pin_name_scl} := {param_scl_value}") # Still use := for clarity? TIA might infer
|
||||
# else:
|
||||
scl_call_params.append(f"{pin_name_scl} := {param_scl_value}")
|
||||
|
||||
processed_inputs.add(pin_name)
|
||||
|
||||
if not dependencies_resolved:
|
||||
return False
|
||||
|
||||
# --- Construcción de la Llamada SCL (con parámetros) ---
|
||||
scl_call_body = ""
|
||||
param_string = ", ".join(scl_call_params) # Join parameters with commas
|
||||
|
||||
if block_type == "FB":
|
||||
if not instance_db_scl:
|
||||
print(f"Error: Call FB '{block_name_scl}' (UID {instr_uid}) sin instancia.")
|
||||
instruction["scl"] = f"// ERROR: FB Call {block_name_scl} sin instancia"
|
||||
instruction["type"] = f"Call_FB_error" # Mark with error
|
||||
return True # Processed (with error)
|
||||
# FB Call: InstanceName(Param1 := Value1, Param2 := Value2);
|
||||
scl_call_body = f"{instance_db_scl}({param_string});"
|
||||
elif block_type == "FC":
|
||||
# FC Call: BlockName(Param1 := Value1, Param2 := Value2);
|
||||
scl_call_body = f"{block_name_scl}({param_string});"
|
||||
else:
|
||||
print(f"Advertencia: Tipo de bloque no soportado para Call UID {instr_uid}: {block_type}")
|
||||
scl_call_body = f"// ERROR: Call a bloque tipo '{block_type}' no soportado: {block_name_scl}"
|
||||
# Mark instruction type with error
|
||||
instruction["type"] = f"Call_{block_type or 'Unknown'}_error" # Add specific type if known
|
||||
|
||||
|
||||
# --- Aplicar Condición EN (usando la expresión SymPy EN) ---
|
||||
scl_final = ""
|
||||
if sympy_en_expr != sympy.true:
|
||||
# Simplify the EN condition before converting to SCL
|
||||
try:
|
||||
#simplified_en_expr = sympy.simplify_logic(sympy_en_expr, force=True)
|
||||
simplified_en_expr = sympy.logic.boolalg.to_dnf(sympy_en_expr, simplify=True)
|
||||
except Exception as e:
|
||||
print(f"Error simplifying EN for Call {instr_uid} ({block_name_scl}): {e}")
|
||||
simplified_en_expr = sympy_en_expr # Fallback
|
||||
en_condition_scl = sympy_expr_to_scl(simplified_en_expr, symbol_manager)
|
||||
|
||||
# Avoid IF TRUE/FALSE blocks
|
||||
if en_condition_scl == "TRUE":
|
||||
scl_final = scl_call_body
|
||||
elif en_condition_scl == "FALSE":
|
||||
scl_final = f"// Call {block_name_scl} (UID {instr_uid}) condition simplified to FALSE."
|
||||
# Also update type to avoid further processing?
|
||||
# instruction["type"] = f"Call_{block_type}{SCL_SUFFIX}_Optimized"
|
||||
else:
|
||||
# Indent the call body within the IF block
|
||||
indented_call = "\n".join([f" {line}" for line in scl_call_body.splitlines()])
|
||||
scl_final = f"IF {en_condition_scl} THEN\n{indented_call}\nEND_IF;"
|
||||
else:
|
||||
# No IF needed if EN is always TRUE
|
||||
scl_final = scl_call_body
|
||||
|
||||
# --- Actualizar Instrucción y Mapa SymPy ---
|
||||
instruction["scl"] = scl_final # Guardar el SCL final generado
|
||||
|
||||
# Update instruction type to mark as processed (unless already marked as error)
|
||||
if "_error" not in instruction.get("type", ""):
|
||||
instruction["type"] = f"Call_{block_type}{SCL_SUFFIX}"
|
||||
|
||||
# Propagar el estado ENO (es la expresión SymPy de EN)
|
||||
map_key_eno = (network_id, instr_uid, "eno")
|
||||
sympy_map[map_key_eno] = sympy_en_expr # Guardar la expresión SymPy para ENO
|
||||
|
||||
# --- Propagar Valores de Salida (Importante pero complejo) ---
|
||||
# Esto requiere conocer la interfaz del bloque llamado (que no tenemos aquí directamente)
|
||||
# O asumir convenciones estándar (ej. FCs tienen Ret_Val, FBs tienen outputs en su instancia)
|
||||
|
||||
# Heurística simple: Si es un FC, intentar propagar Ret_Val si existe en outputs
|
||||
# Si es un FB, las salidas se acceden a través de la instancia (e.g., "MyInstance".Output1)
|
||||
# Por ahora, dejaremos la propagación de salidas más avanzada para una mejora futura
|
||||
# o requerirá pasar información de la interfaz del bloque llamado.
|
||||
|
||||
# Ejemplo básico (necesita mejorar):
|
||||
# for pin_name, dest_list in instruction.get("outputs", {}).items():
|
||||
# if pin_name != 'eno' and dest_list: # Asumir que hay un destino
|
||||
# map_key_out = (network_id, instr_uid, pin_name)
|
||||
# pin_name_scl = format_variable_name(pin_name)
|
||||
# if block_type == "FB" and instance_db_scl:
|
||||
# # Salida de FB: "Instancia".NombrePin
|
||||
# output_scl_access = f"{instance_db_scl}.{pin_name_scl}"
|
||||
# # Podríamos guardar el string SCL o crear/obtener un Symbol
|
||||
# sympy_out_symbol = symbol_manager.get_symbol(output_scl_access)
|
||||
# sympy_map[map_key_out] = sympy_out_symbol if sympy_out_symbol else output_scl_access # Prefiere Symbol
|
||||
# elif block_type == "FC":
|
||||
# # Salida de FC: Requiere asignar a una variable (temporal o de interfaz)
|
||||
# # Esto se complica porque el destino está en 'dest_list'
|
||||
# if len(dest_list) == 1 and dest_list[0].get("type") == "variable":
|
||||
# target_var_name = format_variable_name(dest_list[0].get("name"))
|
||||
# # Guardar el nombre del destino SCL que contendrá el valor
|
||||
# sympy_map[map_key_out] = target_var_name
|
||||
# # Necesitaríamos modificar scl_final para incluir la asignación:
|
||||
# # target_var_name := FC_Call(...); (requiere reestructurar la generación SCL)
|
||||
# else:
|
||||
# # Múltiples destinos o destino no variable es complejo para FC outputs
|
||||
# sympy_map[map_key_out] = f"/* TODO: Assign FC output {pin_name_scl} */"
|
||||
|
||||
|
||||
return True
|
||||
|
||||
|
||||
# --- Processor Information Function ---
|
||||
def get_processor_info():
|
||||
"""Devuelve la información para las llamadas a FC y FB."""
|
||||
# Asegurarse que los type_name coincidan con los usados en x1 y x2
|
||||
return [
|
||||
{'type_name': 'call_fc', 'processor_func': process_call, 'priority': 6}, # Prioridad alta
|
||||
{'type_name': 'call_fb', 'processor_func': process_call, 'priority': 6} # Prioridad alta
|
||||
]
|
1518
x1_to_json.py
1518
x1_to_json.py
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue