Strona używa cookies (ciasteczek). Dowiedz się więcej o celu ich używania i zmianach ustawień. Korzystając ze strony wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki.    X

Libgreattao i jego tekstowa powłoka

W tym rozdziale opiszę sposób poruszania po powłoce wbudowanej w bibliotekę do generowania interfejsów(można ją nazywać biblioteką interakcji), zwanej libgreattao. To moja biblioteka może być użyta do komunikacji z użytkownikiem. Może ona pracować w trzech trybach: normalnym, powłoki, sieciowym. W każdym trybie sposób działania libgreattao jest inny. W tym artykule zajmę się trybem powłoki, ale po kolei.

Libgreattao pozwala aplikacjom na tworzenie okien, dodawanie do nich abstraktów(dla potrzeb libgreattao nazywam je ścieżkami zdarzeń), ustawianie atrybutów abstraktu(skojarzeń). Przykładami atrybutu abstraktu są: opis, nazwa, ikona. W powłoce nie jest istotna klasa okien - jest ona potrzebna jedynie do odwoływania się do okien, a robi się to przez ciąg nazwa_klasy_okna[numer_egzemplarzu]. Jest to również prawdą w trybie sieciowym, jednak nie jest to prawdą w trybie normalnym(w trybie normalnym jest tworzone GUI - plik klasy okna to zbiór elementów interfejsu i elementów odpowiedzialnych za przetwarzanie abstraktów i ich atrybutów, więc w tym trybie klasa okien ma znaczenie). Dla zilustrowania wszystkiego w tej kwestii: /* utworzenie okna odpowiedniej klasy */ void *window = tao_new_window("/desktop/dialogs/question_dialog"); /* dodawanie abstraktów */ tao_add_handler(window, "/message", NULL, NULL); tao_add_handler(window, "/actions/exit", &exit_callback wartość_przekazana_do_procedury); tao_add_handler(window, "/actions/retry", &retry_callback wartość_przekazana_do_procedury2); /* przypisywanie atrybutów do abstraktów */ tao_set_hint(window, "/message", HINT_NAME, "Błąd krytyczny"); tao_set_hint(window, "/message", HINT_DESCRIPTION "Nie można otworzyć pliku wymaganego przez aplikację"); tao_set_hint(window, "/action/exit", HINT_DESCRIPTION "Wyłącza aplikację"); tao_set_hint(window, "/action/retry", HINT_DESCRIPTION "Ponawia próbę załadowania pliku"); W powyższym przykładzie tworzymy trzy abstrakty. Pierwszy z nich odpowiada komunikatowi, a dwa pozostałe akcjom, jakie może podjąć użytkownik. Z tego powodu w przypadku pierwszego wywołania tao_add_handler trzeci i czwarty parametr nie mają znaczenia. Dlaczego przyciskom(ehhhmmm... akcją) przypisujemy tylko opis? Bo nazwa w tym przypadku jest niepotrzebna. W powłoce trzeba będzie odwoływać się do abstraktu po oknie i ścieżce/nazwie abstraktu(drugi argument), a plik klasy okna będzie pewnie zawierać reguły do automatycznego ustawiania np. etykiet na przyciskach, np. z części nazwy/ścieżki abstraktu po ostatnim slash-u. Powłoka oczywiście nie obsługuje ikon.

Uruchamianie aplikacji w trybie powłoki tao

Libgreattao obsługuje dwa przełączniki do uruchomienia powłoki libgreattao. Są to tao-shell-execute-file i tao-na-shell-interactive. W drugim przełączniku użyto ciągu -na- Co on znaczy? To, że po przełączniku nie występuje argument. Postanowiłem dodać możlliwość określenia, że po przełączniku nie występuje argument na wypadek, gdybym chciał dodać możliwość podania wartości do argumentu.

Oba te przełączniki powodują, że nie zostanie aplikacja uruchomiona w trybie normalnym, a w trybie powłoki. Czym się różnią te dwa przełączniki? Pierwszy powoduje wykonanie pliku ze ścieżką podaną w parametrze występującym po tym przełączniku. Drugi powoduje uruchomienie powłoki w trybie interaktywnym. Oba te przełączniki można łączyć, co powoduje, że po wykonaniu podanego pliku, powłoka przejdzie w tryb interaktywny.

Jak wyjść z trybu interaktywnego? Wystarczy wpisać exit kod_powrotu. Jeżeli aplikacja nie zdefiniowała funkcji dla zakończenia aplikacji, to aplikacji zakończy się z podanym kodem powrotu. W przeciwnym wypadku aplikacja będzie mogła sama zdecydować, co z kodem powrotu zrobić.

Jest coś, co powoduje, że ta powłoka przypomina assemblera(analogia choć dziwna jest związane z tym, że instrukcje dostępne w assemblerze są zależne od wielu czynników, m.in od architektury procesora), bo w assemblerze na x86 trzeba było włączyć FPU, przełączyć linię A21 do zwiększenia ilości pamięci, itd. W mojej powłoce po uruchomieniu należy zrobić jedną rzecz - włączyć czasomierze, zupełnie jak na ARM-ach.

O języku

Tworząc język chciałem pójść po najmniejszej linii oporu, dodając możliwie najwięcej funkcjonalności. Stąd np. liczby wewnętrznie są przechowywane w postaci ciągu znaków - nie można utworzyć zmiennej liczbowej, ale można za to utworzyć zmienną tekstową. Innymi skutkami takiej decyzji jest to, że język przypomina assemblera - nie ma znaków działań - by dodać dwie liczby, to należy wprowadzić: =add nazwa_zmiennej_wynikowej wartość1 wartość2 No dobra - można utworzyć zmienną liczbową o nazwie "i" i wartości 2 w taki sposób: =add i 2 0 ;-D .
Jednak dodałem fajne mechanizmy, jakie są w językach interpretowanych, jak zakleszczenia, słowniki czy rozwijanie zmiennych. Jeżeli ktoś chce mieć tablice, to może dołączyć plik znajdujący się w katalogu ze źródłami libgreattao, w podkatalogu shell-utils. Plik ma nazwę types, a obecnie dostarcza tylko obsługę tablic. Tablica jest rodzajem słownika, więc mogłem zaimplementować tablice wykorzystując słownik.

Jeszcze nie mam nazwy języka wykorzystywanego przez libgreattao. Wymyśliłem dwie: "goto language" i "scope switcher" - mam nadzieję, że po przeczytaniu całego artykułu zaproponujesz własną lub oddasz głos na już zaproponowaną nazwę dla mojego języka. Interpreter poleceń ma blisko 6500 linijek, jednak w pliku z kodem trzymam deklaracje funkcji, które należałoby odliczyć.

Ograniczenia

  • Nie można podstawiać zmiennych pod nazwy funkcji/bloków kodu
  • Nazwy modułów nie mogą się zaczynać od znaku @ lub .
  • Nazwy zmiennych nie mogą się zaczynać od kropki - jedynie zmienne wbudowane mogą się zaczynać od kropki
  • Nazwy etykiet nie mogą zaczynać się od kropki - jedynie specjalne nazwy etykiet mogą zaczynać się od kropki
  • Maksymalna długość polecenia to 1024 znaki

