Skip to content

Commit

Permalink
ScriptBuilder v2
Browse files Browse the repository at this point in the history
  • Loading branch information
varun-doshi committed Sep 21, 2024
1 parent c4ffe36 commit ac49dae
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 70 deletions.
67 changes: 49 additions & 18 deletions src/script/engine.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
15 changes: 15 additions & 0 deletions src/script/opcodes/constant.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
}
Expand Down
88 changes: 36 additions & 52 deletions src/script/scriptBuilder.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit ac49dae

Please sign in to comment.