<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -3,10 +3,10 @@ require_once dirname(__FILE__) . '/tree.php';
 
 class FuTreeDSLInterpreter extends Fu {
 
-	var $body, $defs = array(), $output;
+	var $body, $defs = array(), $outer, $output;
 
 	function evaluate($node) {
-		if ($this-&gt;defed($name = $node-&gt;value())) { return $this-&gt;defs[$name]; }
+		if ($scope = $this-&gt;scopeWithDef($name = $node-&gt;value())) { return $scope-&gt;defs[$name]; }
 		if ($incomprisable = $this-&gt;incomprisable($name)) {
 			return $incomprisable-&gt;call(array($node-&gt;firstInner())); }
 		throw err('Undefined symbol')-&gt;ofName($name); }
@@ -32,7 +32,7 @@ class FuTreeDSLInterpreter extends Fu {
 	function symNull()  { return null;  }
 	function symNode($node) { return $node; }
 	function symStr($node) { return $node-&gt;value(); }
-	function symFn($node) { return with(new $this)-&gt;body($node); }
+	function symFn($node) { return with(new $this)-&gt;outer($this)-&gt;body($node); }
 	function symNodeOf($node) { return n($this-&gt;evaluate($node)); }
 	function symExpr($node) { return eval('return ' . join(NL, $node-&gt;values()) . ';'); }
 	function symCall($node) { return $this-&gt;evaluate($node)-&gt;output($this-&gt;output)-&gt;call(); }
@@ -41,10 +41,15 @@ class FuTreeDSLInterpreter extends Fu {
 	function incomprisable($name) {
 		if (method_exists($this, $method = 'sym'.$name)) { return $this-&gt;method($method); } }
 
-	function defed($name) { return array_key_exists($name, $this-&gt;defs); }
+	// Retrieves the first instance, looking back through outers, that has `$name` defined.
+	function scopeWithDef($name) {
+		if (array_key_exists($name, $this-&gt;defs)) { return $this; }
+		if ($this-&gt;outer) { return $this-&gt;outer-&gt;{__FUNCTION__}($name); }
+		return false; }
 
+	// Creates a definition.
 	function symDef($node) {
-		if ($this-&gt;defed($name = $node-&gt;value())) { throw err('Redefinition')-&gt;of($name); }
+		if ($this-&gt;scopeWithDef($name = $node-&gt;value())) { throw err('Redefinition')-&gt;of($name); }
 		return $this-&gt;defs[$name] = ($v = $node-&gt;next()) ? $this-&gt;evaluate($v) : null; }
 
 	function symIf($node) {</diff>
      <filename>lib/tree_dsl.php</filename>
    </modified>
    <modified>
      <diff>@@ -122,4 +122,22 @@ class DefSpec extends DSLInterpreterSpec {
 			_($err-&gt;of())-&gt;shouldBe($this-&gt;undefed()-&gt;value()); } }
 
 	function _should_allow_redef_of_incomprisables() {
-		_($this-&gt;subj-&gt;run(nList(n('def', n('if'), n('true')), n('if'))))-&gt;shouldBe(true); } }
\ No newline at end of file
+		_($this-&gt;subj-&gt;run(nList(n('def', n('if'), n('true')), n('if'))))-&gt;shouldBe(true); } }
+
+
+class LexicalScopeSpec extends DSLInterpreterSpec {
+
+	function _defs_in_fns_should_not_exist_outside() {
+		$tree = nList(n('call', n('fn', n('def', $this-&gt;undefed(), n('true')))), $this-&gt;undefed());
+		if (_($err = rescue(array($this-&gt;subj, 'run'), array($tree)))-&gt;shouldNotBe(null)) {
+			_($err-&gt;msg())-&gt;shouldBe('Undefined symbol');
+			_($err-&gt;ofName())-&gt;shouldBe($this-&gt;undefed()-&gt;value()); } }
+
+	function _defs_outside_fns_should_exist_inside() {
+		$tree = nList(n('def', $this-&gt;undefed(), n('true')), n('call', n('fn', $this-&gt;undefed())));
+		_($this-&gt;subj-&gt;run($tree))-&gt;shouldBe(true); }
+
+	function _defs_outside_multiple_fns_should_exist_inside() {
+		$tree = nList(n('def', $this-&gt;undefed(), n('true')),
+			n('call', n('fn', n('call', n('fn', $this-&gt;undefed())))));
+		_($this-&gt;subj-&gt;run($tree))-&gt;shouldBe(true); } }
\ No newline at end of file</diff>
      <filename>spec/tree_dsl.php</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>ccdf7d1d37f6297b1e301d566b88ba1ffb9271ae</id>
    </parent>
  </parents>
  <author>
    <name>ole</name>
    <email>oliver.saunders@gmail.com</email>
  </author>
  <url>http://github.com/olliesaunders/fluidics/commit/d4c30959f6eef96079eaf21be65659a3a448a91c</url>
  <id>d4c30959f6eef96079eaf21be65659a3a448a91c</id>
  <committed-date>2009-11-09T05:43:43-08:00</committed-date>
  <authored-date>2009-11-09T05:43:43-08:00</authored-date>
  <message>Tree DSL: Now has lexical scope.</message>
  <tree>66c07696957aa042bd3e473f564c611298fa623b</tree>
  <committer>
    <name>ole</name>
    <email>oliver.saunders@gmail.com</email>
  </committer>
</commit>