Wprowadzanie komend i o komendach ogólnie

Komendy w trybie interaktywnym wprowadza się, zatwierdzając każdorazowo wprowadzaną komendę klawiszem enter/return. Są jednak przypadki, gdy wciśnięcie jednego z tych przycisków nie spowoduje uruchomienie komendy, a oczekiwanie na dalszy ciąg komendy. Dzieje się tak, gdy przed naciśnięciem jednego ze wspomnianych klawiszy wprowadziliśmy backslash, otwarty jest cudzysłów lub apostrof, albo ilość nawiasów domykających nie ujętych w cudzysłowia nie jest równa ilości nawiasów otwierających nie ujętych w cudzysłowia. Uwaga: przeprzedzenie znaku znakiem baskslash powoduje, że znak po nim traci swoje znaczenie. Tak więc ciąg \' tak jakby nie zawierał apostrofu, analogicznie należy podjeść do ciągów \", \( i \). Jeżeli naciśniemy przycisk enter w momencie, gdy powłoka oczekuje czegoś innego, np. zamknięcia cudzysłowia, to w miejsce entera/returna zostanie wstawione przejście do nowej linii.

Parametry

Przed każdym parametrem, poza pierwszym, musi wystąpić domyślny separator dla bieżącego polecenia. Nawias/apostrof nie pełni swojej roli, jeśli przed nim lub po nim występuje jakiś inny znak niż domyślny separator dla bieżącego polecenia. Dla przykładu: echo a" Wyświetli: a" (w bloku powyżej powinno być a", ale blog ma jakiś błąd i tego nie wyświetla)
Natomiast echo "a" Wyświetli: a Nawiasy rządzą się oddzielnymi prawami i każdy nawias musi być zamknięty.

Podstawianie zmiennych

By podstawić zmienną z bieżącego zakresu, należy poprzedzić jej nazwę znakiem dolara. Ujęcie nazwy zmiennej z poprzedzającym znakiem dolara w cudzysłów/apostrof/nawias lub poprzedzenie znaku dolara backslashem spowoduje, że w miejsce parametru nie zostanie podstawiona nazwa zmiennej.

Podanie wielu znaków dolara przed nazwą zmiennej ma specjalne znaczenie.
W kodzie powłoki jest pewna funkcja, która wykonuje polecenia, i to ona podstawia zmienne w miejsca wystąpienia ich nazw, wywołując inną funkcję. Ta "inna funkcja" sprawdza czy po znaku dolara nie występuje następny znak dolara. Jeśli tak, to nie podstawia zmienną pod nazwę, a tylko odejmuje jeden znak dolara. Ponieważ komendy, jak scopelevel, execute, jak i inne, wywołują ponownie funkcję wykonującą polecenia, to w połączeniu z odpowiednimi komendami można to wykorzystać to do niecnych celów, jak np. dokonanie operacji na zmiennej leżącą kontekst niżej. Jeśli więc w wywołaniu funkcji a występuje wywołuje funkcję b, to dzięki scopelevel mamy dostęp do zmiennych funkcji a, np.: function a =text a 1 function b =text a 3 scopelevel -1 =add a $$a $a endblock b b echo $a endblock a a Spowoduje wyświetlenie cyfry 4!
Pozwoliło mi to na pozbycie się konieczności implementacji tysiąca drobiazgów, jak referencje czy instrukcji retrun wartość. Funkcje mogą zwracać dowolną ilość rezultatów do dowolnie niskiego poziomu.

Wprowadzanie bloków kodu

Po napotkaniu słowa kluczowego function lub block z następującą po nim nazwą nowo tworzonej funkcji/tworzonego bloku kodu, nastąpi oczekiwanie na wprowadzenie instrukcji. Wprowadzanie instrukcji należy zakończyć słowem kluczowym endblock z opcjonalną nazwą kończonego bloku. Podanie nazwy kończonego bloku pozwala na wykrycie, przez interpreter, błędu nieprawidłowego zamknięcia bloku, a także zwiększa czytelność.

Nawiasy

Nawias jest normalnym ciągiem znaków. Jeżeli jednak jako jedyny parametr(w miejscu nazwy polecenia) występuje nawias, to zawartość nawiasu zostanie użyta, jako polecenie. W takim wypadku, tuż po otwarciu nawiasu musi wystąpić jakiś znak, który będzie domyślnym separatorem parametrów dla bieżącego polecenia, np. można wprowadzić: (\n echo To jest tekst) I spowoduje to wyświetlenie "To jest tekst". Inne przykłady poleceń, które zrobią to samo: echo "To jest tekst" (; echo;To jest tekst)

Pusty parametr

By uzyskać pusty parametr, można wykonać jedno z:
  • Wstawić pusty cudzysłów lub pusty apostrof
  • Wstawić dwa domyślne separatory bieżącego polecenia obok siebie, ale w przypadku, gdy domyślnym separatorem bieżącego polecenia nie jest spacja
Dla przykładu echo ""

(\n echo ) (W powyższym nawiasie występują dwa znaki nowej linii) (; echo;;)

Wybrane polecenia

Powłoka libgreattao powstała do sterowania aplikacją, więc podstawowym poleceniem jest na pewno polecenie uruchamiające akcję zdefiniowaną dla danego abstraktu. Jest nią run. Jako pierwszy parametr należy podać okno, a jako drugi nazwę abstraktu(ścieżkę zdarzenia). Oto przykład dla programu główny.o uruchamiający program edytor.o, a następnie:kończący program główny.o. Źródła obu programów są zamieszczone w katalogu Demos źródeł libgreattao,. run /desktop/dialogs/question_dialog[1] /actions/Button3 run /desktop/dialogs/question_dialog[1] /actions/exit Ponieważ wspomnieliśmy już o zmiennych, to można to uprościć: =window main_window /desktop/dialogs/question_dialog[1] run $main_window /actions/Button3 run $main_window /actions/exit Podanie ciągu znaków jako drugi argument do polecenia run spowoduje, że odpowiednie okno zostanie automatycznie wyszukane - jeżeli nie zostanie znalezione, to wystąpi błąd, ale o błędach nie teraz. Błędy wystąpią za każdym razem, gdy do polecenia podajemy wartość o typie, który nie może zostać przekonwertowany do oczekiwanego typu, np. =add i $a "Tutaj wystąpi błąd".
Polecenie =window: =window nazwa_zmiennej ścieżka_do_okna[numer_okna_o_tej_ścieżce] Spowoduje wyszukanie zmiennej o podanej nazwie w bieżącym bloku kodu. Jeżeli zmienna o podanej nazwie nie istnieje w bieżącym bloku kodu, to zostanie utworzona. Jeżeli w bieżącym bloku kodu istnieje zmienna o podanej nazwie, lecz innym typie niż okno, to wystąpi błąd.

Polecenia rozpoczynające się od znaku równości dokonują przypisania wartości do zmiennej o nazwie podanej jako drugi argument(pierwszym jest nazwa polecenia). Polecenia rozpoczynające się wykrzyknikiem powodują iterowanie po jakiś wartościach, np. !event /desktop/dialogs/question_dialog[1] a "echo $a" spowoduje wyświetlenie nazw wszystkich abstraktów wskazanego okna.

Zmienne

Powłoka libgreattao ma wbudowane następujące typy zmiennych:
  • Ciąg znaków(string)
  • Okno(window)
  • Słownik(dictionary)
Dodatkowe dwa typu są tak naprawdę ciągiem znaków, lecz jeśli polecenie wymaga danego type, to powłoka spraedzi czy wartość danego typu da się przekonwertować do wymaganego typu. Tym dwami typami są:
  • Liczba naturalna(unsigned)
  • Liczba całkowita(signed

Do usuwania zmiennych z bieżącego bloku kodu służy polecenie unset . =text tekst "To jest tekst" unset teskt echo $tekst Powyższy kod, naturalnie, spowoduje błąd.

Rozwijanie/rozszerzanie zmiennych

Przypuśćmy teraz, że mamy zmienną zawierającą dwa parametry, jak ścieżkę okna i nazwę abstraktu. Chcemy teraz wykonać polecenie run z tymi dwoma parametrami. Można to osiągnąć stosując rozszerzenie zmiennej. Robi się to wstawiając .:~ za ostatni znak dolara, poprzedzający nazwę zmiennej. Oto przykład: =text parametry "/desktop/dialogs/question_dialog[1] /actions/Button3" run $.:~parametry

Przypisywanie i usuwanie zmiennych

Jeżeli zmieniasz wartość istniejącej zmiennej, to tak, jakby poprzednia zmienna była usuwana. Tutaj masz listę tego, co się dzieje podczas tworzenia i usuwania zmiennych określonego typu:
  • String usuwanie - wartość jest zwalniana z pamięci; String tworzenie - wartość jest kopiowana
  • Window usuwanie - zmniejsza licznik referencji danego okna - jeżeli licznik osiągnął 0, a okno jest przeznaczone do usunięcia przez program, to je usuwa; Window tworzenie - zwiększa licznik referencji danego okna.
  • Dictionary usuwanie - wartość jest zwalniana z pamięci; Dictionary tworzenie - wszystkie zmienne ze słownika źródłowego są kopiowane

Słowniki

Wspomnieliśmy o tym, jaki ciąg znaków może zostać przekonwertowany na referencję do okna. Teraz wspomnę o tym, jaki ciąg znaków może zostać przekonwertowany na słownik. Taki ciąg powinien wyglądać tak: [klucz1 = wartość1 [klucz2 = wartość2 ... [kluczN = wartośćN]]] Czyli np: okno = /desktop/dialogs/question_dialog[1] action = /actions/exit Tam, gdzie są spacje, to należy postawić spacje. Nie można używać podstawień zmiennych podczas tworzenia słownika. Jeżeli chcesz dodać element z użyciem zmiennej/zmiennych jako klucz/wartość, to utwórz pusty słownik i posłuż się appendtodict. Poniżej prezentuję przykład: =dictionary nazwa_słownika "" appendtodict nazwa_słownika klucz wartość By pobrać wartość ze słownika, należy posłużyć się =fromdict, np. =fromdict a $słownik nazwa_klucza Znak dolara przed słownikiem jest celowy, gdyż komenda ta, w przeciwieństwie do większości komend operujących na słownikach, nie przyjmuję nazwy zmiennej przechowującej słownik, lecz sam słownik. Możemy w miejsce $słownik podstawić ciąg znaków reprezentujący słownik i z niego pobrać wartość.

By usunąć coś ze słownika, to należy posłużyć się komendą removefromdict:

removefromdict nazwa_słownika nazwa_klucza

Słowniki można rozwijać w ten sam sposób , co ciągi znaków. Kolejność podawania elementów na wyjście jest związana z kolejnością ich dodawania. Implementacja tablic jest taka, że przy usuwaniu elementu kolejność jest zachowana.

Bloki kodu i funkcje

Są dwa typy bloków kodu(można utworzyć jeszcze niby jeden, korzystając z nawiasów i polecenia execute-all, ale o tym później), jednak te dwa typy bloków kodu mogą realizować wszystko to, co języki strukturalne, gdyż obsługują polecenia: continue, break, return. Te polecenia opiszę przy okazji instrukcji warunkowych. Dzięki scopelevel lub scopebyname możemy uzyskać coś podobnego do czegoś, co obsługuje Java, czyli break lub continue względem bloku kodu. W przeciwieństwie do Javy, obsługujemy goto.

Jakie obsługujemy typy bloków kodu? Zwykły blok kodu i funkcja. Jak wyglądają oba bloki przedstawiłem już wcześniej. Czym się one jednak różnią? Zwykły blok kodu jest wykonywany, gdy po miejscu zakończenia poprzednio wykonanej instrukcji znajdzie się blok kodu, a my nie użyliśmy instrukcji call, callonce, goto, throwerror, return, break, continue lub instrukcji warunkowej. Funkcja jest wykonywana w momencie wywołania i możliwa jest w niej rekursja. Poza tym, to podczas tworzenia funkcji tworzony jest słownik $.unnamed_params i dodawane do niego są przekazane parametry pozycyjne. Parametry pozycyjne to te, które zostały podane po nazwie funkcji. Dodatkowa różnica polega na tym, że tylko w bloku funkcji lub dziecka tego bloku możemy używać instrukcji functionuse i usemodule. O tych dwóch instrukcjach napiszę później.

Każda funkcja i blok kodu muszą posiadać nazwę. Nazwy mogą się powtarzać.

Etykiety i goto

Etykiety i goto służą do zmiany przebiegu programu. Etykiety możemy tworzyć jedynie w obrębie jakiejś funkcji lub bloku kodu. Jest to spowodowane chęcią uproszczenia implementacji i redukcji użycia pamięci. Wyobraź sobie, że etykietę możesz wstawić gdziekolwiek - wtedy bym musiał przewidywać, jaką etykietę możesz wywołać i jak może wyglądać wykonanie programu po wywołaniu etykiety, lub pamiętać dosłownie każdą wprowadzoną instrukcję. Tryb zapamiętywania instrukcji jest włączany dopiero po napotkaniu słowa kluczowego block lub function, zwiększając odpowiedni licznik po napotkaniu jednego z tych słów kluczowych, a zmniejszając po napotkaniu endblock. Jeżeli licznik ten osiągnie 0, to tryb zapamiętywania jest wyłączany. W takim wypadku nie ma sensu dawać możliwości tworzenia etykiet gdziekolwiek.

Teraz przedstawię dwa przykłady pętli nieskończonej. block nieskończona_pętla echo Wystartowała =text komunikat "Iteracja " =text i 1 : iteracja =cat ile_razy $komunikat $i echo $ile_razy goto iteracja endblock nieskończona_pętla

block nieskończona_pętla function następna scopelevel -1 goto iteracja endblock następna echo Wystartowała =text komunikat "Iteracja " =text i 1 : iteracja =cat ile_razy $komunikat $i echo $ile_razy następna endblock nieskończona_pętla

Jeszcze jeden przykład: block nieskończona_pęta echo Wystartowała =text komunikat "Iteracja " =text i 1 block iteracja =cat ile_razy $komunikat $i echo $ile_razy continue endblock iteracja endblock nieskończona_pętla

Return i break

Return i break są różne. Ich znaczenie jest mało intuicyjne, ale wzięło się to z przyzwyczajeń programistów języków strukturalnych. Otóż break wcale nie powoduje opuszczenia bieżącego bloku. Można za pomocą instrukcji call i callonce wywołać etykietę w bieżącym bloku. Różnica jest taka, że break wyjdzie z biezącego wywołania, a return opuści blok. Jest to wykorzystywane przy wywoływaniu etykiety .initialize, jeżeli interpreter napotka instrukcje endconditionlist, ale o tym w poleceniach warunkowych.

W czym są one podobne? Jeżeli użyto return, lub nie wykonaliśmy żadnych skoków wewnątrz bieżącego bloku, to obie instrukcje powodują skok przed instrukcję endblock bieżącego bloku, czyli jego opuszczenie. Oczywiście - bieżący blok możemy zmienić za pomocą scopelevel lub scopebyname, dając podobne efekty do tych z Javy.

Parametry funkcji

Funkcja ma dwa typy parametrów - nazwane i pozycyjne. Parametry pozycyjne podajemy w ten sposób: Nazwa_Funkcji [parametr1 [parametr2 ... [parametrN]]] W jaki sposób podajemy parametry nazwane? W oto taki sposób: appendtodict .named_params nazwa_parametru1 wartość1 appendtodict .named_params nazwa_parametru2 wartość2 Nazwa_Funkcji Zadziała to tylko wtedy, gdy zmienna $.named_params istnieje. Wcześniej trzeba ją utworzyć: =dictionary .named_params "" Zmienne o tej nazwie to jedyny przypadek, kiedy interpreter nie zablokuje nam możliwości jej utworzenia lub zmiany wartości. Parametry nazwane mogą posłużyć do symulacji this z języków obiektowych, gdyż słownik parametrów nazwanych będzie wykorzystywany przez kolejne wywołania funkcji w tym samym kontekście, lecz również możemy opróżnić słownik, tworząc nowy na jego miejsce.,

Możemy jednocześnie przekazać funkcji parametry nazwane i nienazwane.

Jak jednak obsłużyć parametry wewnątrz funkcji? Sposoby są przeróżne. Pierwszym z nich jest wykorzystanie zmiennej $.@. Zawiera ona to, co wpisaliśmy w wierszu polecenia przy wywołaniu funkcji, poza nazwą funkcji. Ma to jednak sporo wad. Otóż podstawienie zmiennej $.@ pod wywołanie funkcji spowoduje, że zmienna wewnątrz wywołanej funkcji będzie mieć ciąg $.@ jako parametr. Jest to zła technika. Jeżeli chcesz z niej korzystać, to przed wywołaniem funkcji z wykorzystaniem zmiennej $.@, należy posłużyć się wywołaniem funkcji expandvariablesandcallfunction z pliku shell-utils/functions, który leży w katalogu ze źródłami libgreattao. Tak to powinno wyglądać: expandvariablesandcallfunction nazwa_funckji $.@ Możemy wykorzystać =shellparsestring i =shellgettokencount. W poniższy sposób wyświetlimy każdy element przekazany w wierszu polecenia: function echo_all =shellgettokencount i $.@ =text j 0 block process ifintless $j $i =add j $j 1 =shellparsestring wynik $j $.@ echo $wynik continue : .false endblock process endblock echo_all Jednak o warunkach napiszę potem.
Jeżeli jednak chcemy otrzymywać argumenty nazwane i pozycyjne po przetworzeniu? Mamy dwa słowniki - łatwo się domyśleć jednego. Pierwszym słownikiem jest $.named_params, dostępny jednak kontekst niżej od kontekstu wywołania. Drugim słownikiem jest $.unnamed_params, który jest z kolei dostępny w bieżącym kontekście. Drugi słownik zawiera numerowane parametry pozycyjne, zaczynając od liczby 1. Są jeszcze dwie zmienne tworzone podczas wywołania funkcji: $.unnamed_param_count i $.named_param_count. Zawierają one ilość parametrów w słownikach kolejno: pozycyjnych i nazwanych. Można się tym bawić, ale jest prostsza i bardziej czytelna metoda - funkcja paramrequires. Jest ona zdefiniowana w pliku shell-utils/functions w katalogu ze źródłami libgreattao. Tak wygląda definicja dwóch funkcji run. Druga z nich przyjmuje dwa parametry: nazwę abstraktu i okno. Następnie wywołuje ona wbudowaną funkcję run, podając swoje parametry w odwrotnej kolejności. Pierwsza funkcja po prostu wywołuje run. Oto przykład: function run paramrequires positioned_window window positioned_string path buildin run $window $path endblock function run errordisplaymode void paramrequires any_string path any_window window errordisplaymode all buildin run $window $path break : .error errordisplaymode all next endblock Użyto tutaj obsługi błędów i instrukcji next. O obsłudze błędów napiszę później, a teraz zajmijmy się instrukcją next. Wywołuje ona kolejną, dostępną w bieżącym zasięgu funkcję o tej samej nazwie. Możemy w takim wypadku wywołać run podając w dowolnej kolejności okno i nazwę abstraktu, bo w przypadku podania najpierw okna, paramrequires zwróci błąd(zaraz paramrequires omówimy), więc zostanie wywołana pierwsza funkcja z tymi samymi parametrami. Next może się okazać bardzo pomocne do tworzenia szalonych rzeczy, jak choćby funkcji-owijek, np. do debugowania(wyświetla wszystkie podane parametry, wiersz poleceń, itd.).

Teraz omówimy paramrequires. Pisząc o parametrach nie będę teraz wliczać nazwy funkcji. Do paramrequires należy przekazać parzystą liczbę parametrów. Każdy nieparzysty parametr zawiera źródło parametru, zakończone znakiem podkreślenia i typ parametru po nim. Każdy parzysty parametr to nazwa nowo tworzonej zmiennej. Jeżeli nie dopełnimy tych warunków, to paramrequires rzuci wyjątek. Obsługiwane źródła to: any(parametry pozycyjne i nazwane), positioned(parametry pozycyjne), named(parametry nazwane). Obsługiwane typy to: string, window, unsigned, signed. Dla źródła any, paramrequires w pierwszej kolejności szuka elementu o nazwie zmiennej do utworzenia w słowniku parametrów nazwanych, a jeżeli nie znajdzie, to pobiera kolejny parametr z parametrów pozycyjnych, zaczynając od 1. Oczywiście, że przed tym procesem, dodaje ilość parametrów nazwanych i pozycyjnych przekazanych do kontekstu, z którego została wywołana, i sprawdza czy jest równa ilości parametrów przekazanych do siebie podzielić przez 2.

Jeżeli chcemy wywołać paramrquires z bloku kodu wewnątrz funkcji, to możemy to zrobić tak: scopetype readvariable scopebyname nazwa_funkcji paramrequires źródło1_typ1 nazwa1 ... Dla przykładu: function błąd =text kod_błędu "" block jeśli_dwa_parametry ifinteq $.unnamed_param_count 2 varscopelevel -1 kod_błędu varscopelevel -1 komunikat scopetype readvariable scopevbyname błąd paramrequires positioned_unsigned kod_błędu positioned_string komunikat break : .false varscopelevel -1 komunikat scopetype readvariable scopevbyname błąd paramrequires positioned_string komunikat endblock jeśli_dwa_parametry =cat kod_błędu $kod_błędu " " =cat komuniakat $kod_błędu $komunikat echo $komunikat endblock varscopelevel działa podobnie, jak scopelevel, tylko powoduje, że wszystkie odwołania do zmiennej o wskazanej nazwie będą rozpatrywane pod kątem wskazanego poziomu.

Block swich

Z pomocą libgreattao możemy utworzyć prosty block switch. Będzie on działać, jak blok powłoki libgreattao, lecz również jak blok switch.
Oto przykład: block nasz_switch ghostmode goto $i : .1 block 1 echo "wybrano 1" endblock break : .2 block 2 echo "wybrano 2" endblock break : .3 block 3 echo "wybrano 3" endblock break : .error echo Default endblock W przypadku braku etykiety nastąpi skok do do etykiety .error. Instrukcja ghostmode powoduje, że blok nasz_switch będzie pomijany przy zasięganiu zasięg wyżej, jak choćby skok z bloku 3 do etykiety .error bloku wyżej, blok nasz_switch będzie pomijany. Eliminuje to skok do .error bloku nasz_switch w przypadku błędu w którymś z dzieci.

Warunki i pętle

W powłoce libgreattao instrukcje warunkowe są normalnymi instrukcjami, lecz zaczynającymi się od prefixu if. Muszą one zachowywać się odpowiedni sposób - to znaczy, że w przypadku napotkania fałszu, skaczą one poziom wyżej do etykiety false. To wszystko! Możesz samemu pisać własne typy instrukcji warunkowych. Jeżeli chcemy utworzyć etykietę .true i .initialize, a dodatkowo, by etykieta .initialize była wywoływana tylko przy pierwszym sprawdzeniu warunków, to możemy umieścić za listą warunków instrukcję endconditionlist. Etykiety .true jednak w większości przypadków nie będzie potrzebna, gdyż warunki są po prostu normalnymi instrukcjami - jeżeli warunek jest prawdziwy, to zostanie wykonana kolejna instrukcja. To sprawia, że:
  • Warunki połączone są koniunkcją logiczną
  • Warunki działają, jak w C(przynajmniej w nowszych kompilatorach) i Pythonie, czyli są wykonywane dopóki któryś z warunków nie będzie fałszywy
Dzięki takiemu podejściu łatwo można zaimplementować negację. Oto implementacja negacji: function not execute $.@ scopelevel -1 goto .false : .false endblock not Negacja jest zaimplementowana w pliku shell-utils/logic w katalogu ze źródłami libgreattao. W tym samym pliku jest też zaimplementowane OR i AND.

Assercje

W pliku shell-utils/logic w katalogu ze źródłami libgreattao są również zaimplementowane assercje. Assercja nic innego nie robi, tylko powraca po prawidłowym wywołaniu przekazanej jej instrukcji, a w przypadku fałszu, skacze do etykiety .error poziom wyżej. Wcześniej zapomniałem dodać, że brak jakieś etykiety skutkuje rzuceniem wyjątku. Jest też assert_verbose, która w przypadku fałszu dodatkowo wypisuje, co jej podaliśmy jako polecenie do wykonania.

Przykłady pętli

Pętla while: block pętla_while warunek1 warunek2 ... warunekN instrukcje continue : .false endblock Pętla do-while: block pętla_do_while instrukcje warunek1 warunek2 ... warunekN continue : .false endblock Pętla repeat unitl: block repeat_until : .false instrukcje warunek_zakończenia endblock

Pętla for: block pętla_for inicjalizacja goto pierwsza_iteracja : iteracja np.zwiększenie_licznika : pierwsza_iteracja warunek1 warunek2 ... warunekN instrukcje goto iteracja endblock Dla zwiększenia czytelności pętli zastanawiam się nad wprowadzaniem możliwości stosowania etykiet .continue, do której skakałaby instrukcja continue, lecz w przypadku jej braku, skakałaby do do początku bloku(tak, jak obecnie).

Ładne formatowanie warunków

Lista warunków w języku libgreattao wygląda ładnie. Jednak co z funkcjami OR lub AND? Można im przekazać listę warunków w następujący sposób: OR "ifstreq a b" "ifstreq a c" Jednak to nie wygląda pięknie.
Innym sposobem jest skorzystanie z nawiasów, o tak: (\n OR ifstreq a b ifstreq a c) Przed OR-em można wstawić znak przeniesienia do nowej linii, jako iż znak przeniesienia do nowej linii jest domyślnym separatorem. To samo możemy zrobić w przypadku nawiasu zamykającego. Pamiętać jednak należy, by nie wstawiać znaków przeniesienia do nowej linii obok siebie, gdyż takie coś będzie oznaczać parametr pusty i być może spowoduje błąd.

Domknięcia

Domknięcia umożliwiają zwrócenie funkcji z innej funkcji, jednak zwracana funkcja będzie móc korzystać z parametrów przekazanych do funkcji zwracającą funkcję. Taki parametr musi wcześniej zostać zapamiętany w specjalnej strukturze zwracanej funkcji.
Dla przykładu możemy napisać funkcję, która pozwala na podnoszenie liczby przekazanej jako parametr do zapamiętanej potęgi. Oto przykład: function create_power =fromdict power $.unnamed_params 1 scopelevel -1 function power functionuse power =fromdict number $.unnamed_params 1 scopelevel -1 =text power 1 block wykonaj ifintless 1 $power =sub power $power 1 scopelevel -2 =mul power $$power $number continue : .false endblock endblock power endblock create_power Ważna jest instrukcja functionuse. Powoduje ona zapamiętanie zmiennej power z funkcji create_power do struktury reprezentującej zwracaną funkcję(o nazwie power). To się dzieje podczas zapamiętywania/tworzenia funkcji. Natomiast podczas wykonania powoduje to przeniesienie zmiennej o nazwie power ze struktury związanej z funkcją power do kontekstu/zasięgu obecnego bloku. Wykonanie poniższego kodu wywoła wyjątek: function a =text a s echo $a functionuse a endblock a Będzie to spowodowane tym, że zmienna a nie będzie dostępna w momencie napotkania instrukcji echo.

Moduły

Pliki w libgreattao możemy includować tak: script ścieżka_do_pliku Jednak można także ładować moduły. O tak: loadmodule ścieżka_do_pliku wewętrzna_nazwa_modułu Każdy plik zawierający poprawne instrukcje libgreattao można includować pierwszą lub drugą metoda. Druga metoda powoduje, że zmienne i funkcje, które podczas przetwarzania pliku nie zostały utworzone/zmodyfikowane z użyciem instrukcji zmiany kontekstu/poziomu, będą prywatne. Dla zrozumienia tego mechanizmu warto pobrać ze strony domowej libgreattao menadżer plików tao-manager/tao-file-manager w wersji drugiej i przyjrzeć się modułowi libgreattao tego programu. Możliwość ładowania modułów i dodatkowych skryptów powstała nie tylko po to, by użytkownik mógł sobie ułatwić użytkowanie wielu aplikacji, ale powstało również po to, by aplikacje mogły dostarczać przyjazne nazwy funkcji, m.in ułatwiając pracę użytkownikowi, jak również dostarczając stabilniejsze API. Dla przykładu moduł powłoki libgreattao dostarcza takie funkcje, jak ls, copy, rm, cd,. pwd, więc jest parę poleceń przypominających te z uniksowych powłok.

Instrukcja usemodule

Instrukcja usemodule jest przeznaczona specjalnie dla bloków kodu. Powoduje ona, że poziom niżej jest wklejany moduł o nazwie podanej, jako drugi parametr. Jeżeli funkcja wcześniej nie wywołala usemodule, to ten wybrany moduł jest dopinany do łańcucha kontekstów. Jeżeli funkcja wcześniej wywołała usemodule, to moduł jest zamieniany. Wraz z scopelevel, pozwala to w prosty sposób osiągnąć coś na wzór zmiennych prywatnych i publicznych funkcji, które odwołują się do zmiennych prywatnych. By utworzyć funkcję publiczną dla modułu, to należy się posłużyć domknięcie, korzystając ze zmiennej $.module_name, wskazującą na nazwę podaną jako trzeci parametr dla funkcji loadmodule.

Instrukcja hascurrentfiledescriptorflag

Instrukcja służy do sprawdzania czy struktura reprezentująca obecnie aktywnego deskrypora pliku ma określoną flagę. Po załodowaniu pliku lub wystartowaniu w trybie interaktywnym, tworzona jest struktura reprezentująca odpowiedni deskryptor pliku. Może ona posiadać kilka flag, które mówią np., że obecnie powłoka powinna pracować w trybie interaktywnym, debugowania lub oznacza, że obecnie wczytywany jest moduł. Pozwala to na warunkowe przygotowanie modułu do pracy jako moduł - można to wykorzystać by ustawić zmienną podstawianą do polecenia scopelevel, występującego przed definicjami rzeczy publicznych. Jeżeli chcemy, by dana rzecz była publiczna, to scopelevel występujący przed jej definicją powinien mieć parametr -1, jeśli plik został załadowany jako moduł. W przeciwny wypadku do scopelevel należy przekazać parameter 0.

Po co moduły

Na przykładzie modułu powłoki libgreattao drugiej wersji menadżera plików, podam przykład zmiennej currentview. Jeżeli plik zostanie załadowany za pomocą script, to zmienna będzie publiczna, a jeżeli za pomocą loadmodule, to zmienna będzie prywatna. Moduły trochę przypominają obiekty, które nie dopuszczają do swoich zabawek.

Wyjątki

W powłoce libgreattao istnieją cztery typy zachowań po napotkaniu wyjątku: throw, continue, exit, debug. Pierwszy powoduje skok do etykiety .error w bieżącym bloku, ale tylko w przypadku, gdy bieżący kontekst/poziom nie ma ustawionej flagi błędu(domyślnie flaga jest wyzerowana). Poza tym ustawia tą flagę. Gdy jednak flaga jest ustawiona, to skacze do etykiety .error w bloku niżej, jeżeli zachowanie dla obsługi błędów w tym bloku to również throw. Jeżeli etykieta .error nie istnieje w bloku branym pod uwagę, to powoduje to kolejny wyjątek, więc automatycznie(z powodu ustawieina wspomnianej flagi), throw szuka etykiety .error wyżej. Jeżeli throw przeszukiwał któryś blok w poszukiwaniu .error, a zachowanie obslugi błędów dla tego bloku jest inne niż throw, to throw po prostu wychodzi z obecnie obsługiwanego bloku i wyzwala sposób obsługi wyjątków przypisany temu blokowi, do którego throw wyszedł. Continue nić nie robi w przypadku napotkania błędu - zwyczajnie kontynuuje skrypt. Exit powoduje wyjście z programu. Debug natomiast powoduje przejście w interaktywny tryb debugowania.

Obecny tryb obsługi błędów definiuje się poleceniem: errorbehaviour nazwa Nie można natomiast ustawić zachowania debug, gdy program nie został uruchomiony z przełącznikiem --tao-na-shell-enable-debug. W takim przypadku zostanie zachowany stary sposób obsługi błędów. Domyślnym sposobem obsługi błędów jest throw.

Zachowanie obsługi błędów dla bieżącego bloku jest przechowywane w zmiennej $.error_handling_behaviour. Jednak przed wykonaniem bloku do jego kontekstu dopinana jest nowa zmienna $.error_handling_behaviour z wartością zdefiniowaną w zmiennej $.error_handling_behaviour_for_new_context, poza wyjątkiem, gdy $.error_handling_behaviour_for_new_context posiada wartość inherit. W przypadku wartości inherit do nowotworzonej zmiennej $.error_handling_behaviour jest kopiowana wartość z obecnej zmiennej $.error_handling_behaviour. Dodanie obsługi zmiennej $.error_handling_behaviour_for_new_context było podyktowane tym, że być może chcielibyśmy dla naszego bloku kodu ustawić sposób obsługi błędów na continue, lecz wywołujemy w nim funkcję. Ponieważ ta funkcja to dla nas czarna skrzynka, to lepszym zachowaniem dla niej jest throw.

Sposób obsługi błędów określa też flaga mówiąca o tym, czy należy wyświetlać komunikat o błędzie, wraz ze śladem. By ją aktywować, to należy wykonać poniższy kod: errordisplaymode all By ją zdezaktywować, to należy wykonać poniższy kod: errordisplaymode void

Kilka słów na koniec

Mam już niewiele do zrobienia przed wydaniem pierwszej wersji alfa. Chciałbym napisać kilka prostych programów w libgreattao, jak:
  • Tao-multishell: Graficzna/tekstowa(dzięki libgreattao) powłoka do uruchamiania innych programów
  • tao-makefile-ui: Program analizujący plik makefile, pozwalający na wybór celów wykonania make, a także pozwalający na podanie parametrów do makefile, zapisanie ich do późniejszego użycia

Zamierzam napisać kolejny wpis blogowy o tworzeniu własnego, tekstowego instalatora, jednak nie korzystający z libgreattao(<<<co za szkoda!>>>), bo ma być to instalator libgreattao(<<<co za szczęście!>>>) ;-) . Instalator ma być skryptem powłoki, z dodaną licencją i archiwum tar.gz na końcu.

Co do sugestii na temat powłoki/języka, to czekam na sugestie. Moim zdaniem, to stworzyłem bardzo zaawansowanego assemblera(prostota i moc!), ale wynika to z mojego lenistwa. 

linux oprogramowanie programowanie

Komentarze

0 nowych
DjLeo MODERATOR BLOGA  17 #1 09.06.2015 21:15

Napracowałeś się nad tym wpisem, propsy ;)

  #2 09.06.2015 23:52

