Revolut nabídne neomezený mobilní tarif za 12,50 eur (312 Kč). Aktuálně startuje ve Velké Británii a Německu.
Společnost Amazon miliardáře Jeffa Bezose vypustila na oběžnou dráhu první várku družic svého projektu Kuiper, který má z vesmíru poskytovat vysokorychlostní internetové připojení po celém světě a snažit se konkurovat nyní dominantnímu Starlinku nejbohatšího muže planety Elona Muska.
Poslední aktualizací začal model GPT-4o uživatelům příliš podlézat. OpenAI jej tak vrátila k předchozí verzi.
Google Chrome 136 byl prohlášen za stabilní. Nejnovější stabilní verze 136.0.7103.59 přináší řadu novinek z hlediska uživatelů i vývojářů. Podrobný přehled v poznámkách k vydání. Opraveno bylo 8 bezpečnostních chyb. Vylepšeny byly také nástroje pro vývojáře.
Homebrew (Wikipedie), správce balíčků pro macOS a od verze 2.0.0 také pro Linux, byl vydán ve verzi 4.5.0. Na stránce Homebrew Formulae lze procházet seznamem balíčků. K dispozici jsou také různé statistiky.
Byl vydán Mozilla Firefox 138.0. Přehled novinek v poznámkách k vydání a poznámkách k vydání pro vývojáře. Řešeny jsou rovněž bezpečnostní chyby. Nový Firefox 138 je již k dispozici také na Flathubu a Snapcraftu.
Šestnáctý ročník ne-konference jOpenSpace se koná 3. – 5. října 2025 v Hotelu Antoň v Telči. Pro účast je potřeba vyplnit registrační formulář. Ne-konference neznamená, že se organizátorům nechce připravovat program, ale naopak dává prostor všem pozvaným, aby si program sami složili z toho nejzajímavějšího, čím se v poslední době zabývají nebo co je oslovilo. Obsah, který vytvářejí všichni účastníci, se skládá z desetiminutových
… více »Richard Stallman přednáší ve středu 7. května od 16:30 na Technické univerzitě v Liberci o vlivu technologií na svobodu. Přednáška je určená jak odborné tak laické veřejnosti.
Jean-Baptiste Mardelle se v příspěvku na blogu rozepsal o novinkám v nejnovější verzi 25.04.0 editoru videa Kdenlive (Wikipedie). Ke stažení také na Flathubu.
Vedle (Textilosaurus) jsme se bavili o C++ a tom, jak v něm řešit některé věci. Ten program, o kterém jsem tam psal, jsem zveřejnil zde: rgb-assembler. Navrhuji v této diskusi pokračovat zde.
Varování: tenhle text a kód nemá sloužit jako návod, jak by se to mělo dělat – jde spíše o dotazovací a diskusní zápisek.
Původní „zadání“ programu:
Teď zrovna řeším něco hodně primitivního*, kde ani vlákna nejsou, ale snažil jsem se nad tím přemýšlet, jak by to vypadalo v o trošku složitější aplikaci. Máme nějaký vstup, proud zpráv potažmo volání metod. Ty zprávy můžou přicházet i z víc vláken. Zprávy je potřeba nějak roztřídit a poslat „procesorům“ Procesor se zprávou něco provede, někam odešle výsledek… To směrování zpráv může být mnohem složitější, ale prozatím uvažujme, že se budou třídit jen podle typu – textového klíče. Tudíž mi přišlo celkem přirozené použít mapu. Těch procesorů by mohlo být od každého typu víc a mohli bychom balancovat s tím, že vytvoření procesoru na jedné straně spotřebovává nějaký výpočetní výkon a procesor následně zabírá víc paměti a na druhé straně víc procesorů může lépe pracovat paralelně… tohle by se dalo nějak dynamicky konfigurovat a měnit za chodu – ale opět to nechci zesložiťovat, takže pro jednoduchost jsem chtěl zatím jen jeden procesor od každého typu.
*) Má to být interpret příkazů, které budou řídit RGB LED diody. Nakonec to poběží na nějakém jednočipu, ale nejdřív jsem si to chtěl vyzkoušet na „stolním“ C/C++ a udělat si tam prototyp, kde si ujasním formát, příkazy atd. Na vstupu bude posloupnost bajtů a výstupem je, že to různě rozsvěcí RGB LEDky. V podstatě takový jednoúčelový assembler. Je to taková blbost, ale říkal jsem si, že se na tom něco naučím. Má to fungovat tak, že tomu pošleš tu posloupnost bajtů a pak to pojede samo – tzn. v jednom programu si připravíš tu posloupnost (zatím to budu psát ručně), pošleš ji jednorázově jinému programu, ukončíš s ním „spojení“ a v tom druhém programu to pojede. Tzn. nemusíš pokaždé přeflashovat jednočip, aby jinak blikal, jen mu pošleš ty bajty, on si je uloží do RAM a bude je interpretovat. Příkazy můžou být typu: čekej X ms (jeden bajt je ID příkazu, pak jsou volitelně parametry, které můžou být různě dlouhé podle příkazu), nastav intenzitu určité barvy (parametr) na určité diodě (parametr) na hodnotu, kterou najdeš na Xté (parametr) pozici v té posloupnosti bajtů, inkrementuj/dekrementuj hodnotu na Xté pozici, nastav barvu na pevně danou hodnotu (parametrem příkazu je přímo ta hodnota, ne odkaz na její pozici), GOTO na určitou pozici, podmíněné GOTO, které porovná hodnoty na dvou pozicích nebo hodnotu proti konstantě atd. V té posloupnosti tedy nebudou jen data, ale může tam být i nějaká logika, v podstatě program.
Např. při bootu počítače to to tam pošle jednu sekvenci bajtů a od té doby to bude nějak blikat/svítit, dokud se tam nepošle jiná sekvence – bude se interpretovat pořád dokola (když na konci bude GOTO 0); když nastartuje KDE, tak se tam pošle něco jiného a bude to svítit jinak, když přijde e-mail, tak to třeba začne zuřivě blikat, když pustím videopřehrávač, tak se to ztlumí atd.
Na tom jednočipu to bude muset být zjednodušené, ale zatím si s tím hraji na počítači, kde můžu používat i věci z C++17. Původně jsem to chtěl udělat tak, že co příkaz, to položka v mapě a ukazovalo by to buď na nějakou instanci nebo na funkci. Tady by to bylo asi jedno, protože program se jednou nakonfiguruje a pak už se to nemění, ale schválně jsem si říkal, jak by to bylo u programu, který běží dlouhodobě a během svého života se mnohokrát překonfiguruje, změní se hodnoty v mapě atd. – kdo tam bude uklízet ty staré hodnoty, jak poznat, že už ty instance nejsou potřeba… Pak je taky potřeba si mezi tím nějak předávat odkaz na tu paměť, ze které se čte a případně se do ní i zapisuje.
V té paměti se mimochodem nerozlišuje mezi příkazy a daty, takže by tam šlo dělat různá kouzla/prasárny
. Kdyby se narazilo na neexistující příkaz nebo došla data, tak by to skočilo na nějakou domluvenou pozici (obdoba odchycení výjimky), kde by se pokračovalo dál. Mohla by se třeba dělat soutěž, kdo v tom napíše nejzajímavější blikání – něco jako se kdysi dělala dema. Paměť by byla omezená hardwarem, takže třeba jen 1024 bajtů.
Nicméně cílem není napsat minimalistickou implementaci vlastního assembleru, ale spíš najít řešení použitelné pro větší programy, které bude trošku pružnější a nebude tam vše zadrátované v kódu. Viz komentář:
Ve skutečnosti mi nejde o nějaké DSL nebo jazyky – může to být cokoli, filtry e-mailu, obdoba servletů nebo prostě cokoli, co se na základě nějakého klíče (nebo složitějšího mechanismu) vyhledá, předají se tomu nějaká data, ono je to zpracuje a vrátí nebo odešle jinam… a tyhle procesory dat se můžou v čase měnit, můžou vznikat, zanikat.
Mimochodem, ten jazyk, co jsem tam vytvořil je dost hrozný, hodně toho tam chybí a některé příkazy by to chtělo předělat… ale to teď nechci řešit – jako příklad a hřiště, na kterém si lze něco zkoušet to podle mého slouží dobře (pointa není vytvoření nového jazyka). Moje aktuální představa je, předělat ten switch
na mapu (obsahující zřejmě shared_ptr
) a kód v jednotlivých blocích switch
e přesunout do tříd, které budou implementovat (dědit) společné rozhraní. Některé třídy se budou používat ve více instancích – např. CMD_INCREMENT
a CMD_DECREMENT
můžou být implementované v jedné třídě, akorát se instanciuje s jiným parametrem (znaménkem). Ale třeba doporučíte něco lepšího…
Množství kódu k 2017-12-28:
$ cloc-sql.sh commands *.h *.cpp ╭──────────────┬─────────┬───────────┬───────────┬──────┬────────┬──────────────────────────────────────────────────────────────────────────────────╮ │ jazyk │ souborů │ prázdných │ komentářů │ kódu │ celkem │ celkem_graf │ ├──────────────┼─────────┼───────────┼───────────┼──────┼────────┼──────────────────────────────────────────────────────────────────────────────────┤ │ C/C++ Header │ 10 │ 87 │ 250 │ 202 │ 539 │ ████████████████████████████████████████████████████████████████████████████████ │ │ C++ │ 1 │ 14 │ 22 │ 75 │ 111 │ ████████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ │ │ celkem │ 11 │ 101 │ 272 │ 277 │ 650 │ │ ╰──────────────┴─────────┴───────────┴───────────┴──────┴────────┴──────────────────────────────────────────────────────────────────────────────────╯ Record count: 3
Tiskni
Sdílej:
Jedna komponenta bude držet tu mapu a třídit přicházející požadavky. Ale ty procesory (instance v mapě) můžou vznikat někde jinde, vytvoří je nějaká jiná komponenta, která třeba někde načte konfiguraci. A pak se můžou používat na třetím místě – jiná komponenta, která bude např. řídit vlákna a přehazovat úlohy mezi nimi.
Jasně, můžou se ty instance rozkopírovat, aby měl každý svoji, ale dejme tomu, že to nechci* dělat, protože při vytváření instance se třeba něco počítá nebo se získávají nějaká data (která už jsou po dobu existence instance konstantní, takže je lze sdílet i mezi vlákny). A další věc je, že jako komponenta, která vybere procesor v mapě podle klíče, už nemusí mít kontrolu nad tím, kdy daná úloha doběhla. Ty úlohy můžou běžet někde jinde a mezi tím přicházejí další a vybírají se pro ně procesory v mapě. A do toho může přijít požadavek na rekonfiguraci – přiřazení nového procesoru určitému klíči – a od té doby se budou úlohy s tímto klíčem zpracovávat v něm, ale ty staré mají doběhnout ještě v tom starém, jehož instanci nemůžu zrušit.
Ono ta myšlenka, že by data měl vždycky někdo vlastnit a starat se o ně, je sice hezká, ale ono to často nemusí být tak jednoduché – data můžou putovat skrz různé části (vrstvy či komponenty) programu – a kdo je pak vlastní? A co když se budou používat na více místech? Před časem jsem např. narazil na chybu v inotify-tools – tam taky nebylo jasné, kdo data vlastní a kdo by je měl uvolit (takže se program choval buď chybně nebo by unikala paměť a musela by se nějak pečlivě ručně uklízet, což u složitějšího programu může být dost problém – a to tohle byl úplně triviální případ a stejně v něm autor udělal chybu).
*) Pak existuje návrhový vzor muší váha (flyweight), kdy se třída rozdělí na dvě části, jedna je těžká a drží společný stav a druhá je lehká a lze ji libovolně (levně) rozkopírovat a držet v ní nějaký lokální stav (pro vlákno, aktuálně řešenou úlohu atd.). To často dobrý přístup, nicméně tenhle problém to nijak neřeší – pořád zůstává otázka, co s tou společnou těžkou částí – kdo se o ni bude starat a jak se rozhodne, že už je možné ji smazat?
To mi prijde jako hell z navrhu. Ty objekty si nemuze tvorit kdo si zachce. Tim se micha logika do vice vrstev.
Ja bych to resil asi tak, ze objekt by nebyl procesor, ale jedna uloha a po dokonceni by zavolala callback do spravce, aby si uklidil. Mapa na dispatch by obsahovala pointry na factory funkce. Takze pri rekonfiguraci by uloha pozadala dispatcher o zmenu factory funkce nejakeho typu requestu, v mape by se atomicky prepsal pointer a novy requesty uz by tvorily jinou ulohu.
To mi prijde jako hell z navrhu. Ty objekty si nemuze tvorit kdo si zachce. Tim se micha logika do vice vrstev.A proc by nemohl? Co kdyby jeden procesor obsluhoval blikani LED a druhy posilani emailu? Nedavalo by smysl, kdyby kazdy objekt pochazel z jineho modulu?
Ja bych to resil asi tak, ze objekt by nebyl procesor, ale jedna uloha a po dokonceni by zavolala callback do spravce, aby si uklidil. Mapa na dispatch by obsahovala pointry na factory funkce. Takze pri rekonfiguraci by uloha pozadala dispatcher o zmenu factory funkce nejakeho typu requestu, v mape by se atomicky prepsal pointer a novy requesty uz by tvorily jinou ulohu.A tobe prijde normalni, ze puvodni navrh, kde stacil jeden switch nebo v rozsirene variante jedna mapa a k tomu navrhovy vzor command, preroste do takto obludnych rube-goldbergovskych rozmeru? Kam se podel princip KISS? Mnohem jednodussi by bylo divat se na tu mapu jako na nejakou konfiguraci, ktera bude nemenna a predavat ji spolecne s jednotlivymi pozadavky. Pri zmene konfigurace pak vytvorit novou instanci mapy. Odpadnou ti problemy s atomickymi updaty a navic ziskas lepsi konzistenci a mnohem snazsi debugovani a testovani. Dalsim krokem by pak bylo pouziti copy-on-write jako optimalizace pro sdileni dat a na scenu by prisel i ten share_ptr.
Mnohem jednodussi by bylo divat se na tu mapu jako na nejakou konfiguraci, ktera bude nemenna a predavat ji spolecne s jednotlivymi pozadavky.
Tohle se mi líbí, protože to má nějakou přidanou hodnotu – úloha se zpracuje konzistentním způsobem (pokud bude mít víc kroků, tak se na všechny aplikuje jedna konfigurace, místo aby se pro každý krok v době jeho zpracování vzala v tu chvíli platná konfigurace). Ale přijde mi, že to situaci ještě víc komplikuje.
Ale přijde mi, že to situaci ještě víc komplikuje.V cem? Budes mit ctyri jasne definovane zodpovednosti. Dispatcher, konfigurace, procesory, pozadavky. Kazda ta trida bude jasne ohranicena a hlavne kod bude snadno testovatelny a debugovatelny. Navic ziskas srozumitelny kod i pro paralelni zpracovani bez zbytecnych zamku. Jestli se bude vzdy kopirovat cela mapa nebo se bude pouzivat nejaka variace na CoW, je jen implementacni detail.
v mape by se atomicky prepsal pointer a novy requesty uz by tvorily jinou ulohu.
A co když např. jeden procesor bude přičítat 1 a druhý 5? Budu to chtít řešit společným kódem, který se bude lišit jen parametrem. To se dá řešit třídou, od které si udělám dvě instance. Pokud by to byly funkce, tak se buď duplikoval kód nebo bych si musel napsat f1()
a f5()
, které by volali nějakou f()
s parametrem, ne? A stále tam bude ta 1 a 5 zadrátovaná v kódu – jenže já bych třeba chtěl, aby je uživatel mohl zadat v GUI nebo v konfiguraci.
Tak factory funkce muze delat uplne cokoliv. Tohle si predstavuju asi jako ze bych mel class AdderTask, kde bych v konstruktoru specifikoval, kolik ma teda pricitat. Factory funkce by z dostupnych dat stvorila konkretni objekt z obecnyho predpisu.
Kdybych chtel aby uloha byla soucasti nejakeho vetsiho celku, kde je potreba drzet nejaky globalnejsi state, tak zas jen factory vyrobi objekt s vazbou na ten spravce. Nebo napr. muze vracet uz existujici ulohy, pokud prichozi data patri jim.
template<typename T> Memory { T read<T>() { return Serializer<T>::read(); } void write<T>(const T& t) { Serializer<T>::write(t); } uint8_t* read(size_t size); void write(const uint8_t*); } // generická implementace případně např. omezit jen na čísla pomocí enable_if a SFINAE template<typename T> struct Serializer { static void write(const T& t, Memory& memory) { memory.write(reinterpret_cat<uin8_t>(&t), sizeof(T)); } static T read() { reinterpret_cat<T>(*memory.read(sizeof(T))); } } // specializace pro konkrétní typ template<> struct Serializer<X> { static void write(const X& x) { memory.write<TypeOfDataLength>(x.data_length); memory.write(x.data, x.data_length); } static X read() { const auto length = memory.read<TypeOfDataLength>(); return X(memory.read(length), length); } }
Jinymi slovy: Any sufficiently complicated C or Fortran program contains an ad-hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.Nicméně cílem není napsat minimalistickou implementaci vlastního assembleru, ale spíš najít řešení použitelné pro větší programy, které bude trošku pružnější a nebude tam vše zadrátované v kódu. Viz komentář:... prostě cokoli, co se na základě nějakého klíče (nebo složitějšího mechanismu) vyhledá, předají se tomu nějaká data, ono je to zpracuje a vrátí nebo odešle jinam… a tyhle procesory dat se můžou v čase měnit, můžou vznikat, zanikat.
Nicméně cílem není napsat minimalistickou implementaci vlastního assembleru, ale spíš najít řešení použitelné pro větší programy, které bude trošku pružnější a nebude tam vše zadrátované v kódu.Jeden ze zakladnich principu ve vyuce je postupovat od konkretniho k abstraktnimu. A to by se melo odvijet i na tom projektu. Udelat prvni navrh, aby reseni fungovalo, a pak, az je to potreba, zavest dalsi abstrakce. To zda, je to potreba, zavisi od konkretni situace. Pro urcite situace tento switch muze byt naprosto dostacujici a cokoliv navic z toho bude delat bloatware. Dokazi si predstavit situaci, kdy kvuli omezeni hardwaru bude lepsi prejit na nejakou variantu computed-goto nebo primy preklad do strojoveho kodu. Dokazi si take predstavit, ze kvuli omezeni hardwaru (a prenositelnosti) bude lepsi zavest pro kazdy prikaz vlastni objekt a provazat to treba s alokaci registru. V momente, kdy od toho reseni ocekavas, ze to muze: "být cokoli, filtry e-mailu, obdoba servletů nebo prostě cokoli,", tak delat analyzu nema smysl, protoze ti z toho driv nebo pozdeji vyleze Lisp nebo jiny turingovsky uplny jazyk. Jinak ten navrh toho "assembleru" mi prijde ponekud nestastny. Zejmena proto, ze je u nej patrna inspirace skutecnymi "assemblery", napr. explicitni prace s daty na konkretnich adresach. Skutecne assemblery jsou vetsinou hrozne, protoze jejich navrh vychazi z fyzicke implementace procesoru nebo historicke zateze. U nove vytvoreneho "assembleru", ktery bude jen/prevazne interpretovan nema smysl kopirovat omezeni hardwaru a davalo by vetsi smysl si to navrhnout nejak elegantneji, treba jako zasobnikovy procesor, load/store architekturu.
Any sufficiently complicated C or Fortran program contains an ad-hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.
Pěkné :-), ale na nízkoúrovňové věci se to moc nehodí. Tím C/C++ se zabývám pro případy, kde bych se i já zdráhal použít Javu. Pokud bych mohl použít Common Lisp, tak bych mohl použít i Javu a byl bych v tom mnohem efektivnější (což teď nemyslím jako srovnání těch jazyků ale spíš svých schopností, protože s Javou pracuji každý den a CL neznám skoro vůbec).
A to by se melo odvijet i na tom projektu. Udelat prvni navrh, aby reseni fungovalo, a pak, az je to potreba, zavest dalsi abstrakce.
Ten první návrh se switch
em jsem už právě udělal a funguje mi to, jak potřebuji. Psalo se mi to celkem dobře a ty šablony a reference mi umožnili pěkně zapsat to, co jsem chtěl (v Javě bych to dělal jinak, ale tady se mi tenhle způsob líbí).
A teď se právě dostáváme k druhému kroku – jakási simulace, že program je nějak napsaný a do toho přichází požadavek, že se má něco konfigurovat dynamicky a nemá to být zadrátované v kódu.
Pro urcite situace tento switch muze byt naprosto dostacujici a cokoliv navic z toho bude delat bloatware.
Klidně z toho ten bloatware nebo overengineering udělám, protože smyslem tohoto programu je vyzkoušet si různé přístupy. Zkoušet si to až na reálném projektu mi přijde riskantní a hloupé – pořád se bavíme o hodně základních věcech a kódu na pár (desítek, maximálně stovek) řádků, ne o návrhu, který bych psal měsíce do šuplíku, jen tak pro případ, že by se to jednou mohlo hodit.
V momente, kdy od toho reseni ocekavas, ze to muze: "být cokoli, filtry e-mailu, obdoba servletů nebo prostě cokoli,", tak delat analyzu nema smysl, protoze ti z toho driv nebo pozdeji vyleze Lisp nebo jiny turingovsky uplny jazyk.
Umění je v tom, udělat ten návrh právě přiměřeně pružný a univerzální – když to bude málo, tak to nebude vyhovovat požadavkům a bude se to muset pořád předělávat. A když to bude moc, tak se to zase bude špatně používat a vlastně můžeš dát uživatelům rovnou nějaký programovací jazyk a říct, jim, ať si to napíší sami – jenže pak nedodáváš software/aplikaci, ale jen nějakou platformu a klade to obrovské nároky na uživatele (musí umět programovat, místo aby si jen něco naklikal v GUI nebo nakonfiguroval v souboru).
Jinak ten navrh toho "assembleru" mi prijde ponekud nestastny. Zejmena proto, ze je u nej patrna inspirace skutecnymi "assemblery", napr. explicitni prace s daty na konkretnich adresach.
Těch příkazů může být až 256, mám jich rozmyšlených víc a budou tam i praktičtější/přímočařejší jako nastavení RGB na konkrétní hodnoty (ne přes adresu, ale hodnota bude hned v parametru). Ale ty adresy mají smysl pro případ, že tam bude nějaký cyklus, budou se inkrementovat hodnoty a pak to skočí vždy na ten stejný příkaz s tou samou adresou (ale pod ní už bude jiná hodnota, takže se barvy budou měnit).
Problém je s tím, že si ty adresy musíš odpočítat, což je opruz, ale je to optimalizované pro jednoduchost toho interpretu. Ten kód by člověk nemusel psát ručně v hexadecimálním editoru, ale může to dělat v nějakém nástroji, který mu ty adresy dopočítá – a pak z toho vypadne ta posloupnost bajtů, která se dá už snadno interpretovat i na tom jednočipu.
Pokud bych mohl použít Common Lisp, tak bych mohl použít i Javu a byl bych v tom mnohem efektivnější (což teď nemyslím jako srovnání těch jazyků ale spíš svých schopností, protože s Javou pracuji každý den a CL neznám skoro vůbec).Takze jeste vyklad toho aforismu:
It can also be interpreted as a satirical critique of systems that include complex, highly configurable sub-systems.[3] Rather than including a custom interpreter for some domain-specific language, Greenspun's rule suggests using a widely accepted, fully featured language like Lisp.
Klidně z toho ten bloatware nebo overengineering udělám, protože smyslem tohoto programu je vyzkoušet si různé přístupy. Zkoušet si to až na reálném projektu mi přijde riskantní a hloupé – pořád se bavíme o hodně základních věcech a kódu na pár (desítek, maximálně stovek) řádků, ne o návrhu, který bych psal měsíce do šuplíku, jen tak pro případ, že by se to jednou mohlo hodit.V tom pripade doporucuji jako cviceni naprogramovat interpreter Lispu/Scheme nebo Forthu. Je to otazka par desitek/stovek radku kodu a pouceni z toho bude nemale, viz vyse.
Umění je v tom, udělat ten návrh právě přiměřeně pružný a univerzální – když to bude málo, tak to nebude vyhovovat požadavkům a bude se to muset pořád předělávat. A když to bude moc, tak se to zase bude špatně používat a vlastně můžeš dát uživatelům rovnou nějaký programovací jazyk a říct, jim, ať si to napíší sami – jenže pak nedodáváš software/aplikaci, ale jen nějakou platformu a klade to obrovské nároky na uživatele (musí umět programovat, místo aby si jen něco naklikal v GUI nebo nakonfiguroval v souboru).Chapal bych, kdybys takovou hloupost pronesl na serveru abcwindowsu.cz, ale na abclinuxu.cz vetsina lidi vi, ze to tak neni. Musi uzivatel, ktery chce pouzivat shell, znat programovani? Ne, i kdyz je to plnohodnotny programovaci jazyk. Jdou v shellu napsat konfiguraky, ktere si bezny uzivatel upravi podle svych potreb? Ano. (I kdyz LP ma trochu jiny nazor.) Tak v cem je problem? Nejspis v tom si pripustit, ze na tom dat uzivateli plnohodnotny (ac sandboxovany) jazyk neni nic spatneho, ale docela dobry design pattern. V unixech naprosto bezny pattern. Vice viz The Art of Unix Programming.
Ale ty adresy mají smysl pro případ, že tam bude nějaký cyklus, budou se inkrementovat hodnoty a pak to skočí vždy na ten stejný příkaz s tou samou adresou (ale pod ní už bude jiná hodnota, takže se barvy budou měnit).Nechci ti kazit radost z objevovani, ale napovim, ze instrukcni sada, kde skoro kazda instrukce hrabe nekam do pameti, se pozdeji nejspis ukaze jako hodne nepruzne reseni, a ten preklad pro nejaky mikrontroler nebude nejefektivnejsi.
Ten kód by člověk nemusel psát ručně v hexadecimálním editoru, ale může to dělat v nějakém nástroji, který mu ty adresy dopočítá – a pak z toho vypadne ta posloupnost bajtů, která se dá už snadno interpretovat i na tom jednočipu.Povidej mi o tom...
Ten kód by člověk nemusel psát ručně v hexadecimálním editoru, ale může to dělat v nějakém nástroji, který mu ty adresy dopočítá – a pak z toho vypadne ta posloupnost bajtů, která se dá už snadno interpretovat i na tom jednočipu.Jak se to liší od přeflashování programu?
Např. ti přijde e-mail a na RGB panelu se má přehrát nějaká sekvence jako upozornění. Ty bys kvůli tomu pokaždé přeflashoval jednočip?
Tzn. ten nástroj použiješ jednorázově k vytvoření té sekvence a pak ji opakovaně používáš a už to jen přeposíláš jako posloupnost bajtů.
Např. ti přijde e-mail a na RGB panelu se má přehrát nějaká sekvence jako upozornění.To ale není rekonfigurace, ne?
Ty bys kvůli tomu pokaždé přeflashoval jednočip?Reagoval jsem na tu situaci, kdy chceš psát nástroj, který ti dopočítá adresy v tom kódu, který pak nahraješ do jednočipu. Tomu dopočítání adres se říká linkování a tomu nahrání do jednočipu flashování.
Any sufficiently complicated C or Fortran program contains an ad-hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.Velmi brutálně řečeno, tak brutálně že by to mnoha uctívačům "moderního" programování mohlo způsobit otevřenou zlomeninu mozku
Nicméně cílem není napsat minimalistickou implementaci vlastního assembleru, ale spíš najít řešení použitelné pro větší programy, které bude trošku pružnější a nebude tam vše zadrátované v kódu. Viz komentář: Ve skutečnosti mi nejde o nějaké DSL nebo jazyky – může to být cokoli, filtry e-mailu, obdoba servletů nebo prostě cokoli, co se na základě nějakého klíče (nebo složitějšího mechanismu) vyhledá, předají se tomu nějaká data, ono je to zpracuje a vrátí nebo odešle jinam… a tyhle procesory dat se můžou v čase měnit, můžou vznikat, zanikat.Zadání nechápu. Nevidim vůbec podobu nějakého konkrétního výstupu. Tohle vypadá jako "Chci něco obecného, co bude něco obecně dělat s nějakými obecnými daty. Jak na to?"
Moje aktuální představa je, předělat ten switch na mapu (obsahující zřejmě shared_ptr) a kód v jednotlivých blocích switche přesunout do tříd, které budou implementovat (dědit) společné rozhraní. Některé třídy se budou používat ve více instancích – např. CMD_INCREMENT a CMD_DECREMENT můžou být implementované v jedné třídě, akorát se instanciuje s jiným parametrem (znaménkem).To bude asi enterprise assembler. Když to poběží na desktopu jako Java program, návrh to má jako Java program, správu paměti jako Java program, přístupuješ k tomu jako k Java programu... Proč to nenapíšeš v Javě?
Zadání nechápu. Nevidim vůbec podobu nějakého konkrétního výstupu.
Přepsal jsem to na tu mapu a třídy (viz zdrojáky). Už to celkem vypadá, jak jsem chtěl – je tam ten potenciál ty příkazy/konfiguraci měnit a není to tak zadrátované v kódu, jako dřív.
Turing complete jazyk vůbec nepotřeboval, bylo to spíše podobné přehrávání animací.
Jde mi o to, že potřebuješ buď velkou paměť na tom MCU, abys do toho nacpal celou animaci ve formě „neživých“ dat, a nebo potřebuješ udržovat trvalé spojení s počítačem (a na něm musí celou dobu běžet nějaký program), který to řídí a průběžně tam posílá jednotlivé příkazy. Případně třetí možnost: pokaždé přeflashovat ten jednočip novým programem. Proto mi přišlo zajímavé udělat ten interpret, kterému by šlo jednorázově z počítače poslat program v nějakém primitivním jazyce a jednočip by ho pak interpretoval, přičemž by na to stačilo méně paměti a přitom by to vygenerovalo více „entropie“ na těch LEDkách.
P.S. a ještě připomínám, že se tu bavíme ve dvou rovinách a) něco si zkouším v desktopovém C++ a snažím se na tom něco naučit pro případné další programy a b) firmware pro jednočip, který bude mít úplně jinou implementaci než ten desktop a společný bude asi jen ten binární formát/jazyk.
Přepsal jsem to na tu mapu a třídy (viz zdrojáky). Už to celkem vypadá, jak jsem chtěl – je tam ten potenciál ty příkazy/konfiguraci měnit a není to tak zadrátované v kódu, jako dřív.Tak jak to je teď napsané, tak ten
shared_ptr
je zbytečný a stačil by ti unique_ptr
.
Pokud se ti nelíbí ta deklarace té mapy s make_shared
, určitě by se to dalo řešit (třeba přidáním konstruktoru do té mapy, který by z nějak vhodně specifikovaného initializer_list
udělal ty instance i s pointery nebo něco).
Jde mi o to, že potřebuješ buď velkou paměť na tom MCU, abys do toho nacpal celou animaci ve formě „neživých“ dat, a nebo potřebuješ udržovat trvalé spojení s počítačem (a na něm musí celou dobu běžet nějaký program), který to řídí a průběžně tam posílá jednotlivé příkazy.Tohle bylo řešené s ESP8266, které má docela dost RAM (něco jako 96kB nebo taknějak). Ale i kdyby nemělo dost RAM, je to IIRC schopné za běhu zapisovat do flash, která má 1MB. Fungovalo to tak, že se k tomu člověk připojil telefonem, nahrál data a pak to běželo dál samo.
Proto mi přišlo zajímavé udělat ten interpret, kterému by šlo jednorázově z počítače poslat program v nějakém primitivním jazyce a jednočip by ho pak interpretoval, přičemž by na to stačilo méně paměti a přitom by to vygenerovalo více „entropie“ na těch LEDkách.Jsi si jistý, že to není předčasná optimalizace? Teoreticky máš asi pravdu v tom, že s procedurálním jazykem to asi můžeš stlačit o něco víc, nicméně je otázka, jestli ten rozdíl opravdu je natolik velký a stojí to za to. Taky je potřeba brát v úvahu, že taková animace bude asi oproti deklarativnímu zápisu náročnější na vytvoření (v podstatě potřeba naprogramovat) a to zejména má-li být ve výsledku menší než ta deklarativní. Btw. trochu mi to přípomíná TrueType Hinting language, to je taky takový DSL Turing complete jazyk.
Znám, dokonce se mi tu nějaké válí v šuplíku :-) Ale to je kanón na vrabce – chci použít ATmega328 s 2 KB RAM. WiFi tam fakt nechci – má to ovládat svítící logo na bedně počítače složené z deseti WS2812. V nejjednodušším případě to projede cyklus, inkrementuje proměnnou a podmíněným GOTO se to vrátí na začátek a třeba po třech opakováních ta podmínka přestane platit a program se ukončí. Další možnost jsou barevné přechody nebo nějaké posuny barev mezi diodami.
Ale to je kanón na vrabce – chci použít ATmega328 s 2 KB RAM. WiFi tam fakt nechci – má to ovládat svítící logo na bedně počítače složené z deseti WS2812.Záleží jakou metrikou. Co se týče rychlosti CPU a velikosti RAM, tak to jo, ale příkon AFAIK nemá větší (naopak se dá vyladit na extrémně nízký příkon) a fyzicky je mrňavý. Wifi může zůstat vypnutá (já ji zatím ani na nic reálného nepoužil). On ta menší rychlost a paměť u těch Atmelů je v dnešní době skoro spíše umělé omezení...