Permalink
Browse files

Lambda support

  • Loading branch information...
adambaratz committed Oct 12, 2015
1 parent eceea6b commit 315db819e5c38b088253bd9815326a905fa14f21
Showing with 1,189 additions and 89 deletions.
  1. +0 −1 README.md
  2. +4 −0 config.m4
  3. +7 −2 config.w32
  4. +11 −4 generate-tests.php
  5. +61 −0 mustache_class_method_lambda.cpp
  6. +41 −0 mustache_class_method_lambda.hpp
  7. +212 −82 mustache_data.cpp
  8. +130 −0 mustache_lambda.cpp
  9. +27 −0 mustache_lambda.hpp
  10. +177 −0 mustache_lambda_helper.cpp
  11. +35 −0 mustache_lambda_helper.hpp
  12. +5 −0 mustache_private.hpp
  13. +41 −0 mustache_zend_closure_lambda.cpp
  14. +37 −0 mustache_zend_closure_lambda.hpp
  15. +1 −0 php_mustache.cpp
  16. +1 −0 php_mustache.h
  17. +31 −0 tests/MustacheLambdaHelper__render-closure.phpt
  18. +32 −0 tests/MustacheLambdaHelper__render-object.phpt
  19. +16 −0 tests/Mustache__render-lambda-closure-section.phpt
  20. +16 −0 tests/Mustache__render-lambda-closure-variable.phpt
  21. +23 −0 tests/Mustache__render-lambda-object-method-invisible.phpt
  22. +44 −0 tests/Mustache__render-lambda-object-method.phpt
  23. +23 −0 tests/mustache-spec-~lambdas-escaping.phpt
  24. +25 −0 tests/mustache-spec-~lambdas-interpolation-alternate-delimiters.phpt
  25. +24 −0 tests/mustache-spec-~lambdas-interpolation-expansion.phpt
  26. +23 −0 tests/mustache-spec-~lambdas-interpolation-multiple-calls.phpt
  27. +23 −0 tests/mustache-spec-~lambdas-interpolation.phpt
  28. +24 −0 tests/mustache-spec-~lambdas-inverted-section.phpt
  29. +24 −0 tests/mustache-spec-~lambdas-section-alternate-delimiters.phpt
  30. +24 −0 tests/mustache-spec-~lambdas-section-expansion.phpt
  31. +23 −0 tests/mustache-spec-~lambdas-section-multiple-calls.phpt
  32. +24 −0 tests/mustache-spec-~lambdas-section.phpt
