Skip to content

Commit ab299eb

Browse files
committed
Actualización de los nodos de Control, Comparacion y Operaciones.
1 parent 9ee091c commit ab299eb

2 files changed

Lines changed: 122 additions & 40 deletions

File tree

core/translation_rules.py

Lines changed: 89 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,11 @@ def block_to_code(block: Dict[str, Any], level: int = 0) -> str:
6363
target = _safe_str(block.get('target', 'res'))
6464
left = _safe_str(block.get('left', '0'))
6565
right = _safe_str(block.get('right', '0'))
66+
# Leemos el operador, pero si viene vacío ("") o es inválido, forzamos el '+'
6667
op = block.get('op', '+')
67-
# Si no hay target, es una expresión suelta (raro en scripts, pero posible)
68+
if not op or op not in ['+', '-', '*', '/']:
69+
op = '+'
70+
# Si no hay target, es una expresión suelta
6871
if not target:
6972
return f"{indent}{left} {op} {right}\n"
7073
return f"{indent}{target} = {left} {op} {right}\n"
@@ -90,9 +93,13 @@ def block_to_code(block: Dict[str, Any], level: int = 0) -> str:
9093

9194
# Comparaciones (Sueltas o para IF)
9295
if b_type == 'py_compare':
93-
# Nota: Normalmente esto iría dentro de un If, pero si está suelto:
9496
left = _safe_str(block.get('left', 'a'))
97+
# Leemos el operador, pero si viene vacío ("") o es inválido, forzamos el '=='
9598
op = block.get('op', '==')
99+
valid_ops = ['==', '!=', '>', '<', '>=', '<=']
100+
if not op or op not in valid_ops:
101+
op = '=='
102+
96103
right = _safe_str(block.get('right', 'b'))
97104
return f"{indent}{left} {op} {right}\n"
98105

@@ -104,6 +111,17 @@ def block_to_code(block: Dict[str, Any], level: int = 0) -> str:
104111
header = f"{indent}if {cond}:\n"
105112
return header + _generate_body(block.get('body', []), level + 1)
106113

114+
# Elif
115+
if b_type == 'py_elif':
116+
cond = _safe_str(block.get('condition', 'True'))
117+
header = f"{indent}elif {cond}:\n"
118+
return header + _generate_body(block.get('body', []), level + 1)
119+
120+
# Else
121+
if b_type == 'py_else':
122+
header = f"{indent}else:\n"
123+
return header + _generate_body(block.get('body', []), level + 1)
124+
107125
# Loops
108126
if b_type == 'py_loop': # For
109127
iterator = _safe_str(block.get('iterator', 'i'))
@@ -131,12 +149,16 @@ def block_to_code(block: Dict[str, Any], level: int = 0) -> str:
131149
header = f"{indent}class {name}{base_str}:\n"
132150
return header + _generate_body(block.get('body', []), level + 1)
133151

134-
# Try/Except
152+
# Try
135153
if b_type == 'py_try':
136154
header = f"{indent}try:\n"
137-
try_body = _generate_body(block.get('body', []), level + 1)
138-
except_blk = f"{indent}except Exception as e:\n{indent} print(e)\n"
139-
return header + try_body + except_blk
155+
return header + _generate_body(block.get('body', []), level + 1)
156+
157+
# Except
158+
if b_type == 'py_except':
159+
err_type = _safe_str(block.get('error_type', 'Exception as e'))
160+
header = f"{indent}except {err_type}:\n"
161+
return header + _generate_body(block.get('body', []), level + 1)
140162

141163
# Otros
142164
if b_type == 'py_return':
@@ -166,7 +188,15 @@ def block_to_code(block: Dict[str, Any], level: int = 0) -> str:
166188
return f"{indent}import {names}\n"
167189

168190
if b_type == 'py_control':
169-
return f"{indent}{block.get('control_type', 'pass')}\n"
191+
# Si el usuario no interactúa con el desplegable, la variable viene vacía.
192+
# Forzamos a que el valor por defecto sea 'break', igual que en la interfaz visual.
193+
c_type = block.get('control_type', 'break')
194+
195+
# Validación extra de seguridad para evitar inyección de código
196+
if c_type not in ['break', 'continue', 'pass']:
197+
c_type = 'break'
198+
199+
return f"{indent}{c_type}\n"
170200

171201
# MACHINE LEARNING
172202
if ml_rules and b_type.startswith('ml_'):
@@ -209,7 +239,14 @@ def _ast_expr_to_str(node):
209239

210240
def _parse_body(stmts: List[ast.stmt]) -> List[Dict[str, Any]]:
211241
"""Parsea recursivamente una lista de sentencias AST."""
212-
return [ast_node_to_block(n) for n in stmts]
242+
blocks = []
243+
for n in stmts:
244+
res = ast_node_to_block(n)
245+
if isinstance(res, list):
246+
blocks.extend(res)
247+
else:
248+
blocks.append(res)
249+
return blocks
213250

214251
def ast_node_to_block(node: ast.AST) -> Dict[str, Any]:
215252
"""Convierte un nodo AST en un diccionario de bloque."""
@@ -245,11 +282,31 @@ def ast_node_to_block(node: ast.AST) -> Dict[str, Any]:
245282

246283
# Control de Flujo (Recursivo)
247284
if isinstance(node, ast.If):
248-
return {
285+
if_block = {
249286
"type": "py_if",
250287
"condition": _ast_expr_to_str(node.test),
251288
"body": _parse_body(node.body)
252289
}
290+
if node.orelse:
291+
# Detección de Elif (En AST, un elif es un if dentro de un orelse)
292+
if len(node.orelse) == 1 and isinstance(node.orelse[0], ast.If):
293+
elif_res = ast_node_to_block(node.orelse[0])
294+
if isinstance(elif_res, dict):
295+
elif_res['type'] = 'py_elif'
296+
return [if_block, elif_res]
297+
elif isinstance(elif_res, list):
298+
elif_res[0]['type'] = 'py_elif'
299+
return [if_block] + elif_res
300+
else:
301+
# Detección de Else tradicional
302+
else_block = {
303+
"type": "py_else",
304+
"body": _parse_body(node.orelse)
305+
}
306+
return [if_block, else_block]
307+
308+
return if_block
309+
253310
if isinstance(node, ast.For):
254311
return {
255312
"type": "py_loop",
@@ -284,13 +341,32 @@ def ast_node_to_block(node: ast.AST) -> Dict[str, Any]:
284341

285342
# Try/Except
286343
if isinstance(node, ast.Try):
287-
# Mapeamos el cuerpo principal al bloque.
288-
# Nota: Los handlers (except) son complejos de mapear visualmente en un solo nodo.
289-
# Por ahora capturamos el cuerpo del try.
290-
return {
344+
try_block = {
291345
"type": "py_try",
292346
"body": _parse_body(node.body)
293347
}
348+
349+
blocks = [try_block]
350+
351+
# Iteramos sobre todos los bloques 'except' que tenga el código
352+
for handler in node.handlers:
353+
err_type = ""
354+
if handler.type:
355+
err_type = _ast_expr_to_str(handler.type)
356+
# Si el error tiene un alias (ej: except ValueError as e)
357+
if handler.name:
358+
err_type += f" as {handler.name}"
359+
else:
360+
err_type = "Exception as e"
361+
362+
except_block = {
363+
"type": "py_except",
364+
"error_type": err_type,
365+
"body": _parse_body(handler.body)
366+
}
367+
blocks.append(except_block)
368+
369+
return blocks
294370

295371
# Expresiones
296372
if isinstance(node, ast.Expr):

0 commit comments

Comments
 (0)