{"id":15101434,"url":"https://github.com/gremble0/kebab","last_synced_at":"2026-02-14T11:03:04.571Z","repository":{"id":225606690,"uuid":"766389126","full_name":"gremble0/kebab","owner":"gremble0","description":"Compiler and interpreter for the Kebab programming language","archived":false,"fork":false,"pushed_at":"2024-08-31T19:19:13.000Z","size":1174,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-09-08T03:48:31.710Z","etag":null,"topics":["c","compiler","cpp","interpreter","language","llvm"],"latest_commit_sha":null,"homepage":"","language":"C++","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/gremble0.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":"2024-03-03T05:50:31.000Z","updated_at":"2024-08-31T19:19:17.000Z","dependencies_parsed_at":"2024-03-21T04:31:28.751Z","dependency_job_id":"7af3039a-ed0d-410e-a441-f6828102f414","html_url":"https://github.com/gremble0/kebab","commit_stats":{"total_commits":702,"total_committers":1,"mean_commits":702.0,"dds":0.0,"last_synced_commit":"87772505c5a386b72c20fefc06d60d187975cce7"},"previous_names":["gremble0/kebab"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/gremble0/kebab","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gremble0%2Fkebab","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gremble0%2Fkebab/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gremble0%2Fkebab/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gremble0%2Fkebab/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gremble0","download_url":"https://codeload.github.com/gremble0/kebab/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gremble0%2Fkebab/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29443447,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-14T10:51:12.367Z","status":"ssl_error","status_checked_at":"2026-02-14T10:50:52.088Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["c","compiler","cpp","interpreter","language","llvm"],"created_at":"2024-09-25T18:23:00.316Z","updated_at":"2026-02-14T11:03:04.537Z","avatar_url":"https://github.com/gremble0.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Kebab\n## Introduction\nKebab is a strongly typed primarily functional programming language that is currently under development. Here is how it looks:\n\n```clj\n; `;` for comments\n; Basic syntax for the language looks like this. The parser ignores any whitespace\n; and newlines so the following are both valid definitions.\ndef this-is-fine\n= int( 2\n             +\n                       3   )\ndef but-probably-better-like-this = int(2 + 3)\n\n; Some basic constructors\ndef i = int(69 + 420)\ndef l1 = list((int) =\u003e [1, 2, 3])\ndef l2 = list((string) =\u003e [\"123\", \"gg\", \"hhh\"])\ndef add-one = fn((a : int) =\u003e int(a + 1))\ndef b1 = bool(1 == -2)\ndef b2 = bool(1 ~= -2)\n\n; Nested statements inside constructors. The constructor returns the last expression\ndef nested-example = int(\n  def nested = int(5)\n  2 + nested\n)\n\n; Functions are first class citizens and can be made local to some constructor.\n; Here `local-fn` is only visible from inside the int constructor for `nested-example2`\ndef nested-example2 = int(\n  def local-fn = fn(() =\u003e int(42))\n  local-fn()\n)\n```\n\n## Building from source\nThe language consists of two main components an interpreter in C and a compiler using the LLVM compiler toolchain in C++. Before you try to build either of these you will need to initialize the git submodules:\n```sh\ngit submodule update --init\n```\n\n### Building the compiler\nTo build the compiler you will first need to build llvm from source (this will take a while). After initializing llvm as a submodule change your working directory into that submodule:\n```sh\ncd lib/llvm-project\n```\nThen follow [LLVM's instructions for building from source](https://llvm.org/docs/GettingStarted.html#getting-the-source-code-and-building-llvm)\n\nThen simply run make from within the `/compiler/` directory:\n```sh\ncd compiler\nmake\n```\nThen you should end up with the `kebab` executable. This can be used to compile kebab (`.keb`) files into IR (`.ll` files).\n\nIf you want to run the tests you will also need to build googletest from source. After initializing googletest as a submodule change your working directory into that submodule:\n```sh\ncd lib/googletest\n```\nThen follow [GoogleTest's instructions for building from source](https://github.com/google/googletest/tree/main/googletest#readme)\n\nThen simply run make from within the `/compiler/test/` directory, and run the `run_tests` executable.\n```sh\ncd compiler/test\nmake\n./run_tests\n```\n\n### Building the interpreter\nTo build the intepreter you will first need to build nonstdlib from source. After initializing nonstdlib as a submodule change your working directory into the `src` directory under that submodule and run make:\n```sh\ncd lib/nonstdlib/src\nmake\n```\n\nThen simply run `make` from the `interpreter` directory:\n```sh\ncd interpreter\nmake\n```\nThen you should end up with the `kebab` executable. This can be used to interpret kebab (`.keb`) files with its own runtime.\n\n## Typing\nKebab is a statically and strongly typed language. You define types for everything, including the types for parameters, return values, lists, etc. These types are enforced at runtime/compiletime and there is no `any` type. You can (and must) apply these types for every parameter and variable, through either specifying a variables constructor, or its type (more on constructors vs. type declarations later). Just to showcase some the language's advanced typing features here are some slightly absurd function definitions. \n\n```clj\n; Functions can return other functions\ndef ret-fn = fn((outer : int) =\u003e fn((inner : int) =\u003e\n    int(outer + inner)\n))\n\n; Functions can take functions as parameters\ndef takes-fn = fn((fn-param : fn((int) =\u003e string)) =\u003e string(\n  fn-param(42)\n))\n\n; Functions can take lists of functions as parameters\ndef takes-fn = fn((fn-params : list(fn(int) =\u003e string)) =\u003e string(\n  fn-params[0](42)\n))\n\n; A function that takes an int as a parameter and returns a function takes\n; an int as a parameter that returns a list of ints\ndef ret-fn-rets-list = fn((outer : int) =\u003e fn((inner : int) =\u003e list((int) =\u003e \n  [outer, inner]\n)))\n\n; In this signature we can see that `my-function` takes an int and a string as a parameter\n; and returns a string. But from the constructor of `takes-fn` we can see that the function\n; is supposed to return an int. Therefore returning the result of calling my-function is\n; a type error since its return value of `string` is not the right type (`int`) for the function\ndef takes-fn = fn((my-function : fn(int, string) =\u003e string) =\u003e int(\n  my-function(4, \"hello\") ; Error here - my-function does not return an int\n))\n```\n\n## Constructors\n### Primitives\nPrimitive constructors follow this pattern:\n```\ntype(\u003cconstructor-body\u003e)\n```\nWhere the constructor body is any sequence of statements where the last one must be an expression (the return value of the constructor). Some primitive constructors are `char`, `bool`, `int` and `string`. Here are some examples\n```clj\nint(\n  def a = 2\n  a + 2\n)\nbool(true)\nstring(\"hello-world\")\n```\n\n### Lists\nList constructors follow this pattern:\n```\nlist((\u003ctype\u003e) =\u003e \u003cconstructor-body\u003e)\n```\nHere are some examples\n```clj\nlist((string) =\u003e [\"hello\", \",\", \"world\"])\n\nlist((list(string)) =\u003e [\n  [\"hello\", \"world\"],\n  [\"this\", \"is\", \"kebab\"], ; Trailing commas are allowed ;)\n])\n\nlist((fn(int) =\u003e string) =\u003e [\n  fn((a : int) =\u003e int(a)),\n  fn((s : string) =\u003e string(s)),\n])\n```\n\n### Functions\nFunction constructors follow this pattern:\n```\nfn((\u003cparameters\u003e) =\u003e \u003cconstructor\u003e)\n```\nWhere the list of parameters is a comma separated list where each element should look like `\u003cname\u003e : \u003ctype\u003e`. NOTE: The space before the `:` is very important here, as if you were to omit it, it would be included as a part of the name of the parameter which would cause a syntax error. The constructor in the functions body could be any other constructor, including another function constructor.\n\n## Constructors vs. type declarations\nThere are two ways through which kebab gets information about types. The first is through constructor calls. These are some examples of constructor type inference.\n```clj\n; int constructor means a is now bound to the int type\ndef a = int(2)\n; string constructor means b is now bound to the string type\ndef s = string(\"hello\")\n\n; list constructor, parametrized to be of type `string`. Here the list(...)\n; is the constructor call, while the string inside the list constructor\n; is a type declaration the list constructor uses to bind it to that type\ndef b = list((string) =\u003e [\"hello\", \"world\"])\n```\n\nThe strongest combination of constructors and type declarations are seen in functions. Let's analyze this function:\n```clj\ndef my-function = fn((a : int, l : list(string)) =\u003e int(\n  a + 5\n))\n```\n1. First we enter the `fn` constructor.\n2. Then we parse the parameters of the function.\n    1. The first parameter is called `a` and is declared to be of type `int`\n    2. The second parameter is called `l` and is declared to be of type `list`.\n        1. The list is parametrized to be of type string.\n3. Then we parse the function body by calling another constructor - in this case the `int` constructor. This constructor also gives us the return type of the funciton, meaning this function must return an `int`.\n\n## Mutability\nVariables are constant by default, but can be made mutable if you add the `mut` qualifier when defining it. To mutate a mutable variable use a `set` statement.\n```clj\n; This is fine since my-var is mutable\ndef mut my-var = int(4)\nset my-var = int(6) ; my-var is now 6\n\n; This will error since my-const is constant\ndef my-const = int(4) ; This is fine\nset my-const = int(6) ; Error here\n```\n\n## Conditionals\nYou can control the flow of your program with if/elif/else expressions - yes these are expressions. An if/elif/else expression must return a value and therefore always needs to have an else branch. This is how you can use them in kebab.\n```clj\n; a = 1\ndef a = int(\n  if false =\u003e 0\n  elif 2 == 2 =\u003e -1\n  else =\u003e 1\n)\n\n```\n\nYou can also define variables local to a branch or do other calculations inside each branch. For example:\n```clj\n; c = [3, 6]\ndef c = list((int) =\u003e\n  def q = int(1 + 2)\n  if 2 == 2 =\u003e\n    ; `w` is local to this if branch\n    def w = int(6)\n    [q, w]\n  elif 1 == 2 =\u003e\n    printf(\"hello, world\\n\")\n    [q, 1]\n  else =\u003e\n    [1, 2]\n)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgremble0%2Fkebab","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgremble0%2Fkebab","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgremble0%2Fkebab/lists"}