Hlavní navigace

Programovací jazyk Factor

29. 1. 2008
Doba čtení: 13 minut

Sdílet

Dnes si představíme programovací jazyk Factor, který je svojí syntaxí i sémantikou do značné míry podobný programovacímu jazyku Joy, jenž byl na Rootu popsán v předchozích třech týdnech. Zatímco Joy je již na první pohled jazykem vzniklým v akademickém prostředí, je Factor zaměřen spíše prakticky.

Obsah

1. Programovací jazyk Factor
2. Historický vývoj Factoru
3. Překlad základu virtuálního stroje (runtime)
4. Tvorba obrazu paměti virtuálního stroje
5. Základy programování ve Factoru
6. Factor, Forth, Joy a Lisp
7. Literatura
8. Odkazy na Internetu
9. Obsah následující části tohoto článku

1. Programovací jazyk Factor

Factor is an experiment to build a modern, useful concatenative language with strong abstraction capabilities. Though there are some pitfalls, many problems can be more cleanly expressed in a concatenative language. The Factor website has more about specific goals.
(výňatek z blogu o Factoru)

Dalším netradičním programovacím jazykem založeným na kompozici funkcí a vyhodnocování výrazů pomocí postfixového kódu a zásobníku je jazyk Factor. Jedná se o programovací jazyk, který byl do značné míry inspirován minule popsaným jazykem Joy, ovšem na rozdíl od spíše akademického Joye se v případě Factoru jedná o jazyk zaměřený více prakticky, což je názorně vidět například na mnohem větším množství knihoven či existenci poměrně kvalitního a použitelného, i když dosti neobvyklého, integrovaného vývojového prostředí (IDE).

O tom, že je jazyk prakticky použitelný, svědčí i to, že je v něm implementován například HTTP server, služba RPC, parser jazyka XML, poměrně rozsáhlá knihovna pro tvorbu grafického uživatelského rozhraní (GUI), ovladače pro připojení k různým databázím (MySQL, Postgres) a tvorbu popř. zpracování výsledků SQL příkazů, grafické aplikace využívající OpenGL, jednoduché hry typu Tetris, emulátory jazyků založených na Lambda kalkulu nebo dokonce emulátory starobylých automatových her typu Space Invaders.

factor11

Logo programovacího jazyka Factor

Zatímco při práci s programovacím jazykem Joy jsme byli odkázání především na příkazovou řádku (což samo o sobě může být pro některé účely více než dostačující), je možné Factor kromě příkazové řádky ovládat i z integrovaného vývojového prostředí (IDE), které je multiplatformní, tj. lze ho spustit jak na Linuxu či jiných Unixových systémech, tak i na Microsoft Windows či MacOS X (viz seznam podporovaných architektur vypsaný pod tímto odstavcem). Mezi platformy, na kterých je možné Factor oficiálně provozovat, patří:

  • Linux/x86
  • Linux/AMD64
  • Linux/PowerPC
  • Linux/ARM
  • Mac OS X/x86
  • Mac OS X/PowerPC
  • FreeBSD/x86
  • FreeBSD/AMD64
  • OpenBSD/x86
  • OpenBSD/AMD64
  • Solaris/x86
  • Solaris/AMD64
  • MS Windows/x86 (XP and above)
  • MS Windows CE/ARM

Ve skutečnosti, jak si ostatně ukážeme v následující kapitole, je možné Factor (přesněji řečeno jeho virtuální stroj) přeložit i na dalších platformách, postačuje upravit několik systémově závislých operací, které souvisí s implementací přístupu do paměti.

Samotné IDE je z velké části napsáno ve Factoru, ostatně jako všechny další podpůrné utility a knihovny. V IDE je do velké míry využito vlastnosti typické pro mnoho skriptovacích jazyků – reflexe (reflection) a možnosti dynamické změny programového kódu. Reflexe je použita jak při ladění, tak i při procházení programového kódu. Pro Factor existují i pomocné soubory s definicí způsobů obarvení syntaxe programů v něm napsaných, které jsou určené mj. i pro známý textový editor Vim (soubor factor.vim) i Emacs (soubor factor.el).

2. Historický vývoj Factoru

