{"id":18774500,"url":"https://github.com/mmzk1526/haskell-while-code","last_synced_at":"2025-12-14T10:30:17.021Z","repository":{"id":100268463,"uuid":"418224422","full_name":"MMZK1526/Haskell-WHILE-Code","owner":"MMZK1526","description":"Implement the WHILE language introduced in the Imperial College Course Models of Computation","archived":false,"fork":false,"pushed_at":"2023-10-12T08:47:45.000Z","size":121,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-12-29T08:43:23.015Z","etag":null,"topics":["functional-programming","haskell","interpreter","simulator"],"latest_commit_sha":null,"homepage":"","language":"Haskell","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/MMZK1526.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":"2021-10-17T18:42:59.000Z","updated_at":"2023-05-13T20:55:57.000Z","dependencies_parsed_at":"2024-11-07T19:41:16.303Z","dependency_job_id":"3527fcb7-8cde-48a8-871c-928b4782932a","html_url":"https://github.com/MMZK1526/Haskell-WHILE-Code","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MMZK1526%2FHaskell-WHILE-Code","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MMZK1526%2FHaskell-WHILE-Code/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MMZK1526%2FHaskell-WHILE-Code/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MMZK1526%2FHaskell-WHILE-Code/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MMZK1526","download_url":"https://codeload.github.com/MMZK1526/Haskell-WHILE-Code/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239680989,"owners_count":19679509,"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":["functional-programming","haskell","interpreter","simulator"],"created_at":"2024-11-07T19:38:26.852Z","updated_at":"2025-12-14T10:30:16.583Z","avatar_url":"https://github.com/MMZK1526.png","language":"Haskell","readme":"Author: MMZK1526 *et ut* Yitang Chen\n\n# While Language\n## Introduction\nThe ```While Language``` is a simple Turing-Complete language introduced in the Imperial College Course *Models of Computation*. I have made an interpreter in ```Haskell``` for this language.  \n\nHere I am going to introduce the syntax of the language. If you want to know how to use the interpreter straight away, go [here](#while-intepreter-cli).\n\nThe language is originally defined as the following in the course:\n\n```\nC ::= C; C | v := E | if B then C else C | while B do C | Skip\n```\n\nwhere\n\n```\nB ::= true | false | not B | B or B | B and B | E \u003c E | E = E | E \u003e E | ...\nE ::= n | v | E + E | E * E | ...\n```\n\n```v``` is a variable and ```n``` is an integer.\n\nI have modified it so that ```E``` and ```B``` are combined, but the types still matter, *i.e.* ```false + 3``` results in a type error:  \n\n```\nC ::= C; C | v := E | if E then C else C | while E do C | Skip | return [E]\nE ::= true | false | not E | E or E | E and E | E \u003c E | E = E | E \u003e E | E != E | E \u003c= E | E \u003e= E | n | v | E + E | E * E | E - E | E / E | E % E\n```\n\nI have introduced a number of new operators as well as extended the range of ```n``` to $\\mathbb Z$ instead of $\\mathbb N$. Notably, there is a ```return``` syntax. In the original ```While```, the answer configuration is always ```\u003cSkip, s\u003e```, in other word, the information is solely reflected by the context[^1] ```s```. Here by adding ```return```, we can have another answer configuraton ```\u003creturn E, s\u003e```, where ```E``` is either an integer or a boolean, so that we don't have to look into the context to see a result. As you may have anticipated, the ```return``` command terminates the entire program.  \n\n## Syntax\nThe syntax of my ```While``` code resembles ```python``` in the sense that no variable declarations and semicolons are required, but with several variations.  \n\nFirstly, every instruction/expression cannot span across several lines. Therefore, it's recommended to split long expressions into several separate expressions.  \n\nSecondly, one block of indentation must be exactly 2 spaces. I am planning to relax on this restriction.  \n\nThirdly, paranthesis are not allowed for ```if``` and ```while``` statements.  For example, we cannot write ```if(x \u003e 2)```, only ```if x \u003e 2```. We can add colons at the end (as in ```python```), but that is entirely optional.  \n\nIn ```While```, line comments start with ```:)```. There are no block comments.  \n\nThe following are the allowed operators in ```While```:  \n| Symbol | Meaning | Note |\n|--------|---------|------|\n|   `+`    |  Plus   |      |\n|   `-`    |  Minus  |      |\n|   `*`    | Multiply |     |\n|   `/`    | Divide  | rounded towards zero|\n|   `%`    |   Mod   |      |\n|  `:=`    | Assignment | similar to ```=``` in most languages |\n|`\u003c`| Less Than |we don't allow inequalities between boolean values|\n|`\u003e`|Greater Than|we don't allow inequalities between boolean values|\n|`\u003c=`|Less Than or Equal To|we don't allow inequalities between boolean values|\n|`\u003e=`|Greater Than or Equal To|we don't allow inequalities between boolean values|\n|`==`|Equal To|can also be written as `=`|\n|`!=`|Not Equal To| |\n|`\u0026\u0026`|And|can also be written as `\u0026`|\n|`⎮⎮`[^2]|Or|can also be written as `⎮`|\n|`!`|Not| |\n|`:`|Optional ending of a `if`, `else` or `while` statement| |\n\n[^2]: Note that the symbol in the table (```⎮```) is not actually the vertical bar (```|```), however, the latter confuses the markdown table and cannot be rendered properly.  \n\nThe following are the reserved words in ```While```:  \n| Word | Meaning | Note |\n|------|---------|------|\n|`true`|  Boolean TRUE |      |\n|`false`|Boolean FALSE||\n|`if`|If Statement||\n|`else`|The (optional) other branch of `if`||\n|`elif`|Similar to `else if`|without this, nested if would be a pain|\n|`while`|While Statement||\n|`return`|Terminate the program and returns value|if returning a value, the keyword can be omitted|\n\nThe body of a control flow can be empty, which is denoted by an empty line (or a comment).  \n\n[^1]: In the course, the partial function that records the variables are called \"state\", but here we use the term \"context\" to differentiate it from the ```State``` Monad that is widely used in my implementation.  \n\n# While Intepreter CLI\nTo use the CLI, we need to have `ghc` and `cabal`:\n\n```bash\ncabal run whilei -- [arguments]\n```\n\nHere is an example of running and debugging a simple [factorial function](#Example). The full documentaton can be found [here](#Documentation).  \n\nNote that when ran without any arguments, we would start the [While Interactive Shell](#while-interactive-shell).  \n\n## Example\nThe most basic way of using the CLI is to first navigate to the root directory of this repo (namely the same folder as [Main.hs](Main.hs)), then run the following:  \n\n```cabal run whilei -- filename [arg1=val1 arg2=var2 ...]```\n\nFor example, we have a [factorial example](Examples/factorial.while) which takes a parameter ```x``` and returns the factorial of this number. For how to write your own ```While`` code, see [Syntax](#Syntax).  \n\nWe can use the ```While``` program to calculate ```3!``` by running the following:\n\n```\n\u003e cabal run whilei -- Examples/factorial.while x:=3\nResult: 6\n```\n\nWe can also pass in a debug option. The most basic option is ```-d```, which would start an interactive debugger where we can go through the evaluation step by step:  \n\n```\n\u003e cabal run whilei -- -d Examples/factorial.while x:=3\nPress 'x' to dump the context.\nPress 's' to go to the next step.\nPress Enter to go to the next line.\nPress 'r' to go straight to the result.\nPress 'q' to quit.\n\nStep 0:\na := 1\nwhile x \u003e 0\n  a := a * x\n  x := x - 1\nreturn a\n\u003e s\nStep 1:\n[DO NOTHING]\nwhile x \u003e 0\n  a := a * x\n  x := x - 1\nreturn a\n\u003e x\nContext: [(\"a\",1),(\"x\",3)]\nRules applied :[E_ASSIGN_VAL]\n\u003e s\nStep 2:\nwhile x \u003e 0\n  a := a * x\n  x := x - 1\nreturn a\n\u003e x\nContext: [(\"a\",1),(\"x\",3)]\nRules applied :[E_SKIP]\n\u003e r\nProgram completed after 47 steps!\nResult: 6\nContext: [(\"a\",6),(\"x\",0)]\n```\n\nNote that after entering ```x```, the debugger will dump the current context as well as the rules used in that particular step of calculation.  \n\nWe can also dump out the entire steps with the ```--debug=full``` option:   \n\n```\n\u003e cabal run whilei -- --debug=full Examples/factorial.while x:=1\nStep 0:\na := 1\nwhile x \u003e 0\n  a := a * x\n  x := x - 1\nreturn a\n\nStep 1:\n[DO NOTHING]\nwhile x \u003e 0\n  a := a * x\n  x := x - 1\nreturn a\n\nStep 2:\nwhile x \u003e 0\n  a := a * x\n  x := x - 1\nreturn a\n\nStep 3:\nif x \u003e 0\n  a := a * x\n  x := x - 1\n  while x \u003e 0\n    a := a * x\n    x := x - 1\nreturn a\n\nStep 4:\nif 1 \u003e 0\n  a := a * x\n  x := x - 1\n  while x \u003e 0\n    a := a * x\n    x := x - 1\nreturn a\n\nStep 5:\nif true\n  a := a * x\n  x := x - 1\n  while x \u003e 0\n    a := a * x\n    x := x - 1\nreturn a\n\nStep 6:\na := a * x\nx := x - 1\nwhile x \u003e 0\n  a := a * x\n  x := x - 1\nreturn a\n\nStep 7:\na := 1 * x\nx := x - 1\nwhile x \u003e 0\n  a := a * x\n  x := x - 1\nreturn a\n\nStep 8:\na := 1 * 1\nx := x - 1\nwhile x \u003e 0\n  a := a * x\n  x := x - 1\nreturn a\n\nStep 9:\na := 1\nx := x - 1\nwhile x \u003e 0\n  a := a * x\n  x := x - 1\nreturn a\n\nStep 10:\n[DO NOTHING]\nx := x - 1\nwhile x \u003e 0\n  a := a * x\n  x := x - 1\nreturn a\n\nStep 11:\nx := x - 1\nwhile x \u003e 0\n  a := a * x\n  x := x - 1\nreturn a\n\nStep 12:\nx := 1 - 1\nwhile x \u003e 0\n  a := a * x\n  x := x - 1\nreturn a\n\nStep 13:\nx := 0\nwhile x \u003e 0\n  a := a * x\n  x := x - 1\nreturn a\n\nStep 14:\n[DO NOTHING]\nwhile x \u003e 0\n  a := a * x\n  x := x - 1\nreturn a\n\nStep 15:\nwhile x \u003e 0\n  a := a * x\n  x := x - 1\nreturn a\n\nStep 16:\nif x \u003e 0\n  a := a * x\n  x := x - 1\n  while x \u003e 0\n    a := a * x\n    x := x - 1\nreturn a\n\nStep 17:\nif 0 \u003e 0\n  a := a * x\n  x := x - 1\n  while x \u003e 0\n    a := a * x\n    x := x - 1\nreturn a\n\nStep 18:\nif false\n  a := a * x\n  x := x - 1\n  while x \u003e 0\n    a := a * x\n    x := x - 1\nreturn a\n\nStep 19:\n[DO NOTHING]\nreturn a\n\nStep 20:\nreturn a\n\nStep 21:\nreturn 1\n\nContext: [(\"a\",1),(\"x\",0)]\n```\n\nNote that this option does not dump the context after each step.  \n\nThere are more examples in the \\Examples folder, feel free to try them out!  \n\n## Documentation\nThe most general form of command-line arguments looks like the following:  \n\n```cabal run whilei -- [-h] [--debug=full|step] \u003cwhile_code.txt\u003e [\u003cargument_name\u003e:=\u003cvalue\u003e] [...]```\n\nWhere ```\u003cwhile_code.txt\u003e``` is the path of the ```While``` sourcecode. For the syntax of the language, see [Syntax](#Syntax).  \n\nIf the code has undefined variables, we need to pass them as command-line arguments in the form of ```[\u003cargument_name\u003e:=\u003cvalue\u003e]```. For example, if the code contains undefined ```x``` and ```y```, we may pass in ```x:=1 \"y := 3 * 2\"```. Here we can also simplify ```:=``` to ```=```, but this is **NOT** allowed in ```While``` sourcecode as ```=``` there has the same semantic as ```==```.  \n\nWe can pass an expression to the right-hand side of ```:=```, but they must not contain another variable, even if the latter is previously assigned, thus ```x:=1 y:=3*x``` is illegal.  \n\nThe argument assignments must occur after the path of the sourcecode, otherwise there are no requirement of arguments ordering. The CLI always interprets the first non-option argument as the path, and the following non-option arguments as assignments.  \n\nThe following are the available options:  \n\n* ```--help``` or `-h`: Show the help page. If this option is present, other options are ignored.  \n* ```--debug```: Debugging options. If multiple ```--debug``` options are passed in, the first one is used.  \n  * ```--debug=none```: No debugging; simply prints out the result. Default config.  \n  * ```--debug=step``` or `-d`: Starts an interactive debugger that can print out the next step or show current context and rules applied on user input. See [While Debugger](#while-debugger) for more information.  \n  * ```--debug=all```: Prints out all intermediate steps at once, showing the answer configuration. It does not dump the context after each step.  \n\nApart from the options, we can also run it without any input, which would invoke the [While Interactive Shell](#while-interactive-shell).  \n\n## While Debugger\nTo use the debugger, pass the `-d` option.  \n\nIn the debugger, we can track every small-step of evaluation and shows the code after each transformation. We can also look at the variable states as well as the small-step rules being applied.  \n\nThe following are the options within the debugger:  \n\n* `x` or `dump`: Show the current context. Will dump out all variables as well as the rules applied in the latest step.  \n\n* `s` or `step`: Conduct one small-step evaluation.   \n\n* `l` or `line` or enter: Evaluate to the next line of code.  \n\n* `r` or `return` or `result`: Go straight to the result.  \n\n* `q` or `quit`: Quit the debugger.  \n\n## While Interactive Shell\nTo start the Interactive Shell (REPL), run the CLI without argument:  \n\n```cabal run whilei```\n\nThen we can type in any `While` expressions and instructions. For example:  \n\n```\n\u003e cabal run whilei\nWelcome to the While Interactive Shell.\nType in any expression/code or press ':q' to quit.\n\u003e 3 + 5  \n8\n\u003e x := 11\n\u003e \n\u003e while x \u003e 1:\n  \u003e x := x - 3\n  \u003e \n\u003e x\n-1\n\u003e \n\u003e :q\n```\n\nNote that indentations are handled automatically; to outdent, simply enter an empty line. The Interactive Shell outputs results when the latest expression has a value (*i.e* not an assignment) and the current indentations level is zero.  \n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmmzk1526%2Fhaskell-while-code","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmmzk1526%2Fhaskell-while-code","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmmzk1526%2Fhaskell-while-code/lists"}