OPIS / Pollan
CODE

OPIS / Pollan

Kompletny język programowania z polską warstwą słów kluczowych i deterministyczną semantyką.

PROJECT
CODE-044
JĘZYK IMPLEMENTACJI
RUST · 17 CRATE’ÓW
FUNKCJE WBUDOWANE
167
TESTY
~294 · 43 ADR
DOJRZAŁOŚĆ
1.0 (POZIOM C)
STATUS
UKOŃCZONY
DATA
19 sierpnia 2026

Uniwersalny język o czytelnej, opisowej składni i formalnej semantyce. Nie zależy od modeli językowych — każda poprawna konstrukcja ma dokładnie określone znaczenie; AI może generować kod, ale to kompilator nadaje mu sens. Działający potok: interpreter oraz kompilacja natywna przez OIR → C → clang.

OPIS / POLLANJĘZYK PROGRAMOWANIA · INTERPRETER + KOMPILATOR
DOJRZAŁOŚĆ 1.0
WEJŚCIEPRZETWARZANIEKONTROLADECYZJANARZĘDZIEWYJŚCIE01KOD .POLsłowa polskie02LEKSER03PARSER04AST05KONTROLA TYPÓWgeneryki06ŚCIEŻKAinterpreter / natywna07INTERPRETERwyrocznia08OIR → C09CLANG10PROGRAM
17 CRATE’ÓW · 167 FUNKCJI WBUDOWANYCH · 43 ADR · ~294 TESTY · JĘZYK NIE ZALEŻY OD LLM

Jak wygląda program w OPIS-ie

Najkrótszy sensowny program pokazuje trzy rzeczy naraz: deklarację zmiennej, konwersję typu i wypisanie wyniku. Składnia jest opisowa — słowa kluczowe to polskie słowa, a nie tłumaczenia angielskich skrótów.

program "Pierwszy program"

zmienna wiek = 20
napisz "Mam " + tekst(wiek) + " lat"

koniec programu

Zwróć uwagę na tekst(wiek). Funkcja napisz oczekuje tekstu, a wiek jest liczbą — język nie robi cichej konwersji, bo cicha konwersja jest źródłem błędów, których nie widać w kodzie. To decyzja projektowa, nie niedopatrzenie.

Typy i deklaracje

OPIS ma pięć typów podstawowych: liczba, liczba_calkowita, tekst, logiczna i nic. Typ można podać jawnie albo pozwolić kompilatorowi go wywnioskować z wartości początkowej.

zmienna licznik = 0                      # wywnioskowany: liczba_calkowita
zmienna cena jako liczba = 9.99          # jawny
stala VAT = 0.23                         # stała — nie da się zmienić

ustaw licznik na licznik + 1             # przypisanie po deklaracji

Rozdzielenie zmienna (tworzę) od ustaw … na (zmieniam) jest celowe. W większości języków obie operacje wyglądają identycznie, przez co literówka w nazwie tworzy nową zmienną zamiast zgłosić błąd. Tutaj ustaw na nieistniejącej nazwie jest błędem kompilacji.

Sterowanie przepływem

jezeli n <= 1 wtedy
    zwroc 1
inaczej
    zwroc n * silnia(n - 1)
koniec jezeli

dla i od 1 do 100 wykonuj
    ustaw suma na suma + i
koniec dla

dopoki licznik < 10 wykonuj
    ustaw licznik na licznik + 1
    jezeli licznik == 5 wtedy
        kontynuuj
    koniec jezeli
koniec dopoki

dla kazdego element w lista wykonuj
    napisz tekst(element)
koniec dla

Każdy blok domyka się jawnie: koniec jezeli, koniec dla, koniec dopoki. Jest to wielomówne, ale usuwa całą klasę pomyłek z zagnieżdżaniem — i czyni kod czytelnym dla kogoś, kto nigdy wcześniej nie programował.

Funkcje i procedury

Funkcja zwraca wartość i musi zadeklarować jej typ. Procedura nie zwraca nic. To rozróżnienie jest w składni, a nie w konwencji nazewniczej.

funkcja silnia(n jako liczba_calkowita) zwraca liczba_calkowita
    jezeli n <= 1 wtedy
        zwroc 1
    koniec jezeli
    zwroc n * silnia(n - 1)
koniec funkcji

funkcja brutto(netto jako liczba) zwraca liczba
    zwroc netto * (1.0 + VAT)
koniec funkcji

napisz "silnia(10) = " + tekst(silnia(10))
napisz "brutto(100) = " + tekst(brutto(100.0))

Struktury, wyliczenia i dopasowanie wzorców