Szacunek

smieszek07   3 #3 10.06.2015 09:27

Jakie ma to zastosowanie?

nintyfan   10 #4 10.06.2015 09:35

@smieszek07: Powłoka w libgreattao służy do sterowania aplikacjami napisanym w libgreattao - do automatyzacji czynności. Obecnie istnieje podział na programy cui, cli, gui i webowe. Libgreattao pozwala na uruchamianie jednego programu w wielu trybach, co zwiększa możliwości programisty i użytkownika. Libgreattao obecnie nadaje się jedynie do tworzenia niezłożonych aplikacji(tzn. takich, które nie wymagają złożonego interfejsu użytkownika), ale w przyszłości ma to się zmienić. W przyszłości planuję dodać nowego klienta do Freeciv, a dzięki libgreattao, to ten klient będzie się nadawać do pisania boot-ów, być może zastąpi freeciv-web, a dodatkowo będzie go można uruchomić z interfejsem Qt, GTK+ czy nawet konsolowym. Jeżeli udałoby mi się napisać backend libgreattao dla biblioteki SDL, to mielibyśmy pełne pokrycie tego, co oferuje libgreattao z klientami oferowanymi przez Freeciv-a.

Libgreattao poza tym zdejmuje z programisty brzemię projektowania interfejsu użytkownika, gdy plik z odpowiednią klasą okna istnieje. Jeżeli nie istnieje, to programista może zdefiniować własny, a w przyszłości zespół libgreattao(obecnie tylko ja), twórcy dystrybucji, środowiska graficznego czy sam użytkownik będzie mógł zmienić to, jak wygląda i zachowuje się stworzona przez twórców aplikacji klasa okna.

