-
Couldn't load subscription status.
- Fork 1
Description
Scope of Change
XP will become its own language, that is, PHP with syntax additions, some of which have been described in xp-framework/rfc #8. (JIT-)Compilers will be created to create PHP 5.2 and PHP 5.3 (with namespaces) sourcecode from the new language.
Rationale
Designing the XP programming language we had the following goals in mind:
- Get rid of the oddities in PHP - alternative syntaxes like if / endif for example or "__"-magic.
- Overcome limitations in the PHP grammar that do not allow chaining at all points like method calls after new() and array access after method calls.
- Support syntactically what the XP framework has built ontop of PHP: annotations, type-safe enums, return types, thrown exceptions, finallly, with() blocks.
- Integrate with the XP Framework's foundation classes.
- Keep the "change and run" spirit and the ability for rapid development.
Generally speaking, we've tried to follow the "less is more" principle and tried making the syntax more concise as to what it's doing.
Functionality
Like in the XP framework, the entry point is always a class. In their most simple form, these classes have a static main() method. An example:
public class HelloWorld {
public static void main(string[] $args) {
util.cmd.Console::writeLine('Hello World from ', self::class.getName(), '!');
}
}Now you will already start noticing things:
- Classes may also have modifiers.
- The "extends Object" is optional and added by the compiler if omitted.
- The keyword "function" is gone and replaced by the return type. Because
the main() method does not return anything, we use "void". - An array type is written as component[]
- Variables still have dollar signs. This makes it easy to spot them,
that's why we've decided to keep this! - Fully qualified classnames are written with dots.
- The object operator is also a dot (at the same time, the string
concatenation operator is now the tilde, ~).
Compilation
To run the above example, it first needs to be compiled:
# Compile source to HelloWorld.class.php
$ xcc HelloWorld.xp
...
# Now run it, as usual
$ xp HelloWorld
The compilation process may produce warnings and errors. The latter lead to a failure, while warnings are only informational. Examples of errors are parse errors as well as syntactical and structural errors where the
compiled code itself would be erroneous - like method bodies in interface declarations or unresolveable types. Warnings depend on the error handler installed in the compiler - in a JIT-compiler, where things have to go
fast, no warnings may be issued at all as their computation takes time. In the standard error handler, type mismatches or missing members are warnings, for example. In a more pedantic version, missing api docs or
usage of deprecated features will be reported.
Typing
The XP language knows about the following types:
- Primitives
The following primitives exist: int, float, string, bool - Reference types
Classes, interfaces and enums, e.g. lang.Object, util.log.Traceable
and util.DateInterval - Array types
An array is a zero-based and continuously numbered list of any type,
e.g. string[] or util.Date[]. - Map types
A map is a hashtable mapping string keys to any type, e.g. [:string]
or [:lang.XPClass] - The variable type
Marks a type that may either be a primitive or any reference type,
declared with the keyword "var". The compiler will not be able to
verify type correctness in this case and will warn about this -
checks will be deferred until runtime.
The following elements need to be typed:
- A: Member variables
- B: Method parameters
- C: Return type
Local variables don't need to be typed or declared. Their type will be inferred on initialization (D).
Example:
public class Person {
public string $name; // A
public void setName(string $name) { // B
$this.name= $name;
}
public string getName() { // C
return $this.name;
}
public string toString() {
$s= $this.getClassName(); // D, typeof($s) = string
$s~= '<' ~ $this.name ~ '>';
return $s;
}
}Namespaces
Namespaces are called "packages" in the XP language. A package does not exist as its own entity, instead, classes belong to a one by declaration:
package de.thekid.dialog;
public class Album {
// ...
}Imports
Importing is a compile-time feature to enable to use short versions of names but actually mean the longer ones. The "Hello World" example from above could be rewritten as follows:
import util.cmd.Console;
public class HelloWorld {
public static void main(string[] $args) {
Console::writeLine(...);
}
}Also available are static imports which makes writing a line to the console even shorter to write:
import static util.cmd.Console.writeLine;
public class HelloWorld {
public static void main(string[] $args) {
writeLine(...);
}
}At the same time, to avoid name clashes with PHP's native functions, these also need to be imported:
import native standard.substr;
import native mysql.mysql_connect;To enable rapid prototyping, type import on demand can be used:
import util.*;
import static util.cmd.Console.*;
import native sybase_ct.*;Chaining
It is now syntactically possible to continue writing after new
and to use array offsets on method return values:
new Date().toString();
XPClass::forName($name).getMethods()[0];Varargs syntax
To create functions that accept a variable amount of arguments - printf is probably the most famous one of them, you have to resort to func_get_args() in PHP userland. The XP language supports this feature by adding ... to the parameter's type:
public class Format {
public static string printf(string $format, var... $values) {
// Implementation here
}
public static void main(string[] $args) {
self::printf('%d args passed to %s', $args.length, self::class.getName());
}
}This will make the format variable contain the format string and values consist of an array with two values (the length and the class name).
Changed foreach
The foreach loop has changed from the form you know it in PHP to one inspired by C#.
foreach ($method in $class.getMethods()) {
Console::writeLine('- ', $method);
}Ternary shortcut
The ternary shortcut supported in PHP 5.3 upwards will be supported by the XP language:
$a= $a ?: $b; // Same as: $a= $a ? $a : $b;Array syntax
The array keyword from the PHP language has been replaced by the shorter form with square brackets. By means of an extension array length can be determined by using the length pseudo-member.
$a= [1, 2, 3]; // same as $a= array(1, 2, 3);
$i= $a.length; // same as $i= sizeof($a);Arrays can also have types:
// Instantiation
$a= new string[] { 'Hello', 'World' };
// Type
public static void main(string[] $args) { ... }Map syntax
The array keyword in PHP can also declare maps. In XP language, this has been changed:
$a= [one: 1, two: 2]; // same as $a= array('one' => 1, 'two' => 2);Maps can also have types:
// Instantiation
$a= new [:string] { greeting: 'Hello', whom: 'World' };
// Type
public static [:string] map(string[] $args, Closure $block) { ... }Class literal
Every class has a static member called $class which will retrieve the lang.XPClass object associated with it.
// same as $c= XPClass::forName(xp::nameOf(__CLASS__));
$c= self::class;
// same as $c= XPClass::forName('lang.types.String');
$c= lang.types.String::class;Finally: Finally
Especially for cleaning up - and yes, even in 2009 with the amount of memory and computing power we have available - it is still necessary to ensure, for example, file handles are properly closed:
$f= new File($name);
try {
$f.open(FileMode::READ);
return $f.read(0xFF);
} finally {
$f.close();
}Enumerations
The XP framework already offers type-safe enumerations. These were originally introduced in xp-framework/rfc #132 and are now supported with an easier-to-type syntax:
public enum Weekday {
Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
}Enumerations may also have methods:
public enum Coin {
penny(1), nickel(2), dime(10), quarter(25);
public string color() {
switch ($this) {
case self::$penny: return 'copper';
case self::$nickel: return 'nickel';
case self::$dime: case self::$quarter: return 'silver';
}
}
}Members can have methods attached, too:
public abstract enum Operation {
plus {
public int evaluate(int $x, int $y) { return $x + $y; }
},
minus {
public int evaluate(int $x, int $y) { return $x - $y; }
};
public abstract int evaluate(int $x, int $y);
}Annotations
Also supported for quite a while in the XP Framework are annotations. They use "#" one-line comments and are parsed from the class' source when accessed inside the reflection API (see also xp-framework/rfc #16). The XP language can do without this workaround, of course!
public class ArrayListTest extends unittest.TestCase {
[@test] public void emptyList() {
$this.assertEquals([], new ArrayList().values);
}
}What happens technically:
Annotations are stored in the xp registry. The reflection API will retrieve them from there instead of having to parse the class files at runtime.
Anonymous instance creation
To generate "throw-away" instances the XP framework provides the newinstance() functionality, originally described in xp-framework/rfc #80. With the downside of having to declare the class body inside a string and the added overhead of runtime evaluation, this feature is now not only more elegant to write but classes created this way will also be declared at compile time:
$emptyFiles= new io.collections.iterate.IterationFilter() {
public bool accept(io.collections.IOElement $e) {
return 0 == $e.size;
}
};Properties
Properties are special member variables that instead of directly accessing a class field may have methods attached. This way, we can create short syntax but still stay flexible if we need to change the underlying implementation.
import native standard.strlen;
public class String {
protected string $buffer;
public __construct(string $initial= '') {
$this.buffer= $initial;
}
public string length {
get { return strlen($this.buffer); }
set { throw new IllegalAccessException('Cannot set string length!'); }
}
public static void main(string[] $args) {
$s= new String('Hello');
$l= $s.length; // 5
$s.length= 1; // *** IllegalAccessException
}
}Internally, this is implemented by compiling __get() and __set() interceptors.
Indexers
The PHP language allows for userland overloading of array operations via the ArrayAccess interface and its offset* methods. This is kind of different from the usual PHP approach with __ "magic" methods - in the XP language, it's the property syntax again:
public class ArrayList<T> {
protected T[] $elements;
public __construct(T... $initial) {
$this.elements= $initial;
}
public this[int $offset] {
get { return $this.elements[$offset]; }
set { $this.elements[$offset]= $value; }
isset { return $offset >= 0 && $offset < $this.elements.length; }
unset { throw new IllegalAccessException('Immutable'); }
}
public static void main(string[] $args) {
$a= new ArrayList<string>('One', 'Two', 'Three');
$one= $a[0]; // 'One'
$a[2]= 'Drei'; // Now: One, Two, Drei
}
}With syntactic sugar
A keyword "with" is added.
Usage:
with ($tree->addChild(new Node('tagname')) as $node) {
$node->setAttribute('attribute', 'value');
}What happens technically:
The with statement, essentialy a no-op, is resolved to the following sourcecode:
<?php
$node= $tree->addChild(new Node('tagname');
$node->setAttribute('attribute', 'value');
?>Throws clause
Methods will be allowed to have a declarative throws-clause. Unlike the throws-clause in Java, blocks executing a function or method with a throws clause and not handling the list of contained exception will not lead to a compile-time error.
Declaration:
public function connect() throws IOException, ConnectException {
// ...
}The thrown exceptions can be retrieved by means of the reflection API.
What happens technically:
The thrown exceptions will be stored in the xp registry. The reflection API can retrieve them from there.
Security considerations
n/a
Speed impact
Overall development experience will be slower because of the necessary compilation step. The generated sourcecode will show the same runtime performance, in some cases even better.
Dependencies
None, the compiler will emit valid PHP sourcecode using the XP framework. Compiled classes can even use source classes and vice versa.
Related documents
- http://experiments.xp-framework.net/xml/browse?experiments,arena,lang
Experiment - http://msdn.microsoft.com/en-us/library/zw39ybk8(VS.85).aspx
With...End With Statement - http://www.javaworld.com/javaworld/jw-06-2006/jw-0612-dynamic.html
Add dynamic Java code to your application - http://www.freejavaguide.com/jcl.pdf
Understanding the Java ClassLoader