Tu widać, że OPIS nie jest językiem zabawkowym. Wyliczenia niosą wartości, a wybierz/gdy wymusza wyczerpujące dopasowanie — pominięcie przypadku jest błędem kompilacji, nie niespodzianką w czasie działania.

struktura Punkt
    x jako liczba_calkowita
    y jako liczba_calkowita
koniec struktury

wyliczenie Wynik
    Sukces(wartosc)
    Blad(powod)
koniec wyliczenia

funkcja podziel(a jako liczba_calkowita, b jako liczba_calkowita) zwraca Wynik
    jezeli b == 0 wtedy
        zwroc Wynik.Blad("dzielenie przez zero")
    koniec jezeli
    zwroc Wynik.Sukces(a / b)
koniec funkcji

zmienna p = Punkt(3, 4)
ustaw p.x na 10
napisz "suma pol: " + tekst(p.x + p.y)

wybierz podziel(20, 4)
    gdy Sukces(wart)
        napisz "ok: " + tekst(wart)
    gdy Blad(powod)
        napisz "blad: " + powod
koniec wybierz

To jest ten sam wzorzec, który w językach funkcyjnych nazywa się typem wynikowym. Błąd nie jest wyjątkiem lecącym w górę stosu — jest wartością, którą trzeba obsłużyć, żeby program się skompilował.

Obsługa błędów wykonania

sprobuj
    zmienna dane = wczytaj_plik("konfiguracja.json")
    zmienna config = json_parsuj(dane)
blad e
    napisz "nie udalo sie wczytac: " + e
wreszcie
    napisz "koniec proby"
koniec sprobuj

Typy złożone i funkcje wyższego rzędu

zmienna liczby jako lista<liczba_calkowita> = [1, 2, 3, 4, 5]
zmienna ceny jako slownik<tekst, liczba> = {"chleb": 4.50, "mleko": 3.20}

zmienna podwojone = mapuj(liczby, funkcja(x) zwraca liczba_calkowita
    zwroc x * 2
koniec funkcji)

zmienna parzyste = filtruj(liczby, funkcja(x) zwraca logiczna
    zwroc x % 2 == 0
koniec funkcji)

zmienna suma = redukuj(liczby, 0, funkcja(a, b) zwraca liczba_calkowita
    zwroc a + b
koniec funkcji)

Generyki są egzekwowane. lista<liczba_calkowita> nie przyjmie tekstu, a kompilator powie o tym w miejscu przypisania, nie przy pierwszym użyciu.

Grafika i pętla gry

Programy okienkowe uruchamia się innym poleceniem (opis okno plik.pol) i piszą się wokół dwóch procedur: krok liczy stan, rysuj go pokazuje.

program "Odbijajaca sie pilka"

zmienna x = 100.0
zmienna y = 100.0
zmienna dx = 3.0
zmienna dy = 2.0

procedura krok(czas jako liczba)
    ustaw x na x + dx
    ustaw y na y + dy
    jezeli x < 20.0 lub x > 780.0 wtedy
        ustaw dx na -dx
    koniec jezeli
    jezeli y < 20.0 lub y > 580.0 wtedy
        ustaw dy na -dy
    koniec jezeli
koniec procedury

procedura rysuj()
    tlo(17, 19, 21)
    kolor(82, 210, 115)
    kolo(x, y, 20.0)
    kolor(241, 235, 221)
    napis("OPIS", 20.0, 30.0)
koniec procedury

koniec programu

Dostępne są prymitywy rysowania (prostokąt, koło, elipsa, linia, łuk, trójkąt, wielokąt, gradient, piksel), gładkie fonty TTF w trzech odmianach, obrazy, obsługa myszy i klawiatury, widżety oraz dźwięk z silnikiem MML. Na tej warstwie powstały działające przykłady: tetris, szachy z grafiką, symulacje i arkusz kalkulacyjny.

Dwie ścieżki wykonania

Ten sam plik uruchamia się na dwa sposoby i to jest sedno architektury projektu:

# interpreter — wyrocznia, definiuje znaczenie
cargo run -p opis-cli --bin opis -- run examples/dane.pol

# kompilacja natywna — OIR → C → clang
cargo run -p opis-cli --bin opis -- buduj examples/dane.pol

# program okienkowy
cargo run --release -p opis-cli --bin opis -- okno examples/tetris.pol

# debugger z punktami przerwania
cargo run -p opis-cli --bin opis -- debuguj examples/dane.pol

