{"id":18017924,"url":"https://github.com/zac-garby/booleang","last_synced_at":"2025-04-04T16:18:37.090Z","repository":{"id":116695697,"uuid":"125432685","full_name":"zac-garby/booleang","owner":"zac-garby","description":"A structured boolean-logic language.","archived":false,"fork":false,"pushed_at":"2018-11-29T12:46:09.000Z","size":61,"stargazers_count":1,"open_issues_count":11,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-10T01:43:20.479Z","etag":null,"topics":["boolean","logic","programming-language"],"latest_commit_sha":null,"homepage":null,"language":"Go","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/zac-garby.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}},"created_at":"2018-03-15T22:21:20.000Z","updated_at":"2021-10-21T09:23:34.000Z","dependencies_parsed_at":null,"dependency_job_id":"a535e2c2-0ae3-4d1a-98d4-0962301ebb31","html_url":"https://github.com/zac-garby/booleang","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/zac-garby%2Fbooleang","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zac-garby%2Fbooleang/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zac-garby%2Fbooleang/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zac-garby%2Fbooleang/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zac-garby","download_url":"https://codeload.github.com/zac-garby/booleang/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247208307,"owners_count":20901570,"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":["boolean","logic","programming-language"],"created_at":"2024-10-30T04:26:12.644Z","updated_at":"2025-04-04T16:18:37.072Z","avatar_url":"https://github.com/zac-garby.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# booleang\n\n**Note: as of now, everything in this README is theoretical, as the language isn't implemented yet**\n\nA structured boolean-logic programming language. It uses a completely different paradigm from any other language I've seen before, so it might be difficult to actually use it. The main purpose is for experimenting with boolean logic and logic circuits, and possibly also for testing the logic behind real life circuits.\n\nIn Booleang, your code doesn't really _do_ anything. Instead, it describes a logic circuit. The actual API has one function for constructing the execution graph (essentially that means the logic circuit), and another for stepping the simulation. The size of a step can be defined, and by default it's 1s. There is also a way to automatically step the simulation so the steps are in time with real life.\n\nI'm not entirely sure, but I believe it would be theoretically possible to actually write a fully-fledged CPU using Booleang.\n\n## Example\n\n```\ncircuit main {\n    # set a to low\n    0 -\u003e a;\n\n    # output a\n    obit(a);\n\n    # a 1Hz clock\n    clock 1s {\n        # flip a\n        ¬a -\u003e a;\n    }\n}\n```\n\nThis example defines a register `a` which is initally set to `0`. A register can either be `1` or `0`.\n\n`a` is outputted using the `obit` builtin function, which means that it will be persistantly displayed to the terminal. Running the program will produce this output:\n\n```\na = 0\n```\n\nAny other outputted registers would be displayed below.\n\nAfter outputting it, a 1Hz clock is started. Every second, `a` is flipped, so `0` will turn into `1` and vice versa. The cool thing about booleang is that the output changes, so instead of saying `a = 0`, it will change to say:\n\n```\na = 1\n```\n\nSince `a` retains its state, you could think of it as a D-type flip-flop if you were to recreate the circuit in real life.\n\n## Operators\n\nBooleang supports all the logic operators you'd expect:\n\n```\ncircuit main {\n    # and, or, xor, not\n    a \u0026 b -\u003e c;\n    a | b -\u003e c;\n    a ^ b -\u003e c;\n    !a -\u003e b;\n\n    # unicode equivalents\n    a ∧ b -\u003e c;\n    a ∨ b -\u003e c;\n    a ⊻ b -\u003e c;\n    ¬a -\u003e b;\n}\n```\n\nIt's very likely that more will be added in the future. NAND, for example.\n\n## Circuits\n\nYou've already seen a circuit in the first example of this document. A circuit is basically a function, but called a circuit instead to fit in with the logic circuit theme, and also to emphasise the differences. Like functions, circuits can take arguments. But, unlike functions in most other languages, they return values to specific registers too. Look at this example:\n\n```\ncircuit invert (a) -\u003e (b) {\n    ¬a -\u003e b;\n}\n```\n\nIt's a very simple circuit which takes an argument, `a`, and stores the inverse of it in the output parameter `b`. Think of this circuit like a NOT gate:\n\n![](assets/invert.png)\n\nYou could call the above `invert` circuit using this syntax:\n\n```\ncircuit main {\n    0 -\u003e x;\n    invert (x) -\u003e y;\n    obit(y);\n}\n```\n\nAlso, note: output parameters from circuits don't have to be existing registers. If they aren't already defined, they will be created in the calling scope.\n\nCircuits can have any number of input or output parameters. In \u003cbooleang.bl\u003e, you can see an example of a [full adder](https://en.wikipedia.org/wiki/Adder_%28electronics%29#Full_adder).\n\n## Macros\n\nIt may seem quite unwieldy for all registers to be a single bit, but in practice it doesn't matter. Of course, Booleang isn't really a general purpose language, but either way, you can actually represent any digital data using a number of bits. For example, the number 9 could be represented as 4 bits. In the example below, the number 9 is represented using four registers, `b0` being the least significant bit and `b3` being the most.\n\n```\ncircuit four () -\u003e (b0, b1, b2, b3) {\n    1 -\u003e b0;\n    0 -\u003e b1;\n    0 -\u003e b2;\n    1 -\u003e b3;\n}\n```\n\nFour lines just to make a number? Seriously?? No - of course not. This is a perfect use case for _macros_. Macros are used to group together sets of bits into one name.\n\n```\ncircuit four () -\u003e (b0, b1, b2, b3) {\n    %four (b0, b1, b2, b3);\n    (1, 0, 0, 1) -\u003e %four;\n}\n```\n\nThis piece of code does the exact same thing, but in half the space.\n\n## Numbers\n\nOnce you have a number (see Macros above), what can you do with it? Well, you could output it.\n\n```\ncircuit outputting (b0, b1, b2, b3) -\u003e () {\n    onumu(b0, b1, b2, b3);\n}\n```\n\nThe `onumu` function stands for \"output number unsigned\", and interprets all of its inputs as the bits, from least significant to most significant, as an unsigned integer. If your number is signed, use `onums` (for \"output number signed\") to output it - it is assumed that signed numbers use two's complement.\n\n### Arithmetic\n\nSay you have two integers, `%a` and `%b`. How would you add them?\n\nInside a computer, numbers are added using full adder circuits. Full adders take two bits and a carry, `C in`, and output a sum and another carry, `C out`. A full adder looks like this:\n\n![](assets/full-adder.png)\n\nHere's the same thing written in Booleang. If you've downloaded the interpreter, see if you can write it yourself without looking.\n\n```\ncircuit adder (a, b, cin) -\u003e (sum, cout) {\n    (a ^ b) ^ cin) -\u003e sum;\n    ((a ^ b) \u0026 cin) | (a \u0026 b) -\u003e cout;\n}\n```\n\nThen, to actually add the two integers, you'd make a circuit something like this:\n\n![](assets/4-bit-adder.png)\n\nThis might look quite complicated at first. The orange boxes labelled \"FA\" are full adders, as in the previous circuit diagram. The left input is `C in`, and the top two are `A` and `B` (though technically it doesn't matter what order they're in). The right output is `C out`, and the bottom one is `S`.\n\nThe numbers along the top are the the bits of the numbers 9 and 2 - each pair contains one bit from each number. Somewhat comfusingly, both the input numbers and the output (at the bottom) are in the reverse order of what you'd expect.\n\nThe bits along the bottom are the output. The rightmost output bit is the carry, and isn't in the same order as the other bits (just to confuse you even more). Since the numbers are in reverse order, the output would be read as `01011`, which is of course the binary representation of 11, which is 9 + 2.\n\nNow try to recreate this circuit in Booleang; or, just copy the code below:\n\n```\ncircuit add4 (a0, a1, a2, a3, b0, b1, b2, b3) -\u003e (s0, s1, s2, s3, carry) {\n    adder (a0, b0, 0) -\u003e (s0, c0);\n    adder (a1, b1, c0) -\u003e (s1, c1);\n    adder (a2, b2, c1) -\u003e (s2, c2);\n    adder (a3, b3, carry) -\u003e (s3, c3);\n}\n```\n\nRecall that `a0` is used to denote the least significant bit of the number. And there you have it, a 4-bit adder using just a few AND and OR gates. As a fairly trivial exercise, try converting this to an 8-bit adder and see if it still works.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzac-garby%2Fbooleang","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzac-garby%2Fbooleang","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzac-garby%2Fbooleang/lists"}