Files
Patryk Gensch df6cf2f3d3
Some checks failed
docs / deploy (push) Has been cancelled
docs / build (push) Has been cancelled
Added part of docs
2026-05-19 20:51:59 +02:00

7.0 KiB

Dziwactwa silnika

Silnik Piklib/BlooMoo zawiera szereg niestandardowych zachowań, które mogą zaskoczyć programistę przyzwyczajonego do popularnych języków skryptowych. Niniejszy rozdział zbiera najczęstsze z nich w jednym miejscu.

Wyrażenia i operatory

Tylko nawiasy kwadratowe grupują obliczenia

W wyrażeniach arytmetycznych grupowanie wykonuje się wyłącznie za pomocą [ ]. Nawiasy okrągłe ( ) są zarezerwowane dla list argumentów wywołań metod i nie pełnią funkcji grupującej (zobacz Arytmetyka).

@ zamiast / dla dzielenia

Operator dzielenia to znak małpki @, nie /. Próba użycia / w wyrażeniu nie zostanie zinterpretowana jako dzielenie.

Typ wyniku zależy od typu lewego operandu

Wszystkie operacje binarne rzutują prawy operand na typ lewego. Wynik również ma typ lewego operandu. Skutki kolejności są nietrywialne (zobacz Reguła typowania):

"Wartosc" + 2.5  →  "Wartosc2.50000"
2 + "3"          →  5

Operatory na BOOL mają odwróconą logikę

Operator + na BOOL działa jak koniunkcja logiczna (AND), a * jak alternatywa (OR). Operatory -, @ i % na BOOL nie mają efektu (zobacz Operatory arytmetyczne).

% na DOUBLE traci część ułamkową

Reszta z dzielenia w typie DOUBLE jest najpierw obliczana, a następnie obcinana do liczby całkowitej i ponownie rzutowana na DOUBLE. W efekcie 1.5 % 2 daje 1.00000, a nie 1.50000.

&& i || przyjmują wyłącznie BOOL

Operatory logiczne nie wykonują niejawnego rzutowania nawet wtedy, gdy operand byłby konwertowalny do BOOL. Próba użycia wartości innego typu jako operandu kończy się błędem silnika.

Dzielenie przez 0 w wyrażeniach kończy się błędem

W odróżnieniu od metod typów liczbowych (gdzie DIV i MOD zwracają wartość bez zmian), dzielenie operatorem @ lub % przez 0 w wyrażeniu arytmetycznym powoduje wyjście do pulpitu.

Składnia skryptów

Bloki kodu muszą być w jednej linii

Cały blok kodu pomiędzy { a } musi się zmieścić w jednej linii pliku skryptu. Wieloliniowe bloki nie są obsługiwane.

Każda instrukcja musi kończyć się średnikiem

Również ostatnia instrukcja w bloku kodu. Pominięcie końcowego średnika może spowodować, że instrukcja nie zostanie wykonana.

Komentarze: # dla linii, ! dla instrukcji

Linia rozpoczynająca się od # jest pomijana w całości. Pojedyncza instrukcja poprzedzona znakiem ! jest wykomentowana aż do najbliższego średnika.

Komparator równości zmienia się w warunkach złożonych

W warunku prostym @IF równość zapisuje się jako _. W warunku złożonym @IF ten sam komparator zapisuje się jako apostrof '. Pozostałe komparatory (<, >, <_/<', >_/>') zachowują się analogicznie.

Tekst bez cudzysłowów jest najpierw szukany jako zmienna

Wartość zapisana bez cudzysłowów najpierw jest interpretowana jako nazwa zmiennej. Jeśli zmienna o takiej nazwie istnieje, użyta zostanie jej wartość; w przeciwnym razie tekst zostanie potraktowany jako literał typu STRING. Może to prowadzić do trudnych do wykrycia kolizji, gdy literał przypadkowo zbieżny jest z nazwą zmiennej.

Wielokrotna deklaracja obiektu scala właściwości

Powtórzenie linii OBJECT=NAZWA w tym samym pliku nie nadpisuje wcześniejszej definicji — silnik dołącza nowe właściwości do istniejącej i nadpisuje wpisy o tych samych kluczach.

Application.def powinien kończyć się pustą linią

Brak pustej linii na końcu pliku Application.def może spowodować, że ostatnia scena nie zostanie poprawnie zinterpretowana, co objawia się czarnym ekranem.

Liczby

DOUBLE akceptuje literę d jako znak wykładnika

W notacji wykładniczej zarówno e, jak i d są rozpoznawane jako separator wykładnika: 1.23e4 i 1.23d4 są równoważne.

DOUBLE → INTEGER zaokrągla, a nie obcina

Przy rzutowaniu DOUBLE na INTEGER liczba jest zaokrąglana do najbliższej liczby całkowitej, a nie obcinana. Dla wartości dodatnich .5 zaokrąglane jest w górę, dla ujemnych — w dół, więc -0.5 → -1, a 0.5 → 1.

STRING → INTEGER zwraca 0 zamiast błędu

Konwersja tekstu nie będącego liczbą do INTEGER (lub DOUBLE) zwraca 0 (0.00000), a nie generuje błędu. Może to maskować błędy w wyrażeniach łączących literały tekstowe z liczbowymi.

Metody typów

DOUBLE.MOD obcina część ułamkową

Analogicznie do operatora %, metoda MOD typu DOUBLE zwraca część całkowitą reszty z dzielenia.

DOUBLE.SGN zwraca INTEGER, nie DOUBLE

Metoda SGN jest jedyną metodą typu DOUBLE, która nie zmienia wartości zmiennej i jako wartość zwraca INTEGER.

INTEGER.RANDOM(min, max) jest obustronnie włączne

Wariant dwuargumentowy metody RANDOM zwraca wartość z przedziału [min, max], włącznie z oboma końcami. Wariant jednoargumentowy zwraca [0, bound).

INTEGER.DIV i INTEGER.MOD z 0 nie modyfikują zmiennej

W odróżnieniu od dzielenia operatorem @/% w wyrażeniu, metody DIV i MOD na typie INTEGER z dzielnikiem 0 zwracają niezmienioną wartość bieżącą zamiast generować błąd. Analogicznie zachowują się metody na typie DOUBLE.

STRING.COPYFILE ignoruje obiekt-odbiorcę

Metoda COPYFILE na typie STRING nie korzysta z wartości zmiennej, na której została wywołana — operuje wyłącznie na dwóch argumentach reprezentujących ścieżki źródłową i docelową.

STRING.CHANGEAT zastępuje dokładnie jeden znak

Niezależnie od długości ciągu w drugim argumencie, CHANGEAT usuwa jeden znak z bieżącej wartości na podanej pozycji i wstawia w jego miejsce cały ciąg argumentu. Długość ciągu po operacji może być inna niż przed.

THIS w obsłudze sygnałów

THIS zwraca "temp" dla GETNAME

Mimo że THIS jest referencją do obiektu, który wyemitował sygnał, próba pobrania jego nazwy metodą GETNAME zwraca ciąg "temp", co wskazuje na wewnętrzną reprezentację jako obiekt tymczasowy.

Nie wszystkie metody typu działają na THIS

Bezpiecznie działają GET/SET (dla typów prymitywnych) oraz SHOW/HIDE/PLAY/PAUSE/STOP/RESUME (dla obiektów graficznych). Wywołanie metod specyficznych dla typu obiektu (np. GETCFRAMEINEVENT na ANIMO) zazwyczaj kończy się błędem silnika. Szczegóły opisano w sekcji Zmienna THIS.