Escribiendo un intérprete en .NET (Parte 2)

Published on Author lopezLeave a comment

En mi anterior post:

Writing an Interpreter in .NET (Part 1)
Escribiendo un intérprete en .NET (Parte 1)

Presenté expresiones y la implementación de ConstantExpression. Hoy quiero implementar una expresión de variable: una expresión que dado el nombre de una variable retorna su valor asociado. El código de este paso lo pueden bajar desde InterpreterStep02.zip. Y de nuevo, lo quiero implementar usando Test-Driven Development. El código que se bajen es el FINAL del proceso, pero espero que igual sirva como ejemplo de esta forma de desarrollo.

Pueden seguir el código de esta serie y mis progresos en mi AjCodeKata Google Project, en el trunk, dentro del directorio Interpreter. Si quieren ejemplos más complejos, también armados con TDD, ver AjSharp, AjTalk, AjLisp.

La solución de este paso:

Implementé un BindingEnvironment, un lugar donde salvar los nombres de variables y sus valores asociados:

Mis tests:

    public class BindingEnvironmentTests
    {
        [TestMethod]
        public void SetAndGetValue()
        {
            BindingEnvironment environment = new BindingEnvironment();
            environment.SetValue("one", 1);
            Assert.AreEqual(1, environment.GetValue("one"));
        }
        [TestMethod]
        public void GetNullIfUndefinedName()
        {
            BindingEnvironment environment = new BindingEnvironment();
            Assert.IsNull(environment.GetValue("undefined"));
        }
    }

Noten que especifiqué que obtener un valor no definido no da error sino que retorna null. Si hubiera decidido lanzar una excepción, mi tests hubiera debido reflejar esa decisión. Quiero que al usar un lenguaje no sea necesario definir variables, sino simplemente usarlas. Si una variable no “existe”, no está inicializada, entonces es como si tuviera null.

Después, cambié IExpression.Evaluate para que acepte un  BindingEnvironment como parámetro:

    public interface IExpression
    {
        object Evaluate(BindingEnvironment environment);
    }

Escribí una nueva VariableExpression (y adapté la ya existente ConstantExpression):

Mis tests:

        [TestMethod]
        public void EvaluateIntegerVariable()
        {
            BindingEnvironment environment = new BindingEnvironment();
            IExpression expression = new VariableExpression("one");
            environment.SetValue("one", 1);
            Assert.AreEqual(1, expression.Evaluate(environment));
        }
        [TestMethod]
        public void EvaluateUndefinedVariableAsNull()
        {
            BindingEnvironment environment = new BindingEnvironment();
            IExpression expression = new VariableExpression("undefined");
            Assert.IsNull(expression.Evaluate(environment));
        }

Todos los tests, ahora, están en verde:

Pero recuerden: eso es el final. Usando TDD fue pasando de rojo, a verde, a refactor.

Buen code coverage:

Próximos pasos: implementar comandos y un SetCommand: que cambie el valor de una variable. De nuevo, escribir todo eso usando TDD.

Nos leemos!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

Leave a Reply

Your email address will not be published. Required fields are marked *