Learning Factor is tough. One reason for this is that Factor is very different from other programming languages. Programmers today are used to imperative programming languages where data is stored and passed around in named variables (or function calls, which name their variables). Factor is the opposite of this. A lot of code tends to be written in a functional style, and even more jarringly, variables are rare, only referenced in a small fraction of words. Nobody intends to change any of this; it's a feature, not a bug!

Původním autorem tohoto netradičního programovacího jazyka je Slava Pestov, který je mj. také autorem známého multiplatformního programátorského editoru JEdit. Slava původně vyvinul Factor pro účely skriptování her vytvářených v programovacím jazyku Java (dnes je k tomuto účelu možné použít i další skriptovací jazyky, například Jython nebo Groovy).

Později došlo k oddělení jazyka Factor do formy samostatného interpreteru nezávislého na hostitelské aplikaci a krátce poté byla vytvořena i céčková podoba interpreteru běžícího přímo na cílovém procesoru (nativní interpreter), na rozdíl od Javovského interpreteru, který sám běžel na JVM (virtuálním stroji jazyka Java, Java Virtual Machine), což znamenalo, že se některé operace, například správa operační paměti, prováděly vlastně ve dvou vzájemně se ovlivňujících úrovních.

V současnosti se již javovská verze interpreteru nepoužívá, protože se zdá, že Slava z důvodů, které před cca dvěma lety zveřejnil na svém blogu, celkově odstoupil od jakéhokoli dalšího vývoje v Javě. I objem zdrojových textů napsaných v céčku se neustále zmenšuje, protože větší množství kódu interpreteru Factoru i části virtuálního stroje je přepisováno do samotného Factoru (do určité míry se to podobá například projektu PyPy). Podle tvrzení vývojářů by se v budoucnosti mělo dospět do stadia, kdy by v céčku byla napsána pouze nezbytná kostra jazyka a zbylé operace by obstaral samotný Factor.

V podstatě se zde v jiné podobě opakuje historie Unixu, který má taky pouze nezbytnou část napsanou v assembleru a mnohem větší část zbývajícího kódu je v přenositelném céčku. Prozatím jsme ve stadiu, že céčkové zdrojové kódy Factoru, které kromě interpreteru obsahují i platformově závislé operace, mají celkem 270 kB, což není mnoho, když si uvědomíme, že je zde podpora síťování, tří knihoven pro GUI (Cocon, X11 a Win32), OpenGL, podpora pro 14 navzájem odlišných platforem atd. (na jedné platformě nejsou využity všechny zdrojové soubory).

A odkud se vlastně vzal název tohoto programovacího jazyka? Je odvozen od slova factoring resp. refacto­ring, což znamená (neustálou) změnu programového kódu tak, aby program byl ve výsledku složen z velmi krátkých programových sekvencí (slov), které je možné snadno testovat (unit testy) a které současně mají přesně daný účel – tj. dělají pouze to, k čemu byly naprogramovány a dělají to dobře, ve snadno otestovatelné formě. To je ostatně i vlastnost jednoho z ideových předchůdců Factoru – jazyka Forth Chucka Moorea.

factor12

Nové logo programovacího jazyka Factor

3. Překlad základu virtuálního stroje (runtime)

Před prvními pokusy s programovacím jazykem Factor je nutné provést překlad základu virtuálního stroje, který budu v dalším textu nazývat runtime. Zjednodušeně řečeno se jedná o poměrně krátký spustitelný soubor, s velikostí obvykle nepřesahující 150 kB, který se po svém spuštění postará o zavedení a inicializaci obrazu virtuálního stroje (VM) do operační paměti a následný start programového kódu umístěného ve virtuálním stroji (obdobu tohoto řešení můžete hledat například ve Sqeaku). Překlad runtime se provede poměrně jednoduchým způsobem. Nejprve je zapotřebí stáhnout z adresy http://www.fac­torcode.org/dow­nload.fhtml zdrojové kódy runtime. Na této stránce jsou mimochodem dostupné i již přeložené runtime pro některé operační systémy, u nichž se nepředpokládá, že by jejich uživatelé měli nainstalovaný překladač GCC.

