Jazyk dpic #

Programovací jazyk dpic bol špeciálne vytvorený na kreslenie grafov a diagramov s možnosťou ich exportu ako obrázkov alebo vkladania do textových dokumentov. Obsahuje príkazy pre kreslenie lineárnych objektov ako čiara, šipka, krivka, ako aj plošné objekty ako pravouholník, kružnica, elipsa, oblúk a umožňuje vytváranie zložených objektov. Zložitejšie grafických objekty ktoré sa v obrázkoch vyskytujú častejšie, ako sú značky elektronických súčiastok, je možné v dpic kresliť pomocou makier, ktoré obsahujú kód pre nakreslenie objektu. CircuitMacros je rozšírením dpic o knižnice makier pre kreslenie elektronických obvodov a zapojení. Podrobný popis syntaxe jazyka dpic je v dokumentácii.

Programovací jazyk dpic

Programovací jazyk dpic historicky vychádza z jazyka pic vytvoreného Brian W. Kernighan-om v roku 1991. Z programátorského hľadiska dpic patrí do skupiny tzv. mini-jazykov, (DSL) ktoré sú vytvorené pre nejaký konkrétny učel na rozdiel od všeobecne použiteľných jazykov (GPL). Syntax jazyka dpic je veľmi jednoduchá, okrem príkazov na kreslenie grafických objektov má aj základné jazykové konštrukcie na riadenie toku programu ako je podmienkové vetvenie a cyklus. Nie je v ňom možné ale vytvárať funkcie, ktorú sú formálne nahradené makrami. Makrá obsahujú kód pre kreslenie zložitejších objektov a pri ich použití kompilátor nahradí v programe meno makra týmto kódom.

Program #

Program je tvorený textovým súborom, ktorý začína znakmi .PS a končí znakmi .PE. Príkaz na riadku je ukončený bodkočiarkou ; alebo ukončenim riadku (neviditeľný znak \n). Bodkočiarka na ukončenie príkazu nie je povinná, na rozdiel napr. od jazyka C, ale využijeme ju vtedy, ak budeme do jedného riadku zadávať niekoľko príkazov.

.PS                           # zaciatok postupnosti prikazov

scale=2.54                    # príkaz nastavenie parametrov velkosti obrazku
cct_init                      # príkaz pre inicializaciu kniznice makier 
                              #  s analogovými prvkami (rezistor, ...)

line from (1,1) to (2,2)      # príkaz dpic pre vykreslenie čiary
resistor                      # makro pre vykreslenie rezistoru
rezistor(,,E);                # makro s parametrami
resistor(2,,E); rlabel(,R1,); # niekolko príkazov v jednom riadku

.PE                           # koniec postupnosti prikazov

Text za koncom programu je ignorovaný. Ukončenie programu môžeme prakticky využiť pri hľadaní chýb v skripte, kedy pomocou .PE vyradíme zbytok programu zo spracovania.

Komentáre #

Komentáre začínajú znakom # a končia koncom riadku. Blokové komentáre nie sú definované, je ale možné použiť viacriadkové komentáre s riadkami ukončenými \\.

# toto je jednoriadkovy komentar
# toto je dvojriadkovy komentar        \\
  a jeho pokracovanie na dalsom riadku

Warning

White-space (tabulátory, medzery, znak nového riadku) sú vo v argumentoch makier ignorované pred argumentom, nie ale za argumentom.

name( x,
y, z )
    
je ekvivalent

name(x,y,z )

Hodnoty #

Jazyk dpic pozná len numerické hodnoty ktoré môžu byť zapísané v desatinnom tvare alebo môžu byť vo vedeckom formáte. Všetky numerické hodnoty sú interne uchovávané vo formáte floating-point. Všetky grafické prvky ako aj texty sú pokladané za objekty na ploche a sú reprezentované súradnicami polohy ich geometrického stredu.

Premenné #

Meno premennej musí začínať písmenom nasledovaným ľubovolným počtom alfanumerických znakov. Premenné sa vytvoria pri ich definícii, musia byť inicializované numerickou hodnotou a sú globálne t.j. majú platnosť v celom zdrojovom kóde.

d  = 2;
pi = 3.14159265359;
q  = 2*pi*8;

Pre premenné sú definované numerické a logické operácie

binárne aritmetické oprácie
+   -   *   /   %   ^

unárne aritmetické operácie
+=   -=   *=   /=   %=

relačné operácie 
!=   ==   <   >   >=   <=   ||   &&

Warning

Pretože dpic používa pre numerické hodnoty výhradne čísla typu floating point, v dôsledku internej reprezentácie tohoto číselného typu nemusí byť výsledok použitia relačného operátora jednoznačný, napríklad pri porovnaní formálne rovnakých hodnôt súradníc je vyhodnotená vetva False

R1: resistor
up_
R2: resistor     # R1 a R2 majú rovnakú x-ovú súradnicu

if R1.x == R2.x then 
   { ...  }      # vetva True      
   { ...  }      # vetva False -  

Súradnice #

