{"id":22894646,"url":"https://github.com/valentin271/tbc","last_synced_at":"2025-07-15T11:35:45.066Z","repository":{"id":213339534,"uuid":"733632866","full_name":"Valentin271/tbc","owner":"Valentin271","description":"A TinyBASIC compiler in Rust","archived":false,"fork":false,"pushed_at":"2023-12-20T11:52:51.000Z","size":22,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-31T22:39:41.655Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","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/Valentin271.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":"2023-12-19T19:14:01.000Z","updated_at":"2023-12-19T19:16:26.000Z","dependencies_parsed_at":null,"dependency_job_id":"e67ac21a-a2ee-4938-a4f3-801dc53c75c0","html_url":"https://github.com/Valentin271/tbc","commit_stats":null,"previous_names":["valentin271/tbc"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Valentin271/tbc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Valentin271%2Ftbc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Valentin271%2Ftbc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Valentin271%2Ftbc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Valentin271%2Ftbc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Valentin271","download_url":"https://codeload.github.com/Valentin271/tbc/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Valentin271%2Ftbc/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265432297,"owners_count":23764067,"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":[],"created_at":"2024-12-13T23:18:57.953Z","updated_at":"2025-07-15T11:35:45.030Z","avatar_url":"https://github.com/Valentin271.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tiny BASIC compiler\n\nThis is a compiler for a subset of the [Tiny BASIC](https://en.wikipedia.org/wiki/Tiny_BASIC)\nlanguage. It also dumps a number of other files related to the compilation toolchain.\n\nIt uses my library [tiny-elf](https://github.com/Valentin271/tiny-elf/) to manipulate assembly and generate ELF files.\n\n## Parser generator\n\nThis project uses [pest](http://pest.rs/) to generate a parser from a grammar.\nThe grammar is defined in [`src/parser/tinybasic.pest`](src/parser/tinybasic.pest).\n\n## Running\n\nYou can run the project by typing:\n\n```sh\ncargo run -- \u003ctinybasic file\u003e\n```\n\nFor example:\n\n```sh\ncargo run -- data/opt.tb\n```\n\nYou can add the `-r` flag to directly run it. This will also append the return code to the output.\n\n# Features\n\n## Statements\n\nThis is an overview of the language, including limitations related to each statement.\n\n| Statement        | Action                                                                                               |\n| ---------------- | ---------------------------------------------------------------------------------------------------- |\n| `PRINT`          | Prints an expression                                                                                 |\n| `IF`, `ELSE`     | Classical conditional statement. The condition is limited compared to C-style languages, see NOTE 2. |\n| `GOTO`, `GOSUB`  | Go to the specified line, unlike TinyBASIC , this does not support `GOTO \u003cexpression\u003e`               |\n| `INPUT`          | Stores an input into a variable, currently only one digit number are supported                       |\n| `LET`            | Declare a variable. Variables cannot contain strings                                                 |\n| `END` , `RETURN` | Ends the program, this is normally not the semantic for `RETURN`                                     |\n\nNOTE: An expression is a string or an arithmetic expression. Expressions can contain variables,\nand as such, an expression can be a variable. Strings cannot appear in an arithmetic expression.\n\nNOTE 2: A condition is of the form `\u003coperand\u003e \u003crelop\u003e \u003coperand\u003e` where `\u003crelop\u003e` is a relational\noperator and `\u003coperand\u003e` can be a number or a variable, it **cannot** be an expression.\n\nNOTE 3: `INPUT` must really receive one and only one character. This means inputting from the\ncommand line will not work as it also records a `\\n`. Instead you can use `echo -n \"5\" | dump.elf`\n\n## Optimizations\n\nAssembly optimizations can be seen in [`optimize.rs`](src/optimize.rs). It is mostly converting\nan instruction or set of instruction to faster ones.\n\nStructural optimizations, and perhaps the most interesting ones are scattered throughout the code\nin `Optimize` implementations. The major ones are in [`expr.rs`](src/syntax_tree/expr.rs) and\n[`stmt.rs`](src/syntax_tree/stmt.rs). Respectively, they can optimize away arithmetic expressions\nand conditions at compile time.\n\n# Fun\n\nThis compiler outputs multiple files in addition to the executable binary. It actually outputs two\nbinaries:\n\n- `udump.elf`, `u` standing for unoptimized, this is the functioning program without any\n  optimization\n- `dump.elf` is the final file that a compiler would output, this is an executable ELF file with\n  optimizations\n\n## Assembly\n\nIn addition to executable files, this compiler outputs the corresponding assembly code. As for\nexecutables there is `udump.asm` and `dump.asm`.\nThese are also fully functioning, in fact, you can compile them with `nasm`. There is a `make asm`\nrule to compile and link `dump.asm` into `asm.out`.\n\nInterestingly, when compiling with `nasm` you'll notice the file is way bigger than with this\ncompiler (for `opt.tb`, 8.3K after stripping vs 493 bytes). This is mainly due to `nasm` doing its\njob correctly, using multiple sections and aligning them. `xxd asm.out` will reveal the file is mainly zeros.\n\n## [Graphviz](https://graphviz.org/)\n\nFor educational purposes, the parse tree, AST and OST (optimized syntax tree) are dumped using\nGraphviz. Those are very interesting to compare, especially on `opt.rs` which will be stripped of\nunused calculations and statements.\n\n# Project overview\n\nThe code is partially commented. Here is a list of the main modules and files in order of interest.\n\n- [`parser`](src/parser.rs) is the first step of the compiler, it contains the pest generated\n  parser and the grammar\n- [`syntax_tree`](src/syntax_tree.rs) holds the AST and its nodes. It handles their conversion from\n  the parse tree and generation as assembly or Graphviz\n- [`symbol_table`](src/symbol_table.rs) contains the symbol table and its related\n- [`graphviz`](src/graphviz.rs) contains everything related to [Graphviz](https://graphviz.org/)\n\n# Possible improvements\n\nIn no particular order.\n\n- Handle string for `INPUT`\n- Handle numbers greater than 9 for `INPUT`, it is non-trivial to convert integers to string and\n  even harder from string to integer, read syscall only returns what you'd consider a string\n- Put strings in variables\n- Implement `GOSUB` and `RETURN` properly\n- Remove unused assembly functions (`print`, `printn`, `read` in [`syntax_tree.rs`](src/syntax_tree.rs))\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvalentin271%2Ftbc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvalentin271%2Ftbc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvalentin271%2Ftbc/lists"}