Z powodu obecnego podziału na wiele bibliotek do tworzenia GUI, podziału na programy GUI, CLI, CUI i webowe, powstaje mnóstwo programów, które mają realizować to samo, a powstały np. tylko po to, by był np. program do nagrywania płyt dobrze integrujący się ze środowiskiem graficznym. Libgreattao rozwiązuje ten problem dlatego, że ma wiele backendów, wiele trybów pracy, a dla programów (C|G)UI pozwala zmienić interfejs przez edycję plików tekstowych.

Autor edytował komentarz.
nintyfan   10 #5 10.06.2015 09:52

@smieszek07: Wyobraź sobie, że chcesz nagrać wiele płyt w programie do nagrywania płyt napisanym w libgreattao. Zamiast bez przerwy klikać i czekać, aż proces nagrywania płyty się zakończy, to możesz to zautomatyzować. W poprzednich wpisach(o trzech domenach konfiguracji) opisałem, jak przekazywać parametry z wiersza poleceń do powłoki libgreatao, więc możesz przekazać listę plików do nagrania i program do nagrywania płyt, podczas obsługi pętli komunikatów, będzie obsługiwał napisany przez ciebie skrypt, co będzie powodować wypalanie wielu płyt - oczywiście - możesz to zrobić z poziomu basha i poleceń tekstowych, ale to by wymagało nauczenia się nowego programu i trzymania go na dysku,

