Kötetlen beszélgetés a FORTH-szerű nyelvekről

E blogbejegyzést annak kapcsán nyitom, hogy épp egy saját FORTH implementációt írok, vagy legalábbis valami FORTH-hoz nagyon hasonló nyelvet.

Szóval, korábban jópár (valószínűleg egy tucatnál is több) saját programnyelvet írtam, szkriptnyelveket, bár ezalatt az értendő hogy végülis egyfajta „virtuális bájtkódra” fordultak le. (igaz, nem „bájt” kódra hanem „unsigned long long” egységekre de ez asszem mindegy).

Jó sok féle különböző koncepciójú nyelvet megalkottam így, némelyikben volt komoly kifejezéskiértékelő rutin is, meg precedenciaszabályok, stb... Nem bánom ma se hogy ebbe belemásztam mert tudom hogy kezdőknek épp ezen rész a legnehezebben megérthető, felfogható... Na ja, szegénykéimnek többnyire fogalmuk sincs arról, mi a rekurzió... Én meg alaposan megtanultam amíg e projecteken dolgoztam.

Szóval ez mind nagyon oké, de fokozatosan arra jöttem rá, az „én szívem bizony a stackorientált nyelvekért dobog”...

Gyakorlatilag egyfajta FORTH nyelvért. Igazán komikus önmagam számára is, hogy ekkora energiát - lassan fél évtizedet - beleöltem pusztán abba, hogy megalkossak egy nekem leginkább tetsző nyelvet, a végén rájövök hogy hoppá, ez tulajdonképpen rég készen van... Na, de mint írtam fentebb, legalább alaposan megtanultam közben ezek lényegét. Meg úgy általában C nyelven programozni is...

Most tehát ott tartok hogy nekem egy FORTH nyelv kell, de... de, az az igazság, azért a FORTH-tal se vagyok egészen elégedett. Van egypár idiótasága. Jó, na, fogalmazzunk szebben: pár dolog ami miatt a hajamat tépem, bár elismerem, amikor megalkották, biztos megvolt az indoka annak miért épp olyan lett.

Ezek közül az első és legfontosabb, hogy nem tudok napirendre térni afölött, hogy mondjuk a

3.14

az ő számára nem egy lebegőpontos szám hanem valamiféle duplapontos egész szám... Hát azért már bocs, én híve vagyok az egzotikus nyelveknek, az „ezoterikusoknak” is, de ha egy nyelvet komoly munkára is szánunk, ennyire ne rúgjunk már fel minden hagyományt!

A másik az IF-THEN-ELSE szintaxisa.

A harmadik, hogy egyszerűen fogalmam sincs róla, miként kezeli a címkéket. Lehet-e benne egyáltalán bármi módon is olyasmit művelni mint a

goto label;

vagy nem? Nem találtam erre való utalást.

Az se tetszik hogy csupa NAGY betűvel kell írni a szavait - bár lehet hogy akadnak implementációk ahol ez nem kötelező.

Az se hogy nem lehet tetszőleges UNICODE karaktereket alkalmazni az azonosítókban.

Szóval úgy döntöttem, írok egy saját FORTH-ot vagy legalábbis egy olyan nyelvet ami nagyon hasonlít rá, és itt beszélgetnék azokkal akiket ez érdekel. A nyelvnek egyelőre a

Furor

nevet adtam. Illik egy íróhoz azt hiszem... és pont ugyanannyi karakter mint a Forth név is. És még ki is ejthető magyar torokkal...

Nem fogom közreadni amíg készen nem lesz, ezt előre közlöm mindenkivel... Én magam akarom lefejleszteni, egyedül. Eszemben sincs másokkal vitatkozni hónapszám hogy milyen a „tördelési stílusom”, meg ahhoz sincs kedvem hogy megtanuljam valamiféle github vagy más efféle izémizé kezelését. Különben is, ha közreadnám félkészen, minden időm azzal menne el hogy vizsgálgathatnám a mások által beadott patch-eket, módosításokat, és nem én magam programoznék... odalenne minden élvezet!

Majd ha készen lesz, közzéteszem, természetesen totál opensource lesz.

Beszélgetni azonban lehet róla. Itt.

Azt nem hiszem hogy nagyon sokára lenne készen, mert már a legutóbbi nyelveim is nagyon hasonlóak voltak hozzá sok szempontból, itt most az újdonság lényegében csak annyi lesz nekem, hogy ezt a „szótár” részt kell implementálnom valahogyan, erre kihegyezni a dolgot, hogy most ugye nem „függvények” lesznek, hanem „szavak”... Nem tűnik olyan szörnyű nehéznek, hiszen csak egy láncolt lista az egész végeredményben.

Trollok itt lehetőleg kíméljenek. Ezt a topikot szeretném kivételesen tényleg a komoly fejlesztéssel kapcsolatos dolgok megdumálására fenntartani, már ha lehetséges. Sajnos alig is hiszem hogy lehetséges lesz... de, hátha, végülis egy próbát megér. Mindenesetre aki trollban vagy egy csepp jóindulat is, az kérem trollkodja ki magát valami másik topikomban. Már amiatt is mert elsősorban nem velem szúr ki ha itt is elkezdi, hanem a TÖBBIEKKEL. Mert arra már rájöhetett mindegyikőtök hogy bőven elég fafej vagyok hozzá hogy megcsináljam teljesen egyedül is, minden közösségi megbeszélés nélkül ha akarom, és ez is lesz a vége ha jönnek a trollok. Rosszabb esetben törlöm az egész bejegyzést, jobb esetben elmegy a kedvem tőle hogy írjak ide és nem válaszolok senkinek. Ezesetben azonban azok is elesnek a szórakozási lehetőségtől, akik talán szívesen követnék miket írok a fejlesztésről, netán még szívesen beszélgetnének is velem róla.

Értelmes ember illene tudjon társalogni trollkodás nélkül is... Szóval oké, kedves trollok, trollkodjatok, semmi baj de ne itt! Van számos más topikom ahol kiélhetitek magatokat... és ismétlem ezt se magam miatt kérem mert én megírom tök egyedül is a nyelvet, ez nem az első nyelvem lesz hanem a tizensokadik... de mondom a többiekkel szúrtok ki, nem velem, ha itt is elkezditek! Ezt a topikot NEM azért nyitottam hogy segítséget kérjek a megalkotáshoz mert bőségesen elegendő a tudásom a megalkotáshoz egyedül is. Csak gondoltam hátha lehet egy jót szórakozni is közben, beszélgetve róla... De ha nem, akkor nem. Ha a trollok elrontják ezt az örömömet, másokét is elrontják mert akkor abszolút nem lesz beszélgetés. Nagyon durva esetben meg még az is lehet hogy oké, megcsinálom egyedül de aztán még csak meg se osztom, nem teszem elérhetővé... Kitelik tőlem! Ebben az esetben elesek valamiféle „hírnévtől”, az igaz, de ez nem annyira nagyon izgat mert elsődleges célom úgyis csak maga az ALKOTÁS.

Na és akkor azon dolgok amikben eddig végleges döntésre jutottam:

—A törtszámok kérdésköre. Amiben pont van, az a számkonstans törtszámnak lesz tekintve. Józan ember az ilyen számokat úgyis törtszámnak tekinti. A formátuma az, amit a C nyelv „double”-nak nevez, azaz 8 bájtos lebegőpontos szám.

—A szavak definíciója a FORTH nyelvben ugye kettősponttal kezdődik és pontosvesszővel végződik. Ehelyett én ezt fogom alkalmazni:

{ name .......... }

Ahol a "name" természetesen az új szó neve. Azaz a kettőspont helyett nyitó kapcsos zárójel van, a pontosvessző helyett pedig csukó kapcsos zárójel. Ennek oka az, hogy a legtöbb editorban ha ráállunk egy zárójelre akkor automatikusan kijelzi annak párját, ami tök jó, mert így pontosan láthatjuk hol kezdődik és végződik a szó definíciója.

—A szavak case-sensitive -k lesznek.

—A szavak bármilyen UNICODE karaktert tartalmazhatnak majd (aminek kódja 32-nél nagyobb).

—A szavak hossza le lesz korlátozva 32 UNICODE karakterre.

—Minden C stílusú megjegyzés használható lesz, tehát a // és a /* ... */ is, sőt utóbbiak többszörösen egymásba ágyazhatóak lesznek. Ezek azonban kiirtódnak majd a kódból a beolvasás során, azaz ha nincs meg a forráskód, nem lehet őket visszakapni a bájtkódból. Ezzel szemben a hagyományos kerek zárójelek közti „megjegyzések” benne maradnak majd a tokenizált bájtkódban is, így visszanyerhetőek.

