{"id":26481874,"url":"https://github.com/qucumbah/programming-language","last_synced_at":"2026-05-18T09:33:46.433Z","repository":{"id":37409819,"uuid":"487791267","full_name":"qucumbah/programming-language","owner":"qucumbah","description":"Statically typed programming language that compiles to WebAssembly text format","archived":false,"fork":false,"pushed_at":"2022-07-19T06:04:03.000Z","size":365,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-08-31T14:40:45.636Z","etag":null,"topics":["compiler","programming-language","webassembly"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/qucumbah.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-05-02T09:44:50.000Z","updated_at":"2023-03-02T15:37:54.000Z","dependencies_parsed_at":"2022-07-08T01:30:32.532Z","dependency_job_id":null,"html_url":"https://github.com/qucumbah/programming-language","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/qucumbah/programming-language","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qucumbah%2Fprogramming-language","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qucumbah%2Fprogramming-language/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qucumbah%2Fprogramming-language/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qucumbah%2Fprogramming-language/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/qucumbah","download_url":"https://codeload.github.com/qucumbah/programming-language/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qucumbah%2Fprogramming-language/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33172619,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-18T09:27:30.708Z","status":"ssl_error","status_checked_at":"2026-05-18T09:27:28.300Z","response_time":71,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: 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":["compiler","programming-language","webassembly"],"created_at":"2025-03-20T03:36:09.919Z","updated_at":"2026-05-18T09:33:46.416Z","avatar_url":"https://github.com/qucumbah.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Language That Compiles To WebAssembly\n\n- [Language That Compiles To WebAssembly](#language-that-compiles-to-webassembly)\n  - [About](#about)\n  - [Try it out](#try-it-out)\n  - [Usage](#usage)\n  - [Language overview](#language-overview)\n    - [Getting started](#getting-started)\n    - [Type system](#type-system)\n    - [Statements](#statements)\n    - [Expressions](#expressions)\n    - [Numeric literals](#numeric-literals)\n    - [Comments](#comments)\n    - [Explicit type conversions](#explicit-type-conversions)\n    - [Functions](#functions)\n    - [Function parameters](#function-parameters)\n    - [Variables and constants](#variables-and-constants)\n    - [Variable scoping and re-declarations](#variable-scoping-and-re-declarations)\n    - [Operators](#operators)\n    - [Control flow](#control-flow)\n    - [Pointers usage](#pointers-usage)\n    - [Memory declarations](#memory-declarations)\n\n## About\n\nLTCTWA is a low-level statically-typed C-like language that compiles to\nWebAssembly text format.\n\n## Try it out\n\nThere is an interactive demo available on\n[GitHub Pages](https://qucumbah.github.io/programming-language/).\n\n## Usage\n\nThe language is written in typescript and has to be run with Deno.\n\nCompiling a source file into WAST:\n\n`deno run --allow-read ./src/index.ts ./source-file.ltctwa \u003e ./result-file.wast`\n\nYou will need a separate compiler to convert the result into WASM binary.\n[WABT](https://github.com/WebAssembly/wabt) is a good tool for this task.\n\nRunning unit tests:\n\n`deno test --allow-read`\n\n## Language overview\n\n### Getting started\n\nCreate a file named `main.ltctwa` and paste the following contents into it:\n\n```\nfunc export inc(arg: i32): i32 {\n  return arg + 1;\n}\n```\n\nUse `deno run --allow-read ./src/index.ts ./main.ltctwa \u003e ./output.wast` to\ncompile to WebAssembly text format.\n\nThis will produce the following output:\n\n```\n(module\n  (func\n    $inc\n    (export \"inc\")\n    (param i32)\n    (result i32)\n    local.get 0\n    i32.const 1\n    i32.add\n    return\n  )\n)\n```\n\nThe next step is to compile the result into WebAssembly binary, which can be\ndone with `wat2wasm ./dist/compiled.wast -o ./dist/main.wasm`.\n\nNow, the resulting code may be imported and executed from JavaScript:\n\n```js\nasync function main() {\n  const wasm = await getWasm();\n  const result = wasm.exports.inc(15);\n  console.log(result);\n}\n\nasync function getWasm() {\n  const bytes = await fetch(\"main.wasm\").then((res) =\u003e res.arrayBuffer());\n  const module = await WebAssembly.compile(bytes);\n  return WebAssembly.instantiate(module);\n}\n```\n\n### Type system\n\nThere are 7 basic types:\n\n- Signed integers: `i32`, `i64`\n- Unsigned integers: `i32`, `i64`;\n- Floats: `f32`, `f64`;\n- Void (only available for function returns): `void`\n\nThere are also pointer types, which can only point to sections of memory, not to\nother variables.\n\nPointer type is prepended with a `$` symbol: `$i32`, `$$u64` (pointer to\npointer) etc.\n\nThere is no void pointer for generic sections of memory; a pointer to `i32` can\nbe used instead.\n\n### Statements\n\nA program consists of a series of statements that are terminated by the\nsemicolon (`;`).\n\nThere are 5 kinds of statements:\n\n- Conditional Statement (`if`)\n- Loop Statement (`while`)\n- Return Statement (`return`)\n- VariableDeclaration Statement (operator `=`)\n- Expression Statement (any expression terminated with a semicolon)\n\n### Expressions\n\nThere are 7 kinds of expressions:\n\n- Identifier Expression (variables/constants/parameters access)\n- Numeric Expression (numeric literals)\n- Function Call Expression (functionName(arg1value, arg2value))\n- Unary Operator Expression (-val, !val, ...)\n- Binary Operator Expression (val1 + val2, val1 \u003c\u003c val2, ...)\n- Type Conversion Expression (a special kind of binary operator expression: val\n  -\u003e type)\n- Composite Expression (any expression inside parentheses)\n\n### Numeric literals\n\nValues of non-void types can be created with numeric literals:\n\n```\nvar signed: i32 = -1;\nvar unsigned: u32 = 1u;\nvar long: i32 = 1l;\nvar unsignedLong: i32 = 1ul;\nvar float: f32 = 1.;\nvar double: f64 = 1.l;\n```\n\n### Comments\n\nOnly single-line comments are supported. Use `//` for comments:\n\n```\n// This is a comment\nvar someVar: i32 = 15; // Also a comment\n```\n\n### Explicit type conversions\n\nImplicit type conversions are not allowed. All type changes have to be performed\nexplicitly using the type conversion operator `-\u003e`:\n\n```\nconst float: f32 = 5. + 1 -\u003e f32;\n\nconst float: f32 = 5. + 1; // This would fail\n```\n\nType conversions can also be chained. This is useful for converting negative\nfloats to unsigned integer, as this will cause a runtime error in WASM:\n\n```\nconst unsignedLong: u64 = -1. -\u003e i64 -\u003e u64;\n```\n\n### Functions\n\nThere are three kinds of functions: plain (internal, not available in JS),\nexport (available both in module and JS), import (imported from JS).\n\nEach of them has to have an explicit result type.\n\nExamples:\n\n```\nfunc plainFunction(arg1: i32, arg2: i32): i32 {\n  return arg1 \u0026 arg2;\n}\n\nfunc export exportFunction(arg1: i32, arg2: i32): i32 {\n  return arg1 \u0026 arg2;\n}\n\nfunc import(console::log) console_log(arg: i32): void;\n```\n\nImport object is used to pass import function's body from JS.\n\nFor example, to use import function from above it has to be passed like this:\n\n```js\nWebAssembly.instantiate(module, {\n  console: {\n    log: console.log,\n  },\n});\n```\n\n### Function parameters\n\nEach function parameter has to have an explicit non-void type.\n\nAll parameters are constant.\n\n### Variables and constants\n\nAll variables and constants have to be initialized from the start, and have to\nhave an explicit type:\n\n```\nvar someVariable: i32 = 3;\nconst someConstant: f32 = someFloatArgument;\n```\n\n### Variable scoping and re-declarations\n\nVariables, constants and parameters can be re-declared with a different type:\n\n```\nfunc redeclarationFunc(arg: i32): void {\n  const arg: f32 = arg -\u003e f32;\n  const arg: u64 = 15ul;\n\n  var someVar: i32 = 3;\n  var someVar: i64 = someVar -\u003e i64;\n}\n```\n\nVariables are block-scoped:\n\n```\nconst someValue: i32 = 1;\nif (1) {\n  const someValue: f32 = 2.;\n  console_log(someValue); // The value is now 2.0\n}\n```\n\nIf a variable is not declared in the current scope, its value is taken from the\nouter one:\n\n```\nvar someVar: i32 = 1;\nif (1) {\n  console_log(someVar); // The value is still 1\n  \n  // If we change it here, the outer variable will be affected\n  someVar = 2;\n\n  const someVar: i32 = 3;\n  console_log(someVar); // Inside this block of code, someVar's value is now 3\n}\n\nconsole_log(someVar); // But the outer value is still 2\n```\n\n### Operators\n\nOperators precedence table with explanation:\n\n| Precedence | Operator(s)                   | Description                                                                    | Accepted value(s)                    | Return value     |\n| ---------- | ----------------------------- | ------------------------------------------------------------------------------ | ------------------------------------ | ---------------- |\n| 1          | `!`\u003cbr\u003e `@`\u003cbr\u003e `-`           | Logical NOT\u003cbr\u003ePointer dereference\u003cbr\u003eUnary minus                              | Integers\u003cbr\u003ePointers\u003cbr\u003eNon-void\u003cbr\u003e | Same as operands |\n| 2          | `*`\u003cbr\u003e `/`                   | Multiplication\u003cbr\u003eDivision                                                     | Non-void                             | Same as operands |\n| 3          | `+`\u003cbr\u003e `-`                   | Addition\u003cbr\u003eSubtraction                                                        | Non-void                             | Same as operands |\n| 4          | `\u003e`\u003cbr\u003e `\u003c`\u003cbr\u003e `\u003e=`\u003cbr\u003e `\u003c=` | Greater than\u003cbr\u003eLess than\u003cbr\u003eGreater than or equal to\u003cbr\u003eLess than or equal to | Non-void                             | `i32`            |\n| 5          | `==`\u003cbr\u003e `!=`                 | Equal to\u003cbr\u003eNot equal to                                                       | Non-void                             | `i32`            |\n| 6          | `\u003c\u003c`\u003cbr\u003e `\u003e\u003e`                 | Left shift\u003cbr\u003eRight shift                                                      | Integers                             | Same as operands |\n| 7          | `\u0026`                           | Logical AND                                                                    | Integers                             | Same as operands |\n| 8          | `^`                           | Logical XOR                                                                    | Integers                             | Same as operands |\n| 9          | `\\|`                          | Logical OR                                                                     | Integers                             | Same as operands |\n| 10         | `=`                           | Assignment                                                                     | Identifier `=` Non-void              | `void`           |\n| 11         | `-\u003e`                          | Type conversion                                                                | Non-void `-\u003e` `type`                 | `type`           |\n\nPointer type is also included in the non-void values category.\n\nJust as with variable assignment, there is no implicit conversion, so both\noperands have to be the same type. The only two exceptions to this rule are\nassignment and type conversion operators.\n\n### Control flow\n\nThere are three control flow statements: conditional, loop, and return\nstatements.\n\nExamples:\n\n```\nfunc loopTest(arg: u32): i32 {\n  var someVar: i32 = 1;\n  // Conditional and loop statements accept a value of type `i32`\n  while (someVar \u003c arg) {\n    if (someVar == 256) {\n      return 256;\n    }\n    someVar = someVar * 2;\n  }\n\n  return someVar;\n}\n```\n\n### Pointers usage\n\nPointers are represented as `i32` internally.\n\nPointer arithmetic is available, but all adresses are counted in bytes. Example:\n\n```\n// All values have to be converted into pointers\nvar pointerToInt: $i32 = 0 -\u003e $i32;\nvar pointerToNextInt: $i32 = pointerToInt + 4 -\u003e $i32;\n```\n\nIn C, second variable's value would have been calculated as `pointerToInt + 1`.\n\nThe expression would be the same as\n`(byte*)pointerToInt + (1 * sizeof(*pointerToInt))`.\n\nIn LTCTWA, such implicit calculation is absent.\n\nTo manipulate a value that is pointed to, dereference operator \"`@`\" is used:\n\n```\nvar somePointer: $i32 = 100 -\u003e $i32;\n@somePointer = 1;\n@(somePointer + 4) = 2;\nconst two: i32 = @(104 -\u003e $i32);\n\nvar pointerToPointer: $$i32 = 200;\n@pointerToPointer = somePointer;\nconst one = @@pointerToPointer;\nconst two = @(@pointerToPointer + 4 -\u003e $i32);\n```\n\nThere is no way to get an adress of a variable on the stack, only adresses of\nmemory can be used.\n\n### Memory declarations\n\nJust like functions, there are three ways to declare memory: plain (only used\nwithin a module), export (may be accessed from JS), and import (imported from\nJS).\n\nThere may only be one memory declaration per module.\n\nSyntax examples:\n\n```\nmemory(1u);\n\n// This can be accessed in JS as `instance.exports.exportMem`\nmemory(1u) export(exportMem);\n\n// For this to work an instance of `WebAssembly.Memory` has to be passed to the import object\nmemory(1u) import(memoryNamespace::memoryName);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqucumbah%2Fprogramming-language","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fqucumbah%2Fprogramming-language","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqucumbah%2Fprogramming-language/lists"}