Kip (meaning "grammatical mood" in Turkish) is an experimental programming language that uses Turkish grammatical cases as part of its type system. It demonstrates how natural language morphologyβspecifically Turkish noun cases and vowel harmonyβcan be integrated into programming language design.
This is a research/educational project exploring the intersection of linguistics and type theory, not a production programming language.
There is also a tutorial in Turkish and a tutorial in English that explains how to write Kip programs.
Note
Kip is experimental. Expect changes in syntax and behavior over time.
For you to get a taste of what Kip looks like, here is an example program that reads a name and prints a greeting:
selamlamak,
isim iΓ§in okuyup,
("Merhaba "yla ismin birleΕimini) yazmaktΔ±r.
selamla.
- Language Features
- Installation
- Editor Plugins
- WASM Playground
- Bytecode Cache
- Project Structure
- Testing
- Morphological Analysis
- License
Kip uses Turkish noun cases (ismin halleri) to determine argument relationships in function calls:
| 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Δ± | ardΔ±lΔ± |
Because Turkish cases mark grammatical relationships explicitly, Kip allows flexible argument ordering. These two calls are equivalent:
(5'le 3'ΓΌn farkΔ±nΔ±) yaz.
(3'ΓΌn 5'le farkΔ±nΔ±) yaz.
As long as arguments have different case suffixes or different types, Kip can determine which argument is which.
Define algebraic data types with Turkish syntax:
Bir doΔruluk ya doΔru ya da yanlΔ±Ε olabilir.
Bir trafik-Δ±ΕΔ±ΔΔ±
ya kΔ±rmΔ±zΔ±
ya sarΔ±
ya da yeΕil
olabilir.
Type variables are supported for generic data structures:
Bir (ΓΆΔe listesi)
ya boΕ
ya da bir ΓΆΔenin bir ΓΆΔe listesine eki
olabilir.
Pattern match using the conditional suffix -sa/-se:
(bu doΔruluΔun) tersi,
bu doΔruysa, yanlΔ±Ε,
yanlΔ±Εsa, doΔrudur.
Supports nested pattern matching, binders, and wildcard patterns (deΔilse):
(bu trafik-Δ±ΕΔ±ΔΔ±nΔ±n) eylemi,
bu kΔ±rmΔ±zΔ±ysa, "Dur",
sarΔ±ysa, "HazΔ±rlan",
yeΕilse, "GeΓ§"tir.
Define named constants with a definition sentence:
merhaba, "Merhaba"'dΔ±r.
dΓΌnya, "DΓΌnya"'dΔ±r.
Sequencing with -ip/-Δ±p/-up/-ΓΌp suffixes and binding with iΓ§in:
selamlamak,
isim iΓ§in okuyup,
("Merhaba "yla ismin birleΕimini) yazmaktΔ±r.
Integers (tam-sayΔ±):
- Arithmetic:
toplamΔ±,farkΔ±,Γ§arpΔ±mΔ± - Comparison:
eΕitliΔi,kΓΌΓ§ΓΌklΓΌΔΓΌ,bΓΌyΓΌklΓΌΔΓΌ - Other:
faktΓΆriyeli
Strings (dizge):
uzunluΔu- lengthbirleΕimi- concatenationtam-sayΔ±-hali- parse as integer
I/O:
yazmak/yaz- print to stdoutokumak/oku- read from stdin
(* This is a comment *)
5'i yaz. (* Integer literal with case suffix *)
"merhaba"'yΔ± yaz. (* String literal with case suffix *)
3.14'ΓΌ yaz. (* Floating-point literal with case suffix *)
-
Foma - finite-state morphology toolkit
- macOS:
brew install foma - Debian/Ubuntu:
apt install foma libfoma-dev - Fedora:
dnf install foma foma-devel
- macOS:
-
Stack - Haskell build tool
- See haskellstack.org
Tip
If you only want to explore the language, you can start with stack exec kip after a successful build.
Clone this repository, then:
# Quick install (macOS/Linux)
chmod +x install.sh
./install.sh
# Or manual build
stack build
# Install to PATH
stack installThe TRmorph transducer is bundled at vendor/trmorph.fst.
If you have installed to PATH, you can do:
# Start REPL
kip
# Execute a file
kip --exec path/to/file.kip
# Run in test mode (non-REPL, definition logs enabled)
kip --test path/to/file.kip
# Build/update .iz caches for a file or directory tree
kip --build path/to/file-or-dir
# Generate JavaScript
kip --codegen js path/to/file.kip
# Generate strict ES modules into a directory
kip --codegen js-modules --outdir ./out path/to/file.kip
# then run:
node ./out/entry.mjs
# Choose diagnostic language
kip --lang tr --exec path/to/file.kip
kip --lang en --exec path/to/file.kip
# Disable automatic loading of lib/giriΕ.kip
kip --no-prelude --exec path/to/file.kipFor the non-interactive playground runner binary:
stack exec kip-playground -- --exec path/to/file.kip
stack exec kip-playground -- --codegen js path/to/file.kipjs-modules output layout:
__kip_runtime.mjs- runtime and primitive exports- one
.mjsper input/dependency.kipmodule entry.mjs- entrypoint that imports requested input modules
kip-lsp speaks LSP over stdio. You can run it directly for editor integration:
stack exec kip-lspMake sure kip-lsp is on your PATH, or configure your editor to call the
absolute path from stack exec -- which kip-lsp.
This repository includes:
- a Visual Studio Code extension in
vscode-plugin/ - a Vim/Neovim plugin in
.vim/
Both use kip-lsp.
Prerequisites:
kip-lspinstalled and available onPATH, or an absolute executable path- Node.js and npm (for building the extension)
Install and run from source:
cd vscode-plugin
npm install
npm run compile
code --extensionDevelopmentPath=.In the Visual Studio Code Extension Development Host, open a .kip file.
Package and install as a normal extension:
cd vscode-plugin
npm install
npm run compile
npx vsce package
code --install-extension kip-0.1.0.vsixUseful Visual Studio Code settings:
{
"kip.languageServerPath": "kip-lsp",
"kip.languageServerArgs": [],
"kip.trace.server": "off"
}The plugin files are already in the repo under .vim/:
.vim/ftdetect/kip.vim.vim/syntax/kip.vim.vim/plugin/kip.vim
Prerequisites:
kip-lspavailable onPATH(or setg:kip_language_server_path)- Neovim built-in LSP, or
vim-lsp, orcoc.nvim
Use directly from this repo by adding the runtime path:
" ~/.vimrc or init.vim
set runtimepath+=/absolute/path/to/kip/.vimOr copy the folders into your Vim config:
cp -R .vim/ftdetect ~/.vim/
cp -R .vim/syntax ~/.vim/
cp -R .vim/plugin ~/.vim/Plugin options:
let g:kip_language_server_path = 'kip-lsp'
let g:kip_language_server_args = []
let g:kip_trace_server = 'off'
let g:kip_lsp_autostart = 1Plugin commands:
:KipLspInfoshows effective Kip LSP settings:KipLspRestartrestarts the configured LSP client
A browser playground can be built from source under playground/. It compiles the
non-interactive runner (kip-playground) and reactor entrypoint (kip-playground-reactor)
to wasm32-wasi and ships a small HTML/JS harness that runs Kip in the browser.
See playground/README.md for prerequisites, toolchain setup, and build steps.
Kip stores a cached, type-checked version of each .kip file in a sibling .iz file. When you run a file again, Kip will reuse the .iz cache if both the source and its loaded dependencies are unchanged.
If you want to force a fresh parse and type-check, delete the .iz file next to the source.
Important
.iz files include a compiler hash. If the compiler changes, the cache is invalidated automatically.
app/
βββ Main.hs - CLI entry point (kip executable)
βββ Lsp.hs - LSP server entry point (kip-lsp executable)
βββ Playground.hs - Non-interactive runner (kip-playground)
βββ PlaygroundReactor.hs - WASI reactor entrypoint (kip-playground-reactor)
src/
βββ Kip/
β βββ AST.hs - Abstract syntax tree
β βββ Cache.hs - .iz cache handling
β βββ Codegen/
β β βββ JS.hs - JavaScript codegen
β βββ Eval.hs - Interpreter
β βββ Parser.hs - Parser
β βββ Render.hs - Pretty-printing with morphological inflection
β βββ Runner.hs - CLI runner utilities
β βββ TypeCheck.hs - Type checker validating grammatical case usage
βββ Language/
βββ Foma.hs - Haskell bindings to Foma via FFI
lib/
βββ giriΕ.kip - Prelude module loaded by default
βββ temel.kip - Core types
βββ temel/doΔruluk.kip - Boolean functions
βββ temel/dizge.kip - String functions
βββ temel/etki.kip - I/O primitives
βββ temel/liste.kip - List functions
βββ temel/ondalΔ±k-sayΔ±.kip - Floating-point functions
βββ temel/tam-sayΔ±.kip - Integer functions
βββ *.iz - Generated bytecode caches (if built)
tests/
βββ Main.hs - Test suite runner
βββ LspTest.hs - LSP test utilities
βββ succeed/ - Passing golden tests (.kip + .out + optional .in)
βββ fail/ - Failing golden tests (.kip + .err)
βββ repl/ - REPL interaction tests (.repl + .out)
βββ lsp/ - LSP test fixtures (.kip + .json)
playground/
βββ README.md - WASM playground build notes
vscode-plugin/
βββ README.md - VS Code extension for Kip
c/
βββ morphology.c - Foma glue (C)
βββ morphology.h - Foma glue headers
vendor/
βββ trmorph.fst - TRmorph transducer
stack testTest categories:
tests/succeed/- Programs expected to parse, typecheck, and run successfullytests/fail/- Programs expected to fail during parsing, typechecking, or evaluationtests/repl/- REPL interaction tests with expected outputstests/lsp/- LSP server functionality tests (hover, completion, diagnostics, etc.)
The test suite automatically runs kip-lsp tests if kip-lsp is on PATH or KIP_LSP_BIN is set.
JavaScript parity tests run only when node is available on PATH (or NODE_BIN is set).
Useful test env vars:
KIP_BIN: path to a specifickipexecutableKIP_LSP_BIN: path to a specifickip-lspexecutableNODE_BIN: path to a specificnodeexecutable
Kip uses TRmorph for Turkish morphological analysis. When a word has multiple possible parses (e.g., "takasΔ±" could be "taka + possessive" or "takas + accusative"), Kip carries all candidates through parsing and resolves ambiguity during type checking.
For intentionally ambiguous words, use an apostrophe to force a specific parse: taka'sΔ± vs takas'Δ±.
See LICENSE file.