Autor edytował komentarz.
hind   2 #6 10.06.2015 10:15

@nintyfan: No właśnie wygląda to trochę jak odkrywanie koła na nowa. Zwłaszcza że bash ma duże możliwości pod względem skryptowania i tworzenia prostych GUI przy pomocy zenity oraz dialog. Pod tym względem przewagą jest dostęp przez web, ale i to można załatwić przez (fast-)cgi.

nintyfan   10 #7 10.06.2015 10:53

@hind: Mój protokół nie wymaga wysłania tylu danych przez sieć, co HTML/HTTP. Wysyłane są tylko polecenia libgreattao, jak utwórz okno danej klasy, utwórz abstrakt w oknie, zmień atrybut abstraktu, itd. (oczywiście, że są przesyłane także pliki). Gdybyś chciał wykorzystać XUL po HTTP, to narzut byłby większy, a nie miałbyś takich możliwości.

Libgreattao próbuje rozwiązać problemy, o których pisałem. Zenity jest pod GNOMA, a Kdialog pod KDE, a moja biblioteka pozwala na tworzenie GUI dla każdego środowiska graficznego, w zgodzie z jego wytycznymi projektowania interfejsów użytkownika i to bez narzutu ze strony programisty.

Co do mojej powłoki i bash-a, to nie ma co porównywać, bo są adresowane do dwóch różnych rzeczy. Moja powłoka jest przeznaczona do sterowania aplikacją, a bash do uruchamiania poleceń. Gdybyś chciał sterować uruchomioną aplikacją z poziomu bash-a, to każda aplikacja musiałaby dostarczać interfejs cli, więc by musiała, np,. implementować moją powłokę. Moja biblioteka dostarcza interfejs CLI dla każdej aplikacji, a poza tym to jedna powłoka, więc poruszanie się po każdej aplikacji w trybie CLI będzie takie samo.

