diff --git a/README.md b/README.md index d67f878..3af90a8 100644 --- a/README.md +++ b/README.md @@ -6,19 +6,15 @@ Tampiorama provides working, annotated examples and documentation to help you ex ## Quickstart (Docker) -The easiest way to try Tampio, no manual `libvoikko` setup required: +The easiest way to try Tampio, no manual `libvoikko` setup required. + +Compile all examples to HTML (the `.html` files are not committed — they're generated from the `.itp` sources): ```sh -docker compose run --rm tampio +make ``` -This drops you into a shell with `tampio` available. Compile an example to HTML: - -```sh -tampio -i -p examples/basics/hello.itp > examples/basics/hello.html -``` - -Then serve it locally and open it in your browser: +Then serve locally and open in your browser: ```sh python3 -m http.server 9994 --directory examples/basics diff --git a/docs/cheatsheet.md b/docs/cheatsheet.md new file mode 100644 index 0000000..fb269f3 --- /dev/null +++ b/docs/cheatsheet.md @@ -0,0 +1,184 @@ +# Tampio Cheatsheet + +Tampio uses Finnish grammatical cases instead of syntax tokens like `(`, `)`, `,`, `.`. +The case of a word tells the compiler its role — parameter, argument, target, etc. + +## Finnish Cases in Tampio + +| Case (Finnish) | Suffix | Role in Tampio | Example | +|---|---|---|---| +| Nominatiivi | — | Function name; return value; variable base form | `kertoma`, `pieni luku` | +| Genetiivi | `-n` | Function parameter (in definitions and calls); field access | `pienen luvun kertoma` | +| Illatiivi | `-in/-iin/-aan/-ään` | Addend (`lisättynä`); remainder arg (`rajattuna`); assignment target (`luetaan luku`) | `lisättynä kaniin` | +| Adessiivi | `-lla/-llä` | Multiplicand (`kerrottuna`); subtrahend (`vähennettynä`); divisor (`jaettuna`); increment amount | `kerrottuna kertomalla` | +| Translatiivi | `-ksi` | Assignment lvalue (`asetetaan`) | `kuvaukseksi asetetaan` | +| Partitiivi | `-a/-ä/-ta/-tä` | Increment lvalue (`kasvatetaan`); some quantifiers | `laskuria kasvatetaan` | +| Essiivi | `-na/-nä` | Two-parameter function name; type conversion | `merkkijonona`, `kerrottuna` | + +## Arithmetic Operators + +These are essive functions — the first operand is the subject, the second follows the operator in the case shown. + +| Operator | Second arg case | JavaScript | Example | +|---|---|---|---| +| `lisättynä` | illative | `+` | `x lisättynä y:hin` | +| `ynnättynä` | illative | `+` | `x ynnättynä y:hin` | +| `kasvatettuna` | adessive | `+` | `x kasvatettuna y:llä` | +| `vähennettynä` | adessive | `-` | `x vähennettynä y:llä` | +| `kerrottuna` | adessive | `*` | `x kerrottuna y:llä` | +| `jaettuna` | adessive | `/` | `x jaettuna y:llä` | +| `rajattuna` | illative | `%` | `x rajattuna y:hin` | +| `yhdistettynä` | illative | `.concat` | `x yhdistettynä y:hin` | + +Operator chaining is controlled by list separators (see Lists below): + +```tampio +x jaettuna y:llä vähennettynä z:lla lisättynä w:hen # x/(y-(z+w)) +x jaettuna y:llä, vähennettynä z:lla ja lisättynä w:hen # ((x/y)-z)+w +``` + +## Function Definition + +```tampio +[parameter/genitive] [function name] on [expression]. +``` + +The parameter must be two words: an adjective + class name. Use `se` to refer to it in the body. + +```tampio +Pienen luvun kertoma on + riippuen siitä, onko se pienempi tai yhtä suuri kuin yksi, + joko yksi + tai pieni luku kerrottuna pienen luvun edeltäjän kertomalla. +``` + +Or with unnamed parameter (`se` = `this`): + +```tampio +Luvun edeltäjä on se vähennettynä yhdellä. +``` + +## Function Call + +```tampio +[argument/genitive] [function name] +``` + +```tampio +viiden kertoma # factorial(5) +neljän neliöjuuri # sqrt(4) +``` + +## Ternary Expression + +```tampio +riippuen siitä, [onko/eikö] [expr] [operator] [expr], joko [a] tai [b] +``` + +```tampio +riippuen siitä, onko se pienempi tai yhtä suuri kuin yksi, joko yksi tai ... +``` + +## Comparison Operators + +Used in ternaries and `jos` conditions. + +| Tampio | JavaScript | +|---|---| +| `on` (empty) | `==` | +| `on yhtä suuri kuin` | `==` | +| `on sama kuin` | `===` | +| `on erisuuri kuin` | `!=` | +| `on pienempi kuin` | `<` | +| `on suurempi kuin` | `>` | +| `on pienempi tai yhtä suuri kuin` | `<=` | +| `on enintään` | `<=` | +| `on suurempi tai yhtä suuri kuin` | `>=` | +| `on vähintään` | `>=` | + +Negate with `ei ole`: `se ei ole nolla` = `this !== 0`. + +## Variable Declaration + +```tampio +Olkoon [name] uusi [type], jonka [field] on [value]. +Olkoon [name] [value]. +``` + +```tampio +Olkoon pieni muuttuja uusi muuttuja, jonka arvo on nolla. +``` + +## Method Definition (Procedures) + +```tampio +Kun [self] [verb] [parameters], + [statement], + [statement] +ja [last statement]. +``` + +```tampio +Kun nykyinen sivu avautuu, + pieneen muuttujaan luetaan luku +ja nykyinen sivu näyttää pienen muuttujan arvon kertoman. +``` + +## If Statement + +```tampio +, jos [condition], niin [statement list] +, jos taas [condition], niin ... # else if +``` + +```tampio +jos listan koko ei ole nolla, niin + listan ensimmäinen alkio käsitellään +ja listan häntää iteroidaan. +``` + +## Lists (Blocks) + +Commas and `ja` replace `{` / `}`: + +| Syntax | Meaning | +|---|---| +| `[a], [b], [c] ja [d]` | List of four items | +| `[a] eikä muuta` | List of one item | +| `[a].` | List of one item (at end of definition) | + +## Class Definition + +```tampio +[class name/adessive] on [field list]. +``` + +```tampio +Vektorilla on komponentit. # class vektori { komponentit = [] } +Työntekijä on henkilö, jolla on työnantaja. # class Tyontekija extends Henkilö +``` + +## Assignment + +```tampio +[lvalue/translative] asetetaan [expression] # lvalue = expression +[lvalue/partitive] kasvatetaan [expression/adessive] # lvalue += expression +``` + +```tampio +kivan kaverin kuvaukseksi asetetaan teksti "Hän on kiva" +loistavaa laskuria kasvatetaan yhdellä +``` + +## Common Built-ins + +| Tampio | JavaScript | Notes | +|---|---|---| +| `nykyinen sivu` | `document` | HTMLDocument | +| `nykyinen sivu näyttää X` | `document.write(X)` | | +| `teksti "..."` | `"..."` | String literal | +| `lause "..."` | `"..."` | String literal (alternative) | +| `muuttujaan luetaan luku` | `muuttuja.arvo = parseInt(prompt(...))` | Read number | +| `X näytetään käyttäjälle` | `alert(X)` | Browser alert | +| `se` | `this` | Self / first parameter | +| `nolla`…`kymmenen` | `0`…`10` | Number literals | diff --git a/docs/install.md b/docs/install.md new file mode 100644 index 0000000..b8b6d2b --- /dev/null +++ b/docs/install.md @@ -0,0 +1,87 @@ +# Local Setup (without Docker) + +If you prefer not to use Docker, you can install Tampio's dependencies natively. The tricky part is libvoikko and the Finnish morphological dictionary — the Docker path handles all of this for you, so that's recommended if you just want to try the examples. + +## Prerequisites + +- Python 3.8+ +- [libvoikko](https://voikko.puimula.org/) — Finnish morphology library +- `python3-libvoikko` — Python bindings for libvoikko +- fi-x-morpho dictionary — the specific Finnish dictionary Tampio requires + +## Ubuntu / Debian + +```sh +# Install libvoikko, Python bindings, and the base voikko-fi package +sudo apt-get update +sudo apt-get install -y libvoikko-dev voikko-fi python3 python3-libvoikko curl unzip + +# Download the fi-x-morpho dictionary (not available via apt) +# This installs it system-wide; alternatively unzip to ~/.voikko/ +curl -fsSL https://www.puimula.org/htp/testing/voikko-snapshot-v5/dict-morpho.zip \ + -o /tmp/dict-morpho.zip +sudo unzip /tmp/dict-morpho.zip -d /usr/lib/voikko +rm /tmp/dict-morpho.zip +``` + +> **Note:** The `voikko-fi` apt package only ships `mor-standard`. Tampio requires the `fi-x-morpho` variant, which is why the manual download step is needed. + +## macOS + +Install voikko via Homebrew: + +```sh +brew install libvoikko +pip3 install libvoikko +``` + +Then download the dictionary manually: + +```sh +mkdir -p ~/.voikko +curl -fsSL https://www.puimula.org/htp/testing/voikko-snapshot-v5/dict-morpho.zip \ + -o /tmp/dict-morpho.zip +unzip /tmp/dict-morpho.zip -d ~/.voikko +rm /tmp/dict-morpho.zip +``` + +> macOS compatibility is not officially tested — if you run into issues, Docker is the reliable fallback. + +## Install Tampio + +Tampio is not on PyPI. Clone it directly from GitHub: + +```sh +git clone https://github.com/fergusq/tampio.git +``` + +Optionally add a wrapper so you can call `tampio` from anywhere: + +```sh +echo '#!/bin/sh\npython3 /path/to/tampio/tampio.py "$@"' > /usr/local/bin/tampio +chmod +x /usr/local/bin/tampio +``` + +## Verify + +```sh +echo 'Kun nykyinen sivu avautuu, teksti "Hei!" näytetään käyttäjälle.' \ + | python3 tampio/tampio.py /dev/stdin +``` + +If you see HTML output, the setup is working. + +## Build the Examples + +From the Tampiorama root: + +```sh +# Override the Docker command with a direct tampio call +make TAMPIO="python3 /path/to/tampio/tampio.py -i -p" +``` + +Or compile manually: + +```sh +python3 /path/to/tampio/tampio.py -i -p examples/basics/hello.itp > examples/basics/hello.html +``` diff --git a/docs/vs-javascript.md b/docs/vs-javascript.md new file mode 100644 index 0000000..d22ae79 --- /dev/null +++ b/docs/vs-javascript.md @@ -0,0 +1,196 @@ +# Tampio vs JavaScript + +Side-by-side comparisons. Every Tampio program compiles to JavaScript — these show what that translation looks like. + +## Hello World + +**Tampio** +```tampio +Kun nykyinen sivu avautuu, + teksti "Hei maailma!" näytetään käyttäjälle. +``` + +**JavaScript** +```js +document.avautua = function() { + alert("Hei maailma!"); +}; +document.avautua(); +``` + +--- + +## Function Definition + +**Tampio** +```tampio +Pienen luvun kertoma on + riippuen siitä, onko se pienempi tai yhtä suuri kuin yksi, + joko yksi + tai pieni luku kerrottuna pienen luvun edeltäjän kertomalla. + +Luvun edeltäjä on se vähennettynä yhdellä. +``` + +**JavaScript** +```js +Number.prototype.f_kertoma = function() { + var pieni_luku = this; + return (this <= 1) ? 1 : pieni_luku * pieni_luku.f_edeltäjä().f_kertoma(); +}; + +Number.prototype.f_edeltäjä = function() { + return this - 1; +}; +``` + +The parameter `pieni luku` ("small number") becomes the variable name in the compiled JS. `se` compiles to `this`. + +--- + +## Variable Declaration + +**Tampio** +```tampio +Olkoon pieni muuttuja uusi muuttuja, jonka arvo on nolla. +``` + +**JavaScript** +```js +var pieni_muuttuja = new muuttuja({ arvo: 0 }); +``` + +--- + +## Class Definition + +**Tampio** +```tampio +Vektorilla on komponentit. +``` + +**JavaScript** +```js +function vektori(vals) { + if ("komponentit" in vals) this.komponentit = vals["komponentit"]; + else this.komponentit = []; +} +``` + +Fields are constructor parameters. Plural fields become arrays, singular fields become single values. + +### Subclass + +**Tampio** +```tampio +Työntekijä on henkilö, jolla on työnantaja. +``` + +**JavaScript** +```js +function tyontekija(vals) { + henkilö.call(this, vals); + if ("työnantaja" in vals) this.työnantaja = vals["työnantaja"]; +} +tyontekija.prototype = Object.create(henkilö.prototype); +``` + +--- + +## Method Definition + +**Tampio** +```tampio +Kun nykyinen sivu avautuu, + pieneen muuttujaan luetaan luku +ja nykyinen sivu näyttää pienen muuttujan arvon kertoman. +``` + +**JavaScript** +```js +HTMLDocument.prototype.avautua = function() { + pieni_muuttuja.lukea_luku(); + this.write(pieni_muuttuja.f_arvo().f_kertoma()); +}; +``` + +`Kun` = method definition. The self object (`nykyinen sivu`) becomes `this`. Multiple statements separated by commas compile to sequential calls; `ja` marks the last one. + +--- + +## If Statement + +**Tampio** +```tampio +jos lyhyen vektorin dimensio ei ole nolla, niin + nykyinen sivu näyttää lyhyen vektorin ensimmäisen komponentin +ja lyhyen vektorin häntä painetaan nykyiselle sivulle. +``` + +**JavaScript** +```js +if (lyhyt_vektori.f_dimensio() !== 0) { + nykyinen_sivu.näyttää(lyhyt_vektori.f_ensimmäinen_komponentti()); + lyhyt_vektori.f_häntä().painetaan(nykyinen_sivu); +} +``` + +--- + +## Arithmetic + +**Tampio** +```tampio +pieni luku kerrottuna pienen luvun edeltäjän kertomalla +``` + +**JavaScript** +```js +pieni_luku * pieni_luku.f_edeltäjä().f_kertoma() +``` + +| Tampio | JS | Second arg case | +|---|---|---| +| `x lisättynä y:hin` | `x + y` | illative | +| `x vähennettynä y:llä` | `x - y` | adessive | +| `x kerrottuna y:llä` | `x * y` | adessive | +| `x jaettuna y:llä` | `x / y` | adessive | +| `x rajattuna y:hin` | `x % y` | illative | + +--- + +## Field Access + +Field access looks identical to a function call — both use genitive. + +**Tampio** +```tampio +pienen muuttujan arvo # field access +pienen luvun kertoma # function call +``` + +**JavaScript** +```js +pieni_muuttuja.arvo // field access +pieni_luku.f_kertoma() // function call (note the f_ prefix) +``` + +The compiler adds an `f_` prefix to function calls to distinguish them from raw field accesses. + +--- + +## Output + +**Tampio** +```tampio +nykyinen sivu näyttää tekstin "Tulos: " +nykyinen sivu näyttää pienen luvun kertoman +teksti "Virhe!" näytetään käyttäjälle +``` + +**JavaScript** +```js +document.write("Tulos: "); +document.write(pieni_luku.f_kertoma()); +alert("Virhe!"); +``` diff --git a/examples/basics/syntax.css b/examples/basics/syntax.css index 604a4cb..a441d24 100644 --- a/examples/basics/syntax.css +++ b/examples/basics/syntax.css @@ -1,21 +1,12 @@ -/* - * Tampio Syntax Highlighting — Typography & Styling - * - * This stylesheet defines the visual presentation of Tampio source code. - */ - -/* ===== TYPE STYLES ===== */ span.type { font-variant: small-caps; font-size: large; } -/* ===== KEYWORDS ===== */ span.keyword { font-weight: bold; } -/* ===== VARIABLES & FIELDS ===== */ span.field { text-decoration: underline dotted; } @@ -31,12 +22,10 @@ span.variable-or-field { font-size: large; } -/* ===== FUNCTIONS ===== */ span.function { font-style: italic; } -/* ===== OPERATORS ===== */ span.operator { text-decoration: underline dotted; font-weight: bold; @@ -47,17 +36,19 @@ span.conditional-operator { color: #622; } -/* ===== LITERALS ===== */ span.literal { color: #622; } -/* ===== COMMENTS ===== */ span.comment-inline, span.block-comment-inline { color: #226; font-size: small; } +ul:not(.syntax-root) { + list-style: disc; +} + span.comment-global { color: black; font-size: 1.5em; @@ -68,11 +59,6 @@ span.block-comment-global { color: #226; } -/* ===== LIST STYLES ===== */ -ul:not(.syntax-root) { - list-style: disc; -} - ul.syntax-root > li { margin-top: 10px; margin-bottom: 10px; @@ -80,4 +66,4 @@ ul.syntax-root > li { ul.syntax-root { list-style: none; -} \ No newline at end of file +}