Egyelőre ennyi, a többi majd annak fényében, milyen reakciókat kapok.

Hozzászólások

Te amúgy szoktál dolgozni is, vagy az összes energiádat arra használod, hogy itt a blog szekcióban minden második bejegyzés úgy átlagosan a tiéd legyen az emberiség számára mérsékelten hasznos témakörökben?

Ez a sok bölcsesség és briliáns ötlet tényleg megérne már egy saját weboldalt - ahogy azt javasolták is korábban -, amit elég lenne mondjuk havonta egyszer belinkelni, esetleg az új tartalmak címeivel együtt.

Én alapvetően a sokszínűség mellett vagyok, nem zavar, ha mindenféle értelmes vagy (számomra) éppen értelmetlen téma merül fel itt, hiszen a jó részük azért bevonzza a maga kisebb-nagyobb közönségét, időnként még gondolatébresztő vitát is generálva, de ez nekem már kezd kicsit sok lenni.

Most majdnem leírtam, hogy inkább a bilógiai ösztönnek teret adva szedjél fel valakit és inkább vele töltsd el a blogra szánt időd egy részét, s mindjárt szebben süt a nap, továbbá a nyelvújítási törekvéseidet más témakörben kamatoztathatnád, de aztán rájöttem, hogy egyrészt a magánéletedhez semmi közöm, másrészt a bejegyzésem megosztó is lehet.

Végül arra gondoltam, hogy ez mégis elfér egy eleve megosztó blogban.

Csinált egyszer saját veboldalt. 

Kommentelni is lehetett. Aztán minden ideje arra ment el, hogy kimoderálja a neki nem tetsző hozzászólásokat és hozzászólókat. Aztán mikor nem maradt olvasója, bezárta a boltot.

 

De azóta természetesen gyökeresen (vagy bogarasan?) megváltozott, most már nem tenne ilyet, ezért is engedte vissza Trey.

A lebegőpontos számok kezelésénél szerintem valahogy meg kellene oldani, hogy be tudjanak vinni a felhasználók sima float-ot vagy long double-t, quadruple precision-t is, ha az a célod, hogy a nyelv használható legyen numerikus számításokra is (elvégre a számítógépet valaha erre találták ki). Mind a kettőnek van oka, a sima lebegőpontosnak leginkább az, hogy vizsgálni tudd a kerekítési és az egyéb hibák viszonyát: ha lefuttatom float-tal és double-vel is, és nem kapok nagyon eltérő eredményt, akkor bízhatok benne, hogy nem a kerekítési hibát számolom, hanem tényleg azt, amit szeretnék, a long double (vagy quadruple precision) meg arra szokott kelleni, ha van egy nagyobb számolásban egy-két olyan rész, ami nagyon érzékeny a kerekítési hibákra.

Valamikor ujjgyakorlatként csináltam egy virtuális utasításkészletet. A regiszter kizárólag double volt.
Ezt kerekítési hiba mentesen 53 bites integer helyett is tudtad használni és a lebegőpontos minden előnyével.

Szóval az adattípus kizárólag double. Az ötletet mellesleg a LUA-ból merítettem. Érdekes volt, amikor még 5.3-as előtt még bit.band(ertek1, ertek2) módon külső függvényt segítségűl hívva lehetett a logikai műveletet is elvégezni, mert annyira lebegőpontos megközelítésben gondolkoztak.

#!/usr/bin/luajit

local n = 9007*1000 * 1000*1000*1000 -- 1<<53 alatt oké
-- local n = 9008*1000 * 1000*1000*1000 -- 1<<53 és felette végtelen ciklus

for i=n, n+1 do
   print (i)
end

Azóta megjelent a LUA-5.3 verzió. Ebben jelent meg a 64 bites előjeles integer is a double mellett, továbbá a bitshift, and, or, xor C-beli operátorai is bejöttek, így nem kell külső függvény ezekhez.
Eddig a verzióig viszont a double is megfelelt a LUA programokhoz. A fenti luajit még a LUA-5.3 előtti állapot, azért azzal adtam a példát.

64 bites lebegőpontos (double) az lesz benne, minden amiben tizedespont van, alapből ennek lesz tekintve. Tervezem azonban (a későbbiekben) egy BCD aritmetika megírását is, ami bár tulajdonképpen fixpontos lesz, de lesz fenntartva százegynéhány digit az egészrésznek, és ugyanannyi a törtrésznek. Ez már csak elég pontos lesz a legtöbb esetre... Persze lesz lehetőség a számokat kisebb helyre „betömöríteni”, ha nem kell ekkora pontosság mégse.

De ez a jövő zenéje...

Obsessed commandline-maniac.

OK, szóval a numerikus analízisről (profi szinten) lemondasz. Ha nem tudod legalább kétféle float-tal tesztelni, akkor ott nagyjából megette a fene. Nem az a kérdés, hogy a double elég-e (általában igen, néha nem), hanem hogy tudod-e tesztelni a programodat kétféle pontossággal. Ez az, amit annak idején az Algol-ból is kihagytak ("nem érdemes olyat szabványosítani a nyelvben, ami úgyis minden hardvare implementációban különbözik, és nem fogják tudni tartani"), és az eredmény az lett, hogy a) az implementációkban csak megjelent, b) nem volt az Algol-nak a numerikus számításokban esélye a Fortran-nal szemben.

Persze nem mondtad meg, mi a célod a nyelveddel. Ha elsősorban adminisztrációra (ügyvitel-gépesítés) és mondjuk szkriptelésre akarod használni, nem numerikus feladatokra, akkor nem  érdemes ezzel foglalkoznod. (Mondjuk ebben a témában az RPN sem elterjedt).

Főleg szkriptelésre akarom majd használni, különös tekintettel olyan feladatokra amik nagy mennyiségű stringmanipulációval járnak, ráadásul olyan stringekével amik UNICODE karaktereket is tartalmaznak (például ékezetes betűk).

De nézd, ez a topik épp azért van többek közt hogy hssznos ötleteket kapjak... Minthogy a közönséges „float” simán támogatva van az általam használt C nyelvben amiben ezt az én nyelvemet írom, hát akkor legyen meg a te akaratod: mostantól úgy tekintheted, benne lesz ennek a floatnak a támogatása is! Mármint „built-in”!

Egyik célom a nyelvvel úgyis az hogy olyan szkriptnyelv legyen ami mindazt a sok típust tudja amit a C is. A floatot eddig teljesen feleslegesnek éreztem mégis mert én soha nem használtam, nálam a törtszám mindig double volt... De ha szerinted ez mégis ennyire hasznos, ám legyen! Végülis nem egy nagy meló beleépítenem, mert az egész nyelv felépítése olyan - erre a tervezéskor nagy súlyt helyeztem - hogy könnyedén kibővíthetem új típusokkal. Pláne most amikor még az elejénél tartok.

Tehát oké, lesz benne közönséges „float” is.

Obsessed commandline-maniac.

"Főleg szkriptelésre akarom majd használni, különös tekintettel olyan feladatokra amik nagy mennyiségű stringmanipulációval járnak,"
         ---> általad nem kedvelt Python-t ismerd meg. Érdemes az egynyelvűség helyett tanulmányozni meglevő nyelveket.

$ python3
>>> "cseresznye vagy körtepálinka".split()[-1]        # azaz szétcsapjuk és az utolsó elemét kérjük.
'körtepálinka'
>>> "cseresznye vagy körtepálinka".split()[-1][5:]   # azaz szétcsapjuk és az utolsó elemét kérjük és 5. karakterétől kiírjuk
'pálinka'
>>> "cseresznye vagy körtepálinka".split()[-1][5:].capitalize() # előbbi első betűje nagybetűvel
'Pálinka'
>>> "cseresznye vagy körtepálinka".split()[-1][5:].upper()     # előbbi nagybetűsítve
'PÁLINKA'

Ennél egyszerűbb szringmanipulációt nem találsz a szkriptnyelvek terén. És csak alap demót dobtam, sokkal többet tud.
A C típusánál sokkal több szerkezetet ismer. Ha a képességeit össze akarom vetni, akkor a C nem pálya, inkább a Rust-tal lehet összevetni.

Kérlek értsd meg, hogy a Python nálam KI VAN ZÁRVA!

Totál. Véglegesen. Teljesen mindegy mennyi előnye van: Én egyszerűen NEM VAGYOK KÉPES megszokni hogy a behúzás mértéke jelentéssel bír és nem csak esztétikai kérdés!