Autor edytował komentarz.
nintyfan   10 #8 10.06.2015 10:57

@hind: Wspomnę o czymś, co być może przeoczyłeś. Powłoka w libgreattao nie służy do tworzenia interfejsów użytkownika - ona służy do sterowania aplikacją, a Zenity służy do tworzenia okien dialogowych. Zresztą - to czy Zenity uruchomi się bez środowiska graficznego?

hind   2 #9 10.06.2015 11:23

@nintyfan: Dla tego wspomniałem o dialogu, który do tego ma swoje wersje Xdialog i Kdialog, do tego jest też wxWidget. Osobiście wolę nie poznawać aż tyle nowych technik i skupić się już na tym co znam i do obsługi programów, jak już bym potrzebował to pewnie i tak użyłbym pythona, a do interfejsu graficznego glade.
Sterowanie procesem? nie ma problemu. Już teraz tak robię w PHP poprzez popen tworząc interfejs pomiędzy aplikacją konsolową a skryptem.
--
Osobiście nie widzę większego zastosowania dla tej biblioteki, ale na pewno bez powodu nie powstała i ktoś na pewno będzie jej używać

Autor edytował komentarz.
nintyfan   10 #10 10.06.2015 11:34

DIALOG i xDIALOG to wciąż różne programy. Moja biblioteka automatycznie wykrywa, którego backendu użyć, więc nie ma problemu w napisaniu własnej wersji dialog, która będzie działać *prawie* zawsze. Prawie zawsze, bo nie jestem w stanie wszystkiego przewidzieć. Z wxWidget masz trochę racji, ale nie pozwala on tworzyć różnych typów interfejsów dla różnych środowisk, by przestrzegać ich zaleceń tworzenia interfejsów użytkownika. Z tego, co powiem, to wxWidget nie ma dobrej obsługi Qt.

