AjLisp en Javascript (Parte 2) Evaluación de Listas, Formas y Formas Especiales

Published on Author lopezLeave a comment

Anterior Post
Siguiente Post

En el anterior post presenté la estructura y creación de átomos y listas. Pero ¿Cómo se evalúa una lista en AjLisp? Como en otras implementaciones de Lisp, la cabeza de la lista apunta a algo (lo que se llama una forma o forma especial) que se aplica al resto de los elementos. Este es el comienzo del proceso de evaluación de una lista:

List.prototype.evaluate = function(environment) 
{
    var form = this.first().evaluate(environment);		
    return form.apply(this, environment);
}	

El primer elemento debe ser un elemento que evaluado, da un objecto con un .apply como méetodo. Hay dos clases de formas: las normales y las especiales. La implementación de Form:

function Form() {
}
Form.prototype.evaluate = function(environment) { return this; }
Form.prototype.apply = function(list, environment) 
{ 
    if (isNil(list)) return this.eval(list, environment);
    var rest = list.rest();
    if (rest != null)
        rest = rest.evaluateList(environment);
    return this.eval(rest, environment); 
}

La implementación de las especiales:

function SpecialForm() {
}
SpecialForm.prototype.evaluate = function(environment) { return this; }
SpecialForm.prototype.apply = function(list, environment) 
{ 
    if (isNil(list)) return this.eval(list, environment);
    return this.eval(list.rest(), environment);
}

¿Notan la diferencia? Los elementos del resto de la lista SON EVALUADOS en una forma normal. Al contrario, una forma especial no los evalúa. ¿Por qué esa diferencia? Las formas especiales son “primitivas” como (if <cond> <then> <else>…) donde las partes <then> <else>… pueden evaluarse o no bajo el control de la forma especial. Vean:

Special Forms in Lisp

Special forms are those expressions in the Lisp language which do not follow normal rules for evaluation. Some such forms are necessary as primitives of the language, while others may be desirable in order to improve readability, control the evaluation environment, implement abstraction and modularity, affect the flow of control, allow extended scoping mechanisms, define functions which accept a variable number of arguments, or achieve greater efficiency. There exist several long-standing mechanisms for specifying the definition of special forms: FEXPR’s, NLAMBDA’s, and MACRO’s.

¿Ejemplos de Form? Los escribí usando instancias, redefiniendo su método eval:

var listForm = new Form();
listForm.eval = function eval(list) 
{
	return list;
}
var nilpForm = new Form();
nilpForm.eval = function eval(list) 
{
	if (isNil(list))
		return true;
		
	return isNil(list.first());
}
var listpForm = new Form();
listpForm.eval = function eval(list) 
{
	if (isNil(list))
		return true;
		
	return isList(list.first());
}

Un ejemplo de forma especial, el ‘if’:

var ifForm = new SpecialForm();
ifForm.eval = function eval(list, env)
{
	var cond = evaluate(list.first(), env);
	var then = list.rest().first();
	var elsebody = list.rest().rest();
	
	if (!isNil(cond) && cond != false)
		return evaluate(then, env);
	while (!isNil(elsebody)) 
	{
		result = evaluate(elsebody.first(), env);
		elsebody = elsebody.rest();
	}
	
	return result;			
}

Se exponen en el enviroment global:

// Environment
var environment = new Environment();
environment.list = listForm;
environment.first = firstForm;
environment.rest = restForm;
environment.cons = consForm;
environment['do'] = doForm;
environment['if'] = ifForm;
// more settings in environment

Temas para próximos posts: environments, closures, lambdas, macros, el parser y 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 *