{"id":14991138,"url":"https://github.com/isuckatcs/how-to-compile-your-language","last_synced_at":"2025-04-05T18:06:00.779Z","repository":{"id":245950844,"uuid":"806804877","full_name":"isuckatcs/how-to-compile-your-language","owner":"isuckatcs","description":"An introduction to language design through building a compiler frontend and completing a self-paced exercise on top of LLVM.","archived":false,"fork":false,"pushed_at":"2025-03-15T01:06:38.000Z","size":1011,"stargazers_count":112,"open_issues_count":0,"forks_count":18,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-03-29T17:11:12.469Z","etag":null,"topics":["compiler-design","compiler-frontend","compilers","cpp","educational-materials","language-design","languages","llvm","tutorial","tutorial-exercises"],"latest_commit_sha":null,"homepage":"https://isuckatcs.github.io/how-to-compile-your-language/","language":"HTML","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/isuckatcs.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-05-28T00:10:27.000Z","updated_at":"2025-03-26T07:35:24.000Z","dependencies_parsed_at":"2024-08-08T16:18:29.879Z","dependency_job_id":"6ea62f9c-9611-4d79-a3a6-48c33f6af97e","html_url":"https://github.com/isuckatcs/how-to-compile-your-language","commit_stats":{"total_commits":199,"total_committers":2,"mean_commits":99.5,"dds":0.005025125628140725,"last_synced_commit":"fd5ed02628fbc86c8abe093e5a18f627ac59fea3"},"previous_names":["isuckatcs/how-to-compile-your-language"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/isuckatcs%2Fhow-to-compile-your-language","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/isuckatcs%2Fhow-to-compile-your-language/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/isuckatcs%2Fhow-to-compile-your-language/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/isuckatcs%2Fhow-to-compile-your-language/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/isuckatcs","download_url":"https://codeload.github.com/isuckatcs/how-to-compile-your-language/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247378140,"owners_count":20929296,"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":["compiler-design","compiler-frontend","compilers","cpp","educational-materials","language-design","languages","llvm","tutorial","tutorial-exercises"],"created_at":"2024-09-24T14:21:32.700Z","updated_at":"2025-04-05T18:06:00.743Z","avatar_url":"https://github.com/isuckatcs.png","language":"HTML","funding_links":[],"categories":["HTML"],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\u003cimg src=\"https://github.com/isuckatcs/how-to-compile-your-language/actions/workflows/pipeline.yml/badge.svg\" /\u003e\n\u003cimg src=\"https://github.com/isuckatcs/how-to-compile-your-language/actions/workflows/deploy.yml/badge.svg\" /\u003e\n\u003ca href=\"https://codecov.io/github/isuckatcs/how-to-compile-your-language\" target=\"_blank\"\u003e\u003cimg src=\"https://codecov.io/github/isuckatcs/how-to-compile-your-language/branch/main/graph/badge.svg?token=SLOD84JALB\" /\u003e\u003c/a\u003e\n\u003cbr\u003e\n\u003cbr\u003e\n\u003c/div\u003e\n\n![cover](https://isuckatcs.github.io/how-to-compile-your-language/img/cover.png)\n\nA simple programming language implementation with an educational guide that displays modern compiler techniques. \n\n[isuckatcs.github.io/how-to-compile-your-language](https://isuckatcs.github.io/how-to-compile-your-language/)\n\n## Getting Started\n\nThis guide assumes that the project is being built on Linux* but equivalent steps can be performed on any other operating system.\n\n1. Install CMake 3.20 or newer\n   - `apt-get install cmake`\n\n2. Install LLVM and Clang\n   - The project was originally built for **LLVM 14.0.0**. Other versions are not guaranteed to work.\n   - `apt-get install llvm clang`\n\n3. Create a build directory and enter that directory\n   - `mkdir build \u0026\u0026 cd build`\n\n4. Configure CMake and build the project\n   - `cmake path/to/repo/root \u0026\u0026 cmake --build .`\n\nTo run the tests, proceed with these following optional steps.\n\n5. Install Python 3.10 or newer\n   - `apt-get install python`\n\n6. Install the required dependencies\n   - `pip install -r ./test/requirements.txt`\n\n7. Run the `check` target with CMake\n   - `cmake --build . --target check`\n\n\\* tested on Ubuntu 22.04.3 LTS\n\n## Features\n### Clean Syntax\n\nUnambiguous, modern and easy to parse syntax with elements inspired by C, Kotlin, Rust and Swift.\n\n```\nfn main(): void {\n    println(0);\n}\n```\n\n### Static Type System\n\nSimple type system currently supporting the `number` and `void` types with the capability to be expanded by user-defined types. \n\nThe `number` type is implemented as a 64-bit floating point value.\n\n```\nfn main(): void {\n    let x: number = 1234;\n    let y: number = 12.34;\n}\n```\n\n### Lazy Initialization\n\nData-flow analysis based support for detecting lazily initialized and uninitialized variables.\n\n```\nfn dataFlowAnalysis(n: number): void {\n    let uninit: number;\n\n    if n \u003e 3 {\n        uninit = 1;\n    }\n\n    println(uninit);\n}\n```\n```\nmain.yl:8:13: error: 'uninit' is not initialized\n```\n\n### Naive Type Inference\nWhen a variable is initialized, the type specifier can be omitted as the type is inferred from the initializer.\n\n```\nfn main(): void {\n    let typeInference = 1; \n}\n```\n\n### Immutability\n\nImmutable and mutable variables declared with the `let` and `var` keywords.\n\n```\nfn main(): void {\n    let immutable = 1;\n    var mutable = 2;\n\n    while mutable \u003e 2 {\n      immutable = 0;\n      mutable = mutable - 1;\n    }\n}\n```\n```\nmain.yl:6:7: error: 'immutable' cannot be mutated\n```\n\n### Compile Time Expression Evaluation\n\nExpressions are evaluated by a tree-walk interpreter during compilation if possible.\n\n```\nfn main(): void {\n    let x = (1 + 2) * 3 - -4;\n    println(x);\n}\n```\n```\n$ compiler main.yl -res-dump\n\nResolvedFunctionDecl: @(main.addr) main:\n  ResolvedBlock\n    ...\n    ResolvedCallExpr: @(println.addr) println\n      ResolvedDeclRefExpr: @(x.addr) x\n      | value: 13\n```\n\n### Smart Return Check\n\nFlow-sensitive return value analysis made smarter with compile time expression evaluation.\n\n```\nfn maybeReturns(n: number): number {\n    if n \u003e 2 {\n        return 1;\n    } else if n \u003c -2 {\n        return -1;\n    }\n\n    // missing return 'else' branch\n}\n\nfn alwaysReturns(n: number): number {\n    if 0 \u0026\u0026 n \u003e 2 {\n        // unreachable\n    } else {\n        return 0;\n    }\n}\n```\n```\nmain.yl:1:1: error: non-void function doesn't return a value on every path\n```\n\n### Native Code Generation\n\nA source file is first compiled to LLVM IR, which is then passed to the host platform specific LLVM backend to generate a native executable.\n\n```\nfn main(): void {\n    println(1.23);\n}\n```\n```\n$ compiler main.yl -o main.out\n$ ./main.out \n1.23\n```\n\n### Accessible Internals\n\nCapability to print the Abstract Syntax Tree before and after resolution, the Control-Flow Graph and the generated LLVM IR module.\n```\nfn main(): void {\n    println(1.23);\n}\n```\n```\n$ compiler main.yl -ast-dump\n\nFunctionDecl: main:void\n  Block\n    CallExpr:\n      DeclRefExpr: println\n      NumberLiteral: '1.23'\n```\n```\n$ compiler main.yl -res-dump\n\nResolvedFunctionDecl: @(main.addr) main:\n  ResolvedBlock\n    ResolvedCallExpr: @(println.addr) println\n      ResolvedNumberLiteral: '1.23'\n      | value: 1.23\n```\n```\n$ compiler main.yl -cfg-dump\n\nmain:\n[2 (entry)]\n  preds: \n  succs: 1 \n\n[1]\n  preds: 2 \n  succs: 0 \n  ResolvedNumberLiteral: '1.23'\n  | value: 1.23\n  ResolvedCallExpr: @(println.addr) println\n    ResolvedNumberLiteral: '1.23'\n    | value: 1.23\n\n[0 (exit)]\n  preds: 1 \n  succs: \n```\n```\n$ compiler main.yl -llvm-dump\n\ndefine void @__builtin_main() {\n  call void @println(double 1.230000e+00)\n  ret void\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fisuckatcs%2Fhow-to-compile-your-language","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fisuckatcs%2Fhow-to-compile-your-language","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fisuckatcs%2Fhow-to-compile-your-language/lists"}