View
@@ -10,7 +10,6 @@ C++ implementation of [Mustache](http://mustache.github.com/) as a PHP extension
All features of Mustache are supported EXCEPT:
-* Lambda functions
* Whitespace rules. All whitespace is kept as it is in the input template.
View
@@ -58,6 +58,10 @@ if test "$PHP_MUSTACHE" != "no"; then
mustache_exceptions.cpp
mustache_data.cpp
mustache_template.cpp
+ mustache_lambda.cpp
+ mustache_lambda_helper.cpp
+ mustache_class_method_lambda.cpp
+ mustache_zend_closure_lambda.cpp
])
AC_DEFINE(HAVE_MUSTACHELIB,1,[ ])
View
@@ -9,13 +9,18 @@ if( PHP_MUSTACHE != "no" ) {
mustache_mustache.cpp \
mustache_exceptions.cpp \
mustache_data.cpp \
- mustache_template.cpp",
- PHP_MUSTACHE_SHARED,
+ mustache_template.cpp \
+ mustache_lambda.cpp \
+ mustache_lambda_helper.cpp \
+ mustache_class_method_lambda.cpp \
+ mustache_zend_closure_lambda.cpp",
+ PHP_MUSTACHE_SHARED,
"-I" + configure_module_dirname + "/mustache/src");
ADD_SOURCES(configure_module_dirname + "/mustache/src", "\
mustache.cpp \
compiler.cpp \
data.cpp \
+ lambda.cpp \
node.cpp \
renderer.cpp \
tokenizer.cpp \
View
@@ -24,9 +24,6 @@
$specs = array();
$specData = array();
foreach( scandir($specDir) as $file ) {
- if( $file[0] == '~' ) {
- continue;
- }
//if( strlen($file) > 5 && substr($file, -5) == '.json' ) {
if( strlen($file) > 4 && substr($file, -4) == '.yml' ) {
$spec = substr($file, 0, -4);
@@ -47,6 +44,16 @@
foreach( $specData as $spec => $data ) {
$tests = $data['tests'];
foreach( $tests as $test ) {
+ $lambda = null;
+ if (isset($test['data']['lambda'])) {
+ if (!isset($test['data']['lambda']['php'])) {
+ continue;
+ }
+
+ $lambda = $test['data']['lambda']['php'];
+ $test['data']['lambda'] = true;
+ }
+
$output = '';
$output .= '--TEST--' . MY_EOL;
$output .= $test['name'] . MY_EOL;
@@ -57,7 +64,7 @@
$output .= '--FILE--' . MY_EOL;
$output .= '<?php' . MY_EOL;
// MAIN
- $output .= '$test = ' . var_export($test, true) . ';' . MY_EOL;
+ $output .= '$test = ' . str_replace('\'lambda\' => true,', '\'lambda\' => function ($text = \'\') { ' . $lambda . ' },', var_export($test, true)) . ';' . MY_EOL;
$output .= '$mustache = new Mustache();' . MY_EOL;
if( !empty($test['partials']) && is_array($test['partials']) ) {
$output .= 'echo $mustache->render($test["template"], $test["data"], $test["partials"]);' . MY_EOL;
@@ -0,0 +1,61 @@
+
+#include "mustache_private.hpp"
+
+ClassMethodLambda::~ClassMethodLambda()
+{
+#if PHP_MAJOR_VERSION >= 7
+ zval_ptr_dtor(object);
+#else
+ zval_ptr_dtor(&object);
+#endif
+ zval_dtor(&function_name);
+}
+
+#if PHP_MAJOR_VERSION >= 7
+int ClassMethodLambda::getUserFunctionParamCount()
+{
+ zend_class_entry * ce = Z_OBJCE_P(object);
+ HashTable * function_table = NULL;
+ zval * zv = NULL;
+ zend_function * function_entry = NULL;
+
+ if( ce != NULL && &ce->function_table != NULL ) {
+ zv = zend_hash_find(&ce->function_table, Z_STR(function_name));
+ if( zv != NULL ) {
+ function_entry = (zend_function *) Z_PTR_P(zv);
+ return function_entry->common.num_args;
+ }
+ }
+
+ return 0;
+}
+#else
+int ClassMethodLambda::getUserFunctionParamCount()
+{
+ TSRMLS_FETCH();
+
+ zend_class_entry * ce = Z_OBJCE_P(object);
+ HashTable * function_table = NULL;
+ zend_function * function_entry = NULL;
+
+ if( ce != NULL &&
+ &ce->function_table != NULL &&
+ zend_hash_find(&ce->function_table, Z_STRVAL(function_name), Z_STRLEN(function_name) + 1, (void **) &function_entry) == SUCCESS ) {
+ return function_entry->common.num_args;
+ }
+
+ return 0;
+}
+#endif
+
+#if PHP_MAJOR_VERSION >= 7
+int ClassMethodLambda::invokeUserFunction(zval *retval_ptr, int param_count, zval params[])
+{
+ return call_user_function_ex(EG(function_table), object, &function_name, retval_ptr, param_count, params, 1, NULL);
+}
+#else
+int ClassMethodLambda::invokeUserFunction(zval **retval_ptr_ptr, int param_count, zval **params[] TSRMLS_DC)
+{
+ return call_user_function_ex(EG(function_table), &object, &function_name, retval_ptr_ptr, param_count, params, 1, NULL TSRMLS_CC);
+}
+#endif
@@ -0,0 +1,41 @@
+
+#ifndef PHP_MUSTACHE_CLASS_METHOD_LAMBDA_HPP
+#define PHP_MUSTACHE_CLASS_METHOD_LAMBDA_HPP
+
+#include "mustache_lambda.hpp"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+class ClassMethodLambda : public Lambda {
+ private:
+ zval * object;
+ zval function_name;
+
+ protected:
+ int getUserFunctionParamCount();
+#if PHP_MAJOR_VERSION >= 7
+ int invokeUserFunction(zval *retval_ptr, int param_count, zval params[]);
+#else
+ int invokeUserFunction(zval **retval_ptr_ptr, int param_count, zval **params[] TSRMLS_DC);
+#endif
+
+ public:
+ ClassMethodLambda(zval * object, const char * function_name_string) : object(object) {
+ Z_ADDREF_P(object);
+#if PHP_MAJOR_VERSION >= 7
+ ZVAL_STRING(&function_name, function_name_string);
+#else
+ ZVAL_STRING(&function_name, function_name_string, 1);
+#endif
+ };
+ ~ClassMethodLambda();
+};
+
+#ifdef __cplusplus
+ } // extern "C"
+#endif
+
+#endif /* PHP_MUSTACHE_CLASS_METHOD_LAMBDA_HPP */
+
Oops, something went wrong.

0 comments on commit 315db81

Please sign in to comment.