{"id":15681047,"url":"https://github.com/healeycodes/nodots-lang","last_synced_at":"2025-05-07T08:10:42.081Z","repository":{"id":112378174,"uuid":"588105728","full_name":"healeycodes/nodots-lang","owner":"healeycodes","description":"𝐧𝐝 A small programming language with an interpreter, and a WebAssembly compiler.","archived":false,"fork":false,"pushed_at":"2024-06-08T07:44:39.000Z","size":365,"stargazers_count":14,"open_issues_count":1,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-31T08:01:39.633Z","etag":null,"topics":["lark-parser","tree-walk-interpreter"],"latest_commit_sha":null,"homepage":"https://healeycodes.com/profiling-and-optimizing-an-interpreter","language":"Python","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/healeycodes.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-01-12T10:40:39.000Z","updated_at":"2024-10-22T11:27:14.000Z","dependencies_parsed_at":"2024-06-08T08:43:09.069Z","dependency_job_id":"e81a6620-cc7d-444e-8909-630797136ade","html_url":"https://github.com/healeycodes/nodots-lang","commit_stats":{"total_commits":59,"total_committers":1,"mean_commits":59.0,"dds":0.0,"last_synced_commit":"a030fb932078ea4c48f0472efad71975625f54d3"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/healeycodes%2Fnodots-lang","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/healeycodes%2Fnodots-lang/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/healeycodes%2Fnodots-lang/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/healeycodes%2Fnodots-lang/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/healeycodes","download_url":"https://codeload.github.com/healeycodes/nodots-lang/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252839294,"owners_count":21812090,"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":["lark-parser","tree-walk-interpreter"],"created_at":"2024-10-03T16:48:27.231Z","updated_at":"2025-05-07T08:10:42.064Z","avatar_url":"https://github.com/healeycodes.png","language":"Python","readme":"[![Tests](https://github.com/healeycodes/nodots-lang/actions/workflows/python-app.yml/badge.svg)](https://github.com/healeycodes/nodots-lang/actions/workflows/python-app.yml)\n\n# nodots lang\n\u003e My blog posts:\n\u003e - [Adding a Line Profiler to My Language](https://healeycodes.com/adding-a-line-profiler-to-my-language)\n\u003e - [A Custom WebAssembly Compiler](https://healeycodes.com/a-custom-webassembly-compiler)\n\u003e - [Profiling and Optimizing an Interpreter](https://healeycodes.com/profiling-and-optimizing-an-interpreter)\n\u003e - [Adding For Loops to an Interpreter](https://healeycodes.com/adding-for-loops-to-an-interpreter)\n\n\u003cbr\u003e\n\nA small programming language without any dots called **nodots**. There are two versions of this language; static types and a custom WebAssembly compiler (w/ type checking), and dynamic types with a tree-walk interpreter. Both use [Lark](https://lark-parser.readthedocs.io/en/latest/index.html) for parsing.\n\nSource files typically have the `.nd` file extension.\n\n\u003cbr\u003e\n\n## WebAssembly Compiler (static types)\n\n`compiler.py` is a WebAssembly compiler (w/ type checking) that outputs WebAssembly Text. See `grammar_static.py` for the grammar.\n\nThis version is more experimental than the interpreter but you can compile and run an example program with:\n\n```text\npip3 install -r requirements.txt\n./compile.sh\n```\n\nThe example program is a naive algorithm that calculates the n-th Fibonacci number. It requires ~243k function calls and runs 4000x quicker in the compiled version.\n\n```text\nfn fib(i32 n) -\u003e i32\n  if (n == 0)\n    return 0;\n  fi\n  if (n == 1)\n    return 1;\n  fi\n  return fib(n - 1) + fib(n - 2);\nnf\n```\n\nThe binary of this program is 134 bytes when encoded in base64. This is much smaller than: a Python runtime, the Lark parsing library, and a 1k LOC interpreter!\n\n\u003cbr\u003e\n\n## Interpreter (dynamic types)\n\n`interpreter.py` is a tree-walk interpreter. See `grammar.py` for the grammar.\n\nHere's an example program (see `tests.py` for more examples).\n\n```python\n# booleans\n(true or false) and !true;\n\n# numbers!\n(2 * 2) / 4 == 0;\n1 \u003c 2;\n-(8 * 8) \u003e -65;\n\n# strings!\nlog(\"Hello, World!\");\n\n# variables!\nsome_var = 2;\n\n# lists!\nsome_list = list(-1, 3, 4);\nat(some_list, 0); # -1\nmut(some_list, 0, -2); # as in _mutate_\nat(some_list, 0); # -2\njoin(list(1), list(2)); # [1, 2]\nlen(list(1, 2, 3)); # 3\n\n# dictionaries!\nsome_dict = dict(\"a\", 2, \"b\", 3); # (k, v, k, v, ...)\nmut(some_dict, \"a\", \"hi!\");\nat(some_dict, \"a\"); # \"hi!\"\n\n# (also)\nkeys(some_dict);\nvals(some_dict);\n\n# loops!\nsum = 0;\nfor (i = 0; i \u003c 5; i = i + 1)\n  sum = sum + i;\nrof\nlog(sum);\n\n# functions!\nfun some_func(b, c)\n  return b * c;\nnuf\nsome_func(some_var, 5);\n\n# naive fibonacci\nfun fib(x)\n  if (x == 0 or x == 1)\n    return x;\n  fi\n  return fib(x - 1) + fib(x - 2);\nnuf\nfib(10);\n\n# closures!\nfun closure()\n  z = 0;\n  fun inner()\n    z = z + 1;\n    return z;\n  nuf\n  return inner;\nnuf\nclosure()(); # 1\n\n# i/o!\nwrite(\"./foo\", \"bar\");\ndata = read_all(\"./foo\");\n\nfun read_function(chunk)\n  log(chunk);\nnuf\nread(\"./foo\", read_function);\n```\n\n### Install\n\n`pip3 install -r requirements.txt`\n\n### Run\n\n`python3 cli.py sourcefile`\n\n### Line Profiler\n\n`python3 cli.py --profile sourcefile`\n\n### Tests\n\n`./test.sh`\n\n- Mypy type checking\n- Tests programs\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhealeycodes%2Fnodots-lang","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhealeycodes%2Fnodots-lang","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhealeycodes%2Fnodots-lang/lists"}