Co do sterowania procesem, to zauważ, że moja powłoka posiada ustandaryzowany interfejs do sterowania aplikacją i możliwość odpytywania o dostępne możliwości aplikacji, jak windowlist(nie napisałem o tym w sumie), !events(lub showevents), więc nadaje się też do pracy w trybie interaktywnym. Poza tym, to bez mojej biblioteki, dodanie interfejsu cli do aplikacji wymaga nakładu pracy. Dzięki mojej bibliotece piszesz raz coś, co działa z interfejsem cli, cui, gui i sieciowym, i to bez konieczności wgłębiania się w szczegóły.


Napisałem krótkie wprowadzenie, ale jest chyba za krótkie. Dlatego polecam lekturę moich poprzednich wpisów na temat libgreattao.

hind   2 #11 10.06.2015 12:26

Czytałem wcześniejsze wpisy, po prostu biblioteka zaczyna się znacznie rozrastać. Tak że można by się zastanowić nad jej podziałem na obsługę interfejsu i na część odpowiedzialną za język programowania bo z tym przypomina mi się jeden komiks https://xkcd.com/927/.

a co do obsługi dialogu
if [ $DISPLAY ] ; then ; dialog='dialog' ; else ; dialog='xdialog' fi; czy tak jakoś ;)

nintyfan   10 #12 10.06.2015 13:44

