Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Kompilator/preprocesor do PHP
Forum PHP.pl > Forum > PHP
Emsee
Witam wszystkich,

Od pewnego czasu chodzi mi po głowie następujący pomysł: stworzenie języka wysokiego poziomu, który kompilowałby się do PHP. Można sobie to wyobrazić jako PHP z podrasowaną składnią.

Wyobrażam sobie to w następujący sposób: Programista pisze swój program w owym rozszerzonym języku (który, w swej naturze, jest obdarzony interoperacyjnością z PHP). Następnie kompiluje go i wrzuca kod wynikowy na serwer.

Możliwości ulepszenia składni języka:
  • Dostęp do elementów tablicy zwracanej przez funkcję
    Kod
    function getarray() { return {1,2,3}; }

    print getarray()[2];
  • W powyższym przykładzie widać zastosowanie {1,2,3} jako skrócenie dla array(1,2,3) - jest to przykładowy lukier składniowy
  • Dostęp do przedziałów tablicy (ang. array slicing), co występuje np. w pythonie: getarray()[1:2] zwraca tablicę {2,3}, a getarray()[:-2] zwraca {1,2}.
  • Możliwość łańcuchowania wyrażenia konstrukcji obiektu: rzecz pokroju (new Query())->foo()->execute(); w obecnym PHP nie jest możliwa
  • Szybkie pakowanie zmiennych w stylu
    Kod
    a, b = b, a

    jako alias dla list().
  • Aliasy dla całych grup funkcji:
    Kod
    zmienna = "foo"

    zmienna = string.replace(zmienna, "foo", "bar")

    albo nawet

    zmienna = zmienna.replace("foo","bar")

    Celem takiego zabiegu jest zlikwidowanie nieścisłości w nazewnictwie oraz w kolejności parametrów w PHP.
Jeszcze bardziej agresywne rozszerzenia, co do których nie myślałem nad szczegółami implementacji:
  • Wyrażenia lambda (to akurat pojawi się w PHP 5.3, ale można uprościć nieco składnię)
  • Tzw. array comprehensions - ciekawa rzecz występująca w JavaScript/Pythonie:
    Kod
    tablica = *tablica jakichś liczb rzeczywistych z przedziału 0-100

    {round(x) for x in tablica} // zwraca tablicę z zaokrąglonymi wartościami z tablica

    {round(x) for x in tablica if x > 50} // to samo co wyżej, ale teraz filtruje elementy pod kątem wartości
  • Jakiś prostszy sposób na callbacki (nad tym wogóle się jeszcze nie zastanawiałem, możliwe, że dość kłopotliwe z implementacji)
A teraz możliwości wynikające z samego istnienia kompilatora:
  • Z racji, że taka kompilacja nie jest wykonywana przy każdym uruchomieniu skryptu, można pozwolić sobie na bardziej agresywną optymalizację, jak np. inline'owanie funkcji, korzystanie z trace trees i innych technik optymalizacji stosowanych przez kompilatory.
  • Tworzenie 'amalgamacji', czyli łączenie (w wersji 'release') plików danego projektu w celu uniknięcia narzutu związanego z otwieraniem i parsowaniem plików
W ramach proof-of-concept napisałem kompilator obsługujący większość rzeczy z pierwszej listy "feature"'sów. Program zawiera jednak gamę niedociągnięć technicznych, jak i projektowych (jako, że pisałem to dla hecy, nie planując tego jako program 'końcowy'), tak więc nie będę go publikował. Kompilator napisany jest w pythonie, z wykorzystaniem portu YACCa i LEXa na tenże język.

Traz myślę, aby to bardziej ustrukturyzować, czyli napisać design doc, aby to wszystko miało ręce i nogi. Tworzenie parserów to nie jest jednak robota prosta i przyjemna, zmienianie podstawowych założeń/interfejsów w środku prac jest straszną męczarnią, dlatego wpierw chcę to dobrze zaprojektować.

Teraz kieruję pytanie do Was: Co o tym sądzicie? Co wam się nie podoba w tych planach, a jakie cechy byście dodali? Ktoś ma podobne wrażenia/próbował czegoś takiego w przeszłości? A może wskazówki od doświadczonych w temacie? Liczę na konstruktywną dyskusję.
Crozin
Cytat
Możliwość łańcuchowania wyrażenia konstrukcji obiektu: rzecz pokroju (new Query())->foo()->execute(); w obecnym PHP nie jest możliwa
  1. <?
  2.  
  3. class sth{
  4. private $str = null;
  5.  
  6. public function __construct(){
  7. $this->str = 'qwerty';
  8. }
  9.  
  10. public function foo(){
  11. $this->str .= 'foo';
  12.  
  13. return $this;
  14. }
  15.  
  16. public function bar(){
  17. $this->str .= 'bar';
  18.  
  19. return $this;
  20. }
  21.  
  22. public function execute(){
  23. echo $this->str;
  24.  
  25. return $this;
  26. }
  27. }
  28.  
  29. $obj = new sth;
  30. $obj->foo()->bar()->execute();
  31. ?>
