Uživatelské nástroje

Nástroje pro tento web


orbis:oil

Toto je starší verze dokumentu!


OIL neboli skriptovací jazyk ORBISu

Úvod

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ákladní informace

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:

  • definice proměnné stylem Jméno: typ např.
     W: TElement 
  • Cesta k elementu
    ObjecModel.WORK 

    … zápis vrátí číselnou adresu elementu WORK v Objektovém modelu světa

  • Cesta k vlastnosti elementu
    ObjecModel.WORK.Count 

    …Vrátí počet elementů WORK

  • Výraz
    { 2 * 3}

    …Výsledkem je 6

  • Funkce
    ObjecModel.WORK.CreateElement(TOwnerEntity, Karel)
    ObjecModel.WORK.CreateElement(TOwnerEntity, Bohdan)

    …pod WORK vytvoří Entity Karel a Bohdan a poslední řídek vrátí adresu Bohdana

  • Přiřazení
    ObjecModel.WORK.Karel.Name = 'Rudolf'

    …Změní hodnotu vlastnosti Name, tedy přejmenuje Karla na Rudolfa

  • Seznam
    ObjecModel.WORK.Element.Name

    …Vrací seznam jmen všech elementů pod WORK, výsledkem bude Rudolf, Bohdan

  • a kombinace těchto stavů:
    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

Syntaxe

Základní syntaxe

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ě.

kombinace skriptů

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:\

Volání jiného skriptu

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.

Vložení skriptu do aktuálního

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

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é

Definice

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

Typy

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ě

Použití proměnných

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

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).

Syntaxe výrazu

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ší:

  • Na rozdíl od OILu, kde všechny hodnoty jsou jako text a hodnoty uváděny v apostrofech nebo uvozovkách, v rámci výrazu je potřeba rozlišovat typy a čísla psát jako čísla a text jako text.
  • Text (string) je v apostrofech, tedy
    'Karel'

    … uvozovky způsobí syntaktickou chybu

  • Desetinná čísla (float) používají jako oddělovač tečku, tedy
    14.156
  • Typová kontrola … existuje, takže pokud chceme provádět operace s hodnotami různých typů, musíme je pomocí adekvátních funkcí přetypovat
       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
  • Závorky () umožňují oddělovat části výrazu a měnit tak prioritu jeho provádění, posloupnost vykonávání částí výrazu je jinak dané i prioritou operátorů která je v pořadí [^], [*,/,DIV], [+,-], [AND, OR]
    {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í

Proměnné a konstanty

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átory výrazu

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 je platí obě strany výrazu boolean
OR „nebo“ logický součet …True pokud je 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 výrazu

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 FRAC(-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

Formátování

  • TODATETIME() - jen pokud je první parametr text. Pokud druhý parametr s formátem neexistuje, pokusí se funkce převést buď jako ISO zápis (2025-04-15) nebo pomocí lokálního nastavení (typicky 15.4.2025). V případě jiného zápisu je možné definovat jak je datum zapsáno … třeba pro '15/4/2025' je to 'dd/mm/yyyy'.
  • TOSTRING() formátování má smysl jen pokud je první parametr datetime nebo float
    • datetime d-dny (dd číslo dddd název dne) m-měsíce (mm číslo mmmm název) y-rok h-hodiny n-minuty
      d: datetime='15.4.2025 1:58'
      S={TOSTRING(d,'dddd dd.mmmm yyyy hh:nn')}
      // S obsahuje 'úterý 15.duben 2025 01:58'
    • float 0-číslice pokud je, jinak 0 #-číslice, pokud je, jinak nic .-desetinný oddělovač
      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

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í.

FOR

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:

Syntaxe

  • Automatický cyklus FOR v objektovém modelu - prochází všechny elementy dané entity:
    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í
  • Cyklus FOR pomocí celočíselné proměnné a rozsahu:
    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

WHILE

Příkaz WHILE provádí cyklicky kód uzavřený slovem END, dokud platí vstupní podmínka daná výrazem

Syntaxe

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

REPEAT UNTIL

Příkaz REPEAT provádí cyklicky kód ukončený klíčovým slovem UNTIL, dokud neplatí podmínka daná výrazem za UNTIL.

Syntaxe

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

CONTINUE

Příkaz CONTINUE ukončí vykonávání 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

BREAK

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í ...

IF THEN ELSE

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.

Syntaxe

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

EXIT

Příkaz exit ukončí vykonáváni skriptu. Konec, šmytec.

funkce

příklady

orbis/oil.1744721154.txt.gz · Poslední úprava: 2025/04/15 14:45 autor: ppk