Skip to content
Browse files

Implemented an extended syntax for the macro define.

  • Loading branch information...
1 parent b7b3f17 commit 75d6089006af372ab42c9df7579a7153486bc3ae @dahlia dahlia committed
Showing with 49 additions and 3 deletions.
  1. +10 −2 Lisphp/Runtime/Define.php
  2. +8 −1 Lisphp/Test/RuntimeTest.php
  3. +31 −0 README.markdown
View
12 Lisphp/Runtime/Define.php
@@ -5,8 +5,16 @@
final class Lisphp_Runtime_Define implements Lisphp_Applicable {
function apply(Lisphp_Scope $scope, Lisphp_List $arguments) {
- $scope[$arguments[0]] = $retval = $arguments[1]->evaluate($scope);
- return $retval;
+ $name = $arguments[0];
+ if ($name instanceof Lisphp_Symbol) {
+ $retval = $arguments[1]->evaluate($scope);
+ } else if ($name instanceof Lisphp_List) {
+ $params = $name->cdr();
+ $body = $arguments->cdr();
+ $name = $name->car();
+ $retval = new Lisphp_Runtime_Function($scope, $params, $body);
+ }
+ return $scope[$name] = $retval;
}
}
View
9 Lisphp/Test/RuntimeTest.php
@@ -33,7 +33,7 @@ function testEval() {
function testDefine() {
$define = new Lisphp_Runtime_Define;
- $scope = new Lisphp_Scope;
+ $scope = new Lisphp_Scope(Lisphp_Environment::sandbox());
$result = $define->apply($scope, new Lisphp_List(array(
Lisphp_Symbol::get('*pi*'),
new Lisphp_Literal(pi())
@@ -46,6 +46,13 @@ function testDefine() {
)));
$this->assertEquals(pi(), $result);
$this->assertEquals(pi(), $scope['pi2']);
+ $result = $define->apply($scope, Lisphp_Parser::parseForm('(
+ [add a b]
+ {+ a b}
+ )', $_));
+ $this->assertSame($result, $scope['add']);
+ $this->assertType('Lisphp_Runtime_Function', $result);
+ $this->assertFunction(3, $result, 1, 2);
}
function testLet() {
View
31 README.markdown
@@ -96,6 +96,37 @@ Static methods in imported classes are also imported.
[1]: http://pear.php.net/manual/en/standards.naming.php
+Define custom functions
+-----------------------
+
+There is the macro `lambda` that creates a new function. It takes parameters
+list as first argument, and function body trails.
+
+ (lambda (a b) (+ a b))
+
+Functions are also value, so in order to name it use `define`.
+
+ (define fibonacci
+ {lambda [n]
+ (if (= n 0) 0
+ {if (/= n 1)
+ (+ (fibonacci (- n 1))
+ (fibonacci (- n 2)))
+ 1})})
+
+Following code defines the same function.
+
+ (define (fibonacci n)
+ (if (= n 0) 0
+ {if (/= n 1)
+ (+ (fibonacci (- n 1))
+ (fibonacci (- n 2)))
+ 1}))
+
+Function body can contain one or more forms. All forms are evaluated
+sequentially then the evaluated value of last form is returned.
+
+
About lists and `nil`
---------------------

0 comments on commit 75d6089

Please sign in to comment.
Something went wrong with that request. Please try again.