{"id":13671946,"url":"https://github.com/mustafaquraish/cup","last_synced_at":"2026-03-07T22:35:49.539Z","repository":{"id":37502164,"uuid":"453602476","full_name":"mustafaquraish/cup","owner":"mustafaquraish","description":"simple, C-like compiled programming language","archived":false,"fork":false,"pushed_at":"2022-08-24T03:23:36.000Z","size":685,"stargazers_count":299,"open_issues_count":5,"forks_count":11,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-04-27T18:38:32.452Z","etag":null,"topics":["compiler","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/mustafaquraish.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}},"created_at":"2022-01-30T06:09:49.000Z","updated_at":"2025-03-13T14:40:37.000Z","dependencies_parsed_at":"2022-08-02T01:09:54.855Z","dependency_job_id":null,"html_url":"https://github.com/mustafaquraish/cup","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mustafaquraish/cup","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mustafaquraish%2Fcup","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mustafaquraish%2Fcup/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mustafaquraish%2Fcup/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mustafaquraish%2Fcup/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mustafaquraish","download_url":"https://codeload.github.com/mustafaquraish/cup/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mustafaquraish%2Fcup/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30235156,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-07T19:01:10.287Z","status":"ssl_error","status_checked_at":"2026-03-07T18:59:58.103Z","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":["compiler","language"],"created_at":"2024-08-02T09:01:22.623Z","updated_at":"2026-03-07T22:35:49.515Z","avatar_url":"https://github.com/mustafaquraish.png","language":"Rust","funding_links":[],"categories":["Rust","Other"],"sub_categories":[],"readme":"# CUP: C(ompiler) U(nder) P(rogress)\n\nA badly named, in-progress programming language just to learn how these things work. Wait, doesn't everyone write a compiler when they're bored?\n\nCurrently, the language is comparable to C, with some syntax changes inspired by Rust (that also make it a little easier to parse). The compiler outputs assembly code in `yasm` format, so you will need [yasm](https://yasm.tortall.net/) and a linker of your choice to compile it. The included Makefile and scripts use `ld`. (Alternatively, you can use `nasm`, but you will have to change the command being run in `compiler/main.cup` and `meta/bootstrap.sh`)\n\nOnly linux and macOS (only on x86_64) are supported.\n\n## Building\n\n### Tools\n\nMake sure you have `yasm` and `ld` installed, and located on your `PATH`.\n\n### Compiling\n\nThe reference implementation of the compiler is written in CUP, so you'll need to use the pre-compiled YASM files to get the initial executable. You should be able to run the command below to create the `./build/cupcc` compiler:\n```bash\n$ ./meta/bootstrap.sh\n```\nCompile a program (and optionally run it) using:\n```bash\n$ ./build/cupcc /path/to/program.cup -o prog\n$ ./prog 1 2 3 4\n# OR\n$ ./build/cupcc /path/to/program.cup -o prog -r 1 2 3 4\n```\nMake sure to not have the executable name end in `.yasm` or `.o`, since there are some temporary files created during compilation.\n\n---\n\n## Code Samples\n\n### Hello World  \n\nSome common functions you'll want are located in `std/common.cup`\n```rust\nimport \"std/common.cup\";\n\nfn main(arc: int, argv: char**): int {\n    putsln(\"Hello, world!\");\n    return 0;\n}\n```\n\n### Variables\n\nVariables are strongly typed. You can either declare them with a type, or they can be inferred if there is an initial assignment.\n\n```rust\nfn main() {\n    let x: int = 5;  // Explicity define the type\n    let y = 6;       // Infer the type\n    let z = x + y;   // Add them, and infer the type\n}\n```\n\n### Pointers and arrays\n```rust\nfn main() {\n    let x: int[10];  // An array of 10 ints (initializers not supported)\n    let y: int* = x; // Automatically decays to a pointer when passed or assigned\n    let z = y;       // type(z) == int* also works\n    \n    let a = x[0];    // Access the first element (`a` is an int)\n    let b = *(x+1);  // Access the second element (can use pointer arithmetic)\n}\n```\n\n### Structs / Unions / Enums\n\n```rust\n// For now, enums just generate constant values with sequential numbers.\n// They aren't a \"type\" on their own.\nenum Type {\n    TypeInt,\n    TypeFloat,\n    TypeChar,\n}\n\nstruct Variable {\n    typ: int;        // Can't use `Type` here, because it's not a type\n    value: union {   // Anonymous nested structures are allowed.\n        as_int: int;\n        as_char: char;\n        as_ptr: Variable*;  // Can recursively define types.\n    };\n};\n\nfn main() {\n    let x: Variable; // No struct initializers yet\n    x.typ = TypeInt;\n    x.value.as_int = 5;\n}\n```\n\n### Methods for Structs/Unions\n\n```rust\nstruct Value {\n    x: int;\n};\n\nmethod Value::inc(amount: int) {\n    // self (pointer) is implicitly passed in\n    self.x = self.x + amount;\n}\n\nmethod Value::print() {\n    print(self.x);\n}\n\nfn main() {\n    let v: Value;\n    let v_ptr = \u0026v;\n\n    v.x = 0;\n    // Call methods using `::`\n    v::inc(10);\n    v_ptr::print(); // Also works for pointers\n}\n```\n\n### File I/O\n\nFor now, the file I/O is very inspired by C, but it's wrapped using methods for the `File` object. Optionally, you can use the raw syscalls (which behave like C), to deal with file descriptors manually. However it's preferred to use the `File` object as it's more convenient and also provides buffered writes.\n\nA simple implementation of `cat` is:\n```rust\nimport \"std/file.cup\";\n\nfn main(argc: int, argv: char**) {\n    for (let i = 1; i \u003c argc; ++i) {\n        let file = fopen(argv[i], 'r');\n        defer file::close();    // Close the file at the end of the block (in each iteration)\n\n        let buf: char[1024];\n        let n = file::read(buf, 1024); // use file-specific functions\n        while (n \u003e 0) {\n            write(0, buf, n); // Use raw system calls\n            n = file::read(buf, 1024);\n        }\n        // file closed here because of defer\n    }\n}\n```\n\n---\n\nWant some more examples? Check out the [examples](examples/) directory, or the [compiler](compiler/) directory, which contains the implementation of the compiler itself.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmustafaquraish%2Fcup","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmustafaquraish%2Fcup","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmustafaquraish%2Fcup/lists"}