AjLisp in Ruby (2) Context with Name and Values

Previous Post

One of the first classes I implemented in AjLispRb is the environment. This time I called it a context: a dictionary where to save name/values, to store the atom values. The code:

module AjLisp
class Context
    def initialize(parent = nil)
        @parent = parent
        @values = Hash.new
    def getValue(name)
        if @values.has_key?(name)
            return @values[name]
        if @parent != nil
            return @parent.getValue(name)
        return nil
    def setValue(name, value)
        @values[name] = value

The class was coded using TDD, the first tests at test/test_context.rb. Some tests:

def test_not_defined_is_nil
    context = AjLisp::Context.new
def test_set_and_get_value
    context = AjLisp::Context.new
    context.setValue(:foo, "bar")
    assert_equal("bar", context.getValue(:foo))
def test_get_value_from_parent
    parent = AjLisp::Context.new
    parent.setValue(:foo, "bar")
    context = AjLisp::Context.new(parent)
    assert_equal("bar", context.getValue(:foo))

Initially, I used strings for names, but now I’m using Ruby symbols like :foo. I have a test that ensures the independence of parent and child context values:

def test_override_value_from_parent
    parent = AjLisp::Context.new
    parent.setValue(:foo, "bar")
    context = AjLisp::Context.new(parent)
    context.setValue(:foo, "bar2")
    assert_equal("bar2", context.getValue(:foo))
    assert_equal("bar", parent.getValue(:foo))

Each context can have a parent. There is a top context, defined in lib/ajlisp.rb:

module AjLisp
@context = Context.new
@context.setValue :quote, FPrimitiveQuote.instance
@context.setValue :first, PrimitiveFirst.instance
@context.setValue :rest, PrimitiveRest.instance
@context.setValue :cons, PrimitiveCons.instance
@context.setValue :list, PrimitiveList.instance
@context.setValue :lambda, FPrimitiveLambda.instance
@context.setValue :flambda, FPrimitiveFLambda.instance
@context.setValue :mlambda, FPrimitiveMLambda.instance
@context.setValue :let, FPrimitiveLet.instance
@context.setValue :define, FPrimitiveDefine.instance
@context.setValue :do, FPrimitiveDo.instance
@context.setValue :if, FPrimitiveIf.instance
@context.setValue :definef, FPrimitiveDefinef.instance
@context.setValue :definem, FPrimitiveDefinem.instance
@context.setValue :+, PrimitiveAdd.instance
@context.setValue :-, PrimitiveSubtract.instance
@context.setValue :*, PrimitiveMultiply.instance
@context.setValue :/, PrimitiveDivide.instance
def self.context
    return @context
# ...

New context are created in many primitives. At the begin, there is a top context like:

If you have a defined form that returns the second element of a list:

(define second (a) (first (rest a)))

now you have a top context with the new slot:

The top context has a new slot named second with a lambda value (lambda (a) (first (rest a))

When you invoke:

(second (quote (one two three)))

during the invocation a new context is created, its parent set to the top context, and having a new name/value pair:

That context is discarded after second evaluation (unless the context were referenced by recently created closure, details in upcoming post). When you define a simple value:

(define one 1)

the top context is modified, to have a new name/value pair:

Next topics: primitives and special form primitives, their invocation, closures, macros, native methods invocation.

Keep tuned!

Angel “Java” Lopez



One thought on “AjLisp in Ruby (2) Context with Name and Values

  1. Pingback: AjLisp in Ruby (1) Structure, Classes and Tests « Angel “Java” Lopez on Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s