Interpreter jest odniesieniem: jeśli wersja skompilowana zachowuje się inaczej, błąd jest w kompilatorze albo — częściej — w specyfikacji, która czegoś nie dopowiada. Ta para wyłapała większość niejednoznaczności w semantyce języka.

Narzędzia wokół języka

Sam kompilator nie wystarczy, żeby ktokolwiek chciał w danym języku pisać. Dlatego powstały: debugger z krokowaniem i podglądem zmiennych, formatter (opis fmt), serwer języka LSP (opisd) dający podpowiedzi i diagnostykę w edytorze, system modułów (uzyj) oraz kompilacja do samodzielnego pliku wykonywalnego.

Dokumentacja liczy 61 rozdziałów składanych do jednego PDF-a — od pierwszego programu po referencję wszystkich 167 funkcji wbudowanych, listę słów zarezerwowanych, katalog błędów i ściągę składniową.

01

PROBLEM

Nauka programowania po polsku kończy się zwykle na pseudokodzie w podręczniku. Realne języki mają angielskie słowa kluczowe, a próby ich tłumaczenia dają zabawki bez bibliotek, bez narzędzi i bez możliwości zrobienia czegokolwiek poza ćwiczeniem.

Drugi problem jest świeższy: język, którego semantykę „rozumie” dopiero model językowy, nie jest językiem programowania — jest promptem.

02

POMYSŁ

Zbudować pełny język z polskimi słowami kluczowymi i formalną, deterministyczną semantyką, a do tego komplet narzędzi, których oczekuje się od poważnego języka: bibliotekę standardową, debugger, formatter, serwer LSP, moduły i kompilację natywną.

03

PROJEKT

Rdzeń obejmuje zmienne i stałe, typy podstawowe, warunki, pętle dopoki, dla i dla kazdego, funkcje, procedury i rekurencję. Typy złożone to listy i słowniki z egzekwowanymi generykami, struktury, metody z UFCS, dziedziczenie, cechy, wyliczenia oraz wyczerpujące dopasowanie wzorców przez wybierz/gdy.

Obsługa błędów ma pełną konstrukcję sprobuj … blad … wreszcie, łapiącą również błędy wykonania. Biblioteka standardowa pokrywa matematykę, teksty, wejście z konsoli, pliki, JSON, datę i czas oraz sieć HTTP.

Osobną, dużą częścią jest grafika: okno, pętla gry, prymitywy rysowania, gładkie fonty TTF, obrazy, mysz, klawiatura, widżety oraz dźwięk z silnikiem MML.

Narzędzia dopełniają obraz: debugger z punktami przerwania i podglądem zmiennych, kompilacja natywna, system modułów, serwer języka LSP oraz formatter. To ta warstwa oddziela język od ćwiczenia — bez debuggera i podpowiedzi w edytorze nikt nie napisze w nim niczego dłuższego niż przykład z podręcznika.

04

REALIZACJA

Implementacja liczy siedemnaście crate’ów w Ruście, 167 funkcji wbudowanych, 56 przykładów i 43 decyzje architektoniczne zapisane jako ADR. Bramka jakości obejmuje formatowanie, clippy i około 294 testy.

Kompilacja natywna idzie ścieżką OIR → C → clang, a obok działa interpreter pełniący rolę wyroczni: to on definiuje, co program ma robić, i względem niego weryfikowana jest wersja kompilowana.

05

EFEKT

W przykładach leżą działające programy: szachy z grafiką, tetris, arkusz kalkulacyjny, symulacje i przykład uczenia maszynowego. Powstała też pełna instrukcja — 61 rozdziałów w manual_src, składanych do PDF-a.

Deklaracja „język nie zależy od LLM” jest tu decyzją projektową, nie deklaracją ideową. Model może wygenerować kod w OPIS-ie, ale znaczenie tego kodu wynika ze specyfikacji i kompilatora — jest sprawdzalne, powtarzalne i możliwe do zdebugowania. To różnica między językiem programowania a interfejsem konwersacyjnym.

06

GALERIA

04 ZDJĘĆ
  • OPIS — pulpit systemowy napisany w całości w tym języku · zrzut z projektu

  • Pollan — szachy napisane w języku OPIS · zrzut z projektu

  • Pollan — grafika 2D generowana z kodu · zrzut z projektu

  • Pollan — okładka instrukcji języka · zrzut z projektu

07

WNIOSKI

Interpreter jako wyrocznia okazał się najlepszą decyzją w projekcie. Przy dwóch niezależnych ścieżkach wykonania każda rozbieżność wskazuje miejsce, w którym specyfikacja jest niedopowiedziana — a nie miejsce, w którym trzeba zgadywać, która wersja ma rację.