Ovšem samotný překlad je velmi jednoduchý, proto je ho možné provést prakticky kdekoli. Po stažení a rozbalení zdrojových kódů runtime se spustí program make, kterému se předá jako parametr cílová platforma, pro kterou se má překlad runtime provést, například:

make linux-x86-32
nebo
make linux-x86-64 

Program make se v tomto případě pokusí přeložit i verzi runtime podporující grafické integrované vývojové prostředí. K tomu je nutné mít v systému nainstalované vývojové verze knihoven X11, freetype a OpenGL. Výsledkem překladu je spustitelný soubor (ať již s podporou GUI nebo „pouze“ příkazové řádky), který využijeme při tvorbě obrazu paměti virtuálního stroje. Samotná tvorba je popsána v následující kapitole.

factor13

Vývojové prostředí Factoru spuštěné na Linuxu (Ubuntu, Fluxbox)

4. Tvorba obrazu paměti virtuálního stroje

Factor can be used for anything. It is not a scripting language but it is suitable for rapid development. Factor has been used for everything from web applications to game development to XML parser implementation. Factor isn't meant for extremely low-level things, like boot loaders or microcontroller programming, though.

Dalším krokem před prvním spuštěním plnohodnotného interpreteru jazyka Factor je tvorba obrazu paměti virtuálního stroje, ve které budou umístěny nejčastěji používané operátory (funkce, slova). Opět jsou zde poněkud zvýhodněni uživatelé některých vybraných operačních systémů, ke kterým je obraz paměti virtuálního stroje dodáván – má velikost cca 15 MB a název ve formátu factor-verze.image (ovšem není problém si tento obraz zazálohovat a vytvořit si v rámci tréninku obraz vlastní).

Vytvoření obrazu paměti není nijak složité, ovšem je i na výkonnějších počítačích zdlouhavé a na první pohled poněkud tajemné. Přeložené runtime prostředí (onen spustitelný soubor, který jsme vytvořili postupem popsaným v předchozí kapitole) totiž nemůže pracovat samostatně, ale musí mít k dispozici obraz paměti virtuálního stroje. Ten však prozatím nemáme – musíme ho nejdříve vytvořit. Vzhledem k tomu, že pro vytvoření obrazu paměti je zapotřebí plně fungující runtime, mohlo by se zdát, že jsme se ocitli v bludném kruhu.

Řešení je jednoduché – použít někým jiným vytvořený obraz paměti virtuálního stroje, který je určený pouze pro prvotní spuštění (boot) a následné vytvoření plnohodnotného, a také mnohem většího, obrazu paměti plnohodnotného virtuálního stroje. Bootovací obraz paměti pro různé platformy lze stáhnout z výše uvedené stránky http://www.fac­torcode.org/dow­nload.fhtml. Po jeho stažení se spustí runtime s parametrem -i, za který se zadá název bootovacího obrazu paměti, například:

tisnik@tisnik-ubuntu:~/factor/factor$ ./factor -i=boot.x86.32.image 

Po tomto „magickém“ příkazu by se měl začít generovat soubor s plnohodnotným obrazem paměti VM. Zabere to nějaký čas (podle výkonnosti počítače až několik minut) a výsledkem by měl být větší soubor s koncovkou .image, který již bude použit při všech dalších spuštěních interpreteru tohoto programovacího jazyka. Informace o průběhu generování je vypisována na standardní výstup (tučně je zvýrazněna informace o tom, jak se bude příště Factor spouštět):

*** Data GC (0 minor, 0 cards)
Loading P" resource:core/bootstrap/stage2.factor"
Loading P" resource:core/command-line/command-line.factor"
Cross-referencing...
Loading P" resource:core/listener/listener.factor"
Loading P" resource:core/none/none.factor"
.
.
.
Compiling roll
Compiling -roll
Compiling declare
Compiling not
Compiling tuple-class-eq?
Compiling array?
Compiling hashtable?
Compiling vector?
.
.
.
Compiling 10118 words...
Compile finished.

:errors - print 0 compiler errors.
:warnings - print 1006 compiler warnings.