Okés?

Nem akarlak megbántani de kérlek értsd meg hogy minden szó amivel a python felé biztatsz, abszolút kárbaveszett fáradság!

Egyszerűen egy rém gusztustalan megkötésnek érzem ezt a Python részéről, mintha óvszerben kéne szexelnem, vagy kesztyűben kezet mosnom vagy ilyesmi. Majdnem olyan zsigeri szinten gyűlölöm mint a Windowst.

Az belefér, hogy adj nekem ötleteket, milyen szintaktikával lehetne a legjobban megvalósítani ezt vagy azt a funkciót, és még az se izgat ha ez a javasolt szintaktika a Pythonból származik. Oké. De az hogy én magam a Pythont használjam, vagy akár csak jobban belemélyedjek a tanulásába, teljesen kizárt.

Ismerem különben a Pythont annyira amennyire nekem kell: annyira hogy tudjam, ez épp az a nyelv ami nem nekem való...

Egyáltalán, én most azon dolgozom hogy a saját nyelvemet alkossam meg, s nem az a célom hogy egy másik nyelvben váljak mesterré.

Obsessed commandline-maniac.

Esetleg csinalhatsz Pythonhoz "eloforditot" ujjgyakorlatkent, ami a sajat, whitespace-fuggetlen szintaxisodat az overe forditja, es futtatja utana. pl:

n=5
if(n>4){print("nagyobb");n=0;};print("kint");

Ebbol valami ilyet csinal:

n=5
if n>4:
  print("nagyobb")
  n=0
print("kint")

Bar a dict-et ki kell talalni, hogy ne legyen kavarodas..

Regen nekem is fura volt a szintaxisa, de eleg jo nyelv, mar megszoktam.

When you tear out a man's tongue, you are not proving him a liar, you're only telling the world that you fear what he might say. -George R.R. Martin

Nekem inkább gyermeteg fantáziálásnak tűnik az amit itt a kollega leírt. Méghogy megalkotott pár tucat programnyelvet (hint: az nem nyelv, hogy felskiccelek valamit a táblámra és utána a programnyelvvel szemben támasztott általános követelmények 1%-a valósul meg). Inkább meséljen a régebbi nyelvekről, hadd tanuljunk meg mi is, hogy kell azt csinálni.

arch,ubuntu,windows,android
zbook/elitebook/rpi3/nokiax6_DRG_sprout

Mielőtt Poliverzum néven bannolva lettem volna, elkezdtem itt a HUP-on írni (rendszeresen hírt adni) a legelső nyelvem, a „mau” nevű fejlesztéséről, hogy épp hol állok benne, de akkor is jöttek a trollok... a végén épp emiatt lettem bannolva mert az egyiknek nagyon beszóltam. Pedig még nem is ő volt a legocsmányabb troll, de addigra a többiek már nagyon felforralták az agyvizemet.

Persze így utólag visszanézve, az a nyelvem nagyon kezdőszintű volt még azokhoz képest amiket később alkottam (azalatt amíg bannolva voltam), de, azért már a végén egészen jól használható lett az én szkriptelési céljaimra.

Ez most még jobb lesz... Ne hidd ha nem akarod. Különben meg nem olyan rém nagy szám megírni egy szkriptnyelvet, de pláne nem akkor, ha nincs is benne kifejezéskiértékelő meg precedenciaszabály. Na nem mintha azokkal együtt is olyan iszonyú nehéz volna... de azok nélkül pláne nem az. Csak a kezdők hiszik hogy ez akkora nagy csoda. Végeredményben az egész nem más mint egy szövegfeldolgozás ugyebár (a forrásfájl elemzése), maga az interpretált bájtkód végrehajtása meg alig több a végén mint egyetlen ciklus.

Itt nem a megírás a nagy szám, hanem hogy pontosan kitaláljuk, MIT is akarunk megírni, MILYEN legyen a nyelv ahhoz hogy igazán jó legyen...

Obsessed commandline-maniac.

Kérlek nézd meg, milyen az eredeti FORTH nyelv. Én annak mintájára csinálom a magamét. Ez azt jelenti hogy az enyém is mint az eredeti FORTH, egy RPN szintaxisú nyelv lesz, az RPN szintaxis meg tulajdonképpen mondhatni szinonímája annak, hogy nincs benne kifejezéskiértékelő...

Azaz egy példával: az általad megszokott infix notation -t használó nyelvekben ez a kifejezés:

3 + 4 * 2

nyilvánvaló okokból igényli egy kifejezéskiértékelő meglétét, precedenciaszabályokat, stb.

Ezzel szemben ez FORTH nyelven (s az enyémben is ha majd kész lesz) kábé így irandó:

3 4 2 * +

vagy esetleg:

4 2 * 3 +

A lényeg, amint egy utasításhoz (műveleti jelhez) érkezik az interpreter, az AZONNAL végrehajtódik! Emiatt gyors. És emiatt nem kell bele kifejezéskiértékelő.

Természetesen attól hogy nem kell belé kifejezéskiértékelő, még igényel bizonyosfokú tokenizálást, forráskódelemzést, stb, amíg a végrehajtandó bájtkód elkészül.

Obsessed commandline-maniac.

Vágom, gondolom fordított legyel formáról van szó. Ettől az én szememben ez még kifejezés, és ami ezt kiértékeli, az pedig a kifejezéskiértékelő.

 

Mondjuk szerintem egy scriptnyelvbe nem túl szerencsés RPN-t tenni. Egy infix kifejezés kiértékelőt eléggé egyszerű leprogramozni. Szóval hacsak nem arra mész rá, hogy az egész beleférjen pár KB-ba, akkor inkább a megszokott kifejezési formát választanám.

FORTH-ban pont ez volt az egyszerű. Kapott egy literált, tolta bele a stack-be. Kapott mégegyet, tolta bele.
Aztán ha műveleti jelet kapott, akkor a két felsőt kivette és az eredményt beletolta a stack-be.

3 <stack> 4 <stack> 2 <stack> * <2 és 4 szorzata --> stack> + <8 és 3 összege --> stack>
(ROTate volt az egyetlen 3 szintű stack-es művelet, hogy át tudd sorrendezni a stack felső részét. Néha kellett.)

Amiért izgalmas volt: a tudós megírta FORTH-ban az algoritmust, a mérnök pedig gépi kódban 1 héten belül tudta implementálni az új architektúrára is a FORTH értelmezőt.
Tehát elvált az algoritmus byte-kódja az architektúrától, így hordozható lett konkrét példaként a rakéta tűzvezető szoftvere, miközben új architektúrás proci került a NYÁK-ba.

Teljesen így van. Egyszerű háttér, azaz könnyen lehetett bug mentesen implementálni kevés memóriás rendszeren. Az algoritmus viszont mégis hordozható lett.
Cserébe a kor szokásainak megfelelően igen alacsony szinten kellett stack szemlélettel megírni az algoritmust.

Mai szemmel az alább írt LUA sokkal hatékonyabb. Nem véletlen, hogy a LUA értelmezőjét rakják bele egy csomó programba, ahol szkriptelni akarnak.

Igen, egészen jól saccoltad, kb fél évszázaddal ezelőtt találták ki és fel a FORTH-ot...

És abban is igazad van hogy manapság akárhogy keresgélek is a FORTH után az interneten, de akkor is csak az az eredménye hogy bár használják még ma is, de véletlenül se tartozik az elterjedtebb nyelvek közé... és akkor még finoman fogalmaztam.

Ennek ellenére, azt is értsd meg kérlek, hogy én SZERETEM ezt az RPN szintaxist, nekem ez TETSZIK, és miután a nullánál valamivel kisebb az esélye úgyis hogy egy nyelvet amit én írok más is használjon mint én, emiatt ezt simán tekintheted hobbyprojectnek. Akkor meg nem mindegy-e milyennek írom meg? Az elsődleges cél az, hogy NEKEM tetsszen, mert ha olyannak akarnám megírni ami nem tetszik, soha nem is fejezném be érdeklődés hiányában...

Oké, ettől még közreadom majd ha készen lesz, sőt örülni is fogok neki ha más is használja majd. Épp csak nem hiszem hogy ez a „más is használja majd”, ez bekövetkezik...

Tehát nem hiszem azt hogy e nyelvvel megváltom majd a szoftvervilágot. Hogy is hihetnék ebben, én is látom, nem ebbe az irányba megy az úgynevezett „fejlődés”, hiszen a mai pelenkás programozóknak, meg a kóder-trógereknek már a C is egy „nehéz” nyelvnek számít... Elszomorító, tényleg! Nem a C, hanem ez a hozzáállás...

