extern access modifiers don't work - f#

I'm trying to hide my P/Invoke functions, like this one:
[<DllImport("kernel32.dll", SetLastError=true)>]
extern bool private CreateTimerQueueTimer(IntPtr& phNewTimer, nativeint TimerQueue, WaitOrTimerDelegate Callback, nativeint Parameter, uint32 DueTime, uint32 Period, ExecuteFlags Flags)
Strangely, though, the private gets ignored -- which is really annoying, because I want to hide all the unwieldy structs and enums associated with these functions.
I guess I could put everything in a private module, so it's not too big of a deal, but am I missing something?

This will do the job.
module a =
[<AbstractClass>]
type private NativeMethods() =
[<DllImport("kernel32.dll", EntryPoint="CreateTimerQueueTimer",
SetLastError=true)>]
static extern bool sCreateTimerQueueTimer( (* whatever *) )
static member CreateTimerQueueTimer = sCreateTimerQueueTimer
let usedInside = NativeMethods.CreateTimerQueueTimer
module b =
open a
// the next line fails to compile
let usedOutside = NativeMethods.CreateTimerQueueTimer( (* whatever *) )
Notes:
private class can be accessed only from the enclosing module, this is what you need, so just wrap the methods in a NativeMethods class;
You cannot set your extern method private since it wouldn't be accessible from the rest of module a;
extern member of a class is always private, so there's another method with same signature;
Finally, use EntryPoint to resolve naming.

Related

CXXRecordDecl with child VarDecl?

Let's say I have a CXXRecordDecl with only static members, all raised to external linkage:
struct S {
static constexpr int x = 10;
static constexpr int y = 20;
static void foo() {...}
};
The AST is as follow:
TranslatioUnitDecl
...
CXXRecordDecl struct S definition
-CXXRecordDecl implicit struct S
-VarDecl x
-IntegralLiteral 10
-VarDecl y
-IntegralLiteral 20
-CXXMethodDecl foo
...
I think due to the "static" data member, there is no FieldDecl in the CXXRecordDecl, there are 2 VarDecl instead. So how do I access the 2 VarDecl from CXXRecordDecl? There is no API function in CXXRecordDecl for that.
The only way I can think of is to use a RecursiveASTVisitor class and visit all decls. A VarDecl has boolean API functions isStaticDataMember() and isConstexpr() to help, great! But how do I know what is the parent class for these static VarDecl?
Any suggestion will be appreciated profoundly!
I think I found my own answer. There is a base class DeclContext for many block decls, including RecordDecl. This class has public member functions to iterate all the decls within the struct, look at decls_begin() and decls_end().

Idiomatic way to declare static and instance member at once?