8323 compiled words
650 symbol words
10177 words total
Bootstrapping is complete.
Now, you can run ./factor -i=factor.image
*** Code and data GC (1052 minor, 992695 cards)
*** Code heap compaction...
*** Saving ./factor.image... 
factor14

Vývojové prostředí Factoru spuštěné na Microsoft Windows XP

5. Základy programování ve Factoru

Programovací jazyk Factor je, podobně jako jazyk Forth či Joy založen na vyhodnocování výrazů, jejichž operandy jsou uloženy na zásobníku a operátory jsou zapisované v postfixové notaci (RPN). Pro zjednodušení můžeme Factor považovat za interpreter, který ze vstupu načte řetězec, rozloží ho na jednotlivá slova oddělená bílými znaky a postupně tato slova interpretuje. Číselné a řetězcové konstanty jsou zapisovány na zásobník, tj. jsou považovány za slova typu push constant.

Pro manipulaci s hodnotami uloženými na zásobníku je určeno několik slov (funkcí, operátorů), které jsou vypsány níže. V kulatých závorkách je zapsána poznámka, v tomto případě takzvaný stack effect, tj. symbolické vyjádření toho, jak je změněn obsah zásobníku. Bližší informace o tomto zápisu jsem uvedl v seriálu o programovacím jazyce Forth.

Odstranění položek ze zásobníku

drop ( x -- )
2drop ( x y -- )
3drop ( x y z -- )
nip ( x y -- y )
2nip ( x y z -- z )

Copie (duplikace) položek na zásobníku

dup ( x -- x x )
2dup ( x y -- x y x y )
3dup ( x y z -- x y z x y z )
dupd ( x y -- x x y )
over ( x y -- x y x )
pick ( x y z -- x y z x )
tuck ( x y -- y x y )

Změna pořadí položek uložených na zásobníku

swap ( x y -- y x )
swapd ( x y z -- y x z )
rot ( x y z -- y z x )
-rot ( x y z -- z x y )
roll ( x y z t -- y z t x )
-roll ( x y z t -- t x y z ) 

Factor dále podporuje všechny základní matematické operátory, které jsme si již popsali ve článku o programovacím jazyce Joy a také mnoho operátorů nových, které jsou v některých případech docela praktické. Jejich podrobnější popis bude uveden příště.

factor15

Hra Tetris napsaná ve Factoru je pěknou ukázkou refactoringu programového kódu

6. Factor, Forth, Joy a Lisp

Při pohledu na syntaxi a sémantiku Factoru se neubráníme srovnání s dalšími podobnými programovacími jazyky, zejména s Forthem, Joyem a Lispem. To, že se ve Factoru používá postfixová notace, je sice na první pohled zřejmý fakt, ovšem není až tak významný, jako jeho některé další vlastnosti. Programovací jazyky Factor a Joy se v mnohém podobají, Factor například také využívá kombinátory pro náhradu programových smyček a některých typů rekurzí. Podobný je také způsob citace programů a práce se sekvencemi, známými v jiných jazycích spíše pod názvem seznamy.

Factor má také hodně věcí společných se světoznámým Forthem Chucka Moorea; tyto jazyky jsou si paradoxně vzájemně více podobné než Joy a Forth. Týká se to mj. i zásobníku návratových adres (return stack), který je ve Forthu mj. použit pro uložení mezivýsledků při složitější manipulaci se zásobníkem operandů. Ve Factoru je implementován podobný zásobník nazvaný retain stack, který lze použít pro podobné účely; dokonce se při manipulaci s ním používají stejné operátory:

>r ( x -- )
r> ( -- x ) 

Lispem sdílí programovací jazyk Factor podobné názvy a částečně i syntaxi některých funkcí. Kromě „funkcionálních“ operátorů typu map či apply se to týká i zobecněného podmíněného příkazu, který má název cond (v Lispu i Factoru). Například výpis, zda je číslo kladné, záporné či nulové, lze ve Factoru implementovat následovně:

{
    { [ dup 0 > ] [ "positive" ] }
    { [ dup 0 < ] [ "negative" ] }
    { [ dup zero? ]  [ "zero" ] }
} cond 

Podoba s Lispem je zřejmá, až na postfixovou syntaxi místo syntaxe prefixové.

