Bejelentkezés

Keresés a fórumban

Kulcsszó
Ablakkezelők

TÉMA: Új shell írása

Új shell írása 2015 szept. 09 04:02 #1833

  • FossilCodger
  • FossilCodger profilkép
  • Nem elérhető
  • Arany fokozatú fórumozó
  • Hozzászólások: 209
  • Köszönetek: 6
  • Karma: 0
Na e témát azért nyitottam épp az ablakkezelők témakörben, mert:
1. Jobb nem akadt. Nincs például amolyan általános „programozás” témakör.
2. Van köze igenis az ablakkezelőkhöz is (egy kevés...), csak kéretik továbbolvasni...

Tehát. Van nekem egy jóbarátom, aki sokkal jobban is ért a Linuxhoz is és a programozáshoz is mint én. Gyakran cserélünk egymás közt eszmét és szoftvert... Na és Ő nekikezdett hogy írjon egy új ablakkezelőt. Eredetileg nekem is az volt a tervem hogy írok egyet, a saját programnyelvemben. De ha ő már rákattant, csak örülök neki, mert ezt mindigis terhes kötelességemnek éreztem, de egyben muszájnak is, különböző okokból. Most azonban ezen energiám felszabadult, s a következő célomnak szentelhetem, ami egy saját shell megírása. Ez engem sokkal jobban érdekel, mert jobban hasonlít egy programnyelvhez.

És ekkor jött a nagy Ötlet meg Hatlet: Egyszerűen úgy kell megírnom a programnyelvemet, hogy az alapból képes legyen shell funkciók ellátására is!

Rájöttem azonban, hogy a korábban itt beharangozott veremlogikás nyelvem erre teljesen alkalmatlan. Azt ember el nem viselné, ha ezzel kéne kínlódnia a parancssorban! (Én sem, hiába vagyok csak nagy jóindulattal embernek nevezhető...) Mert programozás közben semmi baj egy efféle nyelvvel: megírom amit kell, kipróbálom, ha nem jól működik töröm a fejemet... De egy shellnél egy tévedésnek komoly következményei lehetnek, állományok elvesztése meg ilyesmi.

Átmenetileg tehát félretettem a veremalapú nyelvemet, s megint újba kezdtem, de ez már normálisabb szintaxisú lesz. Nagyjából a maura hasonlít majd, de nem kompatibilis vele. A legfontosabb dolgok már megvannak belőle, készítettem sebességteszteket is. Ennek eredménye az, hogy feladattól függően a natív -O2 direktívával lefordított C kódnál 8-szor ... 40-szer vagyok lassabb, általában azonban, azaz az esetek legnagyobb többségében ez olyan kb 22-szeres lassúság. Néha, nagyon speciális körülmények közt azonban előfordul az is hogy csak 6.5 -ször vagyok lassabb.
A Pythonnál meg úgy nagy általánosságban 1.8 -szor vagyok lassabb, azaz durván 2-szer.

Aki megkérdezi, mi az értelme egy effélének ha lassabb vagyok mint az elterjedt Python, annak az a válaszom, hogy az, hogy ezt tetszőlegesen bővíthetem. És KÖNNYEN. Az eredeti maut istentelenül nehéz volt bővítenem egy idő után. EZT KÖNNYŰ. (Hiába, ez a gyakorlat: most már messze tapasztaltabb vagyok a programnyelvírásban...) Könnyen bővíthetem új alaptípusokkal is, és pláne könnyen új utasításokkal. És az a szép benne, hogy akármennyivel bővítsem is, de ez NEM LASSÍTJA LE a programfutást!

A programnyelv nevének azt adtam, hogy Scrawl. Kedves tulajdonsága, hogy ellentétben a Pythonnal, semmi jelentősége az indentálásnak, sőt a megjegyzéseknek se. Még annak se, mit írunk egy sorba és mit nem. Futás előtt tokenizálja az interpreter, s a tokenizált kódot hajtja végre, amiben nyoma sincs már semmi megjegyzésnek vagy whitespace-nak. Whitespace-t néha kell tennünk ugyan a forráskódba, de csak akkor ha emiatt nem lenne egyértelmű a szintaxis, viszont ekkor se lesz benne whitespace a tokenizált kódban.

Bár szemmel láthatóan hasonlít a maura, de ismétlem nem kompatibilis vele. Nagyjából olyan lehet a viszony köztük, mint a latin nyelv és az olasz között...

Na most e bejegyzést azért írom, mert mint említettem, ezt úgy akarom kibővíteni, hogy alkalmas legyen shell-nek, s gondoltam, esetleg akad errefelé pár muki aki szívesen dumálna-ötletelne azon, milyen legyen egy leendő új shell! Ne aggódjon senki, egyetlen sor programozási segítséget se kérek, sőt, istenőrizz!!! megírom én magam! (Igazából a váza már készen is van, egyetlen képernyőoldal az egész, nem egy nagy wasziszdaß, az egészben csak az a trükk hogy egy helyen forkolnia kell önmagát, oszt' jóóóvan).

Tehát nem programozásról van szó, hanem ötletelésről a funkciókat illetően. Ezt úgy értem, hogy NEM ÓHAJTOK KOMPATIBILIS LENNI A JELENLEG LÉTEZŐ SHELLEKKEL.

Köztudott, hogy a jelenlegi shellek közt is vannak eltérések, inkompatibilitások. Nos nálam szinte semmi se lesz megszokott, de nem azért hogy direkt önkényeskedjek, hanem hogy e „shell” nyelve alkalmas legyen általános programozási feladatok elvégzésére is! Na és hát emiatt MUSZÁJ nem kompatibilisnek lennem. Mert például egy normális programnyelvtől az ember alapból elvárja, hogy a < és a > jelek relációkat fejezzenek ki. A bash esetén azonban ezek átirányításokat valósítanak meg, emiatt is van az hogy az összehasonlító műveletek kezelése (szintaxisa) a shellben annyira nyakatekert hogy ha rászorulok, rángógörcsöt kap tőle az idegrendszerem!

És rengeteg efféle dolog akad még. Na és nálam az elsődleges szerepkör a programozás lesz, a shell dolgait rendelem ennek alá, annak kell alkalmazkodnia. Ugyanakkor nem szeretném ha nagyon elszállna az agyam ezt illetően (sajnos hajlamos vagyok rá, már az Asperger-szindrómás mivoltom miatt is...), és emiatt is jó lenne megdumálni ezeket itt valakikkel. Nyilván persze mert én írom, úgyis az lesz amit én akarok, de ettől még a legőrültebb fantáziakinövéseimet esetleg le lehetne nyesegetni, megfelelő kommunikáció esetén!

Tehát itt lényegében a szintaxis megbeszélését próbálnám megoldani, már ha akad rá érdeklődő. Akadnak konkrét, már megfogalmazott kérdéseim is, de nyugodtan fel lehet dobni bármi mást is ami valakinek eszébe jut.

Ami a programnyelvem eddigi funkcióit illeti, ismétlem egy rakás minden már megvan belőle, mondjuk függvényeket még nem tud, de nem amiatt mintha nehéz lenne megoldanom (a korábbi nyelveimben is megoldottam), csak egyelőre a fontosabb dolgokat fejlesztettem bele. (Nálam is csak 24 órából és egy éjszakából áll egy nap...)

Ja, hogy hogy is néz ki... Oké, itt van pár példaprogi:
@p#g mem 100000
@d#g=0
@c#g =1
@p{0} = 2
@T#g tick
{| 100000 ,2
@d=0
{| @c
if ({A}!/@p{{}})==0 then @d=1 off;
|}
if(@d==0) then @p{@c}={} @c++;
|}
@t#g tick
@t-=@T
"Prímek száma: " @c printnl
"Millsec : " @t printnl
@d#d = #g @t; /=1000000.
"Ez " @d print " sec." NL

E fenti például a prímeket számolja őssze. Itt van ugyanez, egy jóval gyorsabb változatban:
@p#g mem 100000
@d#g=0
@c#g =1
@p{0} = 2
@T#g tick
{| 100000 ,2
@d=0
{| @c !ifthen {A}!/@p{{}} ?d=ONE off; |}
!ifthen @d ?p{c}={} ?c++;
|}
@t#g tick
@t-=@T
"Prímek száma: " @c printnl
"Millsec : " @t printnl
@d#d = #g @t; /=1000000.
"Ez " @d print " sec." NL

A rend kedvéért idemásolom a fenti progi C és Python nyelvű megfelelőit is:
#include <stdio.h>
#include <time.h>
#define MAX 100000
int main(int argc, char **argv){
int primeNumbers[MAX];
int i, j;
int divisible=0;
int count = 1;
primeNumbers[0] = 2;
clock_t start = clock();

for(i=2;i<=MAX;i++){
  divisible = 0;

  for(j=0;j<count;j++){
    // for slots in prime number
    if(i % primeNumbers[j] == 0){
       divisible = 1;
       break;
    }
  }

  if(divisible == 0){
     primeNumbers[count] = i;
     count++;
  }
}
clock_t end = clock();
float seconds = (float)(end - start) / CLOCKS_PER_SEC;
printf("======\nC\n======\n%f seconds\n%d primes\n", seconds, count);
}
import time

def a():
    primeNumbers = []
    for i in range(2, 100000):
        divisible = False
        for number in primeNumbers:
            if i % number == 0:
                divisible = True
                break

        if divisible == False:
            primeNumbers.append(i)

    return primeNumbers

print '======'
print 'Python'
print '======'
tt = time.time()
resp = a()
print time.time() - tt, 'seconds'
print len(resp), 'primes'

Ez meg a Pi értékét számítja ki iterációval:
@p#d=0. @n#d=1. @s#d=1.;
@t#g tick
{| 3000000
@p=@p+@s/@n
@n=+ 2.
@s +/-
|}
@T#g tick
@p= *4.
@T = - @t
"Pí közelítés : " @p printnl
"idő : " @T printnl

Ugyanez sokkal gyorsabban:
@p#d=0. @n#d=1. @s#d=1.;
@t#g tick
{| 3000000
?p+=s/n
?n++++
?s+/-
|}
@T#g tick
@p= *4.
@T = - @t
"Pí közelítés : " @p printnl
"idő : " @T printnl

Ennek is itt a C megfelelője:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

int main(void) {
double p; // összegváltozó
double n; // nevező
double s; // számláló
unsigned long long i;
clock_t CLOCK1;
clock_t CLOCK2;

p=0;
n=1;s=1;
CLOCK1=clock();
for(i=0;i<3000000; i++) {
p=p+s/n;
n=n+2;
s=(-1*s);
}
CLOCK2=clock();
p=p*4;
printf("idő: %g\n",(double)CLOCK2 - (double)CLOCK1);
printf("Pí közelítés: %g\n",p);

return 0;
}

Példaprogi arra, hogyan kezelem a substringeket:
"Kiírom ezt!" + " Meg kiírom \"ezt\" is!" NL
@s#s="0123456789" printnl
"[[ ]]      =  " @w#s=@s[[ ]] printnl
"[[ , ]]    =  " @w#s=@s[[ , ]] printnl
"[[  ,5 ]]  =  " @w#s=@s[[ ,5]] printnl
"[[ 3,5 ]]  =  " @w#s=@s[[3,5]] printnl
"[[ 3 5 ]]  =  " @w#s=@s[[3 5]] printnl
"[[ 3, ]]   =  " @w#s=@s[[3, ]] printnl
"[[ 3 ]]    =  " @w#s=@s[[3  ]] printnl
"[[3,8]][[2,4]] =  " @w#s=@s[[3,8]][[2,4]] printnl
@s="abcdefgh" printnl
=[[3,4]] printnl

E fenti progi outputja:
Kiírom ezt! Meg kiírom "ezt" is!
0123456789
[[ ]]      =  0123456789
[[ , ]]    =  0123456789
[[  ,5 ]]  =  012345
[[ 3,5 ]]  =  345
[[ 3 5 ]]  =  345
[[ 3, ]]   =  3456789
[[ 3 ]]    =  3
[[3,8]][[2,4]] =  567
abcdefgh
de

De rengeteg mindent tud még ezen kívül, holott a tervezett funkcióinak legfeljebb a tizedével vagyok meg még csak, egyszerűen mert többre még nem volt időm.

Na és szóval, olyan irányba óhajtom fejleszteni, hogy alkalmas legyen valamiféle shellnek, még ha nem is lesz kompatibilis az eddigi shellekkel.

Programming is like using toilets; you can't say you are done until paperwork's finished!
Nyilvános megtekintési jogosultság letiltva.

Új shell írása 2015 szept. 09 22:12 #1834

  • FossilCodger
  • FossilCodger profilkép
  • Nem elérhető
  • Arany fokozatú fórumozó
  • Hozzászólások: 209
  • Köszönetek: 6
  • Karma: 0
Semmi élet. Egy birodalom, polgárok nélkül... Királya biztos van, de alattvalók...?

Programming is like using toilets; you can't say you are done until paperwork's finished!
Nyilvános megtekintési jogosultság letiltva.

Új shell írása 2015 szept. 12 06:35 #1835

  • toroka
  • toroka profilkép
  • Nem elérhető
  • Adminisztrátor
  • Hozzászólások: 464
  • Köszönetek: 43
  • Karma: 9
Még király sincs! :) Szabadságra ment kb. öt hétre.
Török Á.
Nyilvános megtekintési jogosultság letiltva.
Az alábbi felhasználók mondtak köszönetet: FossilCodger

Új shell írása 2015 szept. 14 01:37 #1839

  • FossilCodger
  • FossilCodger profilkép
  • Nem elérhető
  • Arany fokozatú fórumozó
  • Hozzászólások: 209
  • Köszönetek: 6
  • Karma: 0
Most dolgozom azon, hogy lehessen függvényeket is tenni belé. Mármint, olyasmit amit Scrawl nyelven írunk, tehát a felhasználó által írt függvényeket. Másnéven alprogramokat.

Na most ez annyiból lesz más mint a C/C++ nyelv esetében, hogy ott ugye minden efféle függvény az adott fájlra nézve globális, tehát egy névtérben van. Nincs olyan, hogy ez csak a main-hoz tartozik, ez meg csak az ezéseshez stb. Nálam ez másként megyen. Nálam ez gyakorlatilag úgy müxi magát, mint a Linux fájlrendszere: azaz működik szépen a fa-struktúra!

Tehát. A főprogram, aminek a neve nálam BIGBOSS, az nem kell (sőt nem is szabad...) hogy elneveztessék. Kötelezően vele kell kezdődjék a fájl. Addig tart, míg el nem ér egy másik függvény nevének definiálásáig. Onnantól kezdve minden függvény az ő (a BIGBOSS) névterébe kerül. Mondhatni tehát, mindegyik az ő „ága”, amennyiben a BIGBOSS-t tekintjük a „gyökér”-nek.

