{"id":21759181,"url":"https://github.com/cryptorodeo/boar-lang","last_synced_at":"2026-02-18T04:33:32.942Z","repository":{"id":38426728,"uuid":"460415264","full_name":"CryptoRodeo/boar-lang","owner":"CryptoRodeo","description":"Interpreter for a toy programming language, built in Go","archived":false,"fork":false,"pushed_at":"2026-01-14T08:17:25.000Z","size":53688,"stargazers_count":2,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-14T12:12:32.542Z","etag":null,"topics":["go","golang","interpreter","language","programming-language","tree-walk-interpreter"],"latest_commit_sha":null,"homepage":"","language":"Go","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/CryptoRodeo.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-02-17T11:56:44.000Z","updated_at":"2025-01-21T16:29:18.000Z","dependencies_parsed_at":"2025-01-21T17:21:00.754Z","dependency_job_id":"ee13cf3e-cafd-445a-8489-df56f5d44ac2","html_url":"https://github.com/CryptoRodeo/boar-lang","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/CryptoRodeo/boar-lang","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CryptoRodeo%2Fboar-lang","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CryptoRodeo%2Fboar-lang/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CryptoRodeo%2Fboar-lang/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CryptoRodeo%2Fboar-lang/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CryptoRodeo","download_url":"https://codeload.github.com/CryptoRodeo/boar-lang/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CryptoRodeo%2Fboar-lang/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29568550,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-18T04:18:28.490Z","status":"ssl_error","status_checked_at":"2026-02-18T04:13:49.018Z","response_time":162,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: 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":["go","golang","interpreter","language","programming-language","tree-walk-interpreter"],"created_at":"2024-11-26T11:29:41.679Z","updated_at":"2026-02-18T04:33:27.932Z","avatar_url":"https://github.com/CryptoRodeo.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Boar lang 🐗\n\n```\n                  #         \n          # # # # # #       \n      # # #         #       \n    # #             # # #   \n    #                 # # # \n    # #   # # #   # # # #   \n    # # # # # # # # #       \n    # # #     # # # #       \n```\n\nLanguage interpreter for a toy programming, built in Go\n\n![workflow](https://github.com/CryptoRodeo/boar-lang/actions/workflows/workflow.yml/badge.svg)\n\n## Details\nBased on [\"Writing An Interpreter In Go\" by Thorsten Ball](https://interpreterbook.com/) with some extra improvements, such as:\n- The ability to read and evaluate `.br` code files (or trigger the REPL using `--prompt`)\n- Additional built in functions for the Hash and Array objects (inspired from other languages such as Ruby)\n- Standard Object#Function invocation: `someObject.someMethod()` as opposed to `someMethod(someObject)`\n- Variable reassignment (`let x = 3; x = \"hello\"` as opposed to `let x = 3; let x = \"hello\"`)\n- Index reassignment for Arrays and Hashes (`hash[key] = expression`, `arr[index] = expression`)\n- For loops\n- Improved REPL: \n  - evaluate multiple lines\n  - user input history\n  - syntax highlighting\n  - helpful suggestions\n  - exit typing `exit()`\n- Base project refactors\n- Additional dev notes for each interpreter component\n\n## Quick Start Guide:\n\nThe recommended way is to use Docker:\n```\ngit clone git@github.com:CryptoRodeo/boar-lang.git\n\ncd ./boar-lang\n\ndocker build . -t boar-lang\n\ndocker run -it --name=\"boar-lang\" boar-lang\n\n# To start the prompt type './boar --prompt'\n$ ./boar --prompt\nHello boar, (type 'exit()' to exit)\n~\u003e \n\n# running an .br file (a test file exists)\n$ ./boar -f ./test.br\n\n```\n\nYou can also just run it regularly (requires go version \u003e= 1.16):\n```\n# Build executable\ngo build -o boar\n\n# Running the prompt\n$ ./boar --prompt\n\nHello kilgore, (type 'exit()' to exit)\n~\u003e \n\n# Running a .br file (a test file exists)\n$ ./boar -f ./test.br\n\n```\n\n## Language Features:\n\n**Basic math operations:**\n```\n~\u003e 5 + 5\n10\n\n~\u003e 8 * 2\n16\n\n~\u003e (1 \u003e 2) == false\ntrue\n\n~\u003e !true\nfalse\n\n```\n\n**Conditional expressions:**\n```\n~\u003e if (1 \u003e 2) { \"a\" } else { \"b\" }\nb\n```\n\n**Evaluating boolean expresisons:**\n```\n~\u003e 1 \u003c 2\ntrue\n~\u003e true == false\nfalse\n```\n\n**dynamic typing:**\n```\n~\u003e let x = 2\n~\u003e x\n2\n\n~\u003e x = \"hello\"\n~\u003e x\nhello\n```\n\n**string concatenation:**\n```\n~\u003e \"Hello\" + \" \" + \"World\"\nHello World\n```\n\n**Error handling:**\n```\n~\u003e let x\n\n🐗 Error!:\n\u003e expected next token to be =, got EOF instead\n\n~\u003e let arr = [1,2 \n\n🐗 Error!:\n\u003e expected next token to be ], got EOF instead\n\n~\u003e \n```\n\n**functions:**\n```\n~\u003e let adder = fn(a,b) { a + b }\n~\u003e adder(2,3)\n5\n~\u003e fn(x) { x * 2; }(2)\n4\n```\n\n**closures**\n```\n~\u003e let newAdder = fn(x) { fn(y) { x + y } };\n~\u003e let addTwo = newAdder(2);\n~\u003e addTwo(3);\n5\n~\u003e let addThree = newAdder(3);\n~\u003e addThree(5)\n8\n```\n\n**first class functions**\n```\n~\u003e let add = fn(a, b) { a + b };\n~\u003e let sub = fn(a, b) { a - b };\n~\u003e let applyFunc = fn(a, b, func) { func(a, b) };\n~\u003e applyFunc(2, 2, add);\n4\n~\u003e applyFunc(10, 2, sub);\n8\n```\n\n**For loops**\n```\n~\u003e let y = 0;\n~\u003e for (let x = 0; x \u003c 10; x = x + 1) { y = x; };\n~\u003e y\n9\n\n~\u003e for (let a = 0; a \u003c 5; a = a + 1) { puts(a); }\n0\n1\n2\n3\n4\n```\n\n**Arrays:**\n```\n#Creating an array\n~\u003e let x = [1,2,3]\n~\u003e x\n[1, 2, 3]\n\n#Adding to the array\n~\u003e let y = push(x,4)\n~\u003e y\n[1, 2, 3, 4]\n\n#Array::len\n~\u003e len(y)\n4\n~\u003e len(x)\n3\n#Array::len alternative\n~\u003e y.len()\n4\n\n#Array::first\n~\u003e x.first()\n1\n\n#Array::last\n~\u003e y.last()\n4\n\n#Array::[]\n~\u003e x[2]\n3\n\n#Array index assignment\n~\u003e x[2] = \"Hello!\"\nHello!\n~\u003e x\n[1, 2, Hello!]\n\n#Array::map\n~\u003e let arr = [1,2,3]\n~\u003e let addTwo = fn(x) { x + 2; }\n~\u003e let res = arr.map(addTwo)\n~\u003e res\n[3, 4, 5]\n\n#Array::pop\n~\u003e let arr = [1,2,3]\n~\u003e let popVal = arr.pop()\n~\u003e arr\n[1, 2]\n~\u003e popVal\n3\n\n#Array::shift\n~\u003e let tb = [\"Tom\", \"Bombadil\"]\n~\u003e let firstName = tb.shift()\n~\u003e firstName\nTom\n~\u003e tb\n[Bombadil]\n\n#Array::slice\n~\u003e let animals = [\"ant\", \"bison\", \"camel\", \"duck\", \"elephant\"];\n~\u003e animals.slice(2)\n[camel, duck, elephant]\n~\u003e animals.slice(2, 4)\n[camel, duck]\n~\u003e animals.slice()\n[ant, bison, camel, duck, elephant]\n```\n\n**Hash Maps:**\n```\n#Creating a hash\n~\u003e let person = { \"name\": \"John\", \"age\": (2*15) }\n~\u003e person\n{age: 30, name: John}\n\n#Hash::[]\n~\u003e person[\"name\"]\nJohn\n~\u003e person[\"age\"]\n30\n\n#Hash Index/Key assignment\n~\u003e let USDrinkingAge = 21\n~\u003e person[\"age\"] = USDrinkingAge\n21\n~\u003e person[\"age\"]\n21\n\n#Hash::valuesAt\n~\u003e person.valuesAt(\"age\", \"name\")\n[21, John]\n\n#Hash::toArray\n~\u003e person.toArray()\n[name, John, age, 21]\n\n#Hash::delete\n~\u003e person.delete(\"age\")\n{name: John, null: null}\n~\u003e person[\"age\"]\nnull\n\n#Hash::dig\n~\u003e let person = { \"name\": \"Tom Bombadil\", \"clothes\": { \"shoes\": \"yellow boots\" } };\n~\u003e person.dig(\"clothes\", \"shoes\")\nyellow boots\n\n```\n## Implementation Details:\n- This interpreter uses a tree-walking strategy, starting at the top of the AST, traversing every AST Node and then evaluating its statement(s)\n- The parser uses the Vaughan Pratt parsing implementation of associating parsing functions with different token types as well as handling different precedence levels.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcryptorodeo%2Fboar-lang","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcryptorodeo%2Fboar-lang","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcryptorodeo%2Fboar-lang/lists"}