xp-framework / rfc

One of the major deficiencies in the development of many projects is that there is no roadmap or strategy available other than in the developers' heads. The XP team publishes its decisions by documenting change requests in form of RFCs.
2 stars 1 forks source link

Extension methods #236

Closed thekid closed 7 years ago

thekid commented 12 years ago

Scope of Change

Extension methods supported by classes inside lang.types will replace native function calls in XP language.

Rationale

When writing XP language code, every PHP function needs to be imported via import native. The reason for this is that native function usage makes code more difficult to port to different platforms (e.g., HipHop, or a future NodeJS platform, for example).

Functionality

To discover native function usage in an XP language project, one can use the grep utility:

$ grep -Hirn '^import native' src | cut -d ' ' -f 3 | sort | uniq -c | sort -rn

Exemplary analysis

For the Dialog photoblog software, the top 10 functions used are:

sprintf, unserialize, sscanf, serialize, substr, sizeof, strpos, is_file, file_get_contents and dirname.

Side note: Especially PHP's serialization mechanism has had multiple problems in the past - accessibility levels (public / private / protected in PHP 4 -> PHP 5) and namespaces vs. non-namespaces (PHP 5.2 -> PHP 5.3) and should thus be replaced by a completely separate functionality in the framework - see RFC #6!

Looking at the next 10 most often used functions, we see:

basename, array_keys, usort, strolower, str_replace, krsort, implode, preg_replace, create_function and max.

Looking at xp-framework/xp-contrib#9

The top 10 PHP functions used are:

strpos, in_array, substr, count, array_pop, explode, str_replace, strtolower, sprintf and strlen.

The next 10 most commonly used functions:

ucfirst, strtoupper, str_repeat, print_r, implode, chr, basename, preg_replace, token_name and token_get_all.

Checking for XP Core converted via xp-framework/xp-language#7

The top 10 PHP functions used are:

sprintf, substr, strle, sizeof, array_keys, implode, strpos, is_array, explode and sscanf.

The next 10 most commonly used functions:

strtolower, trim, func_get_args, str_replace, strtr, rtrim, is_resource, call_user_func_array, array_shift and in_array.

Observation

The most commonly used PHP functions are string and array functions.

Arrays

import lang.types.ArrayExtensions;

public class Test {

  public static void main(string[] $args) {

    // implode('-', array_slice(array_reverse($args), 0, 4));
    $args.reversed().slice(0, 4).join('-');

    $args.sort();
  }
}

Strings

import lang.types.StringExtensions;

public class Test {

  public static void main(string[] $args) {

    // substr($args[0], (FALSE === ($p= strpos($args[0], '@')) ? -1 : $p) + 1)
    $args[0].substring($args[0].indexOf('@')+ 1);

    // strncmp($args[0], 'http', 4)
    if ($args[0].startsWith('http')) { ... }

    // sprintf
    $string= '%#d items in %.3f seconds'.format($num, $timer.elapsedTime());
  }
}

Security considerations

Speed impact

Slower for the unoptimized case, because code such as $string.substr(0, 5); actually gets transformed to StringExtensions::substr($string, 0, 5); which internally calls the native function. If we can inline these calls, then we save ourselves the overhead for the static method call.

Dependencies

Related documents

thekid commented 12 years ago

A working version is available at https://github.com/thekid/xp-framework/compare/rfc-236 - the thing is though that these classes are completely useless for the framework itself. Maybe another place like providing these inside the compiler could be more benefitial.

thekid commented 12 years ago

This here https://github.com/thekid/xp-language/compare/rfc-236 would move the (from a framework point of view - useless) class to the compiler. We would need to bundle a compiled version for runtime support in the cases methods cannot be completely resolved, though (e.g. "hello".length(); will be resolved to StringExtensions::length('hello'); in the first step, but with inlining applied, could easily become strlen("hello"); and thus have no more dependencies on this class at runtime).