Add write, render and optional values to LambdaContext
diff --git a/lib/mustache.dart b/lib/mustache.dart
index eab0f6c..742370c 100644
--- a/lib/mustache.dart
+++ b/lib/mustache.dart
@@ -61,24 +61,26 @@
 abstract class LambdaContext {
   
   /// Render the current section tag in the current context and return the
-  /// result as a string.
-  String renderString();
+  /// result as a string. If provided, value will be added to the top of the
+  /// context's stack.
+  String renderString({Object value});
   
-  /// Render and directly output the current section tag.
-  //TODO note in variable case need to capture output in a string buffer and escape.
-  //void render();
+  /// Render and directly output the current section tag. If provided, value
+  /// will be added to the top of the context's stack.
+  void render({Object value});
   
-  /// Output a string.
-  //TODO note in variable case need to capture output in a string buffer and escape.
-  //void write(Object object);
+  /// Output a string. The output will not be html escaped, and will be written
+  /// before the output returned from the lambda.
+  void write(Object object);
   
   /// Get the unevaluated template source for the current section tag.
   String get source;
   
-  /// Evaluate the string as a mustache template using the current context.
-  String renderSource(String source);  
+  /// Evaluate the string as a mustache template using the current context. If
+  /// provided, value will be added to the top of the context's stack.
+  String renderSource(String source, {Object value});  
   
-  /// Lookup the value of a variable in the current context.
+  /// Lookup the value of a variable in the current context. 
   Object lookup(String variableName);
 }
 
diff --git a/lib/src/lambda_context.dart b/lib/src/lambda_context.dart
index 37056a9..158101c 100644
--- a/lib/src/lambda_context.dart
+++ b/lib/src/lambda_context.dart
@@ -20,27 +20,26 @@
         'LambdaContext accessed outside of callback.', 
         _renderer._templateName, _renderer._source, _node.start);
   }
-  
-  /// Render the current section tag in the current context and return the
-  /// result as a string.
-  String renderString() {
+
+  //TODO is allowing adding value to the stack a good idea?? Not sure.
+  String renderString({Object value}) {
     _checkClosed();
-    return _renderer._renderSubtree(_node);
+    var buffer = new StringBuffer();
+    _renderer._renderSubtree(_node, buffer, value: value);
+    return buffer.toString();
   }
 
-  //FIXME Currently only return values are supported.
-  /// Render and directly output the current section tag.
-//  void render() {
-//    _checkClosed();
-//  }
+  //TODO is allowing adding value to the stack a good idea?? Not sure.
+  void render({Object value}) {
+    _checkClosed();
+    _renderer._renderSubtree(_node, _renderer._sink, value: value);
+  }
 
-  //FIXME Currently only return values are supported.
-  /// Output a string.
-//  void write(Object object) {
-//    _checkClosed();
-//  }
+  void write(Object object) {
+    _checkClosed();
+    _renderer._sink.write(object);
+  }
 
-  /// Get the unevaluated template source for the current section tag.
   String get source {
     _checkClosed();
     
@@ -57,8 +56,8 @@
     return source;
   }
 
-  /// Evaluate the string as a mustache template using the current context.
-  String renderSource(String source) {
+  //TODO is allowing adding value to the stack a good idea?? Not sure.
+  String renderSource(String source, {Object value}) {
     _checkClosed();
     var sink = new StringBuffer();
     // Lambdas used for sections should parse with the current delimiters.
@@ -74,7 +73,11 @@
         _renderer._indent,
         sink,
         _renderer._delimiters);
+    
+    if (value != null) renderer._stack.add(value);
     renderer.render();
+    if (value != null) renderer._stack.removeLast();
+    
     return sink.toString();
   }
 
diff --git a/lib/src/renderer.dart b/lib/src/renderer.dart
index 0387aa0..3c4c054 100644
--- a/lib/src/renderer.dart
+++ b/lib/src/renderer.dart
@@ -232,11 +232,11 @@
     _stack.removeLast();
   }
 
-  String _renderSubtree(node) {
-    var sink = new StringBuffer();
+  void _renderSubtree(node, StringSink sink, {Object value}) {
     var renderer = new _Renderer.subtree(this, node, sink);
+    if (value != null) renderer._stack.add(value);
     renderer.render();
-    return sink.toString();
+    if (value != null) renderer._stack.removeLast();
   }
   
   _renderSection(_Node node) {
@@ -264,8 +264,8 @@
     } else if (value is Function) {
       var context = new _LambdaContext(node, this, isSection: true);
       var output = value(context);
-      context.close();        
-      _write(output);
+      context.close();
+      if (output != null) _write(output);
       
     } else {
       throw _error('Invalid value type for section, '
diff --git a/test/mustache_test.dart b/test/mustache_test.dart
index 8e4f686..6d6cfb5 100644
--- a/test/mustache_test.dart
+++ b/test/mustache_test.dart
@@ -503,8 +503,8 @@
       var values = {'markdown': (ctx) => ctx.source};
       var output = '<dsfsf dsfsdf dfsdfsd>';
       expect(parse(template).renderString(values), equals(output));      
-    });
-
+    });    
+    
     test('Alternate Delimiters', () {
 
       // A lambda's return value should parse with the default delimiters.
@@ -541,6 +541,65 @@
     });
   });
 	
+  group('Lambda context', () {
+    
+    test("LambdaContext write", () {
+      var template = '<{{#markdown}}{{content}}{{/markdown}}>';
+      var values = {'markdown': (ctx) {
+        ctx.write('foo');
+      }};
+      var output = '<foo>';
+      expect(parse(template).renderString(values), equals(output));      
+    });
+
+    test("LambdaContext render", () {
+      var template = '<{{#markdown}}{{content}}{{/markdown}}>';
+      var values = {'content': 'bar', 'markdown': (ctx) {
+        ctx.render();
+      }};
+      var output = '<bar>';
+      expect(parse(template).renderString(values), equals(output));      
+    });
+
+    test("LambdaContext render with value", () {
+      var template = '<{{#markdown}}{{content}}{{/markdown}}>';
+      var values = {'markdown': (LambdaContext ctx) {
+        ctx.render(value: {'content': 'oi!'});
+      }};
+      var output = '<oi!>';
+      expect(parse(template).renderString(values), equals(output));      
+    });
+
+    test("LambdaContext renderString with value", () {
+      var template = '<{{#markdown}}{{content}}{{/markdown}}>';
+      var values = {'markdown': (LambdaContext ctx) {
+        return ctx.renderString(value: {'content': 'oi!'});
+      }};
+      var output = '<oi!>';
+      expect(parse(template).renderString(values), equals(output));      
+    });
+
+    test("LambdaContext write and return", () {
+      var template = '<{{#markdown}}{{content}}{{/markdown}}>';
+      var values = {'markdown': (LambdaContext ctx) {
+        ctx.write('foo');
+        return 'bar';
+      }};
+      var output = '<foobar>';
+      expect(parse(template).renderString(values), equals(output));      
+    });
+
+    test("LambdaContext renderSource with value", () {
+      var template = '<{{#markdown}}{{content}}{{/markdown}}>';
+      var values = {'markdown': (LambdaContext ctx) {
+        return ctx.renderSource(ctx.source, value: {'content': 'oi!'});
+      }};
+      var output = '<oi!>';
+      expect(parse(template).renderString(values), equals(output));      
+    });
+    
+  });
+  
 	group('Other', () {
 		test('Standalone line', () {
 			var val = parse('|\n{{#bob}}\n{{/bob}}\n|').renderString({'bob': []});