Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix and test 'Hylo.DynamicBuffer' #913

Merged
merged 11 commits into from
Sep 7, 2023
2 changes: 2 additions & 0 deletions Library/Hylo/Core/Linear.hylo
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/// A type whose instances are movable and deinitializable.
public trait Linear: Deinitializable, Movable {}
16 changes: 16 additions & 0 deletions Library/Hylo/DynamicBuffer.hylo
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
/// A buffer of elements stored in a contiguous region of memory, whose size is determined at
/// instance creation.
///
/// - Warning: The deinitializer of `DynamicBuffer` does not deinitialize the elements that may
/// be stored in its payload. You must ensure that they are properly deinitialized before
/// `deinit` is called.
public type DynamicBuffer<Header: Deinitializable, Element>: Deinitializable {

/// The description of payloads in `DynamicBuffer`s.
Expand Down Expand Up @@ -36,15 +40,27 @@ public type DynamicBuffer<Header: Deinitializable, Element>: Deinitializable {
&storage = .allocate_bytes(
count: Self.payload_offset() + capacity * MemoryLayout<Element>.stride(),
aligned_at: MemoryLayout<BufferHeader>.alignment())

let p = PointerToMutable<BufferHeader>(type_punning: storage)
p.unsafe_initialize_pointee(fun (_ h: set BufferHeader) -> Void {
&h.0 = capacity.copy()
init_header(&h.1)
})
}

/// Deinitializes `self`.
///
/// - Requires: No element is stored in `self`.
public fun deinit() sink {
storage.deallocate()
}

/// The number of elements that can be stored in `self`.
public fun capacity() -> Int {
if storage == PointerToMutable.null() {
return 0
}

let p = PointerToMutable<BufferHeader>(type_punning: storage)
return p.unsafe[].0.copy()
}
Expand Down
3 changes: 1 addition & 2 deletions Sources/IR/Analysis/Module+Depolymorphize.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ extension Module {

/// Generates the non-parametric resilient API of `self`, reading definitions from `ir`.
public mutating func depolymorphize(in ir: IR.Program) {
let work = functions.keys
for k in work {
for k in functions.keys {
let f = functions[k]!

// Ignore declarations without definition.
Expand Down
9 changes: 7 additions & 2 deletions Sources/IR/Emitter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1260,8 +1260,13 @@ struct Emitter {
let l = emit(infixOperand: lhs, passed: ParameterType(calleeType.inputs[0].type)!.access)

// The callee must be a reference to member function.
guard case .member(let d, _, _) = program[callee.expr].referredDecl else { unreachable() }
let f = Operand.constant(FunctionReference(to: FunctionDecl.ID(d)!, in: &module))
guard case .member(let d, let a, _) = program[callee.expr].referredDecl else {
unreachable()
}

let o = FunctionReference(
to: FunctionDecl.ID(d)!, in: &module, specializedBy: a, in: insertionScope!)
let f = Operand.constant(o)

// Emit the call.
let site = ast.site(of: e)
Expand Down
18 changes: 18 additions & 0 deletions Tests/LibraryTests/TestCases/DynamicBufferTests.hylo
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//- compileAndRun expecting: success

fun test_init_empty() {
var d = DynamicBuffer<Int, Int>()
precondition(d.capacity() == 0)
}

fun test_init_with_capacity() {
var d = DynamicBuffer<Int, Int>(
capacity: 5,
initializing_header_with: fun(_ h: set Int) -> Void { &h = 0 })
precondition(d.capacity() == 5)
}

public fun main() {
test_init_empty()
test_init_with_capacity()
}
Loading