When I extend a type with a new function, I usually want it to be available from both dot-notation and free form. Either can be more readable depending on the situation, and the former helps with IntelliSense while the latter helps with currying.
In C#/VB.net, extension methods do this (although I cannot restrict the function to a static method of the extended static class, as in F#). I can write the function once and then invoke it both ways:
<Extension>
public function bounded(s as string, min as UShort, max as UShort) as string
if min > max then throw new ArgumentOutOfRangeException
if string.IsNullOrEmpty(s) then return new string(" ", min)
if s.Length < min then return s.PadRight(min, " ")
if s.Length > max then return s.Substring(0, max)
return s
end function
' usage
dim b1 = bounded("foo", 10, 15)
dim b2 = "foo".bounded(0, 2)
(That's not quite perfect yet, as I'd like bounded to be a static method of String, but C#/VB.Net can't do that. Point to F# in that regard.)
In F#, on the other side, I have to declare the function separatedly from the method:
// works fine
[<AutoOpen>]
module Utilities =
type List<'T> with
member this.tryHead = if this.IsEmpty then None else Some this.Head
module List =
let tryHead (l : List<'T>) = l.tryHead
Question: Is there a more elegant way to declare both methods at once?
I tried to use:
// doesn't quite work
type List<'T> with
member this.tryHead = if this.IsEmpty then None else Some this.Head
static member tryHead(l : List<'T>) = l.tryHead
which at least would let me skip the module declaration, but while the definition compiles, it doesn't quite work - someList.tryHead is OK, but List.tryHead someList results in a Property tryHead is not static error.
Bonus question: As you can see, the static member definition requires a type annotation. However, no other type could have access to the method that was just defined. Why, then, can't the type be inferred?
I don't know of a way to declare both APIs in a single line of code, but you can get rid of the type annotations by making the function the implementation, and then defining the method it terms of the function:
[<AutoOpen>]
module Utilities =
module List =
let tryHead l = if List.isEmpty l then None else Some (List.head l)
type List<'a> with
member this.tryHead = List.tryHead this

meaning of const in `const ['foo', 'bar']` in dart

I know that const is compile-time constant in dart, but I don't understand mechanism behind const [F0, F1, F2] in the following code:
class Foo {
static const F0 = 'F0';
static const F1 = 'F1';
static const F2 = 'F2';
// const list of const values I guess...
static const CONST_LIST = const [F0, F1, F2]; // please explain this line
static final String FOO = CONST_LIST[0]; // ok
// compile error: 'const' varaibles must be constant value
// static const String BAR = CONST_LIST[1];
}
main() {
// is CONST_LIST const or not?
// below line it's ok for dartanalyzer but
// in runtime: Cannot change the content of an unmodifiable List
Foo.CONST_LIST[1] = 'new value';
}
I noticed that const is required by dart analyzer in const [F0, F1, F2]; but it does make list more like final (runtime immutable list) rather than compile time const.
UPDATE:
Another question is why CONST_LIST[1] is not "constant value". See commented declaration of Foo.BAR.
Günter has answered the second part of your question. Here is some more information about const.
Const means that the object's entire deep state can be determined entirely at compile time and that the object will be frozen and completely immutable.
More information in this article. Also see the following question.
Regarding the second part of your question, consider the following:
const int foo = 10 * 10;
The expression "10 * 10" can be evaluated at compile time, so it is a "constant expression". The types of things you can do in a constant expression need to be quite limited (otherwise you could run arbitrary Dart code in the compiler!). But some of these limitations are being relaxed as dart matures, as you can see in the bug which Günter linked to.
In contrast, consider the following:
final int bar = 10;
final int foo = bar * bar;
Since "bar * bar" is not a constant expression it is evaluated at runtime.
There is an open bug for this: see https://github.com/dart-lang/sdk/issues/3059

Type alias with compile-time checking?

Type Aliases do not provide compile-time type checking
Type aliases are very handy for shortening long type names. Type alias' are just syntatic sugar and are compiled into the aliased type at run-time, meaning two different aliases representing the same type can be used interchangeably without error:
type foo = int
type bar = int
let x : foo = 5
let y : bar = x
type foo = int
type bar = int
val x : foo = 5
val y : bar = 5
I understand why you wouldn't want to treat them as regular types with compile-time type enforcement. Still, in some scenarios, it would be very handy.
Sometimes, I need to differentiate between ints which represent different things
For example, I am importing some functions from a COM library that has several different kinds of values, but they are all represented as ints in my code:
[<DllImport(#"C:\API\COMAPI.dll", EntryPoint="Foobar")>]
extern int Foobar ( int hPool, int hServer )
In C, hPool is of type APIP and hServer and the function return type are both APIV:
typedef unsigned long API_INDEX; // index
typedef API_INDEX * APIV; // value handle
typedef void * APIP; // pool handle
I would like to represent these different types, representing different things, with different types that provide some compile-time type enforcement. That way, I can't accidentally pass an APIP to a function expecting an APIV.
Measures get me half-way there, but require a LOT of extra fluff
So far, the only solution I've found is to use measurements:
type [<Measure>] APIP
type [<Measure>] APIV
Unfortunately, it seems that measures cannot be added directly to externs:
[<DllImport(#"C:\API\COMAPI.dll", EntryPoint="Foobar")>]
extern int<APIV> _Foobar ( int<APIP> hPool, int<APIV> hServer )
error FS0010: Unexpected type application in extern declaration. Expected identifier or other token.
So I am having to write a wrapper function, resulting in a LOT of extra code:
[<DllImport(#"C:\API\COMAPI.dll", EntryPoint="Foobar")>]
extern int private _Foobar ( int hPool, int hServer )
let Foobar ( hPool : int<APIP> ) ( hServer : int<APIV> ) : APIV =
_Foobar( int hPool, int hServer ) |> LanguagePrimitives.Int32WithMeasure
Multiplied by dozens and dozens of imported functions, this is getting really bloated and tiresome.
Is there a more intuitive way to handle this, or am I stuck deciding between compile-time type checking and reasonably readable code?

How to destucture a tuple of records to private values

How do you use a module-level let binding to bind two private values to records in a tuple?
type private T = {F:int}
let private a = {F=1}
let private b, private c = {F=2}, {F=3}
In this example, a works fine, but the bindings for b and c each fail with the error:
error FS0410: The type 'T' is less accessible than the value, member or type 'val patternInput : T * T' it is used in
To see why this doesn't work, decompile it with Reflector. You're creating a tuple and immediately destructuring it. In debug mode anyway, the intermediate tuple is created as an internal field of the enclosing type (an implementation detail of the pattern match). Of course, that makes it more accessible than T, which is private. I'm curious to know if this is a bug (seems like it).
EDIT
It gets weirder...
The following fails to compile (with syntax error), but compiles fine if the types are public and let, instead of let private, is used.
type private T = {a:int; b:int}
let private t = {a=0; b=0}
let private {a=a; b=b} = t //syntax error
type private U() = class end
let private ul = [U()]
let private [u] = ul //syntax error
I think it's safe to say destructuring in module-level private let bindings has some problems.

Resources