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)
|
@print(str)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
pr("eeee")
|
||||||
|
|
||||||
while i < 5:
|
while i < 5:
|
||||||
pr("hello, world")
|
pr("hello, world")
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue