Add lambda argument arity checking to runtime
This commit is contained in:
parent
b9f03b34c1
commit
5c08a1b63e
|
@ -6,6 +6,8 @@ let pr = lambda (str):
|
|||
@print(str)
|
||||
end
|
||||
|
||||
pr("eeee")
|
||||
|
||||
while i < 5:
|
||||
pr("hello, world")
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ pub const RuntimeEnv = struct {
|
|||
const Chunk = struct {
|
||||
env: *RuntimeEnv,
|
||||
name: []coral.io.Byte,
|
||||
arity: u8,
|
||||
opcodes: OpcodeList,
|
||||
constants: ConstList,
|
||||
|
||||
|
@ -141,11 +142,15 @@ pub const RuntimeEnv = struct {
|
|||
},
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
|
@ -982,11 +987,12 @@ pub const RuntimeEnv = struct {
|
|||
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 .{
|
||||
.name = try coral.io.allocate_copy(env.allocator, name),
|
||||
.opcodes = OpcodeList.make(env.allocator),
|
||||
.constants = ConstList.make(env.allocator),
|
||||
.arity = arity,
|
||||
.env = env,
|
||||
};
|
||||
}
|
||||
|
@ -996,7 +1002,13 @@ pub const RuntimeEnv = struct {
|
|||
}
|
||||
|
||||
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 {
|
||||
|
@ -1122,7 +1134,6 @@ pub const RuntimeEnv = struct {
|
|||
method.env.discard(replaced.value);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
pub fn acquire(self: *RuntimeEnv, value: *const RuntimeRef) RuntimeError!*RuntimeRef {
|
||||
|
@ -1147,16 +1158,6 @@ pub const RuntimeEnv = struct {
|
|||
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 {
|
||||
try self.locals.push_all(args);
|
||||
|
||||
|
@ -1222,7 +1223,7 @@ pub const RuntimeEnv = struct {
|
|||
defer self.allocator.deallocate(file_data);
|
||||
|
||||
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();
|
||||
|
||||
|
@ -1539,6 +1540,12 @@ pub const RuntimeEnv = struct {
|
|||
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 {
|
||||
|
|
Loading…
Reference in New Issue