Mass Lenguaje de Programación (3) Comandos

Anterior Post  
Siguiente Post 


Veamos hoy cómo están implementados los comandos en Mass (ver repo). En el proyecto de librería de clases, tengo:



Hay comandos para if, while, for, for each, etc…. Todos implementan la interfaz ICommand:


public interface ICommand
{
    object Execute(Context context);
}

Vean que es muy parecido a IExpression. Igual quise mantener comandos y expresiones por separado, por lo menos en esta primera implementación, para tener un claro delineamiento de los conceptos de base del lenguaje.


Un ejemplo típico de comando es el WhileCommand (parte del código):


public class WhileCommand : ICommand
{
    private static int hashcode = typeof(WhileCommand).GetHashCode();

    private IExpression condition;
    private ICommand command;

    public WhileCommand(IExpression condition, ICommand command)
    {
        this.condition = condition;
        this.command = command;
    }

    public object Execute(Context context)
    {
        for (object value = this.condition.Evaluate(context); 
            value != null && !false.Equals(value);
            value = this.condition.Evaluate(context))
        {
            this.command.Execute(context);
            if (context.HasContinue())
                context.ClearContinue();
            if (context.HasBreak())
            {
                context.ClearBreak();
                break;
            }
        }

        return null;
    }
}

Para Mass: cualquier valor null o false es falso. Todo lo demás es verdadero. Un tema a refactorizar: poner un método IsFalse para se usado tanto en la implementación de While como de If.


Otro ejemplo es el ForEachCommand (parte del código):


public class ForEachCommand : ICommand
{
    private string name;
    private IExpression expression;
    private ICommand command;

    public ForEachCommand(string name, IExpression expression, ICommand command)
    {
        this.name = name;
        this.expression = expression;
        this.command = command;
    }

    public object Execute(Context context)
    {
        var values = (IEnumerable)this.expression.Evaluate(context);

        foreach (var value in values)
        {
            context.Set(this.name, value);
            this.command.Execute(context);
            if (context.HasContinue())
                context.ClearContinue();
            if (context.HasBreak())
            {
                context.ClearBreak();
                break;
            }
        }

        return null;
    }
}

Vean que para Mass, todo lo que sea IEnumerable se puede usar para ser consumido por este comando. Tuve que poner algunos datos en el contexto, para saber si se había hecho un break o un continue.


Y como siempre, todo esto desarrollado con TDD: pueden ver los commits del repo.


Próximos posts: Lexer y Parser, ejemplos de Mass para scripting.


Nos leemos!


Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

This entry was posted in 11699, 1389, 15035, 17834, 5374, 8870. Bookmark the permalink.

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>