Uważam, że zamiast rozbudowywać PHP lepiej napisać własny język. Ale osobiście ja bym się za to nie brał.
Emsee
Cytat(Crozin @ 20.08.2008, 12:14:40 ) *
  1. <?php
  2. $obj = new sth;
  3. $obj->foo()->bar()->execute();
  4. ?>


Chodzi mi właśnie o to, żeby te dwie linijki można było zredukować do jednego polecenia (co jest wybitnie przydatne w przypadku, gdy taki obiekt chcemy podać jako parametr do funkcji - klasyczne PHP wymaga tworzenia zmiennych pomocniczych).

Mój projekt to jest nowy język - z tym, że kompilowany do PHP. Dzięki temu po stronie serwera nie trzeba instalować żadnych nowych runtime'ów, co zmniejsza koszty deploymentu (rozpowszechniania? nie znam polskiego odpowiednika).
Cysiaczek
Wdrożenia...

Dziwny pomysł, bo po co skracać?
  1. <?php
  2. function getarray() { return array(1,2,3); }
  3. ?>


Kod
function getarray() { return {1,2,3}; }


Do czego to się przyda? Naprawdę nie mogę tego pojąć. Może Tobie się to przyda - inni pewnie nawet nie spojrzą.

Pozdrawiam.
mike
Pisanie pseudo języka, który będzie parsowany do języka PHP tylko dlatego że Ci kilka rzeczy w składni nie pasuje to głupota. Mało tego: totalna głupota i strata czasu.
Jeśli nie pasuje Ci język to przeskocz na inny. Przecież to o czym piszesz masz w Javie lub w Pythonie.
zimi
może se odpuść i zacznij pisać w pythonie?

wiem że nie jest to zbyt konstruktywne co właśnie powiedziałem, ale widać że pasuję Ci inny język, więc po prostu inny wykorzystaj, nie widzę powodu aby robić nowy język (tzn. powody prawdopodobnie są ale te które wskazałeś mnie nie przekonują)

jeżeli ktoś się nauczył PHP to, to co napisałeś będzie dla niego tylko nowym manualem, kolejnym po całej masie którą przyda się znać pisząc aplikację...

a łatwość utrzymania będzie gdy ten sposób kodowania stanie się dla kogoś naturalny, a więc niekoniecznie dla PHP-owców

jak napisałeś, zrobiłeś to dla checy i moim zdaniem tutaj to powinno już zostać
a Ty powinieneś wykorzystać Pythona...

zresztą nie napisałeś czemu to zrobiłeś? jaki miałes powód...? brak Pythona na serwie?

a debugowanie? masakra... pluję nam błędem w linijce xxx, szukamy go w kodzie PHP a potem w odpowiedniku Twojego języka? bo inaczej sobie jeszcze tego nie wyobrażam...

gdyby twórcy PHP dorobiliby te "pierdółki" to bym w zasadzie się nie obraził, ale moim zdaniem gra niewarta świeczki..., lepiej po prostu odpal se pythona...
Crozin
Jeśli Ci tak bardzo zależy do skrócenia tego do jednej linijki to możesz zrobić coś takiego:
  1. <?php
  2. class sth{
  3. private $str = null;
  4.  
  5. public static function obj(){
  6. $obj = new sth;
  7. return $obj;
  8. }
  9.  
  10. private function __construct(){
  11. $this->str = 'qwerty';
  12. }
  13.  
  14. //..reszta
  15. }
  16.  
  17. sth::obj()->foo()->bar()->execute();
  18. ?>
mike
Cytat(Emsee @ 20.08.2008, 12:30:07 ) *
Chodzi mi właśnie o to, żeby te dwie linijki można było zredukować do jednego polecenia (co jest wybitnie przydatne w przypadku, gdy taki obiekt chcemy podać jako parametr do funkcji - klasyczne PHP wymaga tworzenia zmiennych pomocniczych).
Poza tym no staaaary. Ty nie masz problemu z językiem tylko z wiedzą tongue.gif
Jeśli chcesz tworzyć nowy obiekt tylko po to by sobie jakąś metodę wykonać to możesz to zrobić. Trzeba pomysłu.
A jelsi przekazujesz obiekt dalej lub on żyje to zmienne pomocnicze są jak nahjbardziej OK.

