kym-tables-overhaul #30
| @ -1,7 +1,5 @@ | ||||
| const Ast = @import("./kym/Ast.zig"); | ||||
| 
 | ||||
| const Table = @import("./kym/Table.zig"); | ||||
| 
 | ||||
| const coral = @import("coral"); | ||||
| 
 | ||||
| const file = @import("./file.zig"); | ||||
| @ -786,6 +784,101 @@ pub const RuntimeEnv = struct { | ||||
| 
 | ||||
| 	const SymbolSet = coral.map.StringTable([:0]coral.io.Byte); | ||||
| 
 | ||||
| 	const Table = struct { | ||||
| 		associative: RefTable, | ||||
| 		contiguous: RefList, | ||||
| 
 | ||||
| 		fn typeinfo_destruct(method: Typeinfo.Method) void { | ||||
| 			const table = @as(*Table, @ptrCast(@alignCast(method.userdata.ptr))); | ||||
| 
 | ||||
| 			{ | ||||
| 				var field_iterable = table.associative.as_iterable(); | ||||
| 
 | ||||
| 				while (field_iterable.next()) |entry| { | ||||
| 					method.env.discard(entry.key); | ||||
| 					method.env.discard(entry.value); | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			table.associative.free(); | ||||
| 
 | ||||
| 			while (table.contiguous.pop()) |value| { | ||||
| 				if (value) |ref| { | ||||
| 					method.env.discard(ref); | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			table.contiguous.free(); | ||||
| 		} | ||||
| 
 | ||||
| 		fn typeinfo_get(method: Typeinfo.Method, index: *const RuntimeRef) RuntimeError!?*RuntimeRef { | ||||
| 			const table = @as(*Table, @ptrCast(@alignCast(method.userdata.ptr))); | ||||
| 			const acquired_index = try method.env.acquire(index); | ||||
| 
 | ||||
| 			defer method.env.discard(acquired_index); | ||||
| 
 | ||||
| 			if (acquired_index.is_fixed()) |fixed| { | ||||
| 				if (fixed < 0) { | ||||
| 					// TODO: Negative indexing. | ||||
| 					unreachable; | ||||
| 				} | ||||
| 
 | ||||
| 				if (fixed < table.contiguous.values.len) { | ||||
| 					return method.env.acquire(table.contiguous.values[@intCast(fixed)] orelse return null); | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			if (table.associative.lookup(acquired_index)) |value_ref| { | ||||
| 				return method.env.acquire(value_ref); | ||||
| 			} | ||||
| 
 | ||||
| 			return null; | ||||
| 		} | ||||
| 
 | ||||
| 		fn typeinfo_set(method: Typeinfo.Method, index: *const RuntimeRef, value: ?*const RuntimeRef) RuntimeError!void { | ||||
| 			const table = @as(*Table, @ptrCast(@alignCast(method.userdata.ptr))); | ||||
| 			const acquired_index = try method.env.acquire(index); | ||||
| 
 | ||||
| 			errdefer method.env.discard(acquired_index); | ||||
| 
 | ||||
| 			if (acquired_index.is_fixed()) |fixed| { | ||||
| 				if (fixed < 0) { | ||||
| 					// TODO: Negative indexing. | ||||
| 					unreachable; | ||||
| 				} | ||||
| 
 | ||||
| 				if (fixed < table.contiguous.values.len) { | ||||
| 					const maybe_replacing = &table.contiguous.values[@intCast(fixed)]; | ||||
| 
 | ||||
| 					if (maybe_replacing.*) |replacing| { | ||||
| 						method.env.discard(replacing); | ||||
| 					} | ||||
| 
 | ||||
| 					maybe_replacing.* = if (value) |ref| try method.env.acquire(ref) else null; | ||||
| 
 | ||||
| 					return; | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			const acquired_value = try method.env.acquire(value orelse { | ||||
| 				if (table.associative.remove(acquired_index)) |removed| { | ||||
| 					method.env.discard(removed.key); | ||||
| 					method.env.discard(removed.value); | ||||
| 				} | ||||
| 
 | ||||
| 				return; | ||||
| 			}); | ||||
| 
 | ||||
| 			errdefer method.env.discard(acquired_value); | ||||
| 
 | ||||
| 			if (try table.associative.replace(acquired_index, acquired_value)) |replaced| { | ||||
| 				method.env.discard(replaced.key); | ||||
| 				method.env.discard(replaced.value); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 	}; | ||||
| 
 | ||||
| 	pub fn acquire(self: *RuntimeEnv, value: *const RuntimeRef) RuntimeError!*RuntimeRef { | ||||
| 		const object = value.object(); | ||||
| 
 | ||||
| @ -1031,8 +1124,27 @@ pub const RuntimeEnv = struct { | ||||
| 	} | ||||
| 
 | ||||
| 	pub fn new_table(self: *RuntimeEnv) RuntimeError!*RuntimeRef { | ||||
| 		// TODO: Unroll this call logic into the environment. | ||||
| 		return Table.new(self); | ||||
| 		var table = Table{ | ||||
| 			.associative = RefTable.make(self.allocator, .{}), | ||||
| 			.contiguous = RefList.make(self.allocator), | ||||
| 		}; | ||||
| 
 | ||||
| 		errdefer { | ||||
| 			table.associative.free(); | ||||
| 			table.contiguous.free(); | ||||
| 		} | ||||
| 
 | ||||
| 		const newed = try self.new_dynamic(&.{ | ||||
| 			.name = "table", | ||||
| 			.size = @sizeOf(Table), | ||||
| 			.destruct = Table.typeinfo_destruct, | ||||
| 			.get = Table.typeinfo_get, | ||||
| 			.set = Table.typeinfo_set, | ||||
| 		}); | ||||
| 
 | ||||
| 		coral.io.copy(self.unbox_dynamic(newed) catch unreachable, coral.io.bytes_of(&table)); | ||||
| 
 | ||||
| 		return newed; | ||||
| 	} | ||||
| 
 | ||||
| 	pub fn raise(self: *RuntimeEnv, error_value: RuntimeError, message: []const coral.io.Byte) RuntimeError { | ||||
|  | ||||
| @ -1,133 +0,0 @@ | ||||
| const coral = @import("coral"); | ||||
| 
 | ||||
| const kym = @import("../kym.zig"); | ||||
| 
 | ||||
| associative: AssociativeTable, | ||||
| contiguous: ContiguousList, | ||||
| 
 | ||||
| const AssociativeTable = coral.map.Table(*kym.RuntimeRef, *kym.RuntimeRef, struct { | ||||
| 	pub fn hash(key: *kym.RuntimeRef) usize { | ||||
| 		return key.hash(); | ||||
| 	} | ||||
| 
 | ||||
| 	pub fn equals(key_a: *kym.RuntimeRef, key_b: *kym.RuntimeRef) bool { | ||||
| 		return key_a.equals(key_b); | ||||
| 	} | ||||
| }); | ||||
| 
 | ||||
| const ContiguousList = coral.list.Stack(?*kym.RuntimeRef); | ||||
| 
 | ||||
| const Self = @This(); | ||||
| 
 | ||||
| pub fn new(env: *kym.RuntimeEnv) kym.RuntimeError!*kym.RuntimeRef { | ||||
| 	var self = Self{ | ||||
| 		.associative = AssociativeTable.make(env.allocator, .{}), | ||||
| 		.contiguous = ContiguousList.make(env.allocator), | ||||
| 	}; | ||||
| 
 | ||||
| 	errdefer { | ||||
| 		self.associative.free(); | ||||
| 		self.contiguous.free(); | ||||
| 	} | ||||
| 
 | ||||
| 	const table = try env.new_dynamic(&.{ | ||||
| 		.name = "table", | ||||
| 		.size = @sizeOf(Self), | ||||
| 		.destruct = typeinfo_destruct, | ||||
| 		.get = typeinfo_get, | ||||
| 		.set = typeinfo_set, | ||||
| 	}); | ||||
| 
 | ||||
| 	coral.io.copy(env.unbox_dynamic(table) catch unreachable, coral.io.bytes_of(&self)); | ||||
| 
 | ||||
| 	return table; | ||||
| } | ||||
| 
 | ||||
| fn typeinfo_destruct(method: kym.Typeinfo.Method) void { | ||||
| 	const table = @as(*Self, @ptrCast(@alignCast(method.userdata.ptr))); | ||||
| 
 | ||||
| 	{ | ||||
| 		var field_iterable = table.associative.as_iterable(); | ||||
| 
 | ||||
| 		while (field_iterable.next()) |entry| { | ||||
| 			method.env.discard(entry.key); | ||||
| 			method.env.discard(entry.value); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	table.associative.free(); | ||||
| 
 | ||||
| 	while (table.contiguous.pop()) |value| { | ||||
| 		if (value) |ref| { | ||||
| 			method.env.discard(ref); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	table.contiguous.free(); | ||||
| } | ||||
| 
 | ||||
| fn typeinfo_get(method: kym.Typeinfo.Method, index: *const kym.RuntimeRef) kym.RuntimeError!?*kym.RuntimeRef { | ||||
| 	const table = @as(*Self, @ptrCast(@alignCast(method.userdata.ptr))); | ||||
| 	const acquired_index = try method.env.acquire(index); | ||||
| 
 | ||||
| 	defer method.env.discard(acquired_index); | ||||
| 
 | ||||
| 	if (acquired_index.is_fixed()) |fixed| { | ||||
| 		if (fixed < 0) { | ||||
| 			// TODO: Negative indexing. | ||||
| 			unreachable; | ||||
| 		} | ||||
| 
 | ||||
| 		if (fixed < table.contiguous.values.len) { | ||||
| 			return method.env.acquire(table.contiguous.values[@intCast(fixed)] orelse return null); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (table.associative.lookup(acquired_index)) |value_ref| { | ||||
| 		return method.env.acquire(value_ref); | ||||
| 	} | ||||
| 
 | ||||
| 	return null; | ||||
| } | ||||
| 
 | ||||
| fn typeinfo_set(method: kym.Typeinfo.Method, index: *const kym.RuntimeRef, value: ?*const kym.RuntimeRef) kym.RuntimeError!void { | ||||
| 	const table = @as(*Self, @ptrCast(@alignCast(method.userdata.ptr))); | ||||
| 	const acquired_index = try method.env.acquire(index); | ||||
| 
 | ||||
| 	errdefer method.env.discard(acquired_index); | ||||
| 
 | ||||
| 	if (acquired_index.is_fixed()) |fixed| { | ||||
| 		if (fixed < 0) { | ||||
| 			// TODO: Negative indexing. | ||||
| 			unreachable; | ||||
| 		} | ||||
| 
 | ||||
| 		if (fixed < table.contiguous.values.len) { | ||||
| 			const maybe_replacing = &table.contiguous.values[@intCast(fixed)]; | ||||
| 
 | ||||
| 			if (maybe_replacing.*) |replacing| { | ||||
| 				method.env.discard(replacing); | ||||
| 			} | ||||
| 
 | ||||
| 			maybe_replacing.* = if (value) |ref| try method.env.acquire(ref) else null; | ||||
| 
 | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	const acquired_value = try method.env.acquire(value orelse { | ||||
| 		if (table.associative.remove(acquired_index)) |removed| { | ||||
| 			method.env.discard(removed.key); | ||||
| 			method.env.discard(removed.value); | ||||
| 		} | ||||
| 
 | ||||
| 		return; | ||||
| 	}); | ||||
| 
 | ||||
| 	errdefer method.env.discard(acquired_value); | ||||
| 
 | ||||
| 	if (try table.associative.replace(acquired_index, acquired_value)) |replaced| { | ||||
| 		method.env.discard(replaced.key); | ||||
| 		method.env.discard(replaced.value); | ||||
| 	} | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user