-
Notifications
You must be signed in to change notification settings - Fork 19
Tutorial
Hello! Kip is an experimental programming language that combines Turkish grammar rules with a type system. Case endings, vowel harmony, and other Turkish morphological features are an integral part of Kip's type-checking process.
This project explores the interaction between programming language design and linguistics. It is not intended for everyday production use; it is a playground for experimentation, tinkering, and discussion.
Note
Kip is experimental; syntax and behavior may change from version to version.
- Core Concepts
- Data Types
- Constant Definitions
- Function Definitions
- Pattern Matching
- Function Calls
- Built-in Types
- Strings
- Effectful Functions
- Modules and Loading
- Polymorphic Types
- Ambiguities and Disambiguation
- Syntax Summary
- Compiler Cache
- Standard Library
- Important Notes
In Kip, function arguments are distinguished by Turkish case endings. This means the order is less important than the case carried by the suffix.
| Case | Turkish Name | Suffix | Example |
|---|---|---|---|
| Nominative | Yalın hal | (none) | defter |
| Accusative | -i hali | -i, -ı, -u, -ü | sayıyı |
| Dative | -e hali | -e, -a | sayıya |
| Locative | -de hali | -de, -da, -te, -ta | listede |
| Ablative | -den hali | -den, -dan, -ten, -tan | listeden |
| Genitive | Tamlayan eki | -in, -ın, -un, -ün | sayının |
| Instrumental | -le eki | -le, -la, ile | sayıyla |
| Possessive (3s) | Tamlanan eki | -i, -ı, -u, -ü, -si, -sı | dosyası |
| Conditional | Şart kipi | -sa, -se | defterse |
Kip uses the Turkish morphological analyzer TRmorph to automatically recognize the correct form of suffixes. For example, the different genitive suffixes in sayının and listesinin (-nın vs -sinin) represent the same grammatical case. This keeps the written form natural.
Kip does not use names with spaces; instead, combine words with a hyphen (-):
tam-sayı
ondalık-sayı
You can define enum-like types as follows, yielding short and readable definitions:
Bir doğruluk ya doğru ya da yanlış olabilir.
Here, doğruluk is the type name, and doğru and yanlış are constructors (data constructors).
The rule is simple:
- Every constructor starts with
ya - The last constructor may start with
ya da(optional) - The definition ends with
olabilir.
Bir gün
ya pazartesi
ya salı
ya çarşamba
ya perşembe
ya cuma
ya cumartesi
ya pazar
olabilir.
Types can refer to themselves; this lets us model trees, lists, and similar structures. It may look long at first, but the structure is quite regular.
Bir (öğe listesi)
ya boş
ya da bir öğenin bir (öğe listesine) eki
olabilir.
In this definition:
-
boş: a constructor with no arguments (an empty leaf) -
ek: a constructor that takes anöğeand anöğe listesi
In 1'in boşa eki:
-
boşa: the argument type, in the dative case (-a) -
eki: the constructor name, with the possessive suffix (-i)
The empty type (Haskell's Void) is defined like this:
Bir boşluk var olamaz.
Define constants by writing the name on the left and the value with a copula on the right:
başlangıç-günü, pazartesidir.
devam-günü, salıdır.
orta-gün, çarşambadır.
Things to note:
- The name comes first:
başlangıç-günü - The value is written with a copula suffix:
pazartesi**dir** - The syntax still reads like a Turkish sentence: "Başlangıç-günü, pazartesidir."
Turkish consonant softening rules apply; Kip accepts them naturally:
(bu ağaca) bakmak,
durmaktır.
ağaç + -a -> ağaca (ç -> c softening)
(argüman1) (argüman2) fonksiyon-adı,
gövde.
(bu doğruluğun) tersi,
bu doğruysa, yanlış;
yanlışsa, doğrudur.
In this definition:
-
(bu doğruluğun): the argument is bound tobu(any name works) -
tersi: the function name (takes the possessive suffix) - Body: pattern matching
(bu öğe listesiyle) (şu öğe listesinin) birleşimi,
bu boşsa,
şu;
ilkin devama ekiyse,
ilkin (devamla şunun birleşimine) ekidir.
In this definition:
- The first argument takes the
-lesuffix:bu öğe listesiyle - The second argument takes the genitive suffix:
şu öğe listesinin - The function name takes the possessive suffix:
birleşimi
Pattern matching uses the conditional (-sa/-se). It reads and writes naturally:
değer yapkıysa,
sonuç,
...
You can bind constructor arguments to names:
(bu öğe listesinin) tersi,
bu boşsa,
boş;
ilkin devama ekiyse,
(devamın tersiyle) ilkinin ekidir.
In ilkin devama ekiyse, ilk and devam bind the constructor arguments. This lets you use those names in the body.
Binder names cannot be repeated within the same pattern branch; this avoids confusion.
Hyphenated names can be used to avoid collisions:
ilk-öğe kalan-listeye ekiyse,
kalan-listedır.
Pattern matches can be nested:
(bu öğe listelerinin) ilk-listesi-boş-mu,
bu boşsa,
doğru;
ilk-liste kalan-listelere ekiyse,
(ilk-liste boşsa,
doğru;
değilse, yanlış).
Use değilse to cover all remaining cases:
(bu doğruluğun) tersi,
bu doğruysa, yanlış;
değilse, doğru.
A match can also be used as an expression, and the scrutinee does not need to be a simple variable. This helps keep transformations fluent:
(bu dizgenin) sayının-bir-fazlası,
((bunun tam-sayı-hali)
yokluksa, 0;
n'nin varlığıysa, (n'nin 1'le toplamıdır)).
Built-in (primitive) types like integers cannot be matched with constructors; you can only match on their own constructors.
("Merhaba "yla "dünya"'nın birleşimini) yaz.
One nice feature of Kip is that argument order is flexible. The two calls below are equivalent:
(5'le 3'ün farkını) yaz.
(3'ün 5'le farkını) yaz.
This flexibility is possible because arguments take different cases. Kip determines which argument is which by looking at the case suffix.
Important
If more than one argument takes the same case, order matters.
Effectful functions defined in the infinitive (-mak/-mek) can be called in the imperative. This makes calls look more natural:
selamlamak,
isim için okuyup,
("Merhaba "yla ismin birleşimini) yazmaktır.
selamla.
Warning
yerleşik is reserved for standard-library and compiler-provided definitions. User code should not introduce new yerleşik declarations.
Bir yerleşik tam-sayı olsun.
Integer operations:
(bu tam-sayıyla) (şu tam-sayının) (toplam tam-sayısı), yerleşiktir.
(bu tam-sayıyla) (şu tam-sayının) (fark tam-sayısı), yerleşiktir.
(bu tam-sayıyla) (şu tam-sayının) (çarpım tam-sayısı), yerleşiktir.
(bu tam-sayının) (şu tam-sayıya) (bölüm tam-sayısı), yerleşiktir.
(bu tam-sayının) (şu tam-sayıyla) (kalan tam-sayısı), yerleşiktir.
(bu tam-sayıyla) (şu tam-sayıya) (bölünürlük doğruluğu), yerleşiktir.
(bu tam-sayıyla) (şu tam-sayının) (eşitlik doğruluğu), yerleşiktir.
(bu tam-sayının) (şu tam-sayıdan) (küçüklük doğruluğu), yerleşiktir.
(bu tam-sayının) (şu tam-sayıdan) (küçük-eşitlik doğruluğu), yerleşiktir.
(bu tam-sayının) (şu tam-sayıdan) (büyüklük doğruluğu), yerleşiktir.
(bu tam-sayıyla) (şu tam-sayının) (büyük-eşitlik doğruluğu), yerleşiktir.
(bu tam-sayının) (dizge-hal dizgesi), yerleşiktir.
(bu tam-sayının) (faktöriyel tam-sayısı), yerleşiktir.
Numeric literals can be used directly; when taking suffixes, use an apostrophe:
5'i yaz.
(5'le 8'in toplamını) yaz.
-1'i yaz.
Bir yerleşik dizge olsun.
String operations:
(bu dizgenin) uzunluğu, yerleşiktir.
(bu dizgeyle) (şu dizgenin) birleşimi, yerleşiktir.
(bu dizgenin) tam-sayı-hali, yerleşiktir.
The tam-sayı-hali conversion may fail; the result is an olasılık value.
Bir yerleşik ondalık-sayı olsun.
Floating-point operations:
(bu ondalık-sayıyla) (şu ondalık-sayının) (toplam ondalık-sayısı), yerleşiktir.
(bu ondalık-sayıyla) (şu ondalık-sayının) (fark ondalık-sayısı), yerleşiktir.
(bu ondalık-sayıyla) (şu ondalık-sayının) (çarpım ondalık-sayısı), yerleşiktir.
(bu ondalık-sayının) (şu ondalık-sayıya) (bölüm ondalık-sayısı), yerleşiktir.
(bu ondalık-sayının) (şu ondalık-sayıyla) (kalan ondalık-sayısı), yerleşiktir.
(bu ondalık-sayıyla) (şu ondalık-sayıya) (bölünürlük doğruluğu), yerleşiktir.
(bu ondalık-sayıyla) (şu ondalık-sayının) (eşitlik doğruluğu), yerleşiktir.
(bu ondalık-sayının) (şu ondalık-sayıdan) (küçüklük doğruluğu), yerleşiktir.
(bu ondalık-sayının) (şu ondalık-sayıdan) (küçük-eşitlik doğruluğu), yerleşiktir.
(bu ondalık-sayının) (şu ondalık-sayıdan) (büyüklük doğruluğu), yerleşiktir.
(bu ondalık-sayıyla) (şu ondalık-sayının) (büyük-eşitlik doğruluğu), yerleşiktir.
(bu ondalık-sayının) (dizge-hal dizgesi), yerleşiktir.
3.14'ü yaz.
(-0.5'in dizge-halini) yaz.
"merhaba"'yı yaz.
"merhaba"'yla "dünya"'nın birleşimini yaz.
Common escape sequences can be used in strings:
"a\nb\tc\\\"d"'yi yaz.
(bu şeyi) yazmak, yerleşiktir.
(bu dizgeyi) yazmak, yerleşiktir.
5'i yaz.
"merhaba"'yı yaz.
okumak, yerleşiktir.
Reads a line from standard input and returns a string. It is ideal for REPL experiments.
(bu dosyadan) (okumak dizge olasılığı), yerleşiktir.
(bu dosyaya) (şu dizgeyi) (yazmak doğruluğu), yerleşiktir.
Reading from a file returns an olasılık type:
çalıştırmak,
("./tests/yazı.tmp"'den okumak)
yokluksa,
"Okunamadı." yazmaktır;
metnin varlığıysa,
metni yazmaktır.
çalıştır.
You can sequence multiple operations with the converb suffixes -ip/-ıp/-up/-üp:
(bu tam-sayıyı) denemek,
bunu yazıp,
(bunla 1'in toplamını) yazmaktır.
5'i dene.
Use için to bind the result of an expression to a name:
selamlamak,
isim için okuyup,
("Merhaba "yla ismin birleşimini) yazmaktır.
selamla.
In this example:
- The
okumakfunction is called - The result is bound to the variable
isim -
isimis used in the next expression
Effectful operations typically return the bitim type (OCaml's unit, C-like languages' void). durmak is a simple value of this type:
(durmak bitimi),
bitimliktir.
Kip files are imported with yükle. The yükle command expects the accusative case (e.g. girişi yükle.). By default, lib/giriş.kip is loaded automatically, so you start with basic modules. You can disable this with --no-prelude.
Important
If automatic loading is enabled, you do not need to load basic modules yourself.
To load manually:
girişi yükle.
Polymorphic types can be defined:
Bir (öğe listesi)
ya boş
ya da bir öğenin bir öğe listesine eki
olabilir.
Here öğe is a type variable. This type can be instantiated as tam-sayı listesi, dizge listesi, doğruluk listesi, and so on.
doğrunun (yanlışın boşa ekine) ekini yaz.
This can be thought of like [true, false] in other languages.
(bu öğe listesinin) uzunluğu,
bu boşsa,
0;
ilkin devama ekiyse,
(devamın uzunluğuyla) 1'in toplamıdır.
(bu öğe listesiyle) (şu öğe listesinin) birleşimi,
bu boşsa,
şu;
ilkin devama ekiyse,
ilkin (devamla şunun birleşimine) ekidir.
(bu öğe listesinin) tersi,
bu boşsa,
boş;
ilkin devama ekiyse,
(devamın tersiyle) (ilkin boşa ekinin) birleşimidir.
(bu tam-sayı listesinin) toplamı,
bu boşsa,
0;
ilkin devama ekiyse,
ilkin (devamın toplamıyla) toplamıdır.
Bir (öğenin olasılığı)
ya yokluğu
ya da bir öğenin varlığı olabilir.
By matching on yokluk and varlık, you can write safe conversions:
(bu dizgenin) sayıya-çevrimi,
((bunun tam-sayı-hali)
yokluksa, yokluğudur;
n'nin varlığıysa, n'nin varlığıdır).
In Turkish, some words can be analyzed in more than one way. For example "takası":
-
taka+ buffer consonant + possessive suffix -
takas+ accusative case
Kip keeps all such possibilities and chooses the correct one during type checking, based on context.
Tip
If Kip cannot resolve a type because of ambiguity, but you know the expression should be valid, you can use an apostrophe to make your intent explicit.
Use apostrophes to disambiguate:
taka'sı (* taka'nın tamlananı *)
takas'ı (* takası -i haliyle *)
You can define functions with the same name but different types:
(bu tam-sayıyla) (şu tam-sayının) birleşimi,
(bu tam-sayıyla) (şu tam-sayının) toplamıdır.
(bu doğrulukla) (şu doğruluğun) birleşimi,
bu doğruysa,
doğru;
yanlışsa,
şudur.
(5'le 2'nin birleşimini) yaz. (* 7 *)
(doğruyla yanlışın birleşimini) yaz. (* doğru *)
Kip selects the correct function based on argument types. For readability, the return type can also be included in the name.
In the standard library, some function names include the return type (e.g. toplam tam-sayısı, uzunluk tam-sayısı). This is used for overloading and readability.
(* Bu bir yorumdur *)
modül-adını yükle.
Bir tip-adı ya yapkı1 ya yapkı2 ya da yapkı3 olabilir.
Bir tip-adı ya yapkı1 ya da bir argüman-tipinin yapkı2 olabilir.
Bir yerleşik tip-adı olsun.
Bir boş-tip var olamaz.
isim, değerdir.
(argüman1) fonksiyon-adı,
gövde.
(argüman1) (argüman2) fonksiyon-adı,
gövde.
fonksiyon-adı, yerleşiktir.
değer yapkıysa, sonuç, değilse, varsayılan-sonuç.
değer yapkı1ysa, sonuç1, yapkı2ysa, sonuç2.
değer bağlayıcının yapkısıysa, bağlayıcıyı-kullanan-sonuç.
ifade1ip, ifade2.
isim için ifadeyi, ismi-kullanan-ifade.
değeri yaz.
Kip stores the parsed and type-checked form of each .kip file in a .iz cache next to it. (Think of it like Python bytecode.) If the source file and its yükle dependencies have not changed, Kip uses the .iz file.
The .iz file also stores hashes for the compiler and the file, so the cache is automatically invalidated when the compiler changes. If you want to re-parse and re-type-check, delete the corresponding .iz file.
Note
The kip --build command helps you pre-generate .iz caches.
lib/temel.kip contains the basic types; standard functions live in related modules:
-
Basic types:
doğruluk,boşluk,olasılık,liste,yerleşik tam-sayı,yerleşik ondalık-sayı,yerleşik dizge -
Extra basic type:
bitim -
lib/temel/doğruluk.kip:tersi,birleşimi,kesişimi -
lib/temel/tam-sayı.kip:toplam tam-sayısı,fark tam-sayısı,çarpım tam-sayısı,bölüm tam-sayısı,kalan tam-sayısı,bölünürlük doğruluğu,eşitlik doğruluğu,küçüklük doğruluğu,küçük-eşitlik doğruluğu,büyüklük doğruluğu,büyük-eşitlik doğruluğu,dizge-hal dizgesi,faktöriyel tam-sayısı -
lib/temel/ondalık-sayı.kip:toplam ondalık-sayısı,fark ondalık-sayısı,çarpım ondalık-sayısı,bölüm ondalık-sayısı,kalan ondalık-sayısı,bölünürlük doğruluğu,eşitlik doğruluğu,küçüklük doğruluğu,küçük-eşitlik doğruluğu,büyüklük doğruluğu,büyük-eşitlik doğruluğu,dizge-hal dizgesi -
lib/temel/dizge.kip:uzunluğu,birleşimi,tam-sayı-hali(result:olasılık) -
lib/temel/liste.kip:uzunluğu,birleşimi,tersi,toplamı(integer list) -
lib/temel/etki.kip:durmak,yazmak(thing/string),okumak, fileokumak, fileyazmak
- Kip does not care about line starts or indentation; you can format freely.
- Single-letter names require an apostrophe:
a'nın,b'ye - Functions and constructors end with -dır/-dir (optional but recommended)
- This is a research project; it is not designed for production use.
Caution
Because it is experimental, we do not recommend using Kip for long-term projects.