7. Literatura

  1. John Backus:
    Can programming by liberated from the von Neumann style?: A functional style and its algebra of programs,
    Source Communications of the ACM archive, 21(8):613–641, August 1978.
  2. H.B.Curry and R.Feys:
    Combinatory Logic,
    North-Holland Publishing Company, 1958.
  3. Paul Hudak et al.:
    Report on the programming language Haskell: a non-strict, purely functional language version 1.2.,
    SIGPLAN Not., 27(5):1–164, 1992. ISSN 0362–1340.
  4. Charles Moore:
    Forth: a new way to program a mini-computer
    Astronomy and Astrophysics Supplement, (15), 1974.
  5. Robert Morris and Lorinda Cherry:
    Dc – an interactive desk calculator
    Technical report, AT&T Bell Laboratories
  6. Jaanus P.:
    Typing tools for typeless stack languages
    In Proceedings from the 23rd EuroForth Conference, pages 40–46, 2006.
  7. Manfred von Thun.:
    Joy: Forth's functional cousin
    In Proceedings from the 17th EuroForth Conference, 2001.

root_podpora

8. Odkazy na Internetu

  1. Factor programming language:
    http://factor­code.org/
  2. Factor documentation:
    http://factor­code.org/respon­der/help/
  3. Factor FAQ:
    http://factor­code.org/faq.fhtml
  4. Factor: a practical stack language (blogpost):
    http://factor-language.blog­spot.com/
  5. Factor-talk --:
    https://lists­.sourceforge.net/lis­ts/listinfo/fac­tor-talk
  6. Factor-talk – archive:
    http://source­forge.net/mai­larchive/forum­.php?forum_na­me=factor-talk
  7. Wikipedia: Factor (programming language):
    http://en.wiki­pedia.org/wiki/Fac­tor_(programmin­g_language)
  8. Wikipedia: Slava Pestov:
    http://en.wiki­pedia.org/wiki/Sla­va_Pestov
  9. Pastebin (collaborative development over IRC):
    http://paste.fac­torcode.org/
  10. planet-factor:
    http://planet­.factorcode.or­g/
  11. Slava Pestov's retro HTML 1.0 home page:
    http://factor­code.org/slava/
  12. concatenative (IRC kanál o podobných programovacích jazycích):
    http://www.ir­cbrowse.com/cda­tes.html?chan­nel=concatena­tive
  13. Vocabulary index (dnes již docela rozsáhlé):
    http://factor­code.org/respon­der/help/show-help?topic=vocab-index
  14. Factor Magic:
    http://fun-factor.blogspot­.com/2007/03/fac­tor-magic.html
  15. Factor Magic, Part 2:
    http://fun-factor.blogspot­.com/2007/04/fac­tor-magic-part-2.html
  16. http://www.la­trobe.edu.au/phi­losophy/phimvt/jo­y.html – Joy Programming Language, stránka s rozcestníkem informací o programovacím jazyku Joy
  17. http://www.la­trobe.edu.au/phi­losophy/phimvt/jo­y/j01tut.html – Tutorial on Joy
  18. http://www.la­trobe.edu.au/phi­losophy/phimvt/jo­y/j06prg.html – Programming in Joy
  19. http://www.la­trobe.edu.au/phi­losophy/phimvt/jo­y/synops.html – Synopsis of the language Joy
  20. http://www.la­trobe.edu.au/phi­losophy/phimvt/jo­y/faq.html – Frequently Asked Questions about Joy, obsahuje i částečné porovnání s dalšími programovacími jazyky založenými na zásobníkovém kódu

9. Obsah následující části tohoto článku

Ve druhé části článku o netradičním programovacím jazyce Factor se zaměřím na popis integrovaného vývojového prostředí, které se v některých ohledech dosti podstatným způsobem odlišuje od dnes používaných IDE. Také si řekneme, pomocí jakých postupů je možné ve Factoru pracovat s různými datovými typy, se kterými jsme se v Joyi nesetkali, nebo které jsou řešeny odlišným (například obecnějším či užitečnějším) způsobem.

Byl pro vás článek přínosný?

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.