├── .github ├── FUNDING.yml └── workflows │ └── ci.yaml ├── .gitignore ├── .gitmodules ├── CHANGELOG.md ├── LICENSE ├── README.md ├── build.zig ├── build.zig.zon ├── buzz.code-workspace ├── example.png ├── examples ├── 2048.buzz ├── fibonacci.buzz ├── fizzbuzz.buzz ├── game-of-life.buzz ├── sdl-wrapped.buzz ├── sdl.buzz ├── sqlite.buzz └── voronoi-diagram.buzz ├── logo.png ├── package-lock.json ├── package.json ├── src ├── Ast.zig ├── Chunk.zig ├── Codegen.zig ├── FFI.zig ├── Jit.zig ├── Parser.zig ├── Reporter.zig ├── Scanner.zig ├── StringParser.zig ├── Token.zig ├── behavior.zig ├── builtin.zig ├── builtin │ ├── fiber.zig │ ├── list.zig │ ├── map.zig │ ├── pattern.zig │ ├── range.zig │ └── str.zig ├── buzz_api.zig ├── disassembler.zig ├── io.zig ├── jit_extern_api.zig ├── jmp.zig ├── lib │ ├── buffer.buzz │ ├── buzz_api.zig │ ├── buzz_buffer.zig │ ├── buzz_crypto.zig │ ├── buzz_debug.zig │ ├── buzz_ffi.zig │ ├── buzz_fs.zig │ ├── buzz_gc.zig │ ├── buzz_http.zig │ ├── buzz_io.zig │ ├── buzz_math.zig │ ├── buzz_os.zig │ ├── buzz_serialize.zig │ ├── buzz_std.zig │ ├── crypto.buzz │ ├── debug.buzz │ ├── errors.buzz │ ├── ffi.buzz │ ├── fs.buzz │ ├── gc.buzz │ ├── http.buzz │ ├── io.buzz │ ├── io.zig │ ├── jmp.zig │ ├── math.buzz │ ├── mimalloc.zig │ ├── os.buzz │ ├── serialize.buzz │ ├── std.buzz │ ├── testing.buzz │ └── wasm.zig ├── linenoise.zig ├── lsp.zig ├── main.zig ├── memory.zig ├── mimalloc.zig ├── mir.zig ├── obj.zig ├── pcre.zig ├── renderer.zig ├── repl.html ├── repl.zig ├── tests │ └── fmt.zig ├── value.zig ├── vm.zig ├── wasm.ts ├── wasm.zig ├── wasm_repl.zig └── zigtypes.zig └── tests ├── 001-basic-types.buzz ├── 002-operators.buzz ├── 003-control-flow.buzz ├── 004-lists.buzz ├── 005-maps.buzz ├── 006-enums.buzz ├── 007-objects.buzz ├── 008-inline-catch.buzz ├── 009-gc.buzz ├── 010-placeholder-cycle.buzz ├── 011-list-map-properties.buzz ├── 012-lambda.buzz ├── 013-import-export.buzz ├── 014-import-lib.buzz ├── 015-interpolation.buzz ├── 016-optionals.buzz ├── 017-for.buzz ├── 018-foreach.buzz ├── 019-is.buzz ├── 021-upvalues.buzz ├── 022-io.buzz ├── 023-std.buzz ├── 024-os.buzz ├── 025-fs.buzz ├── 026-break-continue.buzz ├── 027-run-file.buzz ├── 028-math.buzz ├── 029-default-arguments.buzz ├── 030-str.buzz ├── 031-json.buzz ├── 032-debug.buzz ├── 033-invoke.buzz ├── 034-scope.buzz ├── 035-const-expr.buzz ├── 036-pattern.buzz ├── 037-dead-branches.buzz ├── 038-fibers.buzz ├── 039-buffer.buzz ├── 040-bitwise.buzz ├── 041-iterator.buzz ├── 042-anonymous-objects.buzz ├── 044-break-continue.buzz ├── 045-mutual-import.buzz ├── 046-try-catch.buzz ├── 047-if-arrow.buzz ├── 048-generics.buzz ├── 049-multiline-strings.buzz ├── 050-protocols.buzz ├── 051-functional.buzz ├── 052-inline-if.buzz ├── 053-range.buzz ├── 056-crypto.buzz ├── 057-any.buzz ├── 058-ffi.buzz ├── 059-types-as-value.buzz ├── 060-free-identifiers.buzz ├── 061-utf8.buzz ├── 062-discarded-value.buzz ├── 063-nullable-default.buzz ├── 064-throw-inside-try.buzz ├── 065-inferred-var-type.buzz ├── 066-object-generics.buzz ├── 068-testing.buzz ├── 069-named-expr.buzz ├── 070-block-expression.buzz ├── 071-tail-call.buzz ├── 072-labels.buzz ├── 073-tuples.buzz ├── 074-checked-subscript.buzz ├── 075-composite-assign.buzz ├── bench ├── 001-btree.buzz ├── 002-merkle.buzz ├── 003-nbody.buzz ├── 004-spectral.buzz ├── 005-k-nucleoide.buzz ├── 006-fasta.buzz ├── 007-fib.buzz ├── 008-for.buzz ├── 009-grid.buzz ├── 010-ackermann.buzz ├── 011-bubble-sort.buzz ├── README.md └── reference │ ├── btree.lua │ ├── fasta-output.txt │ ├── fasta.dart │ ├── fasta.lua │ ├── grid.lua │ ├── k-nucleoide.lua │ ├── knucleotide-input.txt │ └── knucleotide-output.txt ├── compile_errors ├── 001-const.buzz ├── 002-break.buzz ├── 004-not-callable.buzz ├── 005-bad-named-variable-value.buzz ├── 006-deep-yield.buzz ├── 007-yield-location.buzz ├── 008-error-message.buzz ├── 009-bad-named-variable-value.buzz ├── 010-multiple-location.buzz ├── 011-protocol.buzz ├── 012-collect-signature.buzz ├── 013-tostring-signature.buzz ├── 014-main-signature.buzz ├── 015-bad-pattern.buzz ├── 016-unused-local.buzz ├── 017-invalid-int-literal.buzz ├── 018-invalid-float-literal.buzz ├── 019-invalid-int-hex-literal.buzz ├── 020-invalid-int-bin-literal.buzz ├── 021-fiber-error-location.buzz ├── 022-var-decl-without-value.buzz ├── 023-empty-import.buzz ├── 024-misplaced-out.buzz ├── 025-multiple-out.buzz ├── 026-out-last-statement.buzz ├── 027-early-return.buzz ├── 028-unused-import.buzz ├── 029-label-not-found.buzz ├── 030-final-objects.buzz ├── 031-long-tuple.buzz ├── 032-tuple-mix.buzz ├── 033-immutable-list.buzz ├── 034-var-not-assigned.buzz └── utils │ └── bad-import.buzz ├── manual ├── 001-cli-args.buzz ├── 002-error.buzz ├── 003-io.buzz ├── 004-os.buzz ├── 005-tcp-client.buzz ├── 006-http-client.buzz └── 007-fd-poller.buzz └── utils ├── foreign.zig ├── import-a.buzz ├── import-b.buzz └── testing.buzz /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [giann] 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # zig 2 | zig-cache/ 3 | \.zig-cache/ 4 | zig-out/ 5 | zig-test/ 6 | dist/ 7 | 8 | .vscode/ 9 | *.bc 10 | *.s 11 | *.dylib 12 | *.so 13 | *.o 14 | 15 | tests/utils/libforeign.* 16 | buzz_history 17 | 18 | node_modules 19 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "mir"] 2 | path = vendors/mir 3 | url = https://github.com/vnmakarov/mir 4 | [submodule "vendors/pcre2"] 5 | path = vendors/pcre2 6 | url = https://github.com/PCRE2Project/pcre2 7 | [submodule "vendors/mimalloc"] 8 | path = vendors/mimalloc 9 | url = https://github.com/microsoft/mimalloc.git 10 | [submodule "vendors/linenoise"] 11 | path = vendors/linenoise 12 | url = https://github.com/antirez/linenoise.git 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright © 2021-present Benoit Giannangeli 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |
3 |
10 |
11 |
", message: "Can read n bytes");
40 |
41 | file.close();
42 | }
43 |
--------------------------------------------------------------------------------
/tests/023-std.buzz:
--------------------------------------------------------------------------------
1 | import "std";
2 |
3 | test "std\parseInt/Double" {
4 | std\assert(std\parseInt("12") == 12, message: "Could parse int");
5 | std\assert(std\parseDouble("12.42") == 12.42, message: "Could parse double");
6 | std\assert(std\parseInt("not a number") == null, message: "Doesn't parse stupid shit");
7 |
8 | std\assert(std\toInt(23.34) == 23, message: "Could cast double to int");
9 | std\assert(std\toDouble(23) == 23.0, message: "Could cast int to double");
10 | std\assert(std\toUd(23) is ud, message: "Could cast int to ud");
11 | std\assert(std\toUd(23.0) is ud, message: "Could cast double to ud");
12 |
13 | std\assert(std\parseUd("42") == std\toUd(42), message: "Could parse ud");
14 | }
15 |
16 | test "char" {
17 | std\assert(std\char(65) == "A", message: "char");
18 | }
19 |
20 | test "random" {
21 | std\assert(std\random(min: 5, max: 10) >= 5, message: "random range");
22 | std\assert(std\random(max: 10) <= 10, message: "random range");
23 | }
24 |
--------------------------------------------------------------------------------
/tests/024-os.buzz:
--------------------------------------------------------------------------------
1 | import "std";
2 | import "os" as os;
3 |
4 | test "os\env" {
5 | std\assert(os\env("HOME") != null, message: "could get env variable");
6 | }
7 |
8 | test "os\time" {
9 | std\assert(os\time() > 0, message: "Got time");
10 | }
11 |
12 | test "os\tmpDir" {
13 | // TODO: replace by .len check
14 | std\assert(os\tmpDir() != "", message: "Got system tmp dir");
15 | }
16 |
17 | test "os\tmpFilename" {
18 | std\assert(os\tmpFilename("buzz_test") != "", message: "Got tmp file name");
19 | }
20 |
21 | test "os\execute" {
22 | std\assert(os\execute([ "./zig-out/bin/buzz", "--version" ]) == 0, message: "Could execute a command");
23 | }
24 |
25 | test "os\sleep" {
26 | os\sleep(500.0);
27 | }
28 |
--------------------------------------------------------------------------------
/tests/025-fs.buzz:
--------------------------------------------------------------------------------
1 | import "std";
2 | import "fs" as fs;
3 |
4 | test "fs\cwd" {
5 | std\assert(fs\currentDirectory() != "", message: "Could get cwd");
6 | }
7 |
8 | test "mkDir/rm" {
9 | fs\makeDirectory("yo");
10 | fs\makeDirectory("{fs\currentDirectory()}/yo2");
11 |
12 | fs\delete("yo");
13 | fs\delete("{fs\currentDirectory()}/yo2");
14 | }
15 |
16 | test "ls" {
17 | var containsREADME = false;
18 | foreach (el in fs\list(fs\currentDirectory())) {
19 | _ = "hello there!";
20 | if (el == "README.md") {
21 | containsREADME = true;
22 | break;
23 | }
24 | }
25 |
26 | final anotherRandomLocal = "bye there!";
27 |
28 | std\assert(anotherRandomLocal == "bye there!", message: "foreach break is wrong");
29 |
30 | std\assert(containsREADME, message: "Could list element in current directory");
31 |
32 | foreach (el in fs\list("/doesnotexist") catch [ "wentwrong" ]) {
33 | std\assert(el == "wentwrong", message: "Trying to list a non existent directory raised an error");
34 | }
35 |
36 | std\assert(fs\exists("README.md"), message: "fs\\exists");
37 | }
38 |
39 | test "move" {
40 | fs\move(source: "README.md", destination: "src/README.md");
41 |
42 | std\assert(
43 | fs\list("src").indexOf("README.md") != null,
44 | message: "Moved file to expected location",
45 | );
46 |
47 | fs\move(source: "src/README.md", destination: "README.md");
48 |
49 | std\assert(
50 | fs\list(".").indexOf("README.md") != null,
51 | message: "Moved file to expected location",
52 | );
53 | }
54 |
--------------------------------------------------------------------------------
/tests/026-break-continue.buzz:
--------------------------------------------------------------------------------
1 | import "std";
2 |
3 | test "break statement" {
4 | var i = 0;
5 | while (i < 10) {
6 | i = i + 1;
7 |
8 | if (i == 3) {
9 | break;
10 | }
11 | }
12 |
13 | std\assert(i == 3, message: "break");
14 | }
15 |
16 | test "continue statement" {
17 | var i = 0;
18 | while (i < 10) {
19 | i = i + 1;
20 |
21 | if (i == 3) {
22 | continue;
23 | }
24 |
25 | i = i + 1;
26 | }
27 |
28 | std\assert(i == 11, message: "break");
29 | }
30 |
--------------------------------------------------------------------------------
/tests/027-run-file.buzz:
--------------------------------------------------------------------------------
1 | import "std";
2 | import "io";
3 |
4 | test "runFile" {
5 | io\runFile("tests/utils/testing.buzz");
6 |
7 | std\assert(true, message: "Could run a buzz file");
8 | }
9 |
10 | test "run non existent file" {
11 | var errorRaised = false;
12 | try {
13 | io\runFile("tests/utils/testingsldkfj.buzz");
14 | } catch {
15 | errorRaised = true;
16 | }
17 |
18 | std\assert(errorRaised, message: "Non existent file raised an error");
19 | }
20 |
--------------------------------------------------------------------------------
/tests/028-math.buzz:
--------------------------------------------------------------------------------
1 | import "std";
2 | import "math" as math;
3 |
4 | test "math" {
5 | std\assert(math\abs(-12.234) == 12.234, message: "math\\abs");
6 | std\assert(math\acos(0.1) == 1.4706289056333368, message: "math\\acos");
7 | std\assert(math\asin(0.1) == 0.1001674211615598, message: "math\\asin");
8 | std\assert(math\atan(0.1) == 0.09966865249116204, message: "math\\atan");
9 | std\assert(math\ceil(12.234) == 13, message: "math\\ceil");
10 | std\assert(math\cos(12.234) == 0.9452715049027691, message: "math\\cos");
11 | std\assert(math\exp(12.234) == 205664.19575705, message: "math\\exp");
12 | std\assert(math\floor(12.234) == 12, message: "math\\floor");
13 | std\assert(math\sin(12.234) == -0.3262848173281347, message: "math\\sin");
14 | std\assert(math\sqrt(12.234) == 3.4977135388707863, message: "math\\sqrt");
15 | std\assert(math\tan(12.234) == -0.34517576763481983, message: "math\\tan");
16 |
17 | std\assert(math\minInt(a: 12, b: 124) == 12, message: "math\\min");
18 | std\assert(math\maxInt(a: 12, b: 124) == 124, message: "math\\max");
19 |
20 | std\assert(math\deg(2.0) == 114.59155902616439, message: "math\\deg");
21 | std\assert(math\rad(math\deg(2.0)) == 2, message: "math\\rad");
22 | }
23 |
--------------------------------------------------------------------------------
/tests/029-default-arguments.buzz:
--------------------------------------------------------------------------------
1 | import "std";
2 |
3 | fun hey(name: str = "Joe", age: int = 12, father: str?, fourth: int = 1) > str => "Hello {name} you're {age} {father} {fourth}";
4 |
5 | test "function default arguments" {
6 | std\assert(hey("John") == "Hello John you're 12 null 1", message: "Could reorder or omit argument");
7 | std\assert(hey(age: 25) == "Hello Joe you're 25 null 1", message: "Could reorder or omit argument");
8 | std\assert(hey(father: "Doe") == "Hello Joe you're 12 Doe 1", message: "Could reorder or omit argument");
9 | std\assert(hey(fourth: 42) == "Hello Joe you're 12 null 42", message: "Could reorder or omit argument");
10 | std\assert(hey(fourth: 12, age: 44) == "Hello Joe you're 44 null 12", message: "Could reorder or omit argument");
11 | }
12 |
--------------------------------------------------------------------------------
/tests/030-str.buzz:
--------------------------------------------------------------------------------
1 | import "std";
2 |
3 | test "str subscript" {
4 | std\assert("hello world"[1] == "e", message: "str subscript");
5 | }
6 |
7 | test "str.len" {
8 | std\assert("hello world".len() == 11, message: "str.len");
9 | }
10 |
11 | test "str.byte" {
12 | std\assert("hello world".byte(1) == 101, message: "str.byte");
13 | }
14 |
15 | test "str.indexOf" {
16 | std\assert("hello world".indexOf("world") == 6, message: "str.indexOf");
17 | std\assert("hello world".indexOf("moon") == null, message: "str.indexOf");
18 | }
19 |
20 | test "str.split" {
21 | final splits = "one,two,three".split(",");
22 |
23 | std\assert(splits[0] == "one" and splits[1] == "two" and splits[2] == "three", message: "str.split");
24 | }
25 |
26 | test "str.sub" {
27 | std\assert("hello world".sub(6) == "world", message: "str.sub");
28 | std\assert("hello world".sub(0, len: 5) == "hello", message: "str.sub");
29 | }
30 |
31 | test "base64" {
32 | std\assert("hello world".encodeBase64() == "aGVsbG8gd29ybGQ=", message: "could encode in b64");
33 | std\assert("aGVsbG8gd29ybGQ=".decodeBase64() == "hello world", message: "could encode in b64");
34 | }
35 |
36 | test "upper/lower" {
37 | std\assert("hello world!".upper() == "HELLO WORLD!", message: "upper");
38 | std\assert("HellO WorlD!".lower() == "hello world!", message: "lower");
39 | }
40 |
41 | test "hex/bin" {
42 | std\assert("c3fcd3d76192e4007dfb496cca67e13b".bin().hex() == "c3fcd3d76192e4007dfb496cca67e13b", message: "hex/bin");
43 | }
44 |
45 | test "trim" {
46 | std\assert(" hello world \t\n".trim() == "hello world", message: "could trim str");
47 | }
48 |
--------------------------------------------------------------------------------
/tests/031-json.buzz:
--------------------------------------------------------------------------------
1 | import "std";
2 | import "serialize";
3 |
4 | test "Json.encode" {
5 | final data = {
6 | "hello": "world",
7 | "bye": 42,
8 | };
9 |
10 | std\assert(
11 | serialize\jsonEncode(serialize\Boxed.init(data)) == `\{"hello":"world","bye":42}`,
12 | message: "valid encode",
13 | );
14 | }
15 |
16 | test "Json.decode" {
17 | std\assert(
18 | serialize\jsonDecode(`[ -12, true, "hello" ]`).listValue()[2].string() == "hello",
19 | message: "could decode simple JSON",
20 | );
21 | }
22 |
23 | test "Boxed.q" {
24 | final data = {
25 | "submap": {
26 |