Daily Archives: August 30, 2011

AjLisp in Javascript (Part 2) List Evaluation, Forms and Special Forms

Previous Post
Next Post

In the previous post I presented the structure and creation of atoms and list. But, how a list is evaluated in AjLisp? As in other lisp implementation, the head of the list points to something (form or special form) to apply to the rest of the elements. This is the initial code in list evaluation:

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

The head should be an element with .apply as method. There are two kinds of form: normal form and special forms. The form implementation:

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); 

The special form implementation:

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);

The difference? The elements of the rest of the list ARE EVALUATED in a normal form. An special form doesn’t evaluate them. Why? Because the special form are “primitives” like (if <cond> <then> <else>…) where the <then> <else>… parts should be evaluated under control of the special form. See:

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.

Form examples? I wrote new forms using instances, overriding their eval method:

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());

An special form example, the ‘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;			

They are exposed in the global environment:

// 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

Topics for upcoming posts: environments, closures, lambdas, macros.

Keep tuned!

Angel “Java” Lopez