@hind: Zamierzałem wydzielić język programowania do osobnej biblioteki, by inne projekty mogły z niego korzystać. Jednak wtedy bibliotekę do obsługi języka libgreattao musiałoby ładować kiedyś po wywołaniu tao_initialize, bo inaczej taki podział zwiększyłby tylko zużycie pamięci. Mógłbym wydzielić też obsługę sieci.

Obecnie jednak całe libgreattao to około 20.000 linijek(nie wliczając plików nagłówkowych).

smieszek07   3 #13 10.06.2015 14:10

@nintyfan: Jakoś mnie to nie przekonuje , jeszcze tego nie widze

pocolog   11 #14 10.06.2015 18:57

Kupa roboty za co gratulacje, ale czy to ma szanse się sprzedać to już wątpię. Jako projekt hobbystyczny świetna sprawa i ten wpis może przysporzy pomocników w projekcie.
To licencja gpl?

nintyfan   10 #15 11.06.2015 08:14

@pocolog:
"
>head LICENSE

GNU LESSER GENERAL PUBLIC LICENSE

Version 3, 29 June 2007

Copyright © 2007 Free Software Foundation, Inc.

Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.

This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below.
"
Odpowiedź LGPLv3. Chciałem jedynie zapewnić ochronę sobie i projektowi, a nie ograniczać zastosowanie w zamkniętych projektach.

smieszek07   3 #16 11.06.2015 21:03

@nintyfan: W ogólności to co stworzyłeś ma służyć do interakcji np skryptu z powłoką graficzne (nie zaleznie od srodowiska ?) , no dobra , a jak to użyć ?

nintyfan   10 #17 11.06.2015 21:52

@smieszek07: To co stworzyłem ma pozwolić na tworzenie aplikacji zgodnie ze wzorcem projektowym nieco podobnym do MVC. Jednak, kiedy program zostanie uruchomiony w trybie powłoki, to interfejs użytkownika nie jest tworzony, a można nim zarządzać za pomocą skryptów lub wpisując komendy w konsoli. Ten artykuł właśnie traktuje o wykonywaniu skryptów/wpisywaniu komend. Moje rozwiązanie pomoże m.in:
a) Zautomatyzować pracę
b) Pisać boty ;-D

Jednak, ze względów bezpieczeństwa, powłoka Libgreattao jest mocno ograniczona. Powłoka to złe słowo, bo nie umożliwia ona na komunikację z systemem, a jedynie z jakąś aplikacją. Zamierzam napisać w Libgreattao pełnoprawną powłokę, która będzie pozwalać m.in zarządzać programami napisanymi w libgreattao tak, jakby ta powłoka siedziała w środku, a wykorzystam do tego tryb sieciowy.

Jutro podam parę przykładów użycia, a teraz idę spać. Sposób uruchomienia programu napisanego z użyciem libgreattao opisałem w tym wpisie tekstowym. Musisz najpierw skompilować libgreattao, a następnie Dema(w katalogu Demos). Następnie uruchamiasz jakieś demo w trybie powłoki.

  #18 16.06.2015 14:03

Jakieś wrapery, biblioteki żeby można pisać w cywilzowanym narzeczu ?
Oprócz tego bloga gdzie szukać info o upublicznieniu repo i doku ?

nintyfan   10 #19 16.06.2015 17:43

@Pietras_ (niezalogowany): Jeszcze nie stworzyłem repozytorium, oprócz tego, co jest na sourceforge. Co do dokumentacji, to jeszcze nie stworzyłem.

Jeżeli chodzi o pisanie w cywilizowanym narzeczu, to oprócz tego, że nie umieszczamy nazw/symboli operacji pomiędzy operandami, a dodatkowo operacji nie można łączyć, to język ma dosyć ładną składnię, dzięki paramrequires i obsłudze tablic, wszystko jest raczej na miejsce. Raczej nie będzie można uzyskać możliwości umieszczanie znaków operacji pomiędzy operandami, a także nie będzie można uzyskać możliwości łączenia operacji.

Co do warunków, to mój język pod tym względem jest świetny.

Może wprowadzę funkcję equation, która pozwoli na stosowanie symboli +,-,*,/,% pomiędzy liczbami, a dodatkowo będzie można korzystać z nawiasów, jako iż nawiasy są normalnymi ciągami znaków.

Dla mnie czytelniejsze jest:
=text a "To jest tekst"
Niż:
char *a="To jest tekst"

Autor edytował komentarz.
nintyfan   10 #20 08.11.2015 21:58

@smieszek07: Uruchamiasz program napisany w libgreattao z przełącznikiem --tao-na-shell-interactive lub --tao-shell-execute-file ścieżka/do/skryptu.

nintyfan   10 #21 08.11.2015 21:59

@Pietras_ (niezalogowany): Na sourceforgu masz wiki, a dodatkowo jest w moim repo dla OpenSUSE.