Pratphall - A typed language targeting PHP*

*Actually, it's just TypeScript cross-compiled.

Home | GitHub | Mailing List

Pratphall

PHP compiled entirely inside browser with the --single option Share


//normal array
var arr = [1, 2, 3, 4, 5];

//loop and print
arr.forEach((value: number) => {
    echo('My value: ' + value + '\n');
});

//compile-time-only class
interface SampleContract extends Pct.CompileTimeOnly {
    requiredProperty: string;
    optionalProperty?: bool;
}

//function using compile-time class
function printInfo(info: SampleContract) {
    echo('Required: ' + info.requiredProperty + '\n');
    if (typeof info.optionalProperty !== 'undefined') {
        echo('Optional: ' + info.optionalProperty + '\n');
    }
}

//type inferred matching
printInfo({ requiredProperty: 'required val' });
//will be converted to double quotes
var a = 'My\nNewline\nString$escaped{$interpolation}';

//concatenation
var b = 99 + ' bottles of beer on the wall';

//compiler warning because type is any
var c: any = 'test string';
var d = 12 + c;

//common JS functions
var_dump(b.length);
var_dump(b.charAt(0));
var_dump(b.split(' '));
//regular array
var a = [1, 2, 3];

//some calls
a.forEach((value: number) => {
    var_dump(value);
});
a.push(4);

//associative array
var b = Pct.newAssocArray({
    prop: 'propValue',
    prop2: ['a', 'b', 'c'],
    closure: function () { echo('Hey!\n'); }
});

//some calls
var c = b.map((value: any) => {
    return gettype(value);
});
c['prop3'] = 15;
var_dump(c.length);
function printNumber(value: number) {
    echo('Number: ' + value + '\n');
}

//compile-time cast only
printNumber(<number><any>'10');

//runtime PHP function cast
printNumber(intval('10'));

//runtime PHP explicit cast
printNumber(Pct.castInt('10'));

//two ways to check a FALSE return
if (<bool><any>strpos('team', 'I') === false) {
    echo('There is no "I" in "team"\n');
}
if (Pct.isFalse(strpos('team', 'I'))) {
    echo('There is no "I" in "team"\n');
}
//assign
var a = 'hey';
var b = Pct.byRef(a);
//pass
function addWord($val: string) {
    $val += ' word';
}
addWord(b);
echo('Changed? ' + (a == 'hey word'));
//return
var c = { d: 15 };
function $getReference(val: { d: number; }) {
    return val.d;
}
var e = Pct.byRef($getReference(c));
e = 20;
echo('Changed? ' + (c.d == 20));
function myprint(one: string, ...args: any[]) {
    echo('First: ' + arguments[0] + '\n');
    echo('Last: ' + arguments[arguments.length - 1] + '\n');
    if (args.length > 0) {
        echo('First args: ' + args[0] + '\n');
        echo('Last args: ' + args[args.length - 1] + '\n');
    }
}

myprint('foo', true, 13.5, 'bar');
function words(prefix?: bool, file = file('default.txt')) {
    file.forEach((line: string) => {
        line.split(' ').forEach((word: string) => {
            if (prefix) echo('Word: ');
            echo(word + '\n');
        });
    });
}

//reads default.txt and prints w/out prefix
words();
//uses array and prints w/ prefix
words(true, ['foo bar', 'fu bar']);
function func() {
    var anonFunc = (value: string) => { echo(value); }
    var anonFunc2 = function (value: string) { echo(value); }
    function nestedFunc(value: string) { echo(value); }
}
//simple
try {
    new ReflectionClass('NonExistentClass');
} catch (err) {
    if (err instanceof ReflectionException) {
        echo('Not found: ' + (<Exception>err).getMessage());
    } else {
        echo('Other: ' + (<Exception>err).getMessage());
    }
} finally {
    echo('This runs always in PHP 5.5');
}

//advanced
Pct.try({
    try: () => {
        new ReflectionClass('NonExistentClass');
    },
    catch: [
        (err: ReflectionException) => {
            echo('Not found: ' + err.getMessage());
        },
        (err: Exception) => {
            echo('Other: ' + err.getMessage());
        }
    ],
    finally: () => {
        echo('This runs always in PHP 5.5');
    }
});
interface Iface {

    numberProperty: number;

    write(param: string);

    notRequired?(...params: any[]): bool;
}

class BaseClass {

    static fileContents = file_get_contents('myfile.txt');

    constructor(public numberProperty: number) {
        echo('Constructed!')
    }
}

class MyClass extends BaseClass implements Iface {

    static getFileContents() {
        return BaseClass.fileContents;
    }

    constructor() {
        super(12);
    }

    __destruct() { echo('Destructing!\n'); }

    private secretFunction() { echo('Hello\n'); }

    write(param: string) {
        echo('Value: ' + param + '\n');
    }

    __invoke(someVal: any) {
        echo('I have been invoked!\n');
        return this.numberProperty + Pct.castInt(someVal);
    }

    __get(prop: string) { return 42; }

    __set(prop: string, value: any) {
        echo('Setting ' + prop + ' with ' + value);
    }

    toString() { return 'MyClass'; }
}

var myClass = new MyClass();
echo('Instance? ' + (myClass instanceof Iface) + '\n');
//call static
var a = MyClass.getFileContents();
//call normal
myClass.write('Hey');
//invoke
var b = myClass.__invoke(20);
var c = myClass.__invoke('15');
//trigger getter/setter
var d = <number>(<any>myClass).someProp;
(<any>myClass).someNewProp = 20;
//string version
var e = myClass.toString();
interface Place extends Pct.CompileTimeOnly {
    zip: string;
    city?: string;
}

interface Weather extends Pct.CompileTimeOnly {
    place: Place;
    temperature: number;
}

function printWeather(weather: Weather) {
    echo('It is ' + weather.temperature + ' in ');
    if (property_exists(weather.place, 'city')) {
        echo(weather.place.city);
    } else echo(weather.place.zip);
}

printWeather({
    place: {
        zip: '75001',
        city: 'Addison'
    },
    temperature: 85
});
printWeather({
    place: {zip: '76020'},
    temperature: 88
});
module MyModule {
    export interface MyIface {
    }

    export module Sub {
        export class MyClass implements MyModule.MyIface {
            causeErr() {
                throw new Exception('Error');
            }
        }
    }
}

import Sub = MyModule.Sub;
var a = new Sub.MyClass();
a.causeErr();