-
Notifications
You must be signed in to change notification settings - Fork 783
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
Add internal block
type for use in the compiler. IncrementalBuilder
only maintains two states
#11750
Conversation
block
type for use in the compiler. IncrementalBuilder
only maintains two states. block
type for use in the compiler. IncrementalBuilder
only maintains two states
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did a review of the block api, I hope that's alright.
Also, sometimes there are reasons to get the underlying array cheaply. I'm using this, posted below, in our codebase here and there. Though going fully unsafe you could do Unsafe.As<Block<'T>, 'T[]> as it's the only field in the struct. I just prefer my code to die a little nicer than with a segfault in the very unlikely case ImmutableArray changes implementations 😅.
let unsafeGetArray(value: ImmutableArray<'T>) =
match MemoryMarshal.TryGetArray(value.AsMemory()) with
| false, _ -> failwith "Expected ImmutableArray to wrap a managed array but it didn't."
| true, seg -> seg.Array
@NinoFloris of course! Thank you for reviewing :) |
@NinoFloris This should be a lot better. :) I didn't realize how naïve my original impl was. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No worries, I picked up a few things since I introduced ImmutableArray into our codebase a few years back. Besides, anything that helps compiler perf is welcome :)
|
||
let choose (chooser: 'T -> 'U option) (arr: block<'T>) : block<'U> = | ||
let builder = ImmutableArray.CreateBuilder(arr.Length) | ||
for i = 0 to arr.Length - 1 do | ||
let result = chooser arr.[i] | ||
if result.IsSome then | ||
builder.Add(result.Value) | ||
builder.ToImmutable() | ||
builder.Capacity <- builder.Count |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you don't know the length it doesn't matter too much if you do ToImmutable. You'll do a copy by changing capacity anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changing the capacity will only copy if the count is different.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough :)
let builder = ImmutableArray.CreateBuilder(acc) | ||
for i = 0 to arrs.Length - 1 do | ||
builder.AddRange(arrs.[i]) | ||
builder.MoveToImmutable() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing capacity <- count or ToImmutable here, as capacity could be anything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is fine. acc
is the total length of the final array.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I completely missed the the length summing loop, yep it's fine!
ImmutableArray.Create(item) | ||
|
||
let filter predicate (arr: block<'T>) : block<'T> = | ||
let builder = ImmutableArray.CreateBuilder(arr.Length) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test for empty initially
This is mostly a refactoring PR. It does add the
block
type for internal compiler use; it is basicallyImmutableArray<'T>
but with F# idiomatic collection functions.Incremental Builder changes:
IncrementalBuilderInitialState
to group the initial state when creating anIncrementalBuilder
internally.IncrementalBuilder
to be top-level.IncrementalBuilder
now manages only two states:IncrementalBuilderInitialState
andIncrementalBuilderState
.