Skip to content

For Contributors

Dmitriy Zayceff edited this page Jan 12, 2015 · 8 revisions

To contributing our project, you need to known how it works!

Build System

To build our project, you need to install the Gradle system (http://www.gradle.org/) and be able to use it.

Architecture

The JPHP project contains the next modules:

  • jphp-runtime - only runtime libraries for JPHP.
  • jphp-core - compiler + runtime.
  • jphp-***-ext - an extension for jphp, e.g.: jphp-net-ext, jphp-json-ext.
  • jphp-android - extension for support Android API.

jphp-core

The compiler has a few parts:

  • Tokenizer (lexer) - org.develnext.jphp.core.tokenizer package
  • Syntax analizer - org.develnext.jphp.core.syntax package
  • Compiler to JVM - org.develnext.jphp.core.compiler package

(!) JPHP doesn't translate your code to Java source code. The project is a fully compiler to the Java VM bytecode.

Our project uses the ASM java library to generate Java VM bytecode.

How create Extension?

You need to know about the php.runtime.Memory class, before we will start.

Memory

This is the basic class for values in JPHP, it's abstract and has a few child classes. PHP is a dynamic type language, however it has inner types: int, bool, string, double, object, array, null. JPHP stores values as objects of classes that implement the abstract Memory class:

  • php.runtime.memory.LongMemory - for int values,
  • php.runtime.memory.DoubleMemory - for double values,
  • php.runtime.memory.NullMemory - for null,
  • php.runtime.memory.FalseMemory - for false,
  • php.runtime.memory.TrueMemory - for true,
  • php.runtime.memory.StringMemory - for string values,
  • php.runtime.memory.ArrayMemory - for arrays,
  • php.runtime.memory.ObjectMemory - for objects.

When you will create extension, you need to use these classes to pass or return values. The all classes have convenient constructors and static methods to create values, for example:

Memory value = LongMemory.valueOf(33);
Memory value = new StringMemory("foobar"); 
Memory value = StringMemory.valueOf("foobar");
  1. Create a class extends from php.runtime.ext.support.Extension.
package com.example;

import php.runtime.env.CompileScope;
import php.runtime.ext.support.Extension;

public class ExampleExtension extends Extension {
    @Override
    public String getVersion() {
        return "1.0";
    }

    @Override
    public void onRegister(CompileScope scope) {
        // ...
        registerClass(scope, Foobar.class);
        // ...
    }
}

In the onRegister method you can register yours importing classes, functions and constants.

How create a Class?

To do that, you can use the next classes:

  • php.runtime.lang.BaseObject
  • php.runtime.lang.BaseException to create a exception class
  • php.runtime.lang.BaseWrapper<T> to create a wrapped class of a native java class

We recomend you to use BaseWrapper in most cases. The next, I will show you how it use:

package org.develnext.jphp.ext.javafx.classes.paint;

import javafx.scene.paint.Color;
import org.develnext.jphp.ext.javafx.JavaFXExtension;
import php.runtime.annotation.Reflection;
import php.runtime.annotation.Reflection.Property;
import php.runtime.annotation.Reflection.Signature;
import php.runtime.env.Environment;
import php.runtime.lang.BaseWrapper;
import php.runtime.reflection.ClassEntity;

@Reflection.Name("ext\\javafx\\paint\\UXColor")
public class UXColor extends BaseWrapper<Color> {
    // If you want to wrap methods from the Color class automatically, 
    // declare an interface named as `WrappedInterface` in the current class
    interface WrappedInterface {
        // Use @Property annotation to create a property with a setter and getter.
        // In this case, ->red property will call getRed() and setRed(double) methods.
        // if setter is not exists in the Color class, the property will be readonly and
        // any tries of writing value will throw an exception.
        @Property double red();
        @Property double blue();
        @Property double green();
        @Property double opacity();
        @Property double brightness();
        @Property double hue();
        @Property double saturation();

        // Wraps the methods of the Color class
        Color grayscale();
        Color invert();
        Color saturate();
        Color desaturate();
        Color interpolate(Color endValue, double t);
    }
    // Else, create methods of the class manually via @Signature annotation.

    public UXColor(Environment env, Color wrappedObject) {
        super(env, wrappedObject);
    }

    public UXColor(Environment env, ClassEntity clazz) {
        super(env, clazz);
    }

    // You should declare a php constructor if your class is not abstract 
    // Use @Signature annotation to wrap your native method
    @Signature
    public void __construct(double red, double blue, double green) {
        __wrappedObject = new Color(red, blue, green, 1.0);
    }

    // You can use overloading methods anywhere and it will works properly. 
    @Signature
    public void __construct(double red, double blue, double green, double opacity) {
        __wrappedObject = new Color(red, blue, green, opacity);
    }

    // Also, it's posibale to wrap a static method, use the static modifier.
    @Signature
    public static Color of(String colorString) {
        return Color.web(colorString);
    }

    // Overloading works =)
    @Signature
    public static Color of(String colorString, double opacity) {
        return Color.web(colorString, opacity);
    }

    @Signature
    public static Color rgb(int red, int blue, int green) {
        return Color.rgb(red, blue, green);
    }

    @Signature
    public static Color rgb(int red, int blue, int green, double opacity) {
        return Color.rgb(red, blue, green, opacity);
    }
}