Különben meg, van jó hírem is: az iménti pillanatokban ihletet kaptam és rájöttem, miként oldhatom meg, hogy a core utasításkészlet szavainak végrehajtásakor mégse kelljen a rendszerstacket piszkálni, azaz sima ugrási utasítással lehessen „meghívni” őket... persze csak addig amíg netán át nincsenek definiálva ezek a mnemonikok, már ha olyan perverz a Programozó hogy egy core kulcsszót átdefiniál. Én nem hiszem, hogy gyakran élek majd e lehetőséggel... De, attól még lesz majd rá mód azért.

Most ezen ötletem miatt át kell írnom az eddig elkészült kód egy részét, de semmi baj, ennyit megér, és nem is egy túl nagy rész az amit át kell írjak. Bár ha sok lenne akkor is megtenném. Nem mindegy mégse hogy a nyelv háromszor gyorsabb lesz-e...

Obsessed commandline-maniac.

Itt nincs kifejezés, itt mnemonikok illetve tokenek vannak. Semmit nem kell kiértékelni. Legalábbis futás közben már nem. De még tokenizálás közben se holmi „kifejezést” (minthogy az nem létezik, hanem inkább olyasmik lehetnek kissé szopatósak mint a címkék kezelése; meg a ciklusok elejének és végének a felismerése (ugye, illik lehetőséget adni a ciklusból való rendkívüli de szabályos kiugrásra), stb.

Nem arra megyek rá hogy beleférjek pár KB-ba, és nem is arról van szó hogy nehéz-e egy infix kifejezéskiértékelőt leprogramozni. Csináltam már olyat... Az addig nehéz amíg az embör gyermöke alaposan meg nem érti, mi az a rekurzió. Onnantól már nem egy ördöngösség... Hanem, én azért csinálok RPN-t, mert:

1. Nekem ez tetszik. Valahogy olyan természetesnek érzem. (Oké, tudom hogy e véleményem sokak szemében most perverz csávónak tüntet fel engem).

2. Messze sokkal gyorsabb egy RPN-szerű szkriptnyelv végrehajtása. Ezt tapasztalatból állítom. Csináltam benchmarkokat a nyelveimhez. Ahol volt kifejezéskiértékelő, pontosabban ahol infix notation volt alkalmazva, ott ha nagyon igyekeztem akkor is kb 30-szor volt lassabb (ugyanazon feladat esetén) a szkriptnyelven írt változat a natív (C-ben megírt) kódhoz képest.

Amennyiben azonban a szintaxis RPN volt, a belassulás a natív kódhoz képest csak kb 12-szeres volt, sőt bizonyos feladatok esetén csak 8-szoros.

Most itt ezen nyelv esetén amit írok, vélelmezem hogy valahol e két érték közt lesz a végső sebesség, azért, mert bár RPN rendszerű, de egyelőre úgy tűnik nekem, nem tudom megúszni hogy minden egyes utasítás végrehajtásakor lefusson egy gépi kódú szubrutinhívás, sajnos ez az ára annak hogy minden így külön „szavakban” van tárolva, amely „szavak” átdefiniálhatók, stb... a régebbi nyelveim esetén nem volt ilyen gond, mert ott minden előre beépített volt, így nem kellett a rendszerstackhoz nyúlkálni az egyes elemi utasításoknál, minden bele volt gyömöszölve az utasításvégrehajtó függvénybe, mert volt abban egy ugrótábla, s a tokenkód alapján az abból kiindexelt címre ugrott és kész... ez marha gyors. Ugye egy ugrásnál nem kell a visszatérési címet elmenteni sehova... Most azonban - legalábbis egyelőre úgy tűnik - ezt nem fogom megúszni, és ez baromira lelassít majd mindent. Jó hát azért remélem nem leszek lassabb most se mint a natív sebesség harmincszorosa, ami nem is olyan rossz, mert szkriptnyelvek esetén állítólag ha százszor lassabb csak mint a natív kód, az még elfogadható...

Na majd meglátjuk, a vak is azt mondta. Motoszkál bennem egy ötlet de elég vad, így egyelőre nem írok róla semmit még. De ezen jár a fejem hogy ezt hogyan tudnám megúszni. Nem teljesen kizárt hogy sikerül, de még nem biztos. Emiatt is haladok most lassan, mert az agykapacitásom fele ezen agyal...

Egyelőre ott tartok hogy kigyűjtöttem már az összes stringkonstanst is a forráskódból, és szétszedtem szavakra a teljes szöveget. A következő lépés a globálisan definiált változók felismerése lesz, majd aztán jön hogy szétszedni a fájl (szólista...) maradékát az egyes definíciókra a határolójelek mentén, aztán ezeket külön-külön betokenizálni...

Hát, elég macerás és undorító szövegfeldolgozás, de programozástechnikailag végülis valóban nem egy ördöngösség. Szerintem egy kicsit is komolyabb játékprogramot messze nehezebb megírni mint egy akármiféle szkriptnyelvet is.

Obsessed commandline-maniac.

Nézd, attól még, hogy mnemonikok, tokenek, kütyafüle van, attól a "5 3 +" még egy kifejezés. De mind1, minek nevezzük, most már értem, mire gondoltál.

Nem igazán értem ezt a megkülönböztetést az RPN és nem RPN között. A két megoldás átjárható, az infix jelölést simán át lehet alakítani RPN-re. Tehát attól még, hogy a nyelvben infix-ek a kifejezések, attól még a végrehajtás lehet RPN-es. Bár őszintén szólva, nem igazán értem, miért kellene jelentős különbségnek lennie a futtatás sebességben. RPN-hez egy stack kell, infixhez meg kettő. Kb. hasonló bonyolultságú a kettő.

 

Azt mondjuk furcsállom, hogyha tokenszintű a scriptnyelv, akkor hogyan lehet csak 8x különbség a C-vel szemben. Nem mértél valamit félre?

Nincs semmi félremérés. Bár azt ne felejtsd el kérlek, amiről most írok az NEM EZ a most készülő nyelv, aminek a Furor nevet adtam, mert ez még semennyire sincs kipróbálható állapotban. A régebben írt nyelveimről beszélek - bár ezek némelyike, például a legutóbb befejezett is, szintén RPN szintaxisú.

A dolog nyitja az (sebességileg), hogy ez amit írtam, hogy 8-szoros különbség, ez így ebben a formában természetesen nem igaz, mert a konkrét sebességkülönbség erősen FELADATFÜGGŐ. Általában véve egy hosszabb, „átlagos” feladatnál mondható akár 15-szörös „lassúságúnak” is. Másrészt azonban akadtak speciális feladatok, ahol nemhogy 8-szoros de mindössze 4.5-szeres csak a belassulás...

Ez persze így hihetetlenül hangzik, de mindjárt elárulom a Nagy Döbbenetes Hit-titkot! A lényeg hogy ez nem pusztán az RPN gyorsabb feldolgozhatóságának tudható be, de annak is, hogy jó fél évtizede azzal szórakozom legkedvesebb hobbymként hogy szkriptnyelveket írogatok, és rájöttem egy pompás trükkre, aminek segítségével a „finite loop”-okat, azaz azon ciklusokat melyeknél előre tudható hányszor kell lefutniuk (ettől persze még ki lehet ugrani belőlük előbb is szabályosan), ezeket tehát az általam felfedezett trükk segítségével gyakorlatilag gépi kódú sebességgel lehet végrehajtani! Azért azzal a sebességgel, mert ténylegesen is gépi kóddal (pontosabban, természetesen natív C kóddal) vannak implementálva... Na, nem a ciklus TÖRZSE! Tehát nem arról van szó hogy mondjuk a GCC lefordítja az egész ciklust s aztán azt valami ocsmány hack által végrehajtom. Nem. Ellenben a ciklus fejrésze, és ami ennél is messze fontosabb, a „lába”, a vége, ahol a tulajdonképpeni ellenőrzés történik, na az lényegében natív kód. Én nem tudom, a Pythonban például ez hogy van, de az a kígyónyelv az én nyelveimhez képest ilyen szempontból például elkeserítően lassú. Vagy inkább örömtelien lassú mert utálom a pythont, örülök ha valahol jobb vagyok nála...

Na és most gondolj bele kérlek: a legtöbb benchmark arra épül hogy van valami feladat, amit sokmilliószor kell végrehajtani, s ennek idejét mérik. A sokmilliószor végrehajtás többnyire egy efféle finite loop által van megvalósítva. Na és az én nyelvem ÉPP a finite loop-okban fényéveket ver rá majdnem minden másik nyelvre! Lényegében mindegyikre, ami szkriptnyelv!

Amennyiben tehát abban a benchmarkban ami épp a teszt lényege, abban kevés utasítás van csak a ciklusmagon belül, az összidőszükséglet jelentős része hagyományos szkriptnyelveknél a ciklusvég végrehajtására megy el, ami azonban nálam natív sebességű. Az ilyen példákban tehát az én nyelvem hihetetlenül jól teljesít. Minél több más utasítás van azonban az adott példában a finite loop (vagy akár több ilyen loop) mellett, annál kisebb az előnyöm.

Van például olyan teszt ami prímszámokat keresgél egy tartományon belül. Itt bárhogy kínlódtam, nem voltam gyorsabb a Pythonnál, csak talán 20 százalékkal. Itt sok utasítás van ami nem ciklus... Ellenben amikor a Pí értékét kell kiszámolni mondjuk 3 millió iterációval, ott alig van utasítás az egyetlen cikluson belül, itt volt hogy csak 3.5-szer voltam lassabb mint a natív kód...

Szóval nemcsak az RPN előnyéről van szó, de arról is hogy van ez a „felfedezésem”, hogy a finite loop-okat hogyan lehet szkriptnyelvben eszméletlen gyorsra kihegyezni. Természetesen ebbe a legújabb nyelvembe is beleveszem majd ezt.

Obsessed commandline-maniac.

Nem tudom megosztani, mert kéne hozzá az egész nyelv maga. Nem tud működni „önmagában”.

A lényegét körbeírhatom azonban, hátha mész vele valamire. Arról van szó, hogy egy ilyen finite ciklus lényege a VÉGE. Az az a rész, ami sokszor hajtódik végre. (Ha jól van implementálva). Tehát, amikor van egy ilyen rész, hogy mondjuk

X DO

// ciklusmag

LOOP

akkor ugye az X bekerül a verembe. Jön a DO. Mit csinál? Hát azt hogy kiszedi az X-et (az értékét) a veremből, ÉS ELTÁROLJA egy speciális helyen - ez a hely gyakorlatilag a DO tokenjében van benne! Az X egy

unsigned long long

érték nálam mindig, minthogy ciklusszámláló esetén semmi értelme nem lenne törtszámot (például float) vagy előjeles egészet használni. Na most a DO tokenje ezért nemcsak a DO tokenkódját tartalmazza, hanem sok más adatot is: Pointert a ciklus végére (LOOP), egy üres unsigned long long helyet is ami a ciklusváltozó maga...

Ez utóbbiba a DO amikor rákerül a vezérlés, betesz egy 0 értéket. Ellenőrzi, a X épp nulla-e, ha igen, nem is kell végrehajtani a ciklust így elugrik a LOOP utánra. Majd folytatódik a végrehajtás, ha az X mégse nulla. Ekkor végrehajtódik a ciklusmag, s a vezérlés a LOOP-ra kerül. Ennek tokenjében van egy pointer a DO tokenjére... Eképp, inkrementálja a tokenben levő ciklusszámláló aktuális értékét, majd összehasonlítja a letárolt X értékkel, hogy egyenlő-e vele. Ha igen, kiugrik a ciklusból (azaz a vezérlés a LOOP után folytatódik), ha kisebb, a progi a DO után folytatódik megint.

Mint látod, maga a LOOP az ami sokszor végrehajtódik, mert a DO csak egyszer, a ciklusba belépéskor, és a LOOP egyáltalán nem piszkál semmiféle veremtárat! Gyakorlatilag globális változókkal dolgozik, azt mondhatjuk, bár e „globális változók” a tokenkódokban vannak elrejtve. Ez azonban nem baj egy szkriptnyelvnél, hiszen a végrehajtandó bájtkód az oprendszer szempontjából közönséges adat, azaz az adatszegmensben van elhelyezve... E megoldás előnye az is, hogy a ciklus belsejéből bármikor kiugorhatsz goto-val vagy akárhogy, nem kell félni hogy szemét marad a veremben. A ciklusváltozó ráadásul eképp el van rejtve minden programutasítás elől, azt lehetetlen megváltoztatni a ciklus futása alatt. Olvasni azonban lehet, van rá speciális utasítás ami a ciklusváltozó aktuális értékét a verem tetejére helyezni. (Nyilván ehhez az kell hogy az az utasítás is ismerje a ciklus elejének pointerét, szóval az le van tárolva ott is a tokenkódban. Hát nem mondom, az efféle ciklusok megvalósítása jelentős programozói munkát igényel a tokenizálás, tágabb értelemben a forráskódelemzés során, DE MEGÉRI!)

A konkrét kód közreadásának semmi értelme, az teljesen érthetetlen volna a programnyelv többi részének ismerete nélkül, de ezek után ha nagyon akarod, magad is megvalósíthatod. Már ha te is programnyelvet akarsz írni... Mert nem hiszem hogy ez az ötletem bármi egyéb körülmények közt használható volna. De szkriptnyelv esetén kincset ér, ez mély meggyőződésem...

Ha a mostani nyelvem készen lesz, abban benne lesz ez a ciklusfajta, csak nem DO és LOOP lesz a kulcsszavak neve...

Obsessed commandline-maniac.

Nyilván arra gondoltam, hogy az interpreter/compiler, és a teszt forráskódját osszad meg.

 

A futtatókörnyezet optimalizálását értem. Csak ezzel a megoldással nem hívhatod meg ugyanazt a fv-t még egyszer, ill. több szálon se futhat. Vagy a fv belépésekor le kell másolni a fv kódját. Amúgy nem gondolnám, hogy konkrétan ez az optimalizálás olyan nagyon sokat számítana. Általában a stacket nem szokták bizgetni egy fv-en belül. A fv eleje létrehozza, a vége pedig megszünteti (de mégha ez nem így van, akkor se nagy kaland a stack pointert átírni 1x a ciklus előtt, és 1x a ciklus végén - a ciklus futásához képest ez elhanyagolható, feltéve, hogy a ciklus azért lefut párszor). És most az, hogy a ciklusváltozó ott van a token mellett, vagy pedig egy másik memóriaterületen, olyan túl sokat nem számít. Inkább az számít, hogy a ciklus feltétele erősen kötött, és emiatt nem kell mindenféle feltételt kiértékelni, hanem a változó értéke alapján azonnal lehet tudni, hogy mit kell csinálni.

Amiatt számít, hol van a ciklusváltozó, mert ha a stackból szednénk mindig ki meg raknánk oda vissza, akkor az a stackpointer birizgálásával is együtt járna, sőt jóeséllyel olyan ellenőrzésekkel is hogy tele van-e a stack stb, ami mind extra munka, s ezért belassítaná a programot.

ezzel a megoldással nem hívhatod meg ugyanazt a fv-t még egyszer,

Miért ne hívhatnám meg mégegyszer? A ciklusfejléc inicializálja a ciklust, minden alkalommal amikor ő lefut, lenullázza a belső ciklusváltoxót. Akárhányszor is meghívhatom a ciklust tehát. Kipróbáltam.

ill. több szálon se futhat.

Hogyne futhatna. NEm először említem, az interpretált bájtkód a processzor szempontjából ADAT-nak számít! Tehát a tokenjeim adatok. A tokenben tárolt ciklusváltozó is. Amiből máris következik, hogy amikor bekövetkezik egy fork() hívás, az egész mindenség, a teljes adatterület duplikálódik. Ezt is kipróbáltam. Előző nyelveim közül jópár képes volt többszálú munkára.

Ha meg a pthread-re gondolsz, ott ugyan nem duplikálódnak az adatterületek, de ott úgyis tudjuk hogy nem igazán illik a külön szálakban azonos függvényeket futtatgatni, épp mert az adatterület nem duplikálódott, és össze ne akadjanak a szálak... Ha valaki iiyen huncutságot művel, vigyázzon! Melelsleg, épp emiatt én a fork()-ot sokkal jobban kedvelem. Egyetlen hátránya hogy rém nehézkes a szálak közti kommunikáció a fork() esetében, gyakorlatilag totál lehetetlen is, kivéve ha a fork() előtt létrehozok valami shared memory szegmenst és azon át kommunikálgatnak egymással a szálak.

Obsessed commandline-maniac.

Most vagy én nem értelek, vagy te keversz össze valamit. Ahhoz, hogy 1 lokális változó módosítsunk, nem kell a stack pointert állítani állandóan. Fv. meghívásakor létrejönnek a lokális változók, utána már simán csak egy adott memóriaterületet kell írni/olvasni. Hasonlóan, mintha a token mellől szednéd a ciklusváltozót.

 

Miért ne hívhatnám meg mégegyszer?

Ha jól értettelek, akkor a token mellett tárolod a ciklusváltozót. Azaz a kód mellett. A fv kódjából pedig csak egy van alapesetben. Ha a cikluson belülről meghívod még egyszer a fv-t (azaz rekurzív a fv), akkor már két változóra van szükség (vagy pontosabban, a rekurzió mélysége által meghatározott számú változóra), viszont neked csak egy van. Kivéve, ha lemásolod a fv kódját is fv híváskor. Erre utaltam.

 

A fork() nem szálat indít, ne keverjük a fogalmakat. Igen, pl. pthread lehet egy szál implementáció. De, nem pthread alatt nem duplikálódnak az adatterületek, hanem konkrétan a szál egyik legfontosabb jellemzője, hogy az adatok nem duplikálódnak. Nem csak a pthread alatt, hanem az összes szálimplementáció ilyen.

 

de ott úgyis tudjuk hogy nem igazán illik a külön szálakban azonos függvényeket futtatgatni

Teljesen alap dolog, hogy szálak azonos fv-eket futtatnak. Arra vannak pl. mutexek, hogy "megvédjék" az adatokat. Ebben semmi huncutság sincs, teljesen szokásos dolog.

Te kevered össze a dolgokat, igen. Mintha valamiért úgy képzelnéd el, hogy az a kód amit végrehajtok, az egy igazi gépi kód amit egy létező processzor végrehajthat!

NEM. Ezek a processzor szempontjából igenis ADATOK. És fork() esetén igenis megduplázódik az adatszegmens, nézz csak utána kérlek. Azt én se állítottam hogy pthread alatt IS duplikálódnánk az adatopk, sőt épp az ellenkezőjét állítottam, olvasd el kérlek mégegyszer figyelmesen! Én a fork() esetén állítottam ezt, ami nagy különbség!

Továbbá, összekeversz 2 fogalmat, persze ez nem okvetlenül a te hibád mert mindkettőnek stack a neve...

A rendszerstack az, amire te kizárólagosan gondolsz. Az a stack azonban amibe az én FORTH-szerű nyelvem teszi az adatokat, az NEM a rendszerstack, hanem egy teljesen másik stack, amit én implementálok (emulálok) szoftveresen. Emiatt minden ami ebben a stackban van (sőt, a veremmutatója is!) egy olyan memóriarészlet (technikai értelemben egy string), ami a program indulásakor a heap-ban van lefoglalva. A világon semmi köze tehát a rendszerstackhoz. Ennek ellenére, ha állandóan ebből olvasgatnánk az adatokat ki meg pakolnánk be a ciklus minden lefutásakor, illene mindig veremtúlcsordulást ellenőrizni, ami teméntelen idő.

Egyáltalán, tapasztalataim szerint a ciklusok a legkritikusabbak egy program sebességét illetően, azaz ezek sebességnövelésére érdemes a legtöbb energiát fordítani programozás közben. Itt kell optimalizálni amit csak lehet. Ehhez képest majdnem minden más elhanyagolható, akármilyen trehányul is írjuk meg, nem gond, mert a sebességet alig befolyásolja. A ciklusok azonban borzasztóan! (de ettől még a többi részt se akarom trehányul megírni, csak jelzem hogy az messze nem olyan lényeges).

Obsessed commandline-maniac.

Hol mondtam én, hogy a fork() esetében nincs másolás?

 

A rekurzióra nem reagáltál amúgy, hogy mi a helyzet vele a ciklusváltozó megvalósítása kapcsán. Nem lehet rekurziót használni emiatt?

 

Szerintem kicsit tekints ki a FORTH-ból. Feltételezem ott lehetett a ciklusváltozó (meg gondolom akkor minden lokális változó) megvalósítása olyan, hogy a stacket kell állandóan módosítani. De létezik más megoldás is a lokális változók megvalósítására, amit már leírtam talán többször is, csak ezekszerint nem ment át: a fv. elején leallokálódik az összes lokális változó, a ciklusváltozó is, és utána csak simán használva van az adott memóriaterület. Ergo nem kell a stackbe ki/be pakolászni állandóan.

Rekurziót nem finite loop-okkal szoktak megvalósítani, hiszen épp azért használunk rekurziót mert eleinte nem tudjuk hányszor kell meghívni önmagunkat...

És tisztában vagyok vele, mi az hogy a függvény elején leallokáljuk a memóriát stb. Programoztam én assemblyben is kérlekalássan, tudom mi a veremkeret, stb... de miért gondolod hogy a ciklusokat megvalósító utasításaim külön függvényekben vannak, vagy maga a ciklus a ciklusmaggal együtt egy külön függvény, stb?! Épp arról elmélkedtem fentebb, hogy ezt akarom elkerülni hogy minden számomra eleminek tekintett utasításhoz egy külön függvényhívás kelljen, mert az lassítana!

Nekem van egy olyn érzésem hogy még mindig fogalmad sincs róla miről beszélek, én meg képtelen vagyok elmagyarázni úgy, hogy megértsd. Szerintem emiatt felesleges is folytatnunk, ezen tényleg csak az segítene ha magát a kódot adnám közre, de az még nincs meg ehhez az új nyelvhez, régi nyelvet meg nem akarok megosztani mert obsolete és deprecated a szememben, hehehe...

Szóval kérlek légy türelmes amíg ez készen lesz! Ezt nem gúnyból írom és nem haragból, de látható hogy így a konkrét kód nélkül valóban nincs értelme. Be is fejezem most a hozzászólást, mert megyek programozni hogy előbb készen legyen...

Obsessed commandline-maniac.

"Amennyiben azonban a szintaxis RPN volt, a belassulás a natív kódhoz képest csak kb 12-szeres volt, sőt bizonyos feladatok esetén csak 8-szoros."
Nézd meg a luajit-et. Relatív pici a motorja és mindössze 4..5-szörös lassulás C-hez képest, miközben struktúrált szkript nyelv a LUA. Annó ezért is fogott meg a LUA.

De ugye te se állítod, hogy a LUA nyelvet én írtam volna?

Na látod, ez a baj a LUA-val. És ez igencsak nagy baj! Nekem legalábbis az. Sosem titkoltam, a legfőbb célom e nyelvvel (is, mint az eddigiekkel amiket írtam) az, hogy olyan legyen amit ÉN ALKOTTAM.

Amúgy a hiúságon kívül van értelmes célja is ennek. Könnyen lehet hogy e nyelv (ha elkészül) szerepel majd valamelyik regényemben. Van már egy ötletem egy regényhez, ami részben egy számítógépes világszimulációban játszódik, és oda épp jó lenne egy létező programnyelv... létező, de olyan ami mégsincs MÉG a mi világunkban... Oké, hangulatkeltés helyett írhatnék valami vizuálisan jól mutató halandzsát is valid kód helyett, de az ilyesmit nem szeretem, az a szememben csalás lenne.

Obsessed commandline-maniac.

Most megleptél. Mikor tettem én ilyen szörnyűséget, milyen esetekben?!

Ha viszont mégis előfordult már "többször is", ahogy írod, akkor miért utálsz ennyire, hogy állandóan piszkálódol? (Most nem e legutóbbi kommentedre gondolok ahol magam is egyetértettem veled, hanem úgy általában).

Ja, egy kiegészítés azért: annyiból nincs igazad hogy „bizonyítani akarnék magam előtt”. Szó sincs erről. Az első nyelvem, a mau esetén valóban ez volt a fő cél, az oké, de azóta annyi sok nyelvet írtam hogy semmi szükségem további bizonyításokra... Egyszerűen szeretek ezzel foglalkozni, magát az ALKOTÁST élvezem!

A cél ehhez képest mellékes. Tehát mindaz mellékes amit „siker”-nek neveznek sokan, ha siker alatt valamiféle széles körű elismerést értesz. Nyilván, örülök neki ha összejön, de tényleg mellékes. A lényeg maga az alkotás folyamata. Ez nálam ugyanúgy igaz a programozásra mint a regényírásra. Ilyen értelemben a regényeimet is önmagamnak írom.

Obsessed commandline-maniac.

Azért az egy elég meghökkentő dolog a grafikonodon, hogy a kb. azonos korú nyelvek közül azt, hogy melyik elterjedt, egyáltalán nem az dönti el, hogy melyik nyelv "jól megtervezett", hanem sokszor a szerencse: a Fortran kb. 70 éves, és népszerű. A létrehozásakor a nyelv tervezése nem volt szempont: Backus mondta el, hogy ezzel nem is foglalkoztak, lehessen beleírni formulákat, és aztán majd úgy csinálják, amihez könnyebb fordítót írni (annak sem volt még elmélete). Nem sokkal utána jött az Algol, és azt már megtervezték. Sehol sincs. Min múlt? A Fortran mögött ott volt az IBM.

Szóval, korábban jópár (valószínűleg egy tucatnál is több) saját programnyelvet írtam

Elnézést, ez mi a baszás?

ne terelj

Jaja, a régi szép idők emlékei... Nos az e könyvekben bemutatott mau programnyelvnél még nagyon kezdő voltam magam is, a tojáshéj a seggemen volt... De azért már a mau is egészen jól működött, és egyvalamire jó most is: elég jól bemutatja, mi a végső határa egy olyan nyelvnek ahol ragaszkodunk hozzá hogy AZONNAL végrehajtódjék a forráskód, az égvilágon bármiféle előzetes tokenizálás vagy elemzés, bájtkód-készítés nélkül!

Ebben a mau unikum. Mert ez nagyon erős limitáció, de ennek ellenére a mau eszméletlenül sokat tud.

Mindazonáltal, a későbbi nyelveim messze sokkal jobbak.

Obsessed commandline-maniac.

Na annyival már megvagyok hogy kiszűrte a forrásfájlból a C stílusú megjegyzéseket, tehát a

//

és a /* ..... */ alakúakat.

Obsessed commandline-maniac.

A /* .... */ -nél nem zavar, hogy ez egy jó nagy csapdát állít akkor, amikor a kikommentelni szánt részben van már komment? Igazából ebből a szempontból a Fortran-os megoldás (sor elejére C vagy ! a kommentelendő rész elejére) biztonságosabb, és ma már nincs olyan looser editor, amelyik ne tudna egész blokkban egymás alatti !-ket (vagy //-eket) írni.

(C++-ban én a /* ... */-t csak arra szoktam használni, hogy a forrásfile elején legyen egy hosszabb dokumentációs blokk, később csak // .)

Abszolút nem zavar. Ugyanis mint írtam fentebb valahol, ezt úgy szándékoztam megcsinálni, hogy a /* ... */ részek EGYMÁSBA ÁGYAZHATÓAK legyenek, és nemcsak __szándékoztam__ így megcsinálni, hanem ezt pont így is csináltam MEG, most, hogy megoldottam!

Obsessed commandline-maniac.

Szerkesztve: 2020. 03. 15., v - 19:53

Na jó, én mindenesetre már legalább egy dolgot köszönhetek az általad feldobott témának: FORTH és a stack alapú végrehajtót interpreteres módon már leprogramoztam, bár fordítót (ahogy a klasszikus FORTH csinálta) eddig még nem írtam. Majd valamikor talán.
Azonban eddig lusta voltam végiggondolni az infix --> postfix átalakítást. Végignéztem egy indiai oktató videóját és felfogtam. Már ez is megy (elvben), de csak akkor hiszek benne, ha saját kézzel leprogramozom.

Well, lassan ugyan, de haladgatok. Megvan az utasításfeldolgozó főciklus, tehát az ami a tokenizált bájtkódot végrehajtja. Egyelőre csak nagyon kevés utasítás van készen hozzá, lényegében csak annyi amennyivel a legegyszerűbb dolgokat tesztelni tudom.

Készen van azonban a számkonstansok értelmezése. Ez a következőt jelenti: minden számkonstans végső soron 8 bájton van tárolva. E 8 bájtos terület nem tárolja a konstans típusát, az utasítástól meg egyéb körülményektől függ, miként van az itt letárolt adat értelmezve. A tokenizálás során azonban a következő szabályok szerint értelmezi a literált:

—Ha van benne tizedespont (akár a legelején vagy a legvégén) akkor törtszámnak van tekintve, s lebegőpontos "double" számként van eltárolva (a C nyelv szabályai szerint).

—Ha nincs benne tizedespont, akkor 8 bájtos egész számként lesz letárolva. Ha a legelső karaktere egy mínusz jel, akkor signed long long int, ha nem az akkor unsigned long long int. Ebből máris következik, ha nullát akarunk letárolni, de double-ként, akkor annak írásképe

0.

kell legyen, azaz ki kell tenni utána a tizedespontot.

Ha a számban nincs tizedespont, használhatunk nemcsak tizes, de más számrendszereket is. Ezek prefixumokkal írhatóak elő. A módszer néhány példán bemutatva:

hexadecimális: $FCE2 vagy $fce2 vagy $FcE2 azaz a kis- és nagybetűk keverhetőek is.

+$FCe2 vagy -$Ea31 ez is hexa, de előjeles, azaz signed long long típusú lesz.

$%1011 bináris szám, ha akarjuk ez is lehet előjeles: -$%1011

$$70 vagy előjelesen -$$70 ez meg oktális.

Amint látható, minden ami nem tizes számrendszer, végső soron a dollár jellel van prefixálva, így később még beleépíthetek igény szerint akárhány másik számrendszert is.

Obsessed commandline-maniac.

Tudom, hogy a C-ben az oktalis szamabrazolas jelen volt, az utobbi par evtizedben elegge kiment a divatbol. (feleslegesnek erzem, de te tudod.. leirtal mostanaban barmit oktaliskent? - filerendszerbeli jogosultsagon kivul mondjuk) A hexa kell, esetleg a binaris is. Nekem a 0x prefix jelenleg jobban kezre all, de mas nyelvben kodolaskor a $ volt az. A b/h postfix is jo tud lenni. A nagyon egyedi megoldasokat ($$, $%) celszeru kerulni, mert szokatlan lesz hasznalatkor.

A signed vs. unsigned-ot azert gondold at! C-ben ha keveredik a muvelet ket oldalan a ketto, akkor unsigned lesz, nem biztos, hogy ezt akarod. Igy a legtobb unsigned lesz, mert epp ugy vetted fel. Szoval a "-1 1 *" RPN kifejezes erteke 18446744073709551615, ami nem egy intuitiv ertek. Ennel az is jobb, ha minden signed, kiveve, ha valami speci prefix volt elotte (vagy mondjuk egy u utana). Tovabba ha a tipus az ertekhez kotodik (ahogy a legtobb scriptnyelvben), kicsit lassabb lesz, de nem kell tudnod epp mi van a muvelet ket oldalan. Egy double-t es egy unsigned long long-ot azert nagyon maskepp kell kezelni, igy az aritmetikai muveletek ki tudjak olvasni a tipust, es megoldjak maguknak.

Komplex/kvaternio tervben van? Vagy majd strukturakent csinalja meg a user?

When you tear out a man's tongue, you are not proving him a liar, you're only telling the world that you fear what he might say. -George R.R. Martin

A kvaternióról nem is nagyon tudom, mi a szösz. Rémlik valami de rém homályosan. A komplex számokkal tisztában vagyok, de se ezt se kvaterniót se más extravaganciát nem építek bele. Nem kell azonban félni, mert mindenféleképpen úgy oldom majd meg hogy lehet a nyelvhez külső libeket gyártani, és e libek kényelmes kezelésére built-in nyelvi eszközök állnak majd rendelkezésre! Ez így volt már némely korábbi nyelvem esetében is, azaz ezt tuti meg tudom oldani, van már benne gyakorlatom. Szóval aki ilyesmit akar magának (vagy grafikus támogatást, akármit) az könnyedén megírhatja hozzá a maga libjeit.

A struktúrák kezelését illetően... Nos, azt szeretném megoldani, de nem most kerül majd rá sor, hanem a legislegvégén, amikor már nagyjából minden készen lesz. Azért akkor, mert ez olyan kérdéskör ami - BEVALLOM! - irtó nagy fejfájást okozott a korábbi nyelveim esetén is. Lényegében akkorát hogy meg se tudtam oldani... Na és nem technikai problémáim voltak vele, hanem szintaktikai. Gyakorlatilag nem voltam képes egy olyan jelölésrendszert kitalálni, ami a következő 4 feltételt teljesítette volna:

1. Tetszik NEKEM, igenis éppen pontosan ÉNNEKEM!

2. Viszonylag könnyű leprogramozni a tokenizálás során.

3. Nem igényel a kezelése runtime - azaz éppen pontosan RUNTIME - jelentős erőforrásokat a géptől, magyarán nem lassít nagyon a futási sebességen

4. A szintaxis olyan amiről vélelmezhetem hogy „human readable” olyanoknak is akik nem Asperger-szindrómások mint én, szóval olyan szintaxis ami „fehér embernek való”...

Lényegében én - bevallom ezt is - eléggé hajlamnos vagyok olyan szintaxisokat kitalálni a nyelv egyes részrendszereinek, ami talán még szép is esztétikailag (egyeseknek...), de semmi esetre se programozóbarát. Ez az egyik oka annak is hogy nem nagyon van kedvem a régebbi nyelveimk közzétételéhez, mert bár tökéletesen működőképesek, még gyorsak is, de csak gúnyt kapnék értük - kizárólag a szintaxis miatt...

Bármit leprogramozok már, simán, de a szintaxis kitalálása mintha nehezen menne nekem. Talán épp azért mert Aspie vagyok. Szóval a struktúrák tervben vannak nálam, de majd csak legutoljára, és ez kifejezetten az a kérdéskör lesz amiben nagyon számítok a HUP olvasóinak bölcs tanácsaira, (de trollkodás nélkül ha lehet...!), mert ez olyan terület amiben tényleg elveszettnek érzem magamat. Mondom nem a programozási részletkérdéseket illetően... De a szintaxissal kapcsolatban!

Vannak dolgok amikben eszembe sincs hagyni hogy más beledumáljon mert magabiztosnak érzem magamat, vagy mert tudom hogy ha nem is tökéletes a megoldásom de NEKEM akkor is úgy tetszik, tehát kész ez van. Ezt tekinthetitek önfejűségnek. De nem minden területre igaz ez akkor se, és a struktúrák kérdése épp egy olyan rész amiben tényleg és totál nem tudom mi legyen. Szóval ezt majd akkor ki kell beszélni, de nem most mert egyelőre még messze fontosabb dolgokat kell tető alá hoznom. Holnap például valószínűleg az jön hogy szétvágom a progit blokkokra, aztán azokra külön-külön meg kell hívnom egy másodlagos szintaktikai elemzőt rekurzívan... Ugyanis hierarchikusan egymásba ágyazottak lesznek a progik (ha úgy tetszik névterek), hasonlóan a Linux könyvtárrendszeréhez!

Szép meló lesz, mondhatom... de azért ebben is van már gyakorlatom, szóval fog ez menni.

Az oktálist én is feleslegesnek tartom, tényleg csak azért tettem bele, hogy mert a könyvtárrendszerben előfordul a használata a jogosultságoknál. A 0x jelöléstől nekem mindig felállt a szőr a hátamon, én még a C-64 időszakából ahhoz szoktam hozzá hogy ott (a gépi kódú programoknál) a $ volt a prefixum, ezért azt használom.

Obsessed commandline-maniac.

Készen van a stringkonstansok kezelése is, valami nagyon alapszinten. Ez azt jelenti, hogy a stringkonstans be van helyettesítve egy speciális tokennal, ami ha rákerül a vezérlés azt csinálja, hogy a stringkonstansra mutató pointert beteszi a veremtárba.

Ja, és van utasítás a kiírására is. Ja és még az is meg van oldva hogy a stringkonstansokban letárolt ESCAPE szekvenciákat tokenizáláskor felismeri és a megfelelő bizbaszokra kicseréli.

Meg kell ugyanakkor jegyezzem, hogy amit itt stringkonstansként emlegetek, az hogy is mondjam... azért nevezem úgy, mert a forráskódban úgy néz ki! Valójában azonban a tokenizálás során nem úgy lesz letárolva, hanem a saját formátumomban. Ezt egy magam által írt spéci stringosztálynak tekinthetitek, habár C és nem C++ nyelven van írva. Eleve ott kezdődik hogy nem záróbájtos hanem hossztárolós... De rengeteg szuper funkciója van! Magának a programnyelvemnek a megvalósításához is e string „osztályt” használom. Szóval ilyen stringekként vannak letárolva a stringkonstansok, dinamikusan van nekik memória allokálva, azaz elvileg ha valaki nagyon perverz, megteheti hogy a stringkonstanst átírja, aztán amikor legközelebb ugyanoda kerül a vezérlés már nem azt tartalmazza a „konstans”, mint eredetileg...

Ez nyilvánvalóan hbák forrása lehet, de nem igazán van kedvem kiküszöbölni e lehetőséget, egyszerűen azért mert nem nagyon tudom másképp elképzelni mint hogy legyen egy flag, ami runtime van ellenőrizve, és ha balérték-helyzetbe kerülne a stringkonstans akkor hibajelzéssel elszáll a progi. Na de a runtime ellenőrzések nagyon belassítanak... szóval, ez szerintem így marad. Vigyázzon a programozó... az eredeti FORTH-nak is ez a jelszava és nekem is!

Obsessed commandline-maniac.

Sajnos az utóbbi napokban sok melóm volt (még holnap is az lesz...), így lassan haladok. Leírom azért, mire jutottam.

—Konstans megadható így is:

aholis ennek az értéke 225 mert ennyi az "á" karakter UNICODE értéke. Azaz az aposztróf után tetszőleges karakter megadható. Maga az aposztróf is akár: ''

—Az is világossá vált előttem, ez a nyelv mégse egy FORTH implementáció lesz... Hanem valami egészen más, mindjárt leírom miért és miben más. Annyiból FORTH-szerű lesz, hogy verem-alapú nyelv, stack-orientált, és az alap kulcsszavaknál igyekszem amennyire csak lehet kompatibilis maradni a FORTH nyelvvel, ilyesmikre gondolok hogy:

dup drop emit

stb.

Lényegében tehát egyszerűbb FORTH programokat könnyű lesz átírni e nyelvre, azt hiszem.

Alapvetően különbözik azonban a FORTH-tól abban, hogy... hogy is fejezzem ki... Például e nyelvben egyáltalán nem lesznek változók! És ez nem vicc!

Tudniillik nem szükségesek. Azért nem, mert olyan „szavak” se lesznek benne mint a FORTH-ban. Nem lesz „szótára”. Lesznek azonban természetesen függvényei, és egy függvény az e nyelvben azonos azzal a fogalommal, hogy „névtér”. E névterek (függvények) azonban egymásba ágyazhatóak/skatulyázhatóak, a Linux könyvtárrendszeréhez hasonlóan. Ez teljesen biztos, mert ez már készen van, sikeresen lefejlesztettem... Na és az úgy van illetve lesz, hogy egy ilyen függvény nem változókat használ adott esetben, hanem a beléágyazott egyéb függvényeket, e függvények azok amik a parent függvény számára adott esetben változóknak is minősülhetnek...

A nyelvemben tehát, hogy igyekezzek röviden fogalmazni, a „változó” mint fogalom nem létezik, hanem bármely függvény betöltheti e feladatkört, amennyiben lesznek bizonyos olyan metódusai, amiket meghívva változószerűen viselkedik. E viselkedés érdekében természetesen nem okvetlenül szükséges hogy az adott függvény számára írjunk bármi végrehajtható kódot is. Mindazonáltal írhatunk, ez nem akadálya a változószerű használatnak...

Gyakorlatilag tehát összemostam 3 fogalmat, ezek:

—névtér

—függvény

—változó

Aki ezt bonyolultnak tartja, gondoljon arra, mi a különbség egy közönséges változó, és egy objektum közt? Lényegében csak egy: a változó mindig csak egyetlenfajta értéket ad vissza (amíg meg nem változtatjuk a tartalmát), egy objektum azonban akárhányfajta értéket is visszaadhat, attól függően melyik metódusát hívjuk meg. Nos, pontosan ez a helyzet az én függvényeimmel is: Lényegében mindegyik egy objektum lesz, mely objektumnak azonban lesz egy „default” viselkedési módja amikor változóként használjuk, illetve lesz neki egy „default” metódusa ami akkor hajtódik végre, ha függvényként használjuk. De, ettől még lehet neki akárhány másik metódusa is, amik meghívhatóak, aztán hogy ezek adnak-e vissza valami értéket a stackon keresztül (netán több értéket is) az attól függ miként írtuk meg ezeket...

Ezzel a módszerrel a struktúrák kérdésköre is megoldódik. A megoldás az hogy nincsenek struktúrák. Nem szükségesek. Objektumok vannak, vagy inkább speciális függvények. Azért speciálisak, mert lehet több „belépési pontjuk” is.

Na megyek aludni...

Obsessed commandline-maniac.