{"id":19502079,"url":"https://github.com/vmmc2/bleach","last_synced_at":"2025-09-17T19:22:19.954Z","repository":{"id":247957747,"uuid":"782026816","full_name":"vmmc2/Bleach","owner":"vmmc2","description":"The implementation of my undergraduate thesis: \"Bleach: A programming language aimed for teaching Compilers.\"","archived":false,"fork":false,"pushed_at":"2024-12-08T21:46:09.000Z","size":878,"stargazers_count":33,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-25T23:34:46.375Z","etag":null,"topics":["compilers","cpp","educational-project","educational-software","interpreters","programming-language"],"latest_commit_sha":null,"homepage":"https://vmmc2.github.io/Bleach-Docs/","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/vmmc2.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,"zenodo":null}},"created_at":"2024-04-04T13:53:00.000Z","updated_at":"2024-12-19T17:17:31.000Z","dependencies_parsed_at":"2024-07-23T04:29:46.345Z","dependency_job_id":"fa7f7139-36b6-4435-b338-ac8b25778410","html_url":"https://github.com/vmmc2/Bleach","commit_stats":null,"previous_names":["vmmc2/bleach"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/vmmc2/Bleach","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vmmc2%2FBleach","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vmmc2%2FBleach/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vmmc2%2FBleach/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vmmc2%2FBleach/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vmmc2","download_url":"https://codeload.github.com/vmmc2/Bleach/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vmmc2%2FBleach/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275649402,"owners_count":25503208,"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","status":"online","status_checked_at":"2025-09-17T02:00:09.119Z","response_time":84,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["compilers","cpp","educational-project","educational-software","interpreters","programming-language"],"created_at":"2024-11-10T22:15:01.450Z","updated_at":"2025-09-17T19:22:19.936Z","avatar_url":"https://github.com/vmmc2.png","language":"C++","readme":"# Bleach\n\n## Intro\n* __The implementation of my undergraduate thesis to obtain my Bachelor's degree in Computer Engineering at Universidade Federal de Pernambuco (UFPE), located in Brazil: \"Bleach: A programming language aimed for teaching Compilers.\"__ \n  * __Author/Student: Victor Miguel de Morais Costa__\n  * __Advisor: Leopoldo Motta Teixeira__\n\n\n## What is Bleach?\n* Bleach is programming language whose main purpose is help students learn and practice concepts from an introductory \"Compilers\" or \"Programming Language Implementation\" course in a way that feels more interesting and rewarding to the students. By using Bleach, the students will be able to learn the foundational ideas of compilers, programming language design and programming language implementation, such as:\n  01. Scanning (Lexing)\n  02. Code Representation\n  03. Parsing\n  04. Expression Evaluation\n  05. Statements and State\n  06. Control Flow Structures\n  07. Functions\n  08. Resolving and Binding\n  09. Classes\n  10. Inheritance\n\n\n## Who is the target audience of this project?\n* The main audience are professors, instructors and teaching assistants that are responsible for lecturing any undergraduate level 'Compilers' course.\n* Hobbists and people interested in the Compilers, Interpreters or Programming Languages.\n* __A note for the main audience: Please note that even if this interpreter for the Bleach language was written in C++, it does not limit any professor or instructor to choose another language (whether it's C, Haskell, Ocaml, Python, Racket, Scheme, SML or any other) to make assignments for their students so they can make their own implementation of Bleach. Feel free and encouraged to do so.__\n\n\n## Why use Bleach?\n* As said previously, Bleach is a programming language whose focus is on concepts. This means that the language will have features (mentioned above) that make it interesting for the students.\n* The language implementation is made with the purpose of being clean and simple to understand. Thus, we can focus on the semantics of Bleach, instead of wasting time coding hacks and tricks or \"leaving thigs as an exercise for the reader/student\".\n* By adopting this approach, it's expected that it will make us, students, more comfortable with basic and essential techniques used in the implementation of a programming language. Moreover, this approach will also improve our understanding of how exactly the language is supposed to behave.\n\n\n## Examples of simple yet useful programs written in Bleach\n1. Hello, World!\n```ts\nfunction greet(){\n  print \"Hello, World!\"; // \"Hello, World!\"\n  std::io::print(\"Hello, World!\"); // \"Hello, World!\"\n}\n\ngreet();\n```\n\n2. Factorial\n```ts\nfunction factorial(n){\n  if(n == 0){\n    return 1;\n  }\n\n  return n * factorial(n - 1);\n}\n\nstd::io::print(factorial(5)); // 120\n```\n\n3. Fibonacci\n```ts\nfunction fibonacci(n) {\n  if(n \u003c= 0){\n    return 0;\n  }elif(n == 1){\n    return 1;\n  }else{\n    return fibonacci(n - 1) + fibonacci(n - 2);\n  }\n}\n\nlet n = 10;\nlet result = fibonacci(n);\nstd::io::print(\"The\", n, \"th Fibonacci number is:\", result);\n```\n\n4. Basic Arithmetic Operations\n```ts\nlet a = 5;\nlet b = 6;\n\nlet sum = a + b;\nlet difference = a - b;\nlet product = a * b;\nlet quotient = a / b;\nlet remainder = a % b;\n\nstd::io::print(\"Sum:\", sum); // 11\nstd::io::print(\"Difference:\", difference); // -1\nstd::io::print(\"Product:\", product); // 30\nstd::io::print(\"Quotient:\", quotient); // 0.833333333333333\nstd::io::print(\"Remainder:\", remainder); // 5\n```\n\n5. Logical Control Flow\n```ts\nlet number = 42;\n\nif(number \u003e 0){\n  std::io::print(\"Positive Number.\"); // \"Positive Number.\"\n}elif(number \u003c 0){\n  std::io::print(\"Negative Number.\");\n}else{\n  std::io::print(\"Zero.\");\n}\n```\n\n6. Loop Control Flow I\n```ts\nlet count = 5;\n\nwhile(count \u003e 0){\n    std::io::print(\"Countdown:\", count);\n    count = count - 1;\n}\nstd::io::print(\"BOOM!\"); // \"BOOM!\"\n```\n\n7. Loop Control Flow II\n```ts\nlet counter = 1;\n\ndo{\n  std::io::print(\"Counter is:\", counter);\n  counter = counter + 1;\n}while(count \u003c= 5);\n```\n\n8. Loop Control Flow III\n```ts\nfor(let i = 1; i \u003c= 5; i = i + 1){\n    std::io::print(\"Current Iteration:\", i);\n}\n\nstd::io::print(\"For loop execution has ended!\");\n```\n\n9. Get User Input\n```ts\nstd::io::print(\"Enter your name:\");\n\nlet name = std::io::readLine();\n\nlet greeting = \"Hello, \" + name + \"!\";\n\nstd::io::print(greeting);\n```\n\n10. String Manipulation\n```ts\nlet first_name = \"John\";\nlet last_name = \"Doe\";\n\nlet full_name = first_name + \" \" + last_name;\nstd::io::print(\"The full name of the person is:\", full_name);\n```\n\n11. Class, Inheritance and Instances Usage\n```ts\n// Base class\nclass Shape {\n  method init(name){\n    self.name = name;\n  }\n\n  method area(){\n    // To be overridden by subclasses\n    return 0;\n  }\n\n  method describe() {\n    return \"This is a \" + self.name;\n  }\n}\n\n// Derived class: Circle\nclass Circle inherits Shape {\n  method init(radius){\n    // Call the base class constructor\n    super.init(\"Circle\");\n    self.radius = radius;\n  }\n\n  method area(){\n    return std::math::pow(self.radius, 2) * 3.14159;\n  }\n}\n\n// Derived class: Rectangle\nclass Rectangle inherits Shape {\n  method init(width, height){\n    // Call the base class constructor\n    super.init(\"Rectangle\");\n    self.width = width;\n    self.height = height;\n  }\n\n  method area(){\n    return self.width * self.height;\n  }\n}\n\n// Derived class: Triangle\nclass Triangle inherits Shape {\n  method init(base, height) {\n    // Call the base class constructor\n    super.init(\"Triangle\");\n    self.base = base;\n    self.height = height;\n  }\n\n  method area(){\n    return (self.base * self.height) / 2;\n  }\n}\n\n// Create instances of each shape\nlet circle = Circle(5);\nlet rectangle = Rectangle(4, 6);\nlet triangle = Triangle(3, 7);\n\n// Print descriptions and areas.\nstd::io::print(circle.describe(), \"with area:\", circle.area());\nstd::io::print(rectangle.describe(), \"with area:\", rectangle.area());\nstd::io::print(triangle.describe(), \"with area:\", triangle.area());\n```\n\n\n## Bleach Language Documentation\n* You can read the official documentation of the Bleach language here: [Bleach Official Documentation](https://vmmc2.github.io/Bleach-Docs/)\n\n\n## Bleach Language Syntax Highlight Visual Studio Code Extension\n* You can install the official Bleach Syntax Highlight extension for Visual Studio Code here: [Bleach Official Syntax Highlight Extension for VS Code](https://marketplace.visualstudio.com/items?itemName=VictorMigueldeMoraisCosta.bleach-language-syntax-highlight)\n* __Remember that a Bleach file must have the ```.bch``` extension. Otherwise, the extension won't work properly.__\n\n\n## How to build the Bleach Tree-Walk Interpreter?\n1. Clone this repository in your local machine.\n2. Go to the ```Bleach``` root directory. Then, execute the following commands inside it at the console/terminal:\n```sh\ncd scripts\nchmod +x bleach_build.sh\n```\n3. Execute the script that builds the Bleach Tree-Walk Interpreter:\n```sh\n./bleach_build.sh\n```\n\n\n## How to run the Bleach Tree-Walk Interpreter?\n1. Execute the script that starts up the Bleach Tree-Walk Interpreter:\n```sh\n./bleach_run.sh # Executes the interpreter in the interactive mode (REPL mode).\n./bleach_run.sh absolute_or_relative_path_to_a_bch_file # Executes the interpreter with the code written inside a Bleach file (\".bch\" extension).\n```\n\n\n## How to clean the built Bleach Tree-Walk Interpreter?\n1. Go to the ```Bleach``` root directory. Then, execute the following commands inside it at the console/terminal:\n```sh\ncd scripts\nchmod +x bleach_clean.sh\n```\n2. Execute the script that cleans the build of the Bleach Tree-Walk Interpreter (if any is present):\n```sh\n./bleach_clean.sh\n```\n\n\n## How to run the unit tests of the Bleach Tree-Walk Interpreter?\n1. Go to the ```Bleach``` root directory. Then, execute the following commands inside it at the console/terminal:\n```sh\ncd scripts\nchmod +x bleach_test_pipeline.sh\n```\n3. Execute the script that run all of the unit tests related to the Bleach Tree-Walk Interpreter:\n```sh\n./bleach_test_pipeline.sh\n```\n\n\n## The undergraduate thesis\n* If you are interested in checking out what motivated me to do this project, the thought process to make the project decisions during the whole thing, then you are more than welcomed to take a look at: [Bleach Thesis Repo](https://github.com/vmmc2/Bleach-Thesis)\n\n\n## Current State of the Bleach Language Context-Free Grammar\n* __Now loops (```for```, ```do-while```, ```while```) must be followed by a block.__\n```txt\nprogram → statement* EOF\nstatement → block | breakStmt | classDeclStmt | continueStmt | doWhileStmt | exprStmt | forStmt | funcDeclStmt | ifStmt | printStmt | returnStmt | varDeclStmt | whileStmt\nblock → \"{\" statement* \"}\"\nbreakStmt → \"break\" \";\"\nclassDeclStmt → \"class\" IDENTIFIER ( \"inherits\" IDENTIFIER )? \"{\" methodDeclStmt* \"}\"\nmethodDeclStmt → \"method\" method\nmethod → IDENTIFIER \"(\" parameters? \")\" block\ncontinueStmt → \"continue\" \";\"\ndoWhileStmt → \"do\" block \"while\" \"(\" expression \")\" \";\"\nexprStmt → expression \";\"\nforStmt → \"for\" \"(\" ( varDecl | exprStmt | \";\" ) expression? \";\" expression? \")\" block\nfuncDeclStmt → \"function\" function\nfunction → IDENTIFIER \"(\" parameters? \")\" block\nparameters → IDENTIFIER ( \",\" IDENTIFIER )*\nifStmt → \"if\" \"(\" expression \")\" statement\n         ( \"elif\" \"(\" expression \")\" statement )*\n         ( \"else\" statement )?\nprintStmt → \"print\" expression \";\"\nreturnStmt → \"return\" expression? \";\"\nvarDeclStmt → \"let\" IDENTIFIER ( \"=\" expression )? \";\"\nwhileStmt → \"while\" \"(\" expression \")\" block\nexpression → assignment\nassignment → ( call \".\" )? IDENTIFIER \"=\" assignment | ternary\nternary → logic_or ( \"?\" expression \":\" expression )*\nlogic_or → logic_and ( \"or\" logic_and )*\nlogic_and → equality ( \"and\" equality )*\nequality → comparison ( ( \"!=\" | \"==\" ) comparison )*\ncomparison → term ( ( \"\u003e\" | \"\u003e=\" | \"\u003c\" | \"\u003c=\" ) term )*\nterm → factor ( ( \"-\" | \"+\" ) factor )*\nfactor → unary ( ( \"/\" | \"*\" | \"%\" ) unary )*\nunary → ( \"!\" | \"-\" ) unary | call\ncall → primary ( \"(\" arguments? \")\" | \".\" IDENTIFIER )*\narguments → expression ( \",\" expression )*\nprimary → \"true\" | \"false\" | \"nil\" | NUMBER | STRING | \"(\" expression \")\" | \"[\" (expression ( \",\" expression )*)? \"]\" | lambdaFunctionExpr | IDENTIFIER | \"super\" . IDENTIFIER\nlambdaFunctionExpr → \"lambda\" \"-\u003e\" \"(\" parameters? \")\" block\n```\n\n\n## Why was Bleach written in C++?\n* The implementation of the Bleach Interpreter was written in C++ due to a couple of reasons which include, but are not restricted to:\n  * __Educational Value:__  C++ provides a solid foundation in many concepts of Computer Science, such as: memory management, data structures, and low-level programming concepts. These concepts are transferable to many other languages and also deepen one's understanding of programming in general.\n  * __Execution Speed:__ While the interpreter itself might not need to execute code as quickly as an application built for real-time processing or high-performance computing, it's still desirable for it to be efficient. This efficiency can manifest in faster parsing, optimization, and execution of the code written in the interpreted language. Since C++ is a high-performance language, it can contribute to faster execution of these tasks, resulting in quicker interpretation of code.\n  * __Familiarity:__ One could argue that another language like Haskell, OCaml, Racket, Scheme or SML is more suitable for this task. However I don't consider myself proficient enough in such language to tackle a project of this scope. Moreover, in my point of view, implementing Bleach in C++ is a good idea because most students have already worked with either in their \"Introduction to Programming\", \"Algorithms \u0026 Data Structures\" or \"Operating Systems\" course. Thus, they don't need to learn a new language just to understand the code written here. Also, the performance of an implementation is an important aspect, so it makes sense for, me at least, to use C++.\n  * __Industry Adoption:__ This reason is specially aimed to those that, like me, want to work in this field of Computer Science. Nowadays, C++ is the 'lingua franca' in it. Some examples to highlight this are:\n    * __Clang:__ C, C++, and Objective-C compiler front-end for the LLVM compiler infrastructure. Known for its fast compile times and excelent error diagnostics.\n    * __Chromium V8:__ Google's open-source JavaScript runtime engine, used in the Chrome browser and Node.js.\n    * __g++:__ The C++ front-end of the GCC compiler, also written in C++.\n    * __LLVM (Low Level Virtual Machine):__ A compiler infrastructure project that includes a collection of modular and reusable compiler and toolchain components. While LLVM itself is written in C++, it provides support for multiple programming languages.\n    * __MSVC (Microsoft Visual C++ Compiler):__ A part of the famous Visual Studio IDE.\n\n\n\u003c!--\n## LLVM Version of the Bleach Language (Not priority right now)\n### Initial Setup\n1. On the root folder of your machine:\n```shell\ngit clone git@github.com:llvm/llvm-project.git\n```\n2. Then run the following commands:\n```shell\ncd llvm-project\nmkdir build\ncd build\n```\n3. Run the following build command: \n```shell\ncmake ../llvm -G \"Unix Makefiles\" -DCMAKE_INSTALL_PREFIX=~/llvm-project/build -DBUILD_SHARED_LIBS=on -DLLVM_ENABLE_PROJECTS=clang -DCMAKE_BUILD_TYPE=Release\n```\n4. Finally:\n```shell\nmake\n```\n--\u003e\n\n\u003c!--\n## Doubts\n* __What is the diference between using a variable and refering to a variable?__\n* __Is it really okay to let a variable be re-declared in the global scope? Not convinced by the author.__\n* __Differences between scopes and environments (the author says they are \"close cousins\"). Also, the author later mentions that scope is a concept/idea and environment is something concrete that implements such concept.__\n* __What is necessary to claim that a programming language is Turing-Complete? In other words, what exactly is Turing-Completeness? According to the author, the programming language needs to have the following features implemented:__\n  * __Arithmetic__\n  * __A little control-flow (what does \"little\" even mean in this context?)__\n  * __The ability to allocate arbitrary amounts of memory__\n* __What is the formal and precise definition of scope in the programming language field? The author, Bob Nystrom, says, in chapter 11, that scope is a set of declarations. Therefore, if two sets don't have the same declarations, then they are not the same scope. Is this correct?__\n* When dealing with \"Get\" expression, the author says the following: \"Since properties are looked up dynamically, they don’t get resolved\". What does this mean?\n--\u003e\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvmmc2%2Fbleach","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvmmc2%2Fbleach","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvmmc2%2Fbleach/lists"}