Add lambda argument arity checking to runtime
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details

This commit is contained in:
kayomn 2023-08-26 21:30:36 +01:00
parent b9f03b34c1
commit 5c08a1b63e
2 changed files with 25 additions and 16 deletions

View File

@ -6,6 +6,8 @@ let pr = lambda (str):
@print(str) @print(str)
end end
pr("eeee")
while i < 5: while i < 5:
pr("hello, world") pr("hello, world")

View File

@ -18,6 +18,7 @@ pub const RuntimeEnv = struct {
const Chunk = struct { const Chunk = struct {
env: *RuntimeEnv, env: *RuntimeEnv,
name: []coral.io.Byte, name: []coral.io.Byte,
arity: u8,
opcodes: OpcodeList, opcodes: OpcodeList,
constants: ConstList, constants: ConstList,
@ -141,11 +142,15 @@ pub const RuntimeEnv = struct {
}, },
.lambda_literal => |literal| { .lambda_literal => |literal| {
if (literal.argument_identifiers.values.len > coral.math.max_int(@typeInfo(u32).Int)) { if (literal.argument_identifiers.values.len > coral.math.max_int(@typeInfo(u8).Int)) {
return error.OutOfMemory; return error.OutOfMemory;
} }
var lambda_chunk = try Chunk.make(chunk.env, "<lambda>"); var lambda_chunk = try Chunk.make(
chunk.env,
"<lambda>",
@intCast(literal.argument_identifiers.values.len),
);
errdefer lambda_chunk.free(); errdefer lambda_chunk.free();
@ -982,11 +987,12 @@ pub const RuntimeEnv = struct {
self.env.allocator.deallocate(self.name); self.env.allocator.deallocate(self.name);
} }
fn make(env: *RuntimeEnv, name: []const coral.io.Byte) coral.io.AllocationError!Chunk { fn make(env: *RuntimeEnv, name: []const coral.io.Byte, arity: u8) coral.io.AllocationError!Chunk {
return .{ return .{
.name = try coral.io.allocate_copy(env.allocator, name), .name = try coral.io.allocate_copy(env.allocator, name),
.opcodes = OpcodeList.make(env.allocator), .opcodes = OpcodeList.make(env.allocator),
.constants = ConstList.make(env.allocator), .constants = ConstList.make(env.allocator),
.arity = arity,
.env = env, .env = env,
}; };
} }
@ -996,7 +1002,13 @@ pub const RuntimeEnv = struct {
} }
fn typeinfo_call(method: Typeinfo.Method) RuntimeError!?*RuntimeRef { fn typeinfo_call(method: Typeinfo.Method) RuntimeError!?*RuntimeRef {
return @as(*Chunk, @ptrCast(@alignCast(method.userdata))).execute(); const chunk = @as(*Chunk, @ptrCast(@alignCast(method.userdata)));
if ((method.env.view_args() catch unreachable).len < chunk.arity) {
return method.env.raise(error.BadOperation, "expected more arguments");
}
return chunk.execute();
} }
fn typeinfo_destruct(method: Typeinfo.Method) void { fn typeinfo_destruct(method: Typeinfo.Method) void {
@ -1122,7 +1134,6 @@ pub const RuntimeEnv = struct {
method.env.discard(replaced.value); method.env.discard(replaced.value);
} }
} }
}; };
pub fn acquire(self: *RuntimeEnv, value: *const RuntimeRef) RuntimeError!*RuntimeRef { pub fn acquire(self: *RuntimeEnv, value: *const RuntimeRef) RuntimeError!*RuntimeRef {
@ -1147,16 +1158,6 @@ pub const RuntimeEnv = struct {
return null; return null;
} }
pub fn acquire_args(self: *RuntimeEnv) RuntimeError!*RuntimeRef {
const frame = self.frames.peek() orelse return self.raise(error.IllegalState, "stack underflow");
_ = frame;
const args_table = self.new_table();
return args_table;
}
pub fn call(self: *RuntimeEnv, callable: *RuntimeRef, args: []const *RuntimeRef) RuntimeError!?*RuntimeRef { pub fn call(self: *RuntimeEnv, callable: *RuntimeRef, args: []const *RuntimeRef) RuntimeError!?*RuntimeRef {
try self.locals.push_all(args); try self.locals.push_all(args);
@ -1222,7 +1223,7 @@ pub const RuntimeEnv = struct {
defer self.allocator.deallocate(file_data); defer self.allocator.deallocate(file_data);
const file_name = file_path.to_string() orelse "<script>"; const file_name = file_path.to_string() orelse "<script>";
var chunk = try Chunk.make(self, file_name); var chunk = try Chunk.make(self, file_name, 0);
defer chunk.free(); defer chunk.free();
@ -1539,6 +1540,12 @@ pub const RuntimeEnv = struct {
else => env.raise(error.TypeMismatch, "expected symbol object") else => env.raise(error.TypeMismatch, "expected symbol object")
}; };
} }
pub fn view_args(self: *RuntimeEnv) RuntimeError![]const ?*const RuntimeRef {
const frame = self.frames.peek() orelse return self.raise(error.IllegalState, "stack underflow");
return self.locals.values[(frame.locals_top - frame.arg_count) ..];
}
}; };
pub const RuntimeError = coral.io.AllocationError || error { pub const RuntimeError = coral.io.AllocationError || error {