Súradnice bodov sú reprezentované ako dvojice (x,y) a nemôžu byť použité ako hodnoty premennej, môžu ale byť reprezentované referenciou. Špeciálny význam má pomenovaná súadnica Here, ktorá obsahuje súradnice posledného vykresleného bodu. Súradnice majú preddefinované atribúty .x, .y, ktoré reprezentujú numerické hodnoty zložiek polohy. Pre prácu so súradnicami sú definované vektorové operácie.

Vytvorenie súradnice #

Novú súradnicu je možné vytvárať z numerických hodnôt ako aj pomocou iných súradníc.

P1: (3,4);      # vytvorenie súradnice bodu
p1 = (3,4);     # chyba   


a = 1; b = 2;   # konverzia numerických hodnôt na súradnice 
P2 = (a, b);
P3 = (a, 0);    # bod na osi x

                # prístup k zložkám súradnice
px = P1.x       # numerická hodnota x-ovej súradnice
py = P1.y       # numerická hodnota y-ovej súradnice
nx = Here.x     # hodnoty aktuálnej pozície
ny = Here.y

P4: (P1, P2)    # ekvivalent (P1.x, P2.y)
P5: P4          # nová súradnica 
P5: P1          # redefinícia súradnice

Poznámka

Je možné používať súradnice zapísané aj bez zátvoriek v tvare x, y, ale z dôvodu možných konfliktov pri expanzii makier je vhodnejší prehľadnejší zápis so zátvorkami (x, y).

line to 1,1
line to (1,1);

Vektorové operácie #

Výsledkom vektorovej operácie nad súradnicami je zase súradnica. Pre násobenie a delenie je platná len post-multiplikacia.

S1: (a,b) + (c,d)      # súčet   
S2: P1 + P2
S3: P1 + (c,d)
S4: Here + (dx,dy)     # offset k aktuálnej polohe

D1: (a,b) - (c,d)      # rozdiel 
D2: P1 - P2
D3: P1 - (c,d)

M1: (a,b)*k            # násobenie, k - numerická hodnota alebo premenná
M2: P1*k
M3: k*P1               # chyba

Q1: (a,b)/k            # delenie       
Q2: P1/k

Poloha medzi dvoma bodmi #

Pri kreslení zapojení často potrebujeme určiť polohu medzi dvoma bodmi, v dpic môžeme použiť konštrukciu between

PB: k between P1 and P2  

Hodnota k určuje relatívnu vzdialenosť ku koncovým bodom, k=0.5 je stredom, k=0 a k=1 sú polohy koncových bodov. Pri hodnote k mimo intervalu 0…1 leží za krajnými bodmi P1 a P2.

_images/cm_0160k.png

Obr. 49 Použitie konštrukcie between.#

Textové reťazce #

Text je postupnosť znakov definované v obyčajných úvodzovkách a nemôže byť použitý ako hodnota premennej. Súradnice geometrického stredu zobrazeného textu ale môže byť reprezentovaná referenciou.

str = "Toto je text"          # chyba   
T1: "Toto je text" at (1,1);  # ok, stred textu je v bode (1,1)

Inštrukcie #

Inštrukcia je jeden alebo viacej príkazov jazyka dpic končiacich znakom bodkočiarky ; alebo znakom konca riadku. Je vhodné implicitne používať znak konca riadku vždy, pri prípadnom dopĺňaní príkazu sa týmto obmedzí vznik chýb. Pretože v jazyku dpic nie je možné vytvárať funkcie a podprogramy, sú skupiny príkazov zoskupené do makier pomocou ktorých sa vykreslujú zložitejšie objekty. V CircuitMacros je program tvorený inštrukciami ktoré sú makrami ako aj samotnými príkazmi jazyka dpic. Formát inštrukcie v má tvar

[referencia:] objekt [ atributy] [ umiestnenie ] [ text ]

Príklady

line from (1,1) to (2,2)           # inštrukcia jazyka dpic
resistor(,,E);                     # makro inštrukcia končí znakom ;
capacitor()                        # makro inštrukcia končí \n
resistor() rlabel(,R2,)            # chyba, neoddelene inštrukcie
line to Here + (2,0); resistor()   # dpic a makro inšrukcia 

Referencie #

Každý zobrazený objekt v môže byť označený referenciou, ktorá reprezentuje polohu jeho geometrického stredu. Pomocou referncie je možné odkazovať sa aj na atribúty objektu. Referencie musí začínať veľkým písmenom nasledovaným ľubovolným počtom alfanumerických znakov.

    L1: line from Here to Here + (2,2);
    R1: resistor();
     S: (5,6);
     
    P1: R1.start     # suradnica
    P2: L1.end
    
    px = R1.end.x    # numericka hodnota

Referencie sú globálne, referencia definovaná v bloku alebo vetve je viditeľná v celom programe. Nové priradenie mena referencie inému objektu pôvodnú referenciu prepíše. Pri kreslení zapojení sa stáva, že musíme presne spojiť dva body zapojenia, ktorých absolútnu polohu nepoznáme. Využitím vektorvých operácií s referenciami na objekty získame spojenie, ktoré sa nepreruší ani pri dodatočnej uprave polohy objektov.

