From 3671a69600994e1686a0d62e07049a565c58d463 Mon Sep 17 00:00:00 2001 From: Will Medrano Date: Sun, 25 Aug 2024 13:43:09 -0700 Subject: [PATCH] Add instructions on how to import. --- build.zig | 7 +++++ site/CHANGELOG.md | 2 +- site/index.md | 4 +-- site/zig-api.md | 65 ++++++++++++++++++++++++++++++++++------------- src/Vm.zig | 9 +++++++ 5 files changed, 66 insertions(+), 21 deletions(-) diff --git a/build.zig b/build.zig index 01a7f86..825f7dc 100644 --- a/build.zig +++ b/build.zig @@ -32,6 +32,13 @@ pub fn build(b: *std.Build) void { check_step.dependOn(&check_exe.step); check_step.dependOn(&check_test.step); + // Module: fizz + _ = b.addModule("fizz", .{ + .root_source_file = b.path("src/root.zig"), + .target = target, + .optimize = optimize, + }); + // Command: zig build run const run_cmd = b.addRunArtifact(exe); run_cmd.step.dependOn(b.getInstallStep()); diff --git a/site/CHANGELOG.md b/site/CHANGELOG.md index 518c28f..4ae593d 100644 --- a/site/CHANGELOG.md +++ b/site/CHANGELOG.md @@ -26,7 +26,7 @@ Will focus on: - Improved error reporting. - Incorporating user feedback. -- Performance tweaks. +- Performance & API tweaks. ### 0.1.0 (Current) diff --git a/site/index.md b/site/index.md index 1c0d2cf..fabfb22 100644 --- a/site/index.md +++ b/site/index.md @@ -56,8 +56,8 @@ Fizz is built in Zig and meant to easily integrate into a Zig codebase. const fizz = @import("fizz"); var vm = try fizz.Vm.init(std.testing.allocator); defer vm.deinit(); -_ = try vm.evalStr(std.testing.allocator, "(define args (list 1 2 3 4))"); -const v = try vm.evalStr(std.testing.allocator, "args"); + +const v = try vm.evalStr(std.testing.allocator, "(list 1 2 3 4)"); const actual = try vm.env.toZig([]i64, std.testing.allocator, v); defer std.testing.allocator.free(actual); try std.testing.expectEqualDeep(&[_]i64{ 1, 2, 3, 4 }, actual); diff --git a/site/zig-api.md b/site/zig-api.md index 922be85..9f4a13f 100644 --- a/site/zig-api.md +++ b/site/zig-api.md @@ -9,11 +9,18 @@ nav_order: 1 ## Quickstart -In the following example, we: - -1. Add fizz as a dependency. - > TODO -1. Create the Fizz virtual machine. +1. Download Fizz and place it in `build.zig.zon`. + ```sh + zig fetch --save https://github.com/wmedrano/fizz/archive/refs/tags/0.1.0.tar.gz + ``` +1. Add Fizz as a dependency in `build.zig`. + ```zig + const fizz = b.dependency("fizz", .{ + .target = target, + .optimize = optimize, + }); + ``` +1. Create the Fizz virtual machine in your code, for example, `src/main.zig`. ```zig const fizz = @import("fizz"); var vm = try fizz.Vm.init(allocator); @@ -21,20 +28,24 @@ In the following example, we: ``` 1. Run some code within the virtual machine. ```zig - _ = try vm.EvalStr(allocator, "(define magic-numbers (list 1 2 3 4))"); - const val = try vm.evalStr( - allocator, - "(struct 'numbers magic-numbers 'numbers-sum (apply + magic-numbers))"); + const src = \\ + \\ (define magic-numbers (list 1 2 3 4)) + \\ (struct + \\ 'numbers magic-numbers + \\ 'numbers-sum (apply + magic-numbers) + \\ ) + ; + const val = try vm.EvalStr(allocator, src); ``` 1. Convert VM values into Zig. ```zig - const ResultType = struct { numbers: []const i64, numbers_sum: i64 }; - const result = try vm.env.toZig( - ResultType, - allocator, - val, - ); - defer allocator.free(result.numbers); + const ResultType = struct { numbers: []const i64, numbers_sum: i64 }; + const result = try vm.env.toZig( + ResultType, + allocator, + val, + ); + defer allocator.free(result.numbers); ``` 1. Run the garbage collector from time to time. ```zig @@ -64,17 +75,35 @@ try vm.runGc(); defer vm.deinit(); ``` +## Evaluating Expressions + +Expressions can be evaluated with `vm.evalStr`. The value of the returned +`fizz.Val` is guaranteed to exist until the next garbage collection run. See +[Extracting Values](#extracting-values) to extend the lifetime of the returned +values. + +```zig +fn evalStr(self: *fizz.Vm, tmp_allocator: std.mem.Allocator, expr: []const u8) fizz.Val +``` + +- `self`: Pointer to the virtual machine. +- `tmp_allocator`: Allocator used for temporary memory for AST and ByteCode + compiler. +- `expr`: Lisp expression to evaluate. If multiple expressions are provided, the + returned `fizz.Val` will contain the value of the final expression. + + ## Extracting Values Values are extracted using `vm.env.toZig`. ```zig -fn toZig(self: *Env, comptime T: type, allocator: Allocator, val: Val) !T +fn toZig(self: *fizz.Env, comptime T: type, allocator: std.mem.Allocator, val: fizz.Val) !T ``` - `self`: A pointer to the environment. - `T`: The desired output Zig type. -- `allocator`: Memory allocator for dynamic memory allocation +- `allocator`: Memory allocator for any string or slice allocations. - `val`: The input value to be converted **Example** diff --git a/src/Vm.zig b/src/Vm.zig index af1e76c..51c238b 100644 --- a/src/Vm.zig +++ b/src/Vm.zig @@ -107,6 +107,15 @@ test "can eval basic expression" { try std.testing.expectEqual(1, vm.env.runtime_stats.function_calls); } +test "multiple expressions returns last expression" { + var vm = try Vm.init(std.testing.allocator); + defer vm.deinit(); + const actual = try vm.evalStr(std.testing.allocator, "4 5 6"); + try vm.env.runGc(); + try std.testing.expectEqual(Val{ .int = 6 }, actual); + try std.testing.expectEqual(1, vm.env.runtime_stats.function_calls); +} + test "can deref symbols" { var vm = try Vm.init(std.testing.allocator); defer vm.deinit();