implementing more native functions
This commit is contained in:
parent
a2200debb4
commit
7ed6cf6dcc
3
samples/native_power.lox
Normal file
3
samples/native_power.lox
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
print power(str2num("3"),str2num("3"));
|
||||||
|
|
||||||
|
print str2num("3") + str2num("4");
|
64
src/native.zig
Normal file
64
src/native.zig
Normal 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);
|
||||||
|
}
|
@ -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,
|
||||||
|
16
src/vm.zig
16
src/vm.zig
@ -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));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user