Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/FSharpSource.targets
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@
<DefineConstants>$(DefineConstants);FX_NO_EXCEPTIONDISPATCHINFO</DefineConstants>
<DefineConstants>$(DefineConstants);FX_NO_TASK</DefineConstants>
<DefineConstants>$(DefineConstants);FX_NO_IOBSERVABLE</DefineConstants>
<DefineConstants>$(DefineConstants);FX_NO_READONLY_COLLECTIONS</DefineConstants>
<DefineConstants>$(DefineConstants);FX_NO_LAZY</DefineConstants>
<DefineConstants>$(DefineConstants);FX_NO_TUPLE</DefineConstants>
<DefineConstants>$(DefineConstants);FX_NO_MONITOR_REPORTS_LOCKTAKEN</DefineConstants>
Expand Down Expand Up @@ -170,6 +171,7 @@
<DefineConstants>$(DefineConstants);FX_NO_APP_DOMAINS</DefineConstants>
<DefineConstants>$(DefineConstants);FX_NO_PROCESS_DIAGNOSTICS</DefineConstants>
<DefineConstants>$(DefineConstants);FX_NO_IOBSERVABLE</DefineConstants>
<DefineConstants>$(DefineConstants);FX_NO_READONLY_COLLECTIONS</DefineConstants>
<DefineConstants>$(DefineConstants);FX_NO_WEB_CLIENT</DefineConstants>
<DefineConstants>$(DefineConstants);FX_NO_CONVERTER</DefineConstants>
<DefineConstants>$(DefineConstants);FX_NO_GET_HASH_CODE_HELPER</DefineConstants>
Expand Down Expand Up @@ -525,6 +527,7 @@
<DefineConstants>$(DefineConstants);FX_NO_PARAMETERIZED_THREAD_START</DefineConstants>
<DefineConstants>$(DefineConstants);FX_NO_STRUCTURAL_EQUALITY</DefineConstants>
<DefineConstants>$(DefineConstants);FX_NO_IOBSERVABLE</DefineConstants>
<DefineConstants>$(DefineConstants);FX_NO_READONLY_COLLECTIONS</DefineConstants>
<DefineConstants>$(DefineConstants);FX_NO_LAZY</DefineConstants>
<DefineConstants>$(DefineConstants);FX_NO_TUPLE</DefineConstants>
<DefineConstants>$(DefineConstants);FX_NO_DELEGATE_CREATE_DELEGATE_FROM_STATIC_METHOD</DefineConstants>
Expand Down
83 changes: 83 additions & 0 deletions src/fsharp/FSharp.Core/fslib-extra-pervasives.fs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@ module ExtraTopLevelOperators =
t.[RuntimeHelpers.StructBox(k)] <- v
let d = (t :> IDictionary<_,_>)
let c = (t :> ICollection<_>)

let dictEnumerator (a: System.Collections.Generic.IEnumerator<System.Collections.DictionaryEntry>) =
{ new System.Collections.IDictionaryEnumerator with
member x.Current = a.Current :> obj
member x.Entry = a.Current
member x.Key = x.Entry.Key
member x.Value = x.Entry.Value
member x.MoveNext () = a.MoveNext()
member x.Reset () = a.Reset()
}

// Give a read-only view of the dictionary
{ new IDictionary<'Key, 'T> with
member s.Item
Expand Down Expand Up @@ -70,6 +81,78 @@ module ExtraTopLevelOperators =
let key = RuntimeHelpers.StructBox(k)
if d.ContainsKey(key) then (r <- d.[key]; true) else false
member s.Remove(k : 'Key) = (raise (NotSupportedException(SR.GetString(SR.thisValueCannotBeMutated))) : bool)
#if FX_NO_READONLY_COLLECTIONS
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FX_ATLEAST_45 is not enough? IReadOnlyDictionary msdn

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

had to exclude portable

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FSHARP_CORE_PORTABLE? because there are really a lot of defines already.
i mean FX_ATLEAST_45 && (!FSHARP_CORE_PORTABLE)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if FX_ATLEAST_45 && not FSHARP_CORE_PORTABLE

but why not explicitly exlude with ne flag. seems like a common pattern here

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are already lot of defines, and is going to be messier with netcore.
i dont think the best long term is one define per class, instead we should simplify the codebase and build permutations
Another factor is: if you undefine FX_NO_READONLY_COLLECTIONS, that's not enogh to compile if the class doesn't exists in the framework. Is not a pure feature flag (like WSDL define )
but that's my idea /cc @dsyme

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use feature-based defines (FX_NO_READONLY_COLLECTIONS) rather than platform defines (FX_ATLEAST_45, FSHARP_CORE_PORTABLE). Granularity of "features" is up to you - merge related ones where possible, split where necessary,

thanks
Don

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thx for reply @dsyme nice to know 😄

#else
interface IReadOnlyDictionary<'Key, 'T> with
member s.Item
with get x = d.[RuntimeHelpers.StructBox(x)]
member s.Keys =
let keys = d.Keys
{ new IEnumerable<'Key> with
member s.GetEnumerator() = (keys |> Seq.map (fun v -> v.Value)).GetEnumerator()
interface System.Collections.IEnumerable with
member s.GetEnumerator() = ((keys |> Seq.map (fun v -> v.Value)) :> System.Collections.IEnumerable).GetEnumerator() }

member s.Values =
{ new IEnumerable<'T> with
member s.GetEnumerator() = d.Values.GetEnumerator()
interface System.Collections.IEnumerable with
member s.GetEnumerator() = (d.Values :> System.Collections.IEnumerable).GetEnumerator() }
member s.ContainsKey(k) = d.ContainsKey(RuntimeHelpers.StructBox(k))
member s.TryGetValue(k,r) =
let key = RuntimeHelpers.StructBox(k)
if d.ContainsKey(key) then (r <- d.[key]; true) else false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can use d.TryGetValue here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how?
image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

type DictWrapper<'k,'v>(d : Dictionary<_,_>) =
    member __.TryGetValue(a : 'k, [<System.Runtime.InteropServices.Out>]b : 'v byref) = 
            d.TryGetValue(a, &b)

Might as well fix above, too.

interface IReadOnlyCollection<KeyValuePair<'Key, 'T>> with
member s.Count = c.Count
#endif
interface System.Collections.IDictionary with
member s.IsReadOnly = true
member s.IsFixedSize = true
member s.IsSynchronized = true
member s.Item
with get x = d.[RuntimeHelpers.StructBox(x :?> 'Key)] :> obj
and set x v = raise (NotSupportedException(SR.GetString(SR.thisValueCannotBeMutated)))
member s.Keys =
let keys = d.Keys
{ new System.Collections.ICollection with
member s.CopyTo(arr,i) =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementer of ICollection.CopyTo is responsible for checking nulls, array bounds, array dimension, 0-based, etc, and throwing appropriate exceptions. See https://msdn.microsoft.com/en-us/library/system.collections.icollection.copyto(v=vs.110).aspx

Example impl here.

let mutable n = 0
for k in keys do
arr.SetValue(k.Value,i+n)
n <- n + 1
member s.IsSynchronized = true
member s.SyncRoot = (t :> System.Collections.ICollection).SyncRoot
member s.Count = keys.Count
interface System.Collections.IEnumerable with
member s.GetEnumerator() = ((keys |> Seq.map (fun v -> v.Value)) :> System.Collections.IEnumerable).GetEnumerator() }

member s.Values =
{ new System.Collections.ICollection with
member s.CopyTo(arr,i) =
let mutable n = 0
for k in d.Values do
arr.SetValue(k,i+n)
n <- n + 1
member s.IsSynchronized = true
member s.SyncRoot = (t :> System.Collections.ICollection).SyncRoot
member s.Count = d.Values.Count
interface System.Collections.IEnumerable with
member s.GetEnumerator() = (d.Values :> System.Collections.IEnumerable).GetEnumerator() }
member s.Count = c.Count
member s.SyncRoot = (t :> System.Collections.ICollection).SyncRoot
member s.Add(k,v) = raise (NotSupportedException(SR.GetString(SR.thisValueCannotBeMutated)))
member s.Contains(k) = d.ContainsKey(RuntimeHelpers.StructBox(k :?> 'Key))
member s.GetEnumerator() =
(c |> Seq.map (fun (KeyValue(k,v)) -> System.Collections.DictionaryEntry(k.Value,v))).GetEnumerator()
|> dictEnumerator

member s.Remove(k) = (raise (NotSupportedException(SR.GetString(SR.thisValueCannotBeMutated))) : unit)
member s.Clear() = raise (NotSupportedException(SR.GetString(SR.thisValueCannotBeMutated)));
member s.CopyTo(arr,i) =
let mutable n = 0
for (KeyValue(k,v)) in c do
arr.SetValue(System.Collections.DictionaryEntry(k.Value,v),i+n)
n <- n + 1
interface ICollection<KeyValuePair<'Key, 'T>> with
member s.Add(x) = raise (NotSupportedException(SR.GetString(SR.thisValueCannotBeMutated)));
member s.Clear() = raise (NotSupportedException(SR.GetString(SR.thisValueCannotBeMutated)));
Expand Down