{"id":17688004,"url":"https://github.com/tanin47/lilit-lang","last_synced_at":"2025-05-13T00:46:05.056Z","repository":{"id":141279223,"uuid":"139770320","full_name":"tanin47/lilit-lang","owner":"tanin47","description":"[Work in progress] A programming language. Ideal for command-line tools","archived":false,"fork":false,"pushed_at":"2020-11-15T05:42:14.000Z","size":578,"stargazers_count":6,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-13T00:45:59.930Z","etag":null,"topics":["programming-language"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tanin47.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-07-04T22:21:56.000Z","updated_at":"2023-06-18T00:21:02.000Z","dependencies_parsed_at":"2024-05-01T20:40:47.559Z","dependency_job_id":"f576ce17-7916-4819-a91a-c366e211df3e","html_url":"https://github.com/tanin47/lilit-lang","commit_stats":null,"previous_names":["tanin47/lilit-lang"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tanin47%2Flilit-lang","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tanin47%2Flilit-lang/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tanin47%2Flilit-lang/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tanin47%2Flilit-lang/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tanin47","download_url":"https://codeload.github.com/tanin47/lilit-lang/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253850875,"owners_count":21973671,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["programming-language"],"created_at":"2024-10-24T11:43:07.491Z","updated_at":"2025-05-13T00:46:05.037Z","avatar_url":"https://github.com/tanin47.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"Lilit\n=======\n\nLilit is a high-level general-purpose programming language.\n\n```\ndef main(args: Array[String]): Void\n  println(\"Hello Lilit!\")\nend\n```\n\nIt aims to be ideal for building low-performant command-line tools.\n\nPlease follow our progress [here](./PROGRESS.md).\n\nPrinciples\n-----------\n\n### Typed\n\nA statically typed language, as codebase grows bigger, is more maintainable than a dynamically-typed language.\n\n### Terse\n\nWe aim be at the highest level of abstraction and reduce the amount of detail programmers need to think and code.\n\nSome features that Lilit offers:\n\n* Complex type system (think Scala), which enables programmers to capture real-world complexity with brevity, though it takes effort to learn.\n* Rich standard library (think Scala + Ruby), which prevents programmers from solving trivial problems on their own. For example, in Python, programmers have to implement their own [getting the first element or null](https://stackoverflow.com/questions/363944/python-idiom-to-return-first-item-or-none), while, in Ruby, they can use `.first` in Ruby's standard library.\n\n\nFeatures\n---------\n\n* Compile to a single executable binary\n* Automatic garbage collection\n* Complex type system (e.g. generic, multiple inheritance, no null)\n* Limited metaprogramming (e.g. type-safe monkey patching)\n\n\nRun\n------\n\nTry `./run.sh`\n\nExample:\n\n```\n$ cargo run examples/printf.lilit\n    Finished dev [unoptimized + debuginfo] target(s) in 0.02s\n     Running `target/debug/lilit examples/printf.lilit`\nLilit 0.1.0\n\n---- Code ----\nclass Native__Void\n  // No implementation.\nend\n\nclass Native__Int\n  // No implementation. This class represents i64 in LLVM.\nend\n\nclass Native__String\n  // No implementation. This class represents i8* in LLVM.\nend\n\ndef native__printf(text: Native__String): Native__Void\n  // No implementation. The body is automatically built to invoke printf(..).\nend\n\nclass Void\nend\n\nclass Int(underlying: Native__Int)\nend\n\nclass String(underlying: Native__String)\nend\n\ndef println(text: String): Void\n  native__printf(text.underlying)\nend\n\ndef main: Int\n  println(\"Hello world!\")\n  123\nend\n\nWrite LLVM object to ./output/main.o\n\n$ clang -S -emit-llvm /home/tanin/projects/bdwgc/.libs/libgc.so -I /home/tanin/projects/bdwgc/include/ -o native/lib.ll native/lib.c\nclang: warning: /home/tanin/projects/bdwgc/.libs/libgc.so: 'linker' input unused [-Wunused-command-line-argument]\n\n$ llc-6.0 -filetype=obj native/lib.ll\n\n$ cc native/lib.o output/main.o /home/tanin/projects/bdwgc/.libs/libgc.so -I /home/tanin/projects/bdwgc/include/ -o main -no-pie\n\n$ ./main\nHello world!\n\n$ echo $?\n123\n```\n\nTechnical detail\n-----------------\n\nHere are the stages of compilers:\n\n1. __Tokenize__ builds a sequence of predefined tokens from a sequence of characters. This stage simplifies Parsing, which is the next step.\n2. __Parsing__ builds a parse tree from the sequence of tokens.\n3. __Index__ builds an index tree, which enables references across all files. The index tree can answer a question like: \"Can we invoke method A on class C?\".\n4. __Analyse__ populates references in the parse tree (e.g. populating a method call with the corresponding method definition). Analyse should populates \nevery necessary info, so Emit doesn't need to traverse the parse tree.\n5. __Emit__ builds LLVM code from the populated parse tree.\n\nThere are 3 layers in Lilit:\n\n1. Application layer is the layer where programmers write their code in Lilit\n2. Native layer, still written in Lilit, are native classes (starting with `Native__`) and native methods (starting with `native__`) don't have implementation; compiler populates their implementation.\n    * A native class contains a corresponding C primitive as its first member. For example, `Native__Int` contains an `i64`, and `Native__String` contains an `i8*`.\n    * A native method must take only params whose types are native classes. A native method converts all params to their C primitive types and invokes a corresponding system function. For example, `native__printf(text: Native__String)` invokes `printf(i8*)`.\n3. C layer contains custom C code that is needed by Native layer.\n\n\nDevelopment tricks\n-------------------\n\n### Use Clang to emit LLVM IR from C code\n\n1. Write C code\n2. Run `clang -S -emit-llvm test.c`\n3. See how Clang build equivalent LLVM IR\n\n### Debug segfault\n\nWhen encountering the error like below:\n\n```\n$ cargo test emit::tests::test_full -- --nocapture\n    Finished dev [unoptimized + debuginfo] target(s) in 0.02s\n     Running target/debug/deps/lilit-e4a1085d58b2f6af\n\nrunning 1 test\nerror: process didn't exit successfully: `/home/tanin/projects/lilit-lang/target/debug/deps/lilit-e4a1085d58b2f6af 'emit::tests::test_full' --nocapture` (signal: 11, SIGSEGV: invalid memory reference)\n```\n\nWe can use GDB to identify which line causes the memory corruption.\n\n1. Run `gdb /home/tanin/projects/lilit-lang/target/debug/deps/lilit-e4a1085d58b2f6af 'emit::tests::test_full'`\n2. Run `run` and see the memory corruption\n3. Run `backtrace` to see which line causes the memory corruption.\n\nWe'd see a backtrace like below:\n\n```\n#0  0x000055555598a53c in LLVMBuildAlloca ()\n#1  0x0000555555665a95 in inkwell::builder::Builder::build_alloca (self=0x7ffff6429520, ty=..., name=...)\n    at /home/tanin/.cargo/git/checkouts/inkwell-9eb0689e3d3f00ac/46d576c/src/builder.rs:173\n#2  0x000055555568a54c in \u003clilit::emit::Emitter as lilit::emit::def::method::EmitterMethod\u003e::apply_method (self=0x7ffff6429518, method=0x7fffe0002aa8)\n    at src/emit/def/method.rs:51\n#3  0x000055555568ea53 in lilit::emit::Emitter::apply_file (self=0x7ffff6429518, file=0x7fffe0001a30) at src/emit/mod.rs:61\n#4  0x000055555568e7fb in lilit::emit::Emitter::apply (self=0x7ffff6429518, files=...) at src/emit/mod.rs:46\n...\n```\n\nFAQs\n-----\n\n### What does Lilit mean?\n\nLilit in Thai (ลิลิต) is [a Thai literary genre](http://cuir.car.chula.ac.th/handle/123456789/51485). 'Lilit' comes from 'Lalit' in Pali and Sansakrit languages. It means 'to play': to play rhythmic positions which have the same tone.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftanin47%2Flilit-lang","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftanin47%2Flilit-lang","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftanin47%2Flilit-lang/lists"}