A co to fluent interfaces to możesz tak:
  1. <?php
  2.  
  3. class example {
  4.  
  5. public static function getInstance() {
  6. return new example();
  7. }
  8.  
  9. public function __construct() {}
  10.  
  11. public function foo() {
  12. echo 'foo';
  13. return $this;
  14. }
  15.  
  16. public function bar() {
  17. echo 'bar';
  18. return $this;
  19. }
  20. }
  21.  
  22. example::getInstance()->foo()->bar();
  23.  
  24. ?>
Cytat
foobar


Update: Hehe, ~Crozin wpadłeś na to samo tylko zrobiłes Singletona. Ja nie, dałem tylko możliwość zrobienia obiektu w jednej linijce.
Emsee
@Cysiaczek: Lukier składniowy to lukier składniowy, służy niczemu innemu jak wygodzie.

@mike: A Ciebie nigdy nie denerwowało, że czasem jest $haystack, a potem $needle, a czasem na odwrót? Nie sądzisz że zerkanie do dokumentacji tylko po to, by sprawdzić, czy dana funkcja to camelCase czy jest_oddzielana_inaczej to pewna przesada? Są to cechy, które negatywnie wpływają na produktywność.

Sposób z metodą statyczną znam, ale jest to, jak by na to nie patrzeć, hack. W swoich wypowiedziać zauważyliście, że inspirowałem się Pythonem, i jest to prawda, bo tandem Python/C to jest coś, co używam na codzień. Nie zawsze jednak istnieje możliwość stosowania Pythona na zewnętrznym serwerze (mod_python bądź fastcgi to dość rzadko spotykana rzecz), a z PHP można się spotkać na właściwie każdym serwerze.
kwiateusz
to spraw sobie edytor z podpowiadaniem skladni i nie będziesz musiał szukac po manualach...
Kocurro
Emsee jakoś nie zauwazyłem negatywnego wpływania na produktywność ... może dlatego, że używam PDT Eclipse i on mi ładnie podpowiada.

Nigdy nie miałem problemu z rzeczami o jakich piszesz a w życiu już trochę nakodziłem w PHP'ie różnych nawet rozbudowanych rzeczy ... i jedno co mogę powiedzieć to to, że jeśli będę potrzebował bardziej zaawansowane rzeczy pisać to zrobię przesiadkę na coś innego.

pozdrawiam,
Łukasz
mike
Cytat(Emsee @ 20.08.2008, 12:50:19 ) *
@mike: A Ciebie nigdy nie denerwowało, że czasem jest $haystack, a potem $needle, a czasem na odwrót? Nie sądzisz że zerkanie do dokumentacji tylko po to, by sprawdzić, czy dana funkcja to camelCase czy jest_oddzielana_inaczej to pewna przesada? Są to cechy, które negatywnie wpływają na produktywność.
Jest niewiele funkcji (jedna czy dwie) w każdej grupie funkcji (array, srting, ...), które nie trzymaja konwencji. Choć fakt czasem to potrafi frustrować ... kogoś początkującego. Wybacz ale kilka rzeczy dzięki doświadczeniu można sobie wpoić.
CamelCase, które wspomniałeś to problem wydumany, bo PHP ignoruje wielkość znaków w funkcjach. Możesz co najwyżej mieć problem z pamięcią czy ma być _ czy nie ale tu jak zauważyłem wcześniej również żaden problem.

Ogólnie myślę, że na siłę chcesz zrobić z PHP Pythona. Pomyłka. Czemu nie zrezygnujesz z PHP. Python jest dużo lepszy w konstrukcji.
Poza tym rzeczy o których piszesz wkrótce się pojawią wraz z kolejnymi wersjami PHP i z czasem z dodaniem przestrzeni nazw.
wrzasq
poza tym jesli ci nie pasuje nazwa funkcji, albo kolejnosc argumentow, to chcesz od razu nowy jezyk tworzyc?! po prostu sobie zrobi jakis mostek prosty:

  1. <?php
  2. function str_pos($needle, $haystack, $offset = 0)
  3. {
  4. return strpos($haystack, $needle, $offset);
  5. }
  6. ?>


o pozostalych pomyslach juz nie bede pisal, bo wszyscy poprzednicy zgodnie wykazali ci, ze pomysl jest kompletnie chybiony.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.