_images/cm_0160c.png

Obr. 50 Použitie referencií pre výpočtu koncového bodu čiary.#

Vetvy #

Vetva je tvorená kódom uzatvoreným do zložených zátvoriek {...}. Vetva umožňuje vytváranie časti obvodu alebo umiestnenie iných komponentov relatívne k poslednej hodnote Here, vo vetve sa vytvorí lokálna kópia Here. S výhodou ich použijeme v prípade, keď potrebujeme nakresliť samostatnú časť obvodu (vetvu) a potom pokračovať v kreslení zapojenia od pôvodnej pozície.

Uzatvorenie kódu do vetvy {...} neovplyvňuje viditeľnosť premenných. Vetvy je možné do seba vnárať.

d=3;
R1: resistor(right_ d,);        # d -> 3
DT: dot;
   {      d = 2;                # Here -> DT
      R2: resistor(down_ d,);   # Here -> R2.end
          ground(at Here, T);   
          d=1.5;
   }

   {  R3: resistor(up_ d,);     # d -> 1.5   Here -> R3.end
          tconn(0.5,O);         
          d=2.5;
   }
                                # Here -> DT
R4: resistor(right_ d);         # d -> 2.5   Here -> R4.end
_images/cm_0160f.png

Obr. 51 Použitie vetiev na kreslenie častí obvodu.#

Vetvy s výhodou využijeme pri popise prvkov zapojenie. Zobrazenie textu mení rovnako ako každý nový element zapojenia hodnotu Here, ak chceme v kreslení pokračovať s pôvodnou súradnicou, uzatvoríme text do vetvy. Príkazy pre popis dvojpólov (llabel …) hodnotu Here nemenia.

line -> 1;
box wid 2 ht 1;     
{
    "top of box" at last box.n above; 
    "bottom of box" at last box.s below;
    line from last box.nw to last box.se; 
    line from last box.sw to last box.ne; 
}
line -> 1;     
box wid 2 ht 1;
_images/cm_0160e.png

Obr. 52 Lokálne súradnice vo vetve.#

Bloky a zložené objekty#

Časť kódu uzatvorená v hranatých zátvorkách [...] predstavuje blok alebo zložený objekt. Program v bloku má vlastnú absolútnu súradnicovú sústavu a po vytvorení má vlastnosti plošného objektu. Premenné v bloku sú rovnako ako vo vetve lokálne, vnútorné referencie vytvorené v bloku sú prístupné pomocou referencie na celý blok.

   w=2;
   move to (1,1.5);                  # poloha zloženého objektu
A:[                                  # blok s absolutnymi suradnicami  
     rr=0.25;                        # inicializácia vnútorných premenných 
     h=w/2; w=w+1/2;                 # použitie vonkajšej premennej  
 B:  box at (0,0) wid w ht h; 
 C1: circle at (0, 0.5) rad rr; 
 C2: circle at (0,-0.5) rad rr;
 C3: circle at B.w rad  rr;
 C4: circle at B.e rad rr;
] 

Pre zložený objeky sú automaticky vypočítané vonkajšie rozmery a sú mu priradené štandardné atribúty

.s   .n   .w   .e   .c
.sw  .se  .nw  .ne
.wid_     .ht_

Pre ukladanie a použitie zloženého objektu na ploche platia rovnaké pravidlá ako pre každý iný plošný objekt.

r = A.rr;                            # chyba, premenná rr nie je viditeľná
r = A.C1.rad                         # použitie vnútorných referncií
line <- from A.B.nw left_ 1 up_ 1; 
line <- from A.ne right_ 1 up_ 1;    # použitie vonkajších referencií a atribútov
right_; box at A.c wid A.wid_ ht A.ht_ dashed;
_images/cm_0160d.png

Obr. 53 Blok reprezentujúci zložený objekt a jeho vonkajší obrys.#

Riadenie toku #

Jazyk dpic obsahuje základnú konštrukciu pre cuklus a podmienkové vetvenie toku programu.

Cyklus #

Formát príkazu pre cyklu

for variable = expr to expr [by [*] incr ] do { anything }.

Jednoduchý cyklus s premennou \(x\) má tvar

for x = 0 to 200  do { line from (rand(), rand())*5 to (rand(),rand())*5; }

kde v zložených zátvorkách je telo cyklu, toto má vlastnosti bloku s relatívnymi súradnicami vztiahnutými k začiatku cyklu. Cykly sa môžu vnárať, počet vnorených cyklov nie je obmedzený. Pri opakovanom prechode telom cyklu sa hodnota kurzoru Here zachováva, čo je zrejmé zo zjednodušeného zápisu kódu

...
for q=0 to 2*pi by 0.1 do{
    x = r*cos(a*q);
    y = r*cos(b*q);
    line to (x,y);        <-- line from Here to (x,y); Here <- (x,y)
}
...
_images/cm_0160b.png

Obr. 54 Príklad použitia cyklu.#

Vetvenie #

Formát vetvenia

if expression then { if-true } else { if-false }