Igenám, de minden függvénynek nemcsak kezdete van, de vége is! A preprocesszor ezt figyeli, szétszedi így függvényekre a fájlt, s mindegyiket szintén tokenizálja. Na de eközben lehet, hogy e függvényekben másik függvényekre is bukkan, hehehe... Mint amikor egy subdirectoryban más subdirectoryk vannak, és így tovább!

A darabolgatással, tokenizálással már megvagyok (rekurzió rulez...!) , most ki kéne találnom valami human readable szintaxist a függvényeim hívogatására és a paraméterátadásra. Itt nem az a nehéz hogy ezt megoldjam mert sokszor megoldottam már, csak valahogy egyiknél se tetszik még nekem se igazán a szintaxis, tehát most ezen kéne morfondíroznom. De ez rém nehéz, mert amikor az asszony páros lábbal rúgott belém, hogy a nagy lendülettől átrepültem még az Óperenciás tengeren is, akkor elfelejtett elég morfondírt csomagolni a bőröndömbe, errefelé meg nem kapható... Most tehát rém nehéz morfondíroznom...

Programming is like using toilets; you can't say you are done until paperwork's finished!
Nyilvános megtekintési jogosultság letiltva.

Új shell írása 2015 szept. 16 03:31 #1840

  • FossilCodger
  • FossilCodger profilkép
  • Nem elérhető
  • Arany fokozatú fórumozó
  • Hozzászólások: 209
  • Köszönetek: 6
  • Karma: 0
Na már meg van oldva a függvényhívás, meg minden ami kölletik hozzája! Alkalmas rekurzív hívásokra is!

Ezenfelül, egy rakás remek ficsőrrel bővítettem ma a kis aranyost. Például vannak infinite ciklusaim is. Na most ebben az a pláne, hogy ezt rém egyszerűen oldottam meg. Van nálam egy általános ciklus-objektum, s ennek a különböző al-esetei a fix számszor lefutó ciklus, a végtlenciklus, desőt még a blokkutasítás is! (Az az, ami a C nyelvben a { } zárójelek közt van). Mindegyik nálam ennek a ciklus-objektumnak egy alesete. A blokkutasítás például mindössze egy egyszer lefutó ciklus, hehehe... Persze, vannak azért specialitásai mindegyiknek, mindegyiket külön rutinok kezelik, itt amire gondolok, az az, hogy a tokenizálás szempontjából teljesen egységesen kezelendőek, mert egyetlen struktúra alkalmas mindegyik adatainak a tárolására.

Na és, ebből az a roppant jóság árad reám, és nyelvem jelenleg még nem létező rengeteg felhasználójára, hogy olyan dolgokat is beleépíthetek e ciklusfajtákba, amikről eddig egyetlen programnyelvben se hallottam! Konkrétan: például a fix számszor lefutó ciklusnál automatikusan generál ciklusváltozót magának, s ennek értékét le lehet kérdezni a ciklusmagon belül. Sőt, egymásba ágyazott ciklusok esetén akármelyik külső ciklus ciklusváltozójának az értékét is le lehet kérdezni! (maximum 26 egymásbaskatulyázási mélységig. Nem hiszem hogy ez elég ne volna). Ki is lehet ugrani belőle, vagy újrakezdeni, ezt is akár valamely külső ciklusra vonatkoztatva is. Na és, képzeljétek, a végtelenciklusomnál is ez a helyzet: bár végtelenszer fut le (amíg ki nem ugrunk belőle...) de ettől még ennek is van ciklusváltozója automatikusan, s lekérdezhetjük ennek értékét is! Gondoljatok csak bele milyen jó ez - e ciklusfajtát általában olyankor használjuk amikor valami streamet dolgozunk fel, amiről nem tudjuk előre mekkora, de szeretnénk tudni a végén, hogy addig hány elemet dolgoztunk fel... s esetleg már közben is kell hogy sorszámot kapjanak az elemek...

Hasonló okokból, mert nálam BELSŐLEG a ciklusobjektumom egyformasága miatt minden ciklus azonos, emiatt a blokkutasításaimból is ki lehet ugrani (ott is érvényes, hogy egymásbaágyazottakból is), vagy akár azok is újrakezdhetőek.

Most azon töröm a morfondíromat, mit találjak ki az elöltesztelő ciklusra. (while). Mármint milyen szintaxist.

Programming is like using toilets; you can't say you are done until paperwork's finished!
Nyilvános megtekintési jogosultság letiltva.

Új shell írása 2015 szept. 19 16:35 #1842

  • janu
  • janu profilkép
  • Nem elérhető
  • Adminisztrátor
  • Hozzászólások: 370
  • Köszönetek: 37
  • Karma: 5
Csak úgy mellékesem: valóban nem vagyok otthon, csak ritkán nézek be. Toroka kézben tartja a dolgot.

Ami meg a ciklus definiálatlan (azaz autogenerált) változót illeti, ebben a formában én sem hallottam róla, mert egyébként létezik, csak nem lekérdezhető. Annak, hogy ciklusváltozót definiálni kell, annak egyik oka, hogy nem ritkán a ciklusból való kilépéskor szükség lehet/van arra, hol hagyta abba a ciklus a működését.

De ez megoldható, ha kilépés előtt lekérdezzük és egy publikus változóhoz rendeljük. Csak macerás...

A kép rejtve van a vendégek elől.
Jelentkezz be vagy regisztrálj, hogy láthasd.


PCLinuxOS Desktop 4.12 64bit
Debian szerver 4.9.0-3-amd64 Jessie
Nyilvános megtekintési jogosultság letiltva.
Oldalmegjelenítési idő: 0.085 másodperc