implementing more native functions

This commit is contained in:
Patrick MARIE 2024-08-29 10:53:22 +02:00
parent a2200debb4
commit 7ed6cf6dcc
4 changed files with 76 additions and 10 deletions

3
samples/native_power.lox Normal file
View File

@ -0,0 +1,3 @@
print power(str2num("3"),str2num("3"));
print str2num("3") + str2num("4");

64
src/native.zig Normal file
View File

@ -0,0 +1,64 @@
const std = @import("std");
const Obj = @import("./object.zig").Obj;
const Value = @import("./values.zig").Value;
const VM = @import("./vm.zig").VM;
pub fn clock(vm: *VM, arg_count: usize, args: []Value) Value {
_ = vm;
_ = arg_count;
_ = args;
const ts = std.time.milliTimestamp();
return Value.number_val(@floatFromInt(ts));
}
pub fn power(vm: *VM, arg_count: usize, args: []Value) Value {
_ = vm;
if (arg_count != 2) {
std.debug.print("power() is expecting 2 arguments.\n", .{});
return Value.nil_val();
}
if (!args[0].is_number() or !args[0].is_number()) {
std.debug.print("args must be numbers.\n", .{});
return Value.nil_val();
}
const result_f64: f64 = std.math.pow(f64, args[0].as_number(), args[1].as_number());
return Value.number_val(result_f64);
}
pub fn str2num(vm: *VM, arg_count: usize, args: []Value) Value {
_ = vm;
if (arg_count != 1 or !args[0].is_string()) {
std.debug.print("str2num() is expecting 1 string argument.\n", .{});
return Value.nil_val();
}
const result = std.fmt.parseFloat(f64, args[0].as_cstring()) catch {
std.debug.print("invalid string for number.\n", .{});
return Value.nil_val();
};
return Value.number_val(result);
}
pub fn num2str(vm: *VM, arg_count: usize, args: []Value) Value {
if (arg_count != 1 or !args[0].is_number()) {
std.debug.print("num2str() is expecting 1 number argument.\n", .{});
return Value.nil_val();
}
const str = std.fmt.allocPrint(vm.allocator, "{d}", .{args[0].as_number()}) catch {
std.debug.print("unable to convert number to string.\n", .{});
return Value.nil_val();
};
const result = Obj.String.new(vm.allocator, str);
return Value.obj_val(result);
}

View File

@ -4,6 +4,7 @@ const Allocator = std.mem.Allocator;
const Chunk = @import("./chunk.zig").Chunk; const Chunk = @import("./chunk.zig").Chunk;
const Value = @import("./values.zig").Value; const Value = @import("./values.zig").Value;
const VM = @import("./vm.zig").VM;
const compute_hash = @import("./utils.zig").compute_hash; const compute_hash = @import("./utils.zig").compute_hash;
@ -13,7 +14,7 @@ pub const ObjType = enum {
Native, Native,
}; };
pub const NativeFn = *const fn (arg_count: usize, args: []Value) Value; pub const NativeFn = *const fn (vm: *VM, arg_count: usize, args: []Value) Value;
pub const Obj = struct { pub const Obj = struct {
kind: ObjType, kind: ObjType,

View File

@ -12,6 +12,8 @@ const ObjType = @import("./object.zig").ObjType;
const NativeFn = @import("./object.zig").NativeFn; const NativeFn = @import("./object.zig").NativeFn;
const Table = @import("./table.zig").Table; const Table = @import("./table.zig").Table;
const natives = @import("./native.zig");
const compile = @import("./compile.zig").compile; const compile = @import("./compile.zig").compile;
const compute_hash = @import("./utils.zig").compute_hash; const compute_hash = @import("./utils.zig").compute_hash;
@ -56,7 +58,9 @@ pub const VM = struct {
} }
pub fn init_vm(self: *VM) void { pub fn init_vm(self: *VM) void {
self.define_native("clock", clock_native); self.define_native("clock", natives.clock);
self.define_native("power", natives.power);
self.define_native("str2num", natives.str2num);
} }
pub fn destroy(self: *VM) void { pub fn destroy(self: *VM) void {
@ -386,8 +390,9 @@ pub const VM = struct {
ObjType.Native => { ObjType.Native => {
const native_obj: *Obj.Native = callee.as_obj().as_native(); const native_obj: *Obj.Native = callee.as_obj().as_native();
const value = native_obj.native( const value = native_obj.native(
self,
arg_count, arg_count,
self.stack[self.current_frame().slots_idx - arg_count .. self.current_frame().slots_idx], self.stack[self.stack_top - arg_count .. self.stack_top],
); );
self.stack_top -= arg_count + 1; self.stack_top -= arg_count + 1;
_ = try self.push(value); _ = try self.push(value);
@ -431,11 +436,4 @@ pub const VM = struct {
_ = self.pop(); _ = self.pop();
_ = self.pop(); _ = self.pop();
} }
pub fn clock_native(arg_count: usize, args: []Value) Value {
const ts = std.time.milliTimestamp();
_ = arg_count;
_ = args;
return Value.number_val(@floatFromInt(ts));
}
}; };