Yggdrasil on LISP-käyttöjärjestelmä (tai oikeastaan Scheme-käyttis), jota olen suunnitellut tässä kaiken muun ohessa "omaan rauhalliseen tahtiini". Tavallani olen yhdistänyt siihen suurimman osan kaikista projekteista, joista olen kiinnostunut. Sekä käyttöliittymäsuunnittelukäsitykseni että visioni tekoälyn käyttämisestä ihmisten elämän helpottajana ovat kantavia ajatuksia Yggdrasilissa. Samoin kiinnostukseni kieliteknologiaan ja reflektiivisiin, ohjelmoijan työtä helpottaviin ohjelmointiympäristöihin on vahvasti mukana. Jos viimeksimainitusta haluaa jonkinlaisen aavistuksen, kannattaa vilkaista esim. Squeakia (http://www.squeak.org/).
Järjestelmän on tarkoitus olla "edistyksellinen", mutta itse asiassa siinä ei ole juuri yhtäkään ideaa, jota ei valmiiksi joku muu olisi kehitellyt. Itse asiassa suuri osa sen ideoista tulee aika vanhoista järjestelmistä, mikä ei liene suurikaan ihme jos nyt lähdetään tarkastelemaan ihan toteutuskieltä... jopa nimen oli alun perin tarkoitus tulla lainatuksi toiselta, vähän samanhenkiseltä projektilta, YASOS:lta ("yet another Scheme operating system"), mutta runo-Eddaa lukiessani tulin siihen tulokseen, että Yggdrasil olisi sittenkin mainiompi nimi. Nimen valintaan vaikutti myös se puolihimmeä puumystiikka, jota erinomaisessa suomenkielisessä Lisp-maailma-oppikirjassa viljellään. (Itse asiassa kyseinen kirja on oppikirjaksi huono, mutta täynnä hauskaa ja mielenkiintoista tietoa.) Lisäksi Yggdrasilin on tarkoitus yhdistää maailma yhdeksi puuksi.
Yritän tällä sivulla selittää, millainen ympäristö Yggdrasilin on tarkoitus olla.
Yggdrasil perustuu yhdelle kielelle, joka on jonkinlainen reflektiivinen Scheme-variantti. Kaikki ohjelmat ovat periaatteessa tällä yhdellä kielellä kirjoitettuja. Tämä ei kuitenkaan tarkoita, että ohjelmien kirjoittamisen käytännön pintakielenä tarvitsisi käyttää Schemeä: voihan erittäin monenkielisiä ohjelmia kääntää Schemeksi, usein varsin suoraviivaisestikin. Oikeastaan järjestelmän ytimessä ei ole tietty kieli, vaan tietty tietomalli: kaikki ohjelmat käsittelevät samassa muodossa olevia tieto-olioita. Monet näistä olioista ovat toki hyvin yksinkertaisia, kuten numeroita. Kuitenkaan ohjelma ei voi esim. esittää näitä numeroita haluamallaan tavalla bitteinä muistissa: numeroiden varsinainen esitystapa on käyttöjärjestelmän asia.
Schemeen Yggdrasilin sitoo erityinen funktio (eval), joka ottaa Scheme-tietorakenteena esitetyn Scheme-ohjelman ja suorittaa sen. (eval) on ainoa portti uusien ohjelmien ajamiseen esim. käyttäjän editoimasta tiedostosta. Periaatteessa on kuviteltavissa, että (eval):n kaltaisia palveluita olisi muitakin, mutta lähes jokaisessa tilanteessa on helpompaa muuntaa suoritusohjeet johonkin (eval):lle kelpaavaan muotoon kuin tehdä uusi (eval) esitystavaltaan erilaisten ohjelmien suorittamiseen.
Yhtenäinen tietomalli aiheuttaa sen, että tietoa esitettäessä ei tyypillisesti tarvitse luopua sen alkuperäisestä identiteetistä. Esimerkiksi siirrettäessä nimien listaa ohjelmalta toiselle ei tarvitse keksiä tekstimuotoa, jossa kyseinen tieto siirretään; oliot voi siirtää sellaisinaan. Ja kun esim. näytölle tulostetaan esim. jokin funktiomäärittely, voi käyttöliittymä mahdollistaa funktiota esittävän tietorakenteen suoramanipuloinnin.
On mahdollista, että korkean tason kielen pakottaminen käyttöjärjestelmätasolla aiheuttaa vakavia suorituskykyongelmia. Toisaalta ohjelmienvälisen kommunikaation tehostuminen ja mahdollisuus jättää pois monia nyt välttämättömiä suojauksia saattavat tosiasiassa tehdä järjestelmästä tietyissä käytöissä tehokkaamman kuin esim. tämän hetken Unix-järjestelmistä.
Scheme on kieli, jossa ei voi tyhjästä taikoa osoitinta mielivaltaiseen paikkaan muistissa. Ei ole mitään keinoa käsitellä oliota, jonka olemassaolosta kukaan ei ole kertonut sinulle. Niinpä ensisijainen suojausjärjestelmä Scheme-järjestelmässä on se, että ohjelmille ei vain yksinkertaisesti kerrota palveluista ja tiedoista, joihin niiden ei haluta pääsevän käsiksi.
Tärkein oikeusmekanismi on siksi nimiavaruus. Kaikki Scheme-ohjelman ei-paikalliset nimet tulkitaan ohjelman "globaalissa nimiavaruudessa", ja se, mitä palveluita (funktioita) kyseisessä nimiavaruudessa on, määrittää, mitä ohjelma voi tehdä. Jos haluaa rajoittaa jonkin funktion käyttöä osittain, sen voi korvata nimiavaruudessa toisella funktiolla, joka esim. tarkistaa syötteitä ja sitten suostuu mahdollisesti kutsumaan alkuperäistä, rajoittamattomampaa funktiota.
Periaatteessa se, millä "suojaustasolla" järjestelmässä liikutaan, on puhtaasti käytettävissä olevista palveluista riippuva asia. "Ydintasolla" voisi hyvinkin olla käytettävissä epäschememäisiä palveluita, kuten mielivaltaisen, numerolla osoitetun muistipaikan ylikirjoitus, jolla voi sotkea koneen täysin. "Ylläpitokäyttäjän" tasolla kaikki turva-abstraktiot ovat käytössä, mutta pääsee käsiksi esim. mihin tahansa nimiavaruuteen. "Tavallisen käyttäjän" tasolla pystyy käyttämään kaikkia palveluita, joista ei ole haittaa muille käyttäjille. "Hiekkalaatikkotasolla" ohjelmia suoritetaan ympäristössä, jossa ne eivät voi tehdä mitään vahingollista. Palveluiden epääminen voi olla hienovaraisempaakin. Periaatteessa ohjelmalle ei tarvitse ikinä antaa käyttöön palveluita, joita sen ei pitäisi tarvita, jolloin tietoturvariskit pienenevät.
Olennaista tietoturvalle on se, että (eval) on luotettu palvelu. Koska se saa suorittaa uusia ohjelmia, sen on myös varmistettava, etteivät nämä ohjelmat pysty tekemään mitään pahaa.
Kätevyyden vuoksi järjestelmä sisältää kahdenlaisia viittauksia, muutettavia ja muuttumattomia. Muuttumattoman viittauksen kautta ei voi käyttää yhtäkään palvelua (ainakaan ydintason alapuolella), joka muuttaa olion sisäistä tilaa (esim. vaihtaa listan ensimmäisen tiedon joksikin muuksi). Muutettavasta viittauksesta pystyy aina tuottamaan vastaavan muuttumattoman, muttei päin vastoin. Muuttumattomia viittauksia voi käyttää esimerkiksi olioiden antamiseen toisten ohjelmien luettaviksi vailla vaaraa siitä, että nämä ohjelmat menevät sotkemaan niitä. (Toinen mahdollisuus on korvata toisen ohjelman nimiavaruudesta olioiden muuttamispalvelut sellaisilla rajoitetuilla palveluilla, jotka eivät suostu koskemaan kyseiseen olioon. Tämä on usein käytännön syistä epäkätevää.)
Kaikki funktiot ovat muuttumattomia (ei ole olemassa palvelua, jolla voisi muuttaa jo olemassa olevan funktion toimintaa muuten kuin uudelleenmäärittelemällä sen käyttämiä alifunktioita), mutta funktioihin voi viitata kahdella tavalla: läpinäkyvillä ja -näkymättömillä viittauksilla. Läpinäkymätön viittaus ei salli tutkia funktion sisäistä rakennetta, paikallista nimiavaruutta, yms. Tämä jaottelu johtuu siitä, että funktio on pääasiallinen (vähemmän rajoitettujen) palveluiden piilotustapa. Mikäli funktiosta pystyisi kaivamaan esiin palvelut, joita se käyttää, ja näistä taas esiin palvelut, joita ne käyttävät, ei mikään palvelu olisi saavuttamattomissa. Periaatteessa saman asian kuin läpinäkymättömillä viittauksilla saisi taas aikaan sillä, että korvaa funktioreflektiiviset palvelut nimiavaruudesta toisilla, jotka eivät suostu kaivelemaan tiettyjä funktioita (eivätkä itseään). Mutta eri viittaustyypit ovat kätevämpiä.
No niin, kaikki pysyy hienosti olioina niin kauan, kuin niitä käsitellään keskusmuistissa. Mutta entä tallettaminen ja lataaminen? Miten tiedostot suhtautuvat tähän sisäiseen tietomalliin?
Yggdrasilissa ei ole tarkoitus olla oikeastaan tiedostojärjestelmää ollenkaan. Sen sijaan kaikki normaalisti luodut oliot voidaan kirjoittaa levylle. Olio voi olla keskusmuistissa tai levyllä tai molemmissa, ja se siirretään tarvittaessa näiden välillä. Yggdrasilin tiedostojärjestelmä on siis eräänlainen pysyvä sivutusosio. Viittauksen säietoteutuksen nimiavaruuteen pitää vain olla tietyssä paikassa levyllä, ja systeemin boottauksen voi hoitaa seuraamalla viittauksia siitä eteenpäin.
Jos tarvitaan jonkinlaista tiedostojärjestelmää, sitä voi simuloida esim. muuttujalla, joka on näkyvissä kaikille tiedostojärjestelmää tarvitseville ohjelmille.
Oliota luotaessa voi erikseen pyytää, ettei sitä koskaan talleteta levylle. Tällainen olio on joko tuhoutumaton, kunnes siihen ei ole viittauksia, tai hävitetään automaattisesti roskankeruun yhteydessä. Ylipäänsä Yggdrasilin oliot ovat roskankeruun alaisia. Sellainen muisti (levytila), johon ei viitata, vapautuu. Olioiden muisti varataan sivukohtaisesti siten, että yhdellä muistisivulla on vain samantyyppisiä olioita. Sivun alussa on viittaus olion tyyppiä edustaviin tietoihin (tyyppiolioon).
Mitä tahansa Yggdrasilissa tehtyjä muutoksia voi perua. Tämä johtuu siitä, että jokainen olioiden tai muuttujien tilaan vaikuttava palvelu (kuten (set!), (set-car!) jne.) tallettaa vanhan arvon perumishistoriaan, jota voi sitten käydä läpi.
Koska (eval) on ainoa reitti antaa koodia suoritettavaksi, mikään ei itse asiassa estä sitä kääntämästä sille annettua koodia konekieliseksi. On myös kuviteltavissa, että (eval) itse asiassa koostuu sarjasta transformaatioita, joissa ohjelmaa muunnetaan pikku hiljaa matalemmalle tasolle.
Scheme on dynaamisesti tyypitetty kieli, eli olioista on saatavissa tieto niiden tyypistä. Kuitenkin monet funktiot on kirjoitettu siten, etteivät jotkin niiden argumentit voi olla kuin yhtä tyyppiä -- muuten funktion suorittamisesta seuraa väistämättä virhetilanne. Tällaisessa funktiossa voidaan tyyppitarkastus siirtää ylemmälle tasolle. (eval) annotoi kääntämänsä funktiot sen mukaan, mitä tyyppejä niiden tiedetään edellyttävän ja palauttavan. Tätä tietoa voidaan käyttää ajonaikaisten tyyppitarkastusten vähentämiseen ja tehokkaamman koodin tuottamiseen.
Useimmissa käyttöjärjestelmissä ero ohjelmien, kirjastopalveluiden ja käyttöjärjestelmän välillä on selvä. Yggdrasilissa nämä kaikki ovat oikeastaan vain funktioita, joita voi kutsua. Funktioita on toki monentyyppisiä: jotkin ovat sivuvaikutuksettomia, jotkin sivuvaikutuksellisia, jotkin voivat kommunikoida käyttäjän kanssa (eräänlainen sivuvaikutus), jotkin voivat aloittaa uuden suoritussäikeen. Osa "ohjelmista" on itse asiassa funktiotakaisinkutsuja, eli käyttöön asennettuja "koukkuja", joita käyttöjärjestelmän palvelut kutsuvat tietyissä tilanteissa (kuten jonkin tiedon tullessa saataville).
Varsinaista tietojärjestelmää Yggdrasil ei ehkä tarvitse, mutta Yggdrasilissa on yhtenäinen tietovarasto. Tämä tietovarasto sisältää, no, tietoja, eräänlaisina ontologisina väitteinä. Kaikkien ohjelmien tulee käyttää tätä yhteistä tietovarastoa, koska sillä tavoin ohjelmat voivat hyötyä toistensa tiedoista. Esimerkiksi DHCP-asiakas voi panna tietovarastoon tiedon, että suositettu IRC-palvelin on mikä onkaan, ja jokin toinen ohjelma voi käyttää tätä. Edelleen sähköpostiohjelma voi tallettaa tunnettuja osoitteita tietovarastoon, ja kirjoitusohjelma voi käyttää niitä apuna sanatäydennyksessä tai oikaisuluvussa. Ja niin edelleen.
Tietovarastosta voi sekä kysellä tietoja (enemmän tai vähemmän) yksinkertaisellä kyselykielellä, tai sinne voi laittaa koukun, joka aktivoituu tietyn tiedon tullessa. Myös lume-tason interaktiota käyttävät ohjelmat ohjaavat kaiken interaktionsa tietovaraston kautta.
Käyttöjärjestelmä perusohjelmineen ja -kirjastoineen tarjoaa perinteisesti monipuolisen ja hyvän käyttö- ja ohjelmointiympäristön. Myös Yggdrasil pyrkii tarjoamaan käyttäjälle tai ohjelmoijalle paljon sellaista, mistä on hyötyä monenlaisissa tilanteissa. Palvelut sisältävät paljon sellaista perinteistä kuten kuvankäsittelyä, säännöllisten lausekkeiden palveluita ja standardien tietomuotojen / protokollien käsittelyä, mutta myös vähemmän tavanomaisia asioita, kuten parsereita erilaisista pintasyntakseista (s-lausekkeet, erilaiset infix-notaatiot, monitulkintaiset heuristisesti jäsennetyt notaatiot) tietorakenteiksi ja takaisin, vaihtoehtoisia ohjelmansuoritusmalleja (toteutettavissa Schemen jatkeilla), päättelypalveluita sekä monimutkaisia käyttöliittymäpalveluita. Yggdrasilissa on myös osajärjestelmä, joka sallii eri Yggdrasil-koneiden "keskustella" keskenään, ts. vaihtaa käsityksiä.
Kun ohjelmien toiminnassa on ongelmia, Yggdrasil sekä mahdollistaa ohjelmien korjaamisen lennossa että yrittää auttaa käyttäjää paikallistamaan ja selvittämään ongelman. Yggdrasil sisältää palveluita, joiden tarkoitus on ymmärtää järjestelmää itseään ja tehdä järkeviä ehdotuksia virhetilanteiden korjaamiseksi. (Jos et yhtään arvaa, mitä tämä tarkoittaa, ota selvää Interlisp-D:stä ja DWIM:sta.)
Yggdrasilin ohjelmat voivat käyttää kolmen eri tason käyttöliittymäpalveluita eli olla käyttäjän kanssa tekemisissä kolmella erilaisella tavalla. Palveluita voi myös käyttää sekaisin eli ohjelma voi kommunikoida käyttäjän kanssa useammalla eri tavalla.
Suuntio-tasolla ohjelma saa käyttöönsä (mahdollisesti virtuaalisen) näyttö- ja äänialueen. Ohjelma voi antaa ohjeita siitä, mitä kyseiselle näyttöalueelle piirretään tai mitä ääniä soitetaan, ja se saa tietoja käyttäjän painamista nappuloista ja hiiren liikkeistä. On käyttöliittymäkomponentin (Karu) tehtävä huolehtia siitä, missä tämä näyttöalue näkyy vai näkyykö ollenkaan, miten äänet soitetaan ja mitkä käyttäjän syötteistä lähetetään ohjelmalle.
Kaiku-tasolla ohjelma esittää korkean tason kuvauksia käyttäjäinteraktioista. Nämä kuvaukset muistuttavat graafisten käyttöliittymien widgettejä kuten nappuloita ja valikoita, mutta ne eivät ota kantaa tarkkaan representaatioonsa. Ne ovat pyyntöjä Karulle, sellaisia kuin "saata tämä teksti käyttäjän tietoon" tai "pane käyttäjä valitsemaan näistä vaihtoehdoista". Aikaisempia ajatuksia kaiku-tasoa vastaavasta systeemistä on sivulla DI-widgetien toteutuksia.
Lume-tasolla ohjelmat kirjoittavat ja saavat kaikki tietonsa tietovaraston kautta, ja ohjelmien toiminta on olennaisesti reagointia tietovaraston tietoihin siitä, mitä käyttäjä haluaa. Tietojen selvittäminen tai selvittämättä jättäminen, esittäminen tai esittämättä jättäminen on olennaisesti Karun ongelma. Lume-tason pointti on mahdollistaa järjestelmän kaiken interaktion käyminen yhden käyttöliittymän läpi. Vain lume-tasolla käyttäjä voi tosissaan vastata kysymykseen "Satutko tietämään, mikä on lähtevän sähköpostin palvelimesi?" vaihtamalla aihetta: "Hei, missä on viime viikolla kirjoittamani artikkeli?" Lume-taso sallii myös Kaiku-tasoa korkeamman ohjelmien käyttöliittymäriippumattomuuden. Periaatteessa Lume-tasolla toimivan ohjelman ei tarvitse tietää, käytetäänkö sitä osana asiantuntijajärjestelmää vai jutteleeko käyttäjä sen kanssa samalla kun vaihtaa päivän kuulumisia koneen kanssa.
Karu on luonnollisesti aika monimutkainen järjestelmä. Sen suunnittelun kantavana pointtina tulee olla kaksi päämäärää: (1) käyttäjän ei tarvitse tehdä sellaista, minkä kone voi tehdä automaattisesti (kuten järjestellä ikkunoita) ja (2) sitä ei voi käyttää väärin. Karusta on tarkoitus tehdä sellainen, että missä tahansa tilanteessa käyttäjä voi vaihtaa aihetta, kysyä miksi häneltä kysytään jotain tai pyytää tarkennusta.
kategoria: projektit kategoria: keskeneräiset
Pikalinkit: