From 29a70dcdc46a492547afc60f8889ceebd5c50270 Mon Sep 17 00:00:00 2001 From: Amitay Horwitz Date: Fri, 21 Aug 2015 16:26:23 +0300 Subject: [PATCH] Added another example program + some documentation --- README.md | 19 +++++++++++++++++++ specs/lisp-spec.js | 24 ++++++++++++++++++++---- src/lisp.js | 18 +++++++++++++++++- 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 2f0f9d4..888eeb7 100644 --- a/README.md +++ b/README.md @@ -80,4 +80,23 @@ var map = [ ['map', 'inc', 'coll'] ]; console.log(lisp.run(map)); // Prints [2, 3, 4] + +// Contains (checks if element exists in collection) +var contains = [ + // Define contains function + ['define', 'contains', + ['lambda', ['el', 'coll'], + ['if', ['empty', 'coll'], + false, + ['or', + ['=', 'el', ['car', 'coll']], + ['contains', 'el', ['cdr', 'coll']]]]]], + + // Define some collection + ['define', 'coll', ['quote', [1, 2, 3]]], + + // Check if collection contains 2 + ['contains', 2, 'coll'] +]; +console.log(lisp.run(contains)); // Prints true ``` diff --git a/specs/lisp-spec.js b/specs/lisp-spec.js index 57696fa..bbf0a70 100644 --- a/specs/lisp-spec.js +++ b/specs/lisp-spec.js @@ -143,7 +143,7 @@ describe('lispjs', function () { describe('programs tests', function () { it('should calculate fibonacci recursively', function () { - var prog = + var fib = ['define', 'fib', ['lambda', ['n'], ['if', ['<', 'n', 2], @@ -152,7 +152,7 @@ describe('lispjs', function () { ['fib', ['-', 'n', 1]], ['fib', ['-', 'n', 2]]]]]]; - var fibEnv = lisp.evaluate(prog, lisp.defaultEnv)[1]; + var fibEnv = lisp.evaluate(fib, lisp.defaultEnv)[1]; var tests = [ {input: 0, output: 1}, @@ -168,14 +168,14 @@ describe('lispjs', function () { }); it('should calculate factorial recursively', function () { - var prog = + var fact = ['define', 'fact', ['lambda', ['n'], ['if', ['<', 'n', 2], 1, ['*', 'n', ['fact', ['-', 'n', 1]]]]]]; - var factEnv = lisp.evaluate(prog, lisp.defaultEnv)[1]; + var factEnv = lisp.evaluate(fact, lisp.defaultEnv)[1]; var tests = [ {input: 0, output: 1}, @@ -215,6 +215,22 @@ describe('lispjs', function () { assert.deepEqual(lisp.run(prog), [2, 3, 4]); }); + + it('should search for element in collection', function () { + var contains = + ['define', 'contains', + ['lambda', ['el', 'coll'], + ['if', ['empty', 'coll'], + false, + ['or', + ['=', 'el', ['car', 'coll']], + ['contains', 'el', ['cdr', 'coll']]]]]]; + + var containsEnv = lisp.evaluate(contains, lisp.defaultEnv)[1]; + + assert.equal(lisp.getResult(['contains', 0, ['quote', [1, 2, 3]]], containsEnv), false); + assert.equal(lisp.getResult(['contains', 2, ['quote', [1, 2, 3]]], containsEnv), true); + }); }); }); \ No newline at end of file diff --git a/src/lisp.js b/src/lisp.js index d191e99..cc14508 100644 --- a/src/lisp.js +++ b/src/lisp.js @@ -1,3 +1,7 @@ +/** + * Evaluate an expression with given environment. + * Returns a tuple [result, env] - with evaluation result and new environment + */ function evaluate(expr, env) { if (isBound(expr, env)) { return [env[expr], env]; @@ -14,10 +18,19 @@ function evaluate(expr, env) { return [expr, env]; } +/** + * Evaluate an expression with given environment. + * Returns just the evaluation result + */ function getResult(expr, env) { return evaluate(expr, env)[0]; } +/** + * Run a program in with default environment. + * A program is a list of expressions. + * Returns the evaluation result of the last expression + */ function run(prog) { var result = [null, defaultEnv]; prog.forEach(function (expr) { @@ -76,6 +89,9 @@ var defaultEnv = { '-': function (a, b) { return a - b; }, '*': function (a, b) { return a * b; }, '/': function (a, b) { return a / b; }, + and: function (a, b) { return a && b; }, + or: function (a, b) { return a || b; }, + not: function (expr) { return !expr; }, car: function (xs) { return xs[0]; }, cdr: function (xs) { return xs.slice(1); }, cons: function (x, xs) { return [x].concat(xs); }, @@ -87,4 +103,4 @@ module.exports = { evaluate: evaluate, getResult: getResult, run: run -}; \ No newline at end of file +};