Vlastní slovo OIL neznamená olej, jak by se mohl mnohý anglofon domnívat, ale zkratku z Orbis Interactive Language. Je to jazyk jednoduchý, vlastně to skoro ani není jazyk a už vůbec není interativní.
OIL je interpret. To znamená, že zdrojový kód se předem nekompiluje, ale provádí se postupně řádek po řádku. Což zároveň znamená, že na případné chyby se přijde až k nim jazyk dojde a pokusí se je provést.
Základem příkazového řádku OILu je pohyb po objektovém modelu ORBISu. Ten se odehrává relativně vůči aktivnímu elementu, kterým je, pokud není jinak řečeno WORLD. Na rozdíl od jiných jazyků je jediným akceptovatelným operátorem v řádku „=“, tedy přiřazení, běžné operátory jsou samozřejmě také k dispozici, ale jen v rámci výrazu, který je vždy v samostatném bloku.
Změnu aktivního elementu je možné provést nastavením systémové proměnné ACTIVEELEMENT
. každý řádek má výsledek kterým je buď hodnota, nebo seznam hodnot. Cesta zápisu může být i absolutní, pak řádek začíná slovem World.
Příkazový řádek tedy v souhrnu disponovat těmito jevy:
Jméno: typ
např. W: TElement
ObjecModel.WORK
… zápis vrátí číselnou adresu elementu WORK v Objektovém modelu světa
ObjecModel.WORK.Count
…Vrátí počet elementů WORK
{ 2 * 3}
…Výsledkem je 6
ObjecModel.WORK.CreateElement(TOwnerEntity, Karel) ObjecModel.WORK.CreateElement(TOwnerEntity, Bohdan)
…pod WORK vytvoří Entity Karel a Bohdan a poslední řídek vrátí adresu Bohdana
ObjecModel.WORK.Karel.Name = 'Rudolf'
…Změní hodnotu vlastnosti Name, tedy přejmenuje Karla na Rudolfa
ObjecModel.WORK.Element.Name
…Vrací seznam jmen všech elementů pod WORK, výsledkem bude Rudolf, Bohdan
W: TElement // definice proměnné W i: integer // a celočíselné proměnné i S: string // textové S Bobo: TElement // a nakonec objektového Boba W = ÓbjecModel.WORK // do W přiřadíme element WORK W.CreateElement(TOwnerEntity, Karel) // ve WORK vytvoříme entitu Karel // to samé provedeme s Bohdanem ale jinak Bobo = Create(TOwnerEntity, Bohdan) // do proměnné Bobo přiřadíme vytvořeného Bohdana W.NextElement = Bobo // a vložíme ho do WORK aby se stal součásti modelu W.Karel.Name = 'Rudolf' // Karla přejmenujeme na Rudolfa i = {W.Count * 2} // do i přijde dvojnásobná hodnota počtu elementů WORK, tedy 4 S = cat(" Dvojnásobný počet elementů ve WORK je ", i) // v S je text Dvojnásobný počet elementů ve WORK je 4
OIL není case sensitiv, tedy nezáleží na velikosti písmen. Všechny konstantní hodnoty jsou chápány jako text a tedy uzavřeny v apostrofech nebo uvozovkách (toto pravidlo neplatí ve výrazech). Rozdíl je jen v tom, že u apostrofů se automaticky mažou vnější mezery, u uvozovek ne.
S: string = ' 12
' nastaví proměnnou S na "12"
zatímco
S: string = " 12 "
nastaví proměnnou S na " 12 "
Cesta k elementu, resp. k jeho vlastnosti je sekvence jmen elementů v modelu oddělaná tečkami.
ObjectModel.Karel.Count
Výrazy jsou (až na vyjímky) ohraničené složenými závorkami {}.
Těmi vyjímkami je automaticky chápaný výraz v kostrukcích jako např. IF výraz THEN, WHILE výraz a podobně.
Cestu k souboru tak jak je uváděna v následujících řádcích je možné zapisovat relativně … pokud leží pod adresářem, ze kterého je spuštěna řídící aplikace (pak začíná přímo názvem prvního podřazeného adresáře). Je samozřejmě možný i absolutní zápis, začínající označením disku s dvojtečkou a lomítkem … c:\
Z příkazového řádku OILu lze volat jiný skript pomocí funkce CALL
CALL(Led\Review.oil)
tohle např. způsobí přezobrazení hlavního mapového okna aplikace
parametr cesty se zde uvádí bez apostrofů či uvozovek. Což zároveň znamená, že se dá použít jen pevná hodnota a ne proměnná či jiný parametr.
Pokud vyvstane tato potřeba, lze to vyřešit vlastností hlavního nástroje:
s: string = 'LED\Review.oil' MainTool.ExecuteScript=S
Je potřeba si uvědomit, že volaný skript nic neví o proměnných aktuálního OILu a ani aktuální OIL nevidí proměnné volaného skriptu, takže je-li potřeba předat nějaké parametry, musí se to udělat jinou cestou.
Funkce INCLUDE umožňuje vložit jeden skript do jiného a tím i používat knihovnu často používaných funkcí a proměnných bez opakování v každém OILu.
—
Syntaxe je
INCLUDE('Cesta ke skriptu')
na rozdíl od funce CALL je parametr cesty uveden v apostrofech nebo uvozovkách, umožňuje tedy aplikaci proměnné.
Příklad:
Include('LED\ProtoUtils.oil') CheckProto() M.NextText="Ahoj světe!"
vloží OIL pro práci s oknem protokolu, funkce CHeckProto ho otevře a poslední řádek vypíše text.
Komentáře, neboli poznámky lze tvořit několika způsoby:
;
středník komentuje celou řádku, je-li uveden na začátku//
dvojité lomítko … kdekoliv, komentuje text od něj až do konce řádku*
hvězdička (asterisk) …blokový komentář, komentuje více řádků až do příštího výskytu, je-li uvedena na začátcích řádku (jako první znak)
Proměnné je možné definovat kdekoliv v kódu, každopádně před jejím prvním použitím. Jejich název by neměl obsahovat mezery a doporučoval bych i šetřit s diakritikou a použitím jiných záhadných znaků. Existuje jen jedna vyjímka při které se proměnná, neexistuje-li, vytváří automaticky a to je v hlavičce cyklu for
Definice proměnné se provádí následujícím zápisem:
jméno_proměnné: typ // takže například S: string // textová proměnná D: float // desetinné číslo
Název typu | Popis |
---|---|
char | jednoznaková textová hodnota |
string | text |
boolean | logická proměnná true nebo false |
integer | celočíselná hodnota |
float | desetinné číslo |
datetime | datum a čas |
TElement | objekt, uvedená může být jakákoliv třída která je potomkem elementu, TElement platí obecně |
Proměnné lze používat jednoduše, případné přetypování probíhá automaticky, pokud je to možné.
Např.
S: string=" 3" i: integer i=S
nastaví do S text obsahující 3 a následně vloží do i celočíselnou hodnotu 3.
Proměnná je zároveň i zakukleným objektem, který disponuje vlastnostmi umožňující delikátnější komunikaci s nimi, tedy číst i nastavovat pomocí nich hodnoty:
Vlastnost | Použití |
---|---|
AsChar | pokusí se převést hodnotu proměnné jako znak |
AsString | Vrací hodnotu jako text |
AsBoolean | podobně |
AsInteger | podobně |
AsFloat | podobně |
AsDatetime | podobně |
Value | stejný typ jako sama proměnná |
Příklady:
F: float="0,04568156" // u desetinného čísla je jedno zda použijeme jako oddělovač tečku nebo čárku F // hodnota F je nyní v exponenciálním tvaru, tedy 4.56815600000000E-0002 // protože není exponenciální podoba vhodná pro čitelné výpisy, použijeme raději konstrukci F.Value // a ejhle, objeví se původní velmi lidské 0,04568156
nebo
CH: char="A" // v CH je nyní znak A CH.AsInteger = {CH.AsInteger + 1} // pomocí výrazu zvýšíme celočíselný kód znaku o jedna a vrátíme do CH CH // a výsledkem operace je písmeno B
Výrazy slouží k aritmetickým nebo porovnávacím operacím nad hodnotami představovanými objekty (elementy), jejich vlastnostmi nebo obecně proměnnými. Nepoužívají se striktně jenom ve skriptech, ale i mimo ně (např funkce hledání výrazem v LEDu).
Výraz v rámci OILu je uzavřen složenými závorkami… {..}
. Výjimkou je hlavička IF
a WHILE
… tam je samozřejmé, že se jedná o výraz a závorka se nepoužívá. Další vyjímkou je samostatné použití například v dialogu „Hledání ve vrstvách výrazem“ v LEDu. Pak se ve výrazu nevyskytují žádné proměnné, ale spouští se na každý testovaný objekt a je možné v něm používat přímo vlastnosti testovaného objektu.
Výraz, stejně jako zbytek OILu není case senzitivní, takže velikost písmen nerozhoduje.
Další syntaktická pravidla jsou ale mnohem přísnější:
'Karel'
… uvozovky způsobí syntaktickou chybu
14.156
S: string = '3' i: integer i = {S + 2} // tohle by způsobilo chybu, nemůžem sčítat text a číslo, napíšeme tedy i = {S.AsInteger + 2} // přetypování pomocí vlastnosti proměnné // nebo i = {ToInteger(S) + 2} // přetypování pomocí funkce // Každopádně v i je teď hodnota 5
{3 + 2 * 2} // zde je výsledek 7, nejprve se násobí, pak sčítá {(3 + 2) * 2} // zatímco tady 10 - provede se součet v závorce a pak násobení
Jak už možná bylo řečeno, ve výrazu je možné použít všechny proměnné definované kdekoliv skriptu, jen je zde třeba respektovat jejich typ. Specialitou je několik konstant existujících právě jen ve výrazu:
Konstanta | Použití |
---|---|
NIL | používá se pro zjištění inicializace objektu např A = nil je pravdivé, pokud není vytvořen |
PI | float … Ludolfovo číslo, tedy 3.141… atd |
NOW | datetime …je vlastně funkce bez závorek, vracející momentální čas na úroveň vteřin |
TRUE | boolean …logická hodnota ANO, tedy pravda |
FALSE | boolean …logická hodnota NE, tedy nepravda (někdo by řekl lež) |
Operátor je kouzelné slovo které provede operaci s jednou nebo více hodnotami
Operátor | Použití | Výsledek |
---|---|---|
^ | mocnina - operand a exponent tedy např 2 ^ 3 je 2 na třetí, čili 8 | float nebo integer |
* | násobení např. 2 * 3 je 2 krát 3 tedy 6 | float nebo integer |
/ | dělení … 5 / 2 tedy 5 děleno 2 je 2.5 | float |
DIV | celočíselné dělení …totéž jen s celými čísly, ne desetiny | integer |
MOD | zbytek po celočíselném dělení …5 mod 3 = 2 10 mod 3 = 1 | integer |
= | „rovná se“ …True pokud jsou obě hodnoty stejné | boolean |
> | „větší než“ …True pokud jsou je první hodnota větší než druhá | boolean |
> | „menší než“ …True pokud jsou je první hodnota menší než druhá | boolean |
>= | „větší nebo rovno“ …True pokud je první hodnota větší nebo rovna druhé | boolean |
⇐ | „menší nebo rovno“ …True pokud je první hodnota menší nebo rovna druhé | boolean |
<> | „různé“ …True pokud je první hodnota jiná než druhá | boolean |
AND | „a zároveň“ logický součin …True pokud platí obě strany výrazu | boolean |
OR | „nebo“ logický součet …True pokud platí alespoň jedna strana výrazu | boolean |
NOT | logický zápor …převrací logickou hodnotu výrazu za sebou True - false | boolean |
IS | objekt vlevo je potomkem třídy vpravo zapsané jako text: E is 'TElement ' | boolean |
CONTAINSTEXT | Text vlevo obsahuje text vpravo - velikost znaků nerozhoduje | boolean |
STARTSTEXT | Text vlevo začíná textem vpravo - velikost znaků nerozhoduje | boolean |
ENDSTEXT | Text vlevo končí textem vpravo - velikost znaků nerozhoduje | boolean |
MATCH | Text vlevo odpovídá regulárnímu výrazu vpravo (taky text) | boolean |
Poslední operátor, MATCH porovnává textovou hodnotu s regulárním výrazem, více o regulárních výrazech jako o zajímavém prostředku pro analýzu textové hodnoty se můžete dozvědět třeba na této stránce v češtině, Případně si lze regulární výraz poskládat a otestovat na stránce regex101 v angličtině.
funkce je uvedena klíčovým slovem za nímž následuje v jednoduché závorce jeden, výjimečně dva parametry, přičemž prvním parametrem je měněná hodnota, druhým mohou být pravidla provedení.
Funkce | Použití | Výsledek |
---|---|---|
CLASS() | Objekt na vstupu výrazu odpovídá třídě v závorce - trochu atypická funkce pracující se vstupním parametrem, nachází uplatnění hlavně v prohledávacích algoritmech | boolean |
ROUND() | Převede float na integer zaokrouhlením: ROUND(4.65) = 5 | integer |
TRUNC() | Převede float na integer odříznutím desetinné části: TRUNC(4.65) = 4 | integer |
FRAC() | Vrátí desetinnou část: FRAC(54.156) = 0.156 | float |
ODD() | Testuje, zda je argument liché číslo | boolean |
ABS() | Vrátí absolutní hodnotu parametru ABS(-12) = 12 | integer nebo float |
EXP(x) | e na x kde e je základ přirozených logaritmů (eulerovo číslo) | float |
LN(x) | vrátí přirozený logaritmus x | float |
SQR(x) | vrátí druhou mocninu x | float |
SQRT(x) | vrátí druhou odmocninu x | float |
COS(x) | kosinus x | float |
SIN(x) | sinus x | float |
ARCTAN(x) | arkus tangens x | float |
TOBOOLEAN() | Převede parametr na logickou hodnotu | boolean |
TOINTEGER() | Převede parametr na integer | integer |
TOFLOAT() | Převede parametr na float | datetime |
TODATETIME() | Převede parametr na datetime, druhý parametr je v případě textu formát | datetime |
TOSTRING() | Převede parametr na string, formátování opět může řídit druhý parametr | datetime |
d: datetime='15.4.2025 1:58' S={TOSTRING(d,'dddd dd.mmmm yyyy hh:nn')} // S obsahuje 'úterý 15.duben 2025 01:58'
f: float={pi} S: string S={TOSTRING(f,'000.00')} // S obsahuje '003,14' S={TOSTRING(f,'#.000')} // S obsahuje '3,142'
Příkazy běhu programu jsou ty, které ohraničují cyklické provádění kódu za nějaké podmínky, případně tyto cykly zkracují nebo z nich vyskakují.
příkaz FOR je uzavřen slovem END - provádí určený počet cyklů kódu, má 2 hlavní principy a 4 možné zápisy:
include('LED\ProtoUtils.oil') CheckProto() for E in ObjectModel.Karel // první varianta prochází elementy Karla M.NextText=E.Name // a vypisuje do textového protokolu jejich jména end // nebo for E out ObjectModel.Karel // druhá varianta prochází vlastníky Karla (nadřazené objekty) M.NextText=E.Name // a činí s nimi totéž end // jak je vidět, END uzavírá kód, který se v cyklu provádí
for i = 1 to 3 // první varianta provede 3 cykly 1 - 3 ShowMessage(i) // a v každém zobrazí dialog s hodnotou i end // nebo for i = 3 downto 1 // druhá varianta provede 3 cykly sestupně, tedy 3 - 1 M.NextText=E.Name // a činí s nimi totéž end // Ani proměnná E, ani i nemusejí být předem definovány, vytvářejí se automaticky
Příkaz WHILE provádí cyklicky kód uzavřený slovem END, dokud platí vstupní podmínka daná výrazem
while <výraz> <kód k provedení> end // příklad: i: integer i='1' // výchozí hodnota i je 1 while i < 10 // dokud platí že i je menší než 10 // libovolný kód i={i + 1} // a zvýšíme hodnotu i o 1 end // zvýšení hodnoty je nutné, jinak by vznikl nekonečný cyklus protože chudák i by nikdy nebylo větší než 10
Příkaz REPEAT provádí cyklicky kód ukončený klíčovým slovem UNTIL, dokud neplatí podmínka daná výrazem za UNTIL.
repeat <kód k provedení> until <výraz> // příklad: i: integer i='1' // výchozí hodnota i je 1 repeat // opakujeme následující kód odsud // libovolný kód i={i + 1} // a zvýšíme hodnotu i o 1 until i > 10 // dokud i nepřesáhne hodnotu 10 // zvýšení hodnoty je nutné, jinak by vznikl nekonečný cyklus protože i by opět nikdy nebylo větší než 10
Příkaz CONTINUE ukončí vykonávání zbytku stávajícího cyklu a přeskočí na další kolo.
for i = 1 to 5 // začínáme cykly 1 - 5 if ODD(i) then continue // pokud je i liché, přeskočíme na další kolo end ShowMessage(i) // takže ve výsledku se zobrazí dialog jen dvakrát pro hodnoty 2 a 4 end
Příkaz BREAK ukončí vykonávání cyklu a přeskočí na kód následující za ním.
for i = 1 to 5 // začínáme cykly 1 - 5 if i > 3 then break // pokud je i větší než 3 ukončíme vykonávání cyklu end ShowMessage(i) // takže ve výsledku se zobrazí dialog jen třikrát pro hodnoty 1,2,3 end // po volání break pokračuje OIL zde ... pokud tu je co k provedení ...
Příkaz IF umožňuje podmíněné provedení části kódu. Podmínku definuje logický výraz mezi klíčovými slovy IF a END. ELSE je nepovinné, případně odděluje část prováděnou při nesplnění podmínky.
if <výraz> then <kod> end // nebo if <výraz> then <kód> else <jiný kód> end // příklad: for i = 1 to 10 if i mod 2 = 0 then // začátek podmíněné části - výraz zjišťuje jestli je i sudé // <kod1> // pokud ano, provádí se tato pasáž else // <kod2> // a pokud ne, provede se kod2 end end
Příkaz exit ukončí vykonáváni skriptu. Konec, šmytec.