From ac49daed361f7755875abfbe4a84330b3bdecfd8 Mon Sep 17 00:00:00 2001 From: varun-doshi Date: Sat, 21 Sep 2024 20:15:41 +0530 Subject: [PATCH] ScriptBuilder v2 --- src/script/engine.zig | 67 ++++++++++++++++++------- src/script/opcodes/constant.zig | 15 ++++++ src/script/scriptBuilder.zig | 88 ++++++++++++++------------------- 3 files changed, 100 insertions(+), 70 deletions(-) diff --git a/src/script/engine.zig b/src/script/engine.zig index f95a539..fb0a0d0 100644 --- a/src/script/engine.zig +++ b/src/script/engine.zig @@ -56,11 +56,11 @@ pub const Engine = struct { /// Log debug information fn log(self: *Engine, comptime format: []const u8, args: anytype) void { _ = self; - // _ = format; - // _ = args; + _ = format; + _ = args; // Uncomment this if you need to access the log // In the future it would be cool to log somewhere else than stderr - std.debug.print(format, args); + // std.debug.print(format, args); } /// Execute the script @@ -843,25 +843,56 @@ test "Script execution - OP_SHA256" { try std.testing.expectEqualSlices(u8, expected_hash[0..], hash_bytes); } -test "Build engine" { - var allocator = std.testing.allocator; +test "ScriptBuilder Smoke test" { + const allocator = std.testing.allocator; var sb = try ScriptBuilder.new(allocator); + sb.deinit(); + + var engine = try (try (try (try sb.pushInt(1)).pushInt(2)).pushOpcode(Opcode.OP_ADD)).build(); - try sb.pushInt(&allocator, 1); - // _ = try r.pushInt(&allocator, 1); - try sb.pushInt(&allocator, 1); - try sb.pushOpcode(&allocator, Opcode.OP_ADD); - std.debug.print("sb:{any}\n", .{sb}); - var engine = try sb.build(&allocator); defer engine.deinit(); try std.testing.expectEqual(@as(usize, 1), engine.stack.len()); - // // Check the stack elements - // const element0 = try engine.stack.peekInt(0); - // const element1 = try engine.stack.peekInt(1); - // const element2 = try engine.stack.peekInt(2); - // const element3 = try engine.stack.peekInt(3); - defer sb.deinit(&allocator); - // std.debug.print("hello"); + defer sb.deinit(); +} + +//METHOD 1 +test "ScriptBuilder OP_SWAP METHOD 1" { + var sb = try ScriptBuilder.new(std.testing.allocator); + + var engine = try (try (try (try (try sb.pushInt(1)).pushInt(2)).pushInt(3)).pushOpcode(Opcode.OP_SWAP)).build(); + + defer engine.deinit(); + defer sb.deinit(); + + try std.testing.expectEqual(@as(usize, 3), engine.stack.len()); + + const element0 = try engine.stack.peekInt(0); + const element1 = try engine.stack.peekInt(1); + + try std.testing.expectEqual(2, element0); + try std.testing.expectEqual(3, element1); +} +//METHOD 2 +test "ScriptBuilder OP_SWAP METHOD 2" { + var sb = try ScriptBuilder.new(std.testing.allocator); + + //requirement to assign to _ can be removed + _ = try sb.pushInt(1); + _ = try sb.pushInt(2); + _ = try sb.pushInt(3); + _ = try sb.pushOpcode(Opcode.OP_SWAP); + var engine = try sb.build(); + + defer engine.deinit(); + defer sb.deinit(); + + try std.testing.expectEqual(@as(usize, 3), engine.stack.len()); + + const element0 = try engine.stack.peekInt(0); + const element1 = try engine.stack.peekInt(1); + + try std.testing.expectEqual(2, element0); + try std.testing.expectEqual(3, element1); } diff --git a/src/script/opcodes/constant.zig b/src/script/opcodes/constant.zig index 70a0219..26e083e 100644 --- a/src/script/opcodes/constant.zig +++ b/src/script/opcodes/constant.zig @@ -367,6 +367,21 @@ pub const Opcode = enum(u8) { pub fn pushOpcode(num: u8) Opcode { return switch (num) { 1 => Opcode.OP_1, + 2 => Opcode.OP_2, + 3 => Opcode.OP_3, + 4 => Opcode.OP_4, + 5 => Opcode.OP_5, + 6 => Opcode.OP_6, + 7 => Opcode.OP_7, + 8 => Opcode.OP_8, + 9 => Opcode.OP_9, + 10 => Opcode.OP_10, + 11 => Opcode.OP_11, + 12 => Opcode.OP_12, + 13 => Opcode.OP_13, + 14 => Opcode.OP_14, + 15 => Opcode.OP_15, + 16 => Opcode.OP_16, else => Opcode.OP_0, }; } diff --git a/src/script/scriptBuilder.zig b/src/script/scriptBuilder.zig index 3675367..af22a3f 100644 --- a/src/script/scriptBuilder.zig +++ b/src/script/scriptBuilder.zig @@ -7,89 +7,73 @@ const ScriptNum = Script.ScriptNum; const asBool = Script.asBool; const asInt = Script.asInt; const testing = std.testing; - +///ScriptBuilder is a library to generate easier scripts, useful for faster testing pub const ScriptBuilder = struct { + /// Number of opcodes in the script(this is not a necessary field and may be removed later) opcodeCount: u8, + + /// Dynamic array holding the opcodes opcodes: []u8, + ///Memory Allocator + allocator: Allocator, + + /// Initialize a new ScriptBuilder + /// + /// # Arguments + /// - `allocator`: Memory allocator for managing engine resources + /// + /// # Returns + /// - `!ScriptBuilder`: use with `try` pub fn new(allocator: std.mem.Allocator) !ScriptBuilder { return ScriptBuilder{ .opcodeCount = 0, .opcodes = try allocator.alloc(u8, 0), + .allocator = allocator, }; } - pub fn pushOpcode(self: *ScriptBuilder, allocator: *Allocator, op: Opcode) !void { + ///Push an OPcode to the ScriptBuilder + pub fn pushOpcode(self: *ScriptBuilder, op: Opcode) !*ScriptBuilder { // Resize the array to add one more element - const newOpcodes = try allocator.realloc(self.opcodes, self.opcodeCount + 1); + const newOpcodes = try self.allocator.realloc(self.opcodes, self.opcodeCount + 1); + newOpcodes[self.opcodeCount] = op.toBytes(); self.opcodes = newOpcodes; self.opcodeCount += 1; - // return self; + return self; } - pub fn pushInt(self: *ScriptBuilder, allocator: *Allocator, num: u8) !void { - const newOpcodes = try allocator.realloc(self.opcodes, self.opcodeCount + 1); + ///Push an Int to the SciptBuilder + /// OP_1...OP_16 + pub fn pushInt(self: *ScriptBuilder, num: u8) !*ScriptBuilder { + const newOpcodes = try self.allocator.realloc(self.opcodes, self.opcodeCount + 1); const op = Opcode.pushOpcode(num); newOpcodes[self.opcodeCount] = op.toBytes(); self.opcodes = newOpcodes; self.opcodeCount += 1; - // return self; + return self; } - pub fn deinit(self: *ScriptBuilder, allocator: *Allocator) void { + /// Deallocate all resources used by the Engine + pub fn deinit(self: *ScriptBuilder) void { if (self.opcodes.len > 0) { - allocator.free(self.opcodes); + self.allocator.free(self.opcodes); } } - pub fn build(self: *ScriptBuilder, allocator: *Allocator) !engine.Engine { + ///Execute the script. It creates an engine and executes the opcodes. + /// + /// Returns + /// Instance of the engine + pub fn build(self: *ScriptBuilder) !engine.Engine { const script = Script.init(self.opcodes); - var script_engine = engine.Engine.init(allocator.*, script, .{}); + var script_engine = engine.Engine.init(self.allocator, script, .{}); try script_engine.execute(); return script_engine; } }; -test "ScriptBuilder" { - var allocator = std.testing.allocator; - var sb = try ScriptBuilder.new(allocator); - defer sb.deinit(&allocator); - - std.debug.print("sb:{any}\n", .{sb}); -} -test "ScriptBuilder push" { - var allocator = std.testing.allocator; - - var sb = try ScriptBuilder.new(allocator); - defer sb.deinit(&allocator); - - // const op0: u8 = Opcode.Op_1; - - _ = try sb.pushOpcode(&allocator, Opcode.OP_0); - _ = try sb.pushInt(&allocator, 1); - - std.debug.print("sb:{any}\n", .{sb}); -} - -// test "Build engine" { -// var allocator = std.testing.allocator; -// var sb = try ScriptBuilder.new(allocator); - -// try sb.pushOpcode(&allocator, Opcode.OP_0); -// try sb.pushInt(&allocator, 1); - -// std.debug.print("sb:{any}\n", .{sb}); -// const e = try sb.build(&allocator); - -// try std.testing.expectEqual(@as(usize, 2), e.stack.len()); - -// // // Check the stack elements -// // const element0 = try engine.stack.peekInt(0); -// // const element1 = try engine.stack.peekInt(1); -// // const element2 = try engine.stack.peekInt(2); -// // const element3 = try engine.stack.peekInt(3); -// defer sb.deinit(&allocator); -// // std.debug.print("hello"); -// } +// zig function chaining issue +// https://github.com/ziglang/zig/issues/5705