Evaluación de Expresiones en JavaScript y Python
Clase 42 de 58 • Curso de Creación de Lenguajes de Programación: Intérpretes
Resumen
¿Qué es eval
y por qué es importante?
La función eval
es una herramienta poderosa que permite evaluar expresiones de texto en tiempo de ejecución en lenguajes como JavaScript y Python. Sin embargo, su uso indiscriminado puede ser riesgoso debido a la posibilidad de ejecutar código malicioso si no se toman las debidas precauciones. Esencialmente, eval
ejecuta cualquier cadena de texto que se le pase, por lo que se debe evitar su uso con entradas de usuarios o datos externos no confiables.
¿Cómo se estructura el evaluador para enteros?
Para desarrollar un evaluador de enteros, primero se deben crear pruebas que guíen el desarrollo de la función evaluate
. Implementar pruebas permite definir cómo debería comportarse el código antes de escribirlo.
# Ejemplo de una suite de pruebas en Python
class EvaluatorTest(TestCase):
def test_integer_evaluation(self):
tests = [
("5", 5),
("10", 10)
]
for source, expected in tests:
evaluated = evaluate_test(source)
test_integers(evaluated, expected)
En este fragmento, se define una función de prueba test_integer_evaluation
que evalúa distintas cadenas y comprueba que su valor coincida con el esperado.
¿Cómo se implementa la función evaluate
?
La implementación de evaluate
es esencial para interpretar los nodos AST (Abstract Syntax Tree) y convertirlos en objetos de nuestro sistema. Se empieza con los nodos de programa y se avanza hacia los nodos de expresión e integer, aplicando recursividad.
# Implementación básica de evaluate
def evaluate(node: AST.Node) -> Optional[Object]:
node_type = type(node)
if node_type == AST.Program:
return evaluate_statements(node.statements)
elif node_type == AST.ExpressionStatement:
if node.expression is not None:
return evaluate(node.expression)
elif node_type == AST.Integer:
return Integer(node.value)
return None
La función evaluate
es recursiva y puede recibir diferentes tipos de nodos, comenzando desde el nodo del programa general hasta nodos más específicos.
¿Cómo se asegura la correcta evaluación de objetos enteros?
La función evaluate_statements
recorre los statements de un programa y utiliza evaluate
de forma recursiva para interpretar cada uno.
def evaluate_statements(statements: List[AST.Statement]) -> Optional[Object]:
result = None
for statement in statements:
result = evaluate(statement)
return result
La función se asegura de recorrer todos los statements y devolver el objeto evaluado. También se añaden validaciones para corroborar que los tipos y valores de los objetos son correctos.
¿Qué sigue después de los enteros?
Una vez implementada la base para la evaluación de enteros, el siguiente paso es ampliar el evaluador para manejar otros tipos de nodos como booleanos, operadores, return statements y llamadas a funciones. Este proceso de expansión sigue la misma lógica recursiva, asegurando que todos los posibles nodos de un programa puedan ser interpretados adecuadamente.
Este proceso de desarrollo es iterativo y requiere agregar más pruebas y casos para validar la funcionalidad a medida que nuestro lenguaje de programación Platzi crece y se enriquece con nuevas características. La clave del éxito reside en definir una lógica clara y efectiva para la evaluación de cada componente del AST.