{"id":30049914,"url":"https://github.com/exoad/kira","last_synced_at":"2025-10-26T13:45:33.376Z","repository":{"id":311478133,"uuid":"1010398057","full_name":"exoad/kira","owner":"exoad","description":"A Simple, Practical, \u0026 Grounded Object-Oriented Programming Language.","archived":false,"fork":false,"pushed_at":"2025-09-29T16:50:53.000Z","size":6211,"stargazers_count":2,"open_issues_count":4,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-29T18:39:02.140Z","etag":null,"topics":["programming-language"],"latest_commit_sha":null,"homepage":"https://exoad.github.io/kira/","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/exoad.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-06-29T01:32:11.000Z","updated_at":"2025-09-27T21:59:26.000Z","dependencies_parsed_at":"2025-08-24T21:56:21.670Z","dependency_job_id":"0126d7ee-3660-449a-a61a-d89c1ffeadf9","html_url":"https://github.com/exoad/kira","commit_stats":null,"previous_names":["exoad/kira"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/exoad/kira","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exoad%2Fkira","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exoad%2Fkira/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exoad%2Fkira/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exoad%2Fkira/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/exoad","download_url":"https://codeload.github.com/exoad/kira/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exoad%2Fkira/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":281114862,"owners_count":26446042,"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","status":"online","status_checked_at":"2025-10-26T02:00:06.575Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":"2025-08-07T12:39:00.243Z","updated_at":"2025-10-26T13:45:33.370Z","avatar_url":"https://github.com/exoad.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n\u003cimg src=\"./public/logo_simple.png\" width=64/\u003e\u003cbr/\u003eKira\n\u003c/h1\u003e\n\u003cp align=\"center\"\u003e\n\u003cstrong\u003e\nA modern object-oriented programming language focused on simplicity \u0026 practicality.\n\u003c/strong\u003e\n\u003c/p\u003e\n\n\u003e [!NOTE]\n\u003e This project is currently under active development. Documentation may be incomplete.\n\n**Kira** is a modern, pure object-oriented programming language with expressive syntax inspired by Swift, Kotlin, and\nDart. It functions as a flexible toolkit—similar to Haxe—supporting transpilation and ahead-of-time (AOT) compilation to\nmultiple targets, including source code, bytecode, bitcode, and machine code.\n\nKira enforces three core principles: **privacy**, **immutability**, and **static behavior**. All declarations are\nprivate and immutable by default. To enable mutability or public access, use the `mut` or `pub` modifiers respectively.\nClasses contain only instance-level data; static and companion members are managed via namespaces.\n\n---\n\n# Kira Language Specifications\n\nVersion 1.1\n\nOctober 1, 2025\n\n## Hello World\n\n```\n@trace(\"Hello World!\")\n```\n\n## Comments\n\nKira supports comments via `//`. Anything after will be stripped out by the preprocessor.\n\n```\n// I won't appear in the generated output!\n\n```\n\n## Variables\n\nKira is a statically-typed language meaning that all variables must declare a type.\n\n```\nname: Str = \"John\"\nage: Int32 = 34\nisOk: Bool = true\n```\n\n## Control Flow Structures\n\nThese structures help determine which pieces of your code will run. Kira\nhas the following control structures:\n\n1. `if-else` selection statements\n2. `while` loops\n3. `do-while` loops\n4. `for` loops\n\n```\n// If-Else Selection Statement\nif name == \"John\" {\n    @trace(\"Hi John\")\n} else if name == \"Jamie\" {\n    @trace(\"Hi Jamie\")\n} else {\n    @trace(\"Who are you?\")\n}\n\n// While Loop\nwhile true {\n    @trace(\"Looping forever...\")\n}\n\n// Do-While Loop\ndo {\n    @trace(\"I will be printed once!\")\n} while false\n\n// For Loop\nfor i: Int32 in 1..10 {\n    @trace(i)\n}\n```\n\n\u003e Note: These are statements and not expressions (e.g. you cannot return using a control flow structure).\n\n## Functions\n\nKira treats functions as first-class citizens, meaning you can use them as values and pass them around.\n\nTo return a value, Kira uses the `return` keyword. If a function has no return, it must\nspecify its return type as `Void` or `Nothing`.\n\n```\nfx sumOf(a: Int32, b: Int32 = 3): Int32 {Inte\n    return a + b\n}\n```\n\nFunction parameters can either be specified using their name or using position.\n\n## String Interpolation\n\nUsing the `${}` syntax, you can embed expressions directly into strings.\n\n```\nname: Str = \"John\"\nage: Int32 = 34\n@trace(\"My name is ${name} and I am ${age} years old.\")\n```\n\n\u003e Please note that there is no `$var` syntax without the curly braces. This is to avoid ambiguity and confusion.\n\u003e \n\u003e Additionally, you can escape the dollar sign by using `\\$`.\n\n## Module System\n\nKira uses a module system for you to organize your source structure. Each piece of Kira source file\nstarts off with a module declaration:\n\n```\nmodule \"author:module_name/module_name/submodule_name\"\n```\n\n-   `author` represents the organization or individual that this belongs to.\n-   `module_name` represents what project this source file falls under.\n-   `submodule_name` represents this individual source file's name\n\n\u003e Whatever is at the end of the module declaration is what the file is named. For example, if\n\u003e the module declaration is `module \"kira:lib.types\"`, then the file must be named `types.kira`.\n\u003e \n\u003e Additionally, all intermediate `module_name` must be directories.\n\n### Using a submodule\n\nOften times, you would include or import submodules, not entire modules themselves per submodule. This is\nto save on compile time and also potential bloating. To include another submodule:\n\n```\nuse \"author:module_name/submodule_name\"\n```\n\nFor example, to use all builtin types from Kira (e.g. `Int32`, `Str`), you need to use the submodule `kira:lib.types`.\n\n\u003e There is no wildcard import. **You must explicitly import each submodule you want to use.**\n\n## Classes\n\nKira supports classes, an object-oriented principle. Class in Kira are very easy and malleable to understand and\nlightweight;\nhowever, they do have some limitations:\n\n1. No multi-inheritance (Diamond Inheritance Problem)\n2. Only one default constructor\n3. No nested structures (classes, enums, namespaces)\n4. No companion or static members\n5. All fields that are virtual can be provided through the constructor.\n6. No direct abstract classes or interfaces\n\n```\npub class Vector2\n{\n    require pub mut x: Float32\n    require pub mut y: Float32\n\n    pub fx dot(other: Vector2): Float32 {\n        return (other.x * x) + (other.y * y)\n    }\n\n    pub mut fx toStr(): Str {\n        return \"( ${x}, ${y} )\"\n    }\n}\n\na: Vector2 = Vector2 { 3, 3 }\nb: Vector2 = Vector2 { 3, 3, toStr = fx() { return \"\u003c ${x}, ${y} \u003e\" } }\n@trace(a.dot(b))\n```\n\n\u003e For constructor calls, you can also use named parameters like so:\n\u003e ```\n\u003e b: Vector2 = Vector2 { y = 3, x = 3 }\n\u003e ```\n\u003e \n\u003e They follow the same rules as function parameters with positional and named parameters.\n\n### Inheritance\n\nMulti-inheritance is not allowed, but to share common functions across multiple classes, Kira supports [traits](##Traits)\n\nInheritance is very simple, there are only several types of allowed patterns:\n\n1. **Concrete classes**\n2. **(Semi-)Abstract classes**\n3. **Interface-Like classes**\n\nHowever, all of these utilize the format of classes meaning that you can only use ONE of these even if it is Interface-Like.\n\nHere are some examples of the previously mentioned patterns:\n\n#### Concrete Classes (Normal Classes)\n\nAll members are implemented, with the only exception being property fields.\n\n```\npub class Student {\n\trequire pub name: String\n\trequire pub mut gpa: Float32\n\t\n\tpub fx passing(): Boolean {\n\t\treturn gpa \u003e 2.0\n\t}\n}\n```\n\n#### (Semi-)Abstract Classes\n\nSemi Abstract classes are created where you add unimplemented member function (methods) into the mix of concrete classes. However, they are \"semi\" abstract because Kira allows anonymous classes to be made everywhere by passing functions directly to the constructor.\n\n```\npub class Human {\n\tpub scientificName: String= \"Homo Sapien\"\n\t\n\tpub fx speak(): Void\n\t\n\tpub fx walk(): Void {\n\t\t@trace(\"Walking...\")\n\t}\n}\n```\n\n\n#### Interface-Like Classes\n\nThis pattern is the most redundant and should be avoided. Instead, prefer to use traits if you need to share common functionalities across multiple classes. In general, interface like classes define no property members and only abstract function members:\n\n```\npub class Animalia {\n\tpub fx reproduce(): Animalia\n\t\n\tpub fx die(): Void\n\t\n\tpub fx eat(): Void\n\t\n\tpub fx isAlive(): Bool\n}\n```\n\n## Immutability By Default\n\nEverything in Kira is immutable or closed by default. This means variables cannot be reassigned/mutated, classes\ncannot be inherited from, methods in classes cannot be overridden by default.\n\nIn order to allow for mutability, specify the `mut` modifier before the element you want to make mutable.\n\n## Visibility Modifiers\n\nThere are only 2 visibility levels allowed:\n\n1. public - `pub`\n2. internal - implicit (i.e. no keyword used)\n\n\n### Public Modifier\n\nThe `pub` modifier specifies that anything outside can look inside. For example, a submodule which has a\nclass:\n\n```\nclass A {\n}\n\npub class B {\n}\n```\n\nAn external submodule that uses this cannot see `class A`, but can see `class B`. Additionally, `class B` can see\n`class A` and vice versa.\n\nWithin classes themselves, the modifier only serves as encapsulation purposes (i.e. hiding data and fields). If\na member of a class does not have the `pub` modifier, that field can only be access through the setter during\nconstruction or within a neighboring method that can expose it (getter). Additionally, if the class is inheritable, it means that\nfield is also private from the child and the child cannot access it.\n\n\u003e **Why no `protected`?**\n\u003e\n\u003e In other languages like Java, the `protected` keyword is another visibility layer that allows for only the members of\n\u003e the class\n\u003e and children of that class to view that field.\n\u003e\n\u003e Kira does not utilize this layer simply because it is extra overhead and increases the learning curve. Creating a\n\u003e binary system where\n\u003e it is either the field is visible or not makes it not only easier, but gives more freedom to the programmer in\n\u003e designing their APIs.\n\n### Internal Modifier\n\nWhen no modifier is used to denote visibility, it implies that the field is not visible anywhere else. Tl;dr, an internal\nvisibility is mutually exclusive to public visibility. This is similar to other language's `private` keyword.\n\nWhen used within a class, it represents that the field is private and cannot be accessed outside of the class or from a child class.\n\n## Null Safety\n\nKira incorporates sound null-safety as one of its core pillars. It does so using a core type: `Maybe\u003c A \u003e`.\n\nWithout boxing a type in `Maybe`, you are not allowed to assign the literal `null` to anything:\n\n```\na: Int32 = null // error!\n\nb: Maybe\u003cInt32\u003e = null // ok!\n```\n\n`Maybe` also enables for field-valuation meaning you can achieve the following without using a getter for the internally\nheld value:\n\n```\nmut a: Maybe\u003cInt32\u003e = null\n\n@trace(a) // null\n@trace(a.value) // null\n\na = 32\n\n@trace(a) // 32\n@trace(a.value) // 32\n```\n\n### Null Safety Operators\n\n**Null Safe Get**\n\n`Maybe\u003c A \u003e::unwrapOr(option: A)`\n\nIf the underlying value is `null`, return `option` provided as `A` else return the underlying value.\n\n```\nmut a: Maybe\u003cInt32\u003e = null\n\nif a == null {\n    @trace(\"Null\")\n} else {\n    @trace(a)\n}\n\n// is akin to:\n\n@trace(a.unwrapOr(0))\n```\n\n**Sanity Checks**\n\nIf you do not like using `==` to check if the value is equal to `null`, there are 2 methods to help you:\n\n1. `Maybe\u003c A \u003e::isNull(): Bool` - returns `true` if the underlying value is `null` else `false`\n2. `Maybe\u003c A \u003e::isSome(): Bool` - returns `true` if the underlying value is not `null` else `false`\n\n## Exceptions\n\nKira only has unchecked exceptions meaning that you do not need to catch everything. Exceptions are only strings that\ndenote what went wrong:\n\n```\nthrow \"Something went wrong.\"\n```\n\n### Exception Handling\n\nExceptions can be caught by using a `try-on` expression:\n\n```\ntry {\n    // ...\n} on e: Str {\n    @trace(e)\n}\n```\n\n\u003e **Note:** The variable required after `on` is always guaranteed to be of `Str`\n\n## Memory Model\n\nKira uses an Automatic Reference Counting (ARC) memory model similar to Swift. Every object has a reference counter and\nwhen this counter drops\nto zero, the object is freed from memory. However, in certain scenarios like a circular reference where A and B\nreference each other, it can cause\nthem to never be deallocated leading to undefined behavior and/or memory faults.\n\nTo mitigate this, Kira has 2 types that are intrinsified by the compiler:\n\n1. `Weak\u003c T \u003e` - Used to denote a non-strong reference to mitigate circular references and allow for deallocation.\n2. `Unsafe\u003c T \u003e` - Signifies that the reference count should not be increased as the object will outlive the reference.\n   _This is a strictly performance oriented feature._\n\n## Finalizers \u0026 Initializers Blocks\n\nThese are special functions that are only callable by the runtime and not from Kira itself. They are meant to be\nexecuted right at the\ntime of object allocation and deallocation and are only permitted within classes.\n\n### Initializers\n\nInitializers are ran right at the moment of object construction. It is accomplished by introducing the `initially`\nblock:\n\n```\nclass Person {\n    require pub age: Int32\n\n    initially {\n        if age \u003c 0 {\n            @trace(\"Age must be \u003e= 0!\")\n        }\n    }\n}\n```\n\n### Finalizers\n\nFinalizers are used to clean up external resources from things like File IO. It is accomplished by introducing the\n`finally` block:\n\n```\nclass FileIO {\n\n    finally {\n        doCleanup()\n    }\n}\n```\n\nAll code in the finally block is called and ran when the object is about to be deallocated.\n\n## Core Types\n\nCore types are intrinsified by the compiler, meaning the compiler both recognizes them and also will optimize\nspecifically for them.\n\nIn other languages, such as Java, they are known as primitive types and boxed types. Kira does not perform boxing,\neverything is an object.\n\n### Integer Like\n\n1. `Int32` - 32-bit integer\n2. `Int64` - 64-bit integer\n3. `Int16` - 16-bit integer\n4. `Int8` - 8-bit integer\n\n### Floating Point\n\n1. `Float32` - 32-bit floating point\n2. `Float64` - 64-bit floating point\n\n### Logical\n\n1. `Bool` - Represents a boolean which can either be `true` or `false`. Backed by an 8-bit integer.\n\n### Unit Types\n\n1. `Void` - Specifies no return type\n2. `Never` - Specifies a function will never complete (i.e. all code after is dead code).\n\n### Reference Types\n\n1. `Weak\u003c A \u003e` - Weak Reference\n2. `Unsafe\u003c A \u003e` - Unsafe Reference\n3. `Maybe\u003c A \u003e` - Null Safety. Allows for assigning the `null` literal.\n4. `Any` - Root of all classes\n5. `Type` - Runtime type representation\n6. `Fx\u003c R, [ T: Any ] \u003e` - Function type representation\n7. `Module` - Module metadata, recursive for submodules.\n8. `Ref\u003c A \u003e` - Holds a reference to an object directly (i.e. boxing `A`)\n9. `Result\u003c A, B \u003e` - A different approach to null safety where it allows for a reason if `A` is null via `B`\n10. `Val\u003c A \u003e` - A trait that is used to denote that it can be referenced directly as `A`. Used by `Maybe`\n\n### Sequence Types\n\n1. `Str` - String/Character Sequence\n2. `Arr\u003c A \u003e` - Static immutable array structure\n3. `List\u003c A \u003e` - Dynamic mutable array structure (not-compiler-optimized)\n4. `Map\u003c K, V \u003e` - Dynamic mutable hash table structure (not-compiler-optimized)\n5. `Set\u003c A \u003e` - Dynamic mutable hash set structure (not-compiler-optimized)\n\n## Traits / Compile Time \"Mixins\"\n\nKira does not support multi-inheritance as previously seen; however, in order to suffice for allowing sharing common components across classes, **traits** are a good alternative. \n\nTraits allow injecting a class with functions/methods at compile time directly. Additionally, it can also serve as a way to inject abstract methods or no-implementation functions that the target class must take care of.\n\nHowever, traits differ from Mixins and Interfaces in that they are an entirely compile-time feature. This means that you cannot perform runtime checks for if a type has a trait to it (however, this can be implemented by directly checking if a certain method/function exists within).\n\nWithin Kira, you are only allowed to define functions within traits, and each function also implicitly points to the current instance like in classes (i.e. there is no `self` or `this` or `::` operands to access the current scope).\n\n\u003e **Mutability Note:** All functions in a trait are mutable or overrideable, specifying the `mut` modifier will have no effect.\n\u003e \n\u003e **Visibility Note:** You are able to enforce visibility modifiers on the trait itself and also functions. This is done by using the normal modifiers. However, when a function is marked with or without a modifier, it is not able to be changed by the implementing type.\n\u003e\n\u003e **Implementer Features:** The implementer class is allowed to use specific functions in order ot refer\n\nImplementing a trait:\n\n```\ntrait Animal {\n\tfx makeNoise(): Void\n\t\n\tpub fx canConsume(items: Arr\u003cStr\u003e): Bool {\n\t\treturn items.any([ \"water\", \"air\" ])\n\t}\n}\n\nclass Dog: Animal {\n\tfx makeNoise(): Void {\n\t\t@trace(\"Woof\")\n\t}\n\t\n\tpub fx canConsume(items: Arr\u003cStr\u003e): Bool {\n\t\treturn \n\t}\n}\n```\n\n## Compile-Time Intrinsics \n\nKira supports compiler-integrated intrinsics for compile-time execution. These are not user-definable and are designed\nto simplify expressions, enable metaprogramming, and support DSL construction.\n\n**Properties:**\n\n-   Prefixed with `@`\n-   Treated as standard identifiers\n-   Function-like or directive-like\n-   Executed during any compiler phase\n\n```zig\na: Map\u003cString, Any\u003e = @json_decode(`\n  {\n    \"hello\": 1,\n    \"world\": 2\n  }\n`)\n\n@trace(a[\"hello\"]) // Outputs 1 to debugger\n```\n\t\n## Operator Overloading\n\nKira supports operator overloading to make user-defined types feel more natural. Additionally, they are also the mechanic by which the \nbase types like `Int32`, `Str`, etc. are implemented. \n\nTo overload an operator, you must define a method/class function member with the name of intrinsic that matches the operator. For example,\nto overload the addition operator `+`, you must define a method named `op_add`:\n\n```\nclass Vector2 {\n    require pub mut x: Float32\n    require pub mut y: Float32\n\n    pub fx @op_add(other: Vector2): Vector2 {\n        return Vector2 { x + other.x, y + other.y }\n    }\n}\n```\n\nYou can also look under the hood of how this works, as the following two pieces of code are equivalent:\n\n```\na: Int32 = 1\nb: Int32 = 2\nc: Int32 = a + b // This is syntactic sugar for:\nc: Int32 = a.@op_add(b)\n```\n\n\u003e Overloaded operators can return anything and take anything just like a function (recall that a marker intrinsic is just a placeholder for a \n\u003e special symbol). This makes them powerful yet confusing if not used properly and sparingly.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexoad%2Fkira","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fexoad%2Fkira","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexoad%2Fkira/lists"}