Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added new syntax named 'CBLOCK' . The content in %{ }% will copied into the generated .c file #21

Merged
merged 2 commits into from Oct 15, 2013

Conversation

racklin
Copy link
Contributor

@racklin racklin commented Oct 11, 2013

Hi.

I have implement a new syntax named 'CBLOCK'.
The idea is inspired by Mozilla's XPIDL C++ Block . http://www-archive.mozilla.org/scriptable/xpidl/idl-authors-guide/keywords.html

Syntax is

%{
// This text is in CBLOCK.
}%

The CBLOCK copied text into generated .c file.
It is useful and help us to call C functions more easier, and have ability to using 3rd libs in zephir.

The CBLOCK before namespace class will copied CONTENT to generated .c file and after headers .

The CBLOCK inside method statement, will copied CONTENT to generated .c file inline (AT IT's Position)

Here is unit-test for example:

**
 * CBLOCK tests
 /* asfas
 */

%{
// top statement before namespace, add to after headers
#define MAX_FACTOR 40
}%

namespace Test;

%{
// top statement before class, add to after headers
// test include .h
#include "kernel/require.h"
}%

%{

// c implement fibonacci
static long fibonacci(long n) {
        if (n < 2) return n;
        else return fibonacci(n-2)+fibonacci(n-1);
}

}%

class Cblock
{
        public function testCblock1()
        {
                int a = 0;
                %{
                a = MAX_FACTOR;
                }%

                return a;
       }

        public function testCblock2()
        {
            long a = 0;

            %{
            a = fibonacci(MAX_FACTOR);
            }%

            return a;
        }

AND Generated .c file below:

#ifdef HAVE_CONFIG_H
#include "../ext_config.h"
#endif

#include <php.h>
#include "../php_ext.h"
#include "../ext.h"

#include <Zend/zend_operators.h>
#include <Zend/zend_exceptions.h>
#include <Zend/zend_interfaces.h>

#include "kernel/main.h"

// top statement before namespace, add to after headers
#define MAX_FACTOR 40


// top statement before class, add to after headers
// test include .h
#include "kernel/require.h"



// c implement fibonacci
static long fibonacci(long n) {
        if (n < 2) return n;
        else return fibonacci(n-2)+fibonacci(n-1);
}




/**
 * CBLOCK tests
 /* asfas
 */
ZEPHIR_INIT_CLASS(Test_Cblock) {

        ZEPHIR_REGISTER_CLASS(Test, Cblock, test, cblock, test_cblock_method_entry, 0);


        return SUCCESS;

}

PHP_METHOD(Test_Cblock, testCblock1) {

        int a = 0;



                a = MAX_FACTOR;

        RETURN_LONG(a);

}

PHP_METHOD(Test_Cblock, testCblock2) {

        long a = 0;



            a = fibonacci(MAX_FACTOR);

        RETURN_LONG(a);

}

@phalcon
Copy link

phalcon commented Oct 11, 2013

I like the idea, however, this would sometimes make things harder for the compiler, because there could be unregistered activity the language cannot track, for instance:

 %{
a = fibonacci(MAX_FACTOR);
}%

The variable 'a' is mutated inside a "shadow" block of code, for Zephir, the variable wasn't mutated so the variable will be reported as unused, but the variable was actually used!

Our idea of integrate C-functions into Zephir is via optimizers. Check this example:

https://github.com/phalcon/zephir/blob/master/Library/Optimizers/FunctionCall/StrlenOptimizer.php#L25

It intercepts calls to 'strlen' and replaces the generated code by a call to a c-function.

It also adds the proper header:
https://github.com/phalcon/zephir/blob/master/Library/Optimizers/FunctionCall/StrlenOptimizer.php#L43

Returns a 'compiled expression' which has the right data-type Zephir can understand.
https://github.com/phalcon/zephir/blob/master/Library/Optimizers/FunctionCall/StrlenOptimizer.php#L46

@racklin
Copy link
Contributor Author

racklin commented Oct 11, 2013

@phalcon I agree.

In the most case, Zephir user should use Optimized Function Calls we provided.
And we will implementing populate and general function calls to Optimized c-function.

Zephir is a DSL and Generate to c .
So i think it should have an ability to calling 3rd c libraries.
It will make Zephir more flexible and powerful.

For instance

  1. Declare the interfaces for c libraries - like VALA .
  2. Embedded codeblock to generated target files. like XPIDL, CoffeeScript.

Hopefully, you'll never need to use it, but if you ever need to intersperse snippets of JavaScript within your CoffeeScript, you can use backticks to pass it straight through.

Go back to my example cblock.zep https://github.com/racklin/zephir/blob/d6b1e3651151c0e1c66cd58ff024be967b190ab0/test/cblock.zep
fibonacci(40) is very slow in PHP - benchmark [http://fengmk2.github.io/blog/2011/fibonacci/nodejs-python-php-ruby-lua.html]

But Zephir with CBLOCK, we can implement simple c-function fibonacci in zephir CBLOCK. and calling in zephir . NOW with Zephir extension, fibonacii(40) only used 0.8s in my MBP.

And the other example is Zephir currently not support require php file.
With cblock , we can #include "kernel/require.h" and calling zephir_require or zephir_require_ret in cblock.

So, with Optimizer FunctionCall + CBLOCK will make Zephir more flexible and these two features were complementary not mutex .

Finally, You CAN calling c-function, implements c-function in CBLOCK, not mean You SHOULD.
😄

@phalcon
Copy link

phalcon commented Oct 11, 2013

I'm not opposed on allowing integrate 3rd party libraries in Zephir or call C-code, I think this is obviously something required. But just embed c-code wherever a developer wants looks ugly and it makes Zephir completely unusable. That would restrict us to make optimizations just because there could be hidden code that Zephir can't understand or analyze.

The idea is allow the developer to write his own optimizers having clean interfaces allowing Zephir to know the kind of parameters that must be passed to C-functions and also which data-types are returned.

For example, you could have the following file structure.

optimizers/
  fibonacci.php # this intercepts calls to function "fibonacci" telling Zephir which header include and the c-code
ext/
  test/
    myclass.c # code generated
  kernel/
  my-fibonacci.h # fibonacci prototype
  my-fibonacci.c # here is implemented the fibonacci in "c"
test/
  myclass.zep # here we call a function "fibonnacci" calling the c version

fibonacci.php:

<?php

class FibonacciOptimizer
{   
    public function optimize(array $expression, Call $call, CompilationContext $context)
    {
        $context->headersManager->add('my-fibonnaci.h');

        $resolvedParams = $call->getReadOnlyResolvedParams($expression['parameters'], $context, $expression);
        return new CompiledExpression('int', 'fibonacci(' . $resolvedParams[0] . ')', $expression);
    }
}

my-fibonacci.h:

int fibonacci(int n);

my-fibonacci.c:

int fibonacci(long n) {
        if (n < 2) return n;
        else return fibonacci(n - 2) + fibonacci(n - 1);
}

myclass.zep

namespace Test;

class MyClass
{

    public function someMethod()
    {
        int a;

        a = fibonacci(40);
        return a;
    }
}

This will be an structured way of integrate C functions in a way that Zephir can understand. Zephir can mutate the variable 'a' in a controlled way.

Even if you do the following, Zephir will do the right thing:

int a;
a = fibonacci(40);
return a;
var a;
a = fibonacci(40);
return a;
double a;
a = fibonacci(40);
return a;
return fibonacci(40);
var a = [];
let a = [fibonnaci(1), fibonnaci(2)];
return a;

All this without have to write C-code!

@racklin
Copy link
Contributor Author

racklin commented Oct 13, 2013

@phalcon I agree and understand your concerns.

Please consider that CBLOCK or (c-code with comments) is part of Zephir features, It make Zephir flexible.

The most projects(and Phalcon 2.0) developers SHOULD NOT using CBLOCK to implements or calling c-function.
But sometimes or special extensions,they CAN use CBLOCK and that is helpful.

As list before, XPIDL , CoffeeScript support embedded target code modifiers.

Google's Go (http://golang.org/) also have a c-code embedded by comments, called
c-go . (http://golang.org/cmd/cgo/) .

Thanks.

@phalcon
Copy link

phalcon commented Oct 14, 2013

Could you please rebase against the current master?

Signed-off-by: Rack Lin <racklin@gmail.com>
Signed-off-by: Rack Lin <racklin@gmail.com>

Conflicts:
	parser/parser.c
	parser/parser.out
	parser/scanner.c
@racklin
Copy link
Contributor Author

racklin commented Oct 15, 2013

@phalcon Hi, I have rebase and push again. Thanks.

phalcon pushed a commit that referenced this pull request Oct 15, 2013
Added new syntax named 'CBLOCK' . The content in `%{ }%` will copied into the generated .c file
@phalcon phalcon merged commit fb3b286 into zephir-lang:master Oct 15, 2013
@phalcon
Copy link

phalcon commented Oct 15, 2013

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants