How can I match a function parameter of a given type, regardless of whether it's passed by value, reference or pointer? - clang

Here's a clang AST matcher which will match a function any of whose parameters are a std::vector (of any type) passed by value or reference:
DeclarationMatcher funcMatcher = functionDecl(
anyOf(hasAnyParameter(
hasType(references(recordDecl(matchesName("std::vector"))))),
hasAnyParameter(hasType(recordDecl(matchesName("std::vector"))))));
I'd like to know if there is some matcher which will match e.g. std::vector&, std::vector* and std::vector?
Obviously I could expand the matcher above for the pointer case, but I was wondering if clang AST has some concept of the 'underlying' type. I've spent quite a bit of time looking here.

Related

Why does reference equality for functions which are bound to the same variable return false?

let f x = System.Object.ReferenceEquals(x,x)
f id // false
I thought that at first it might because a function could be converted to a closure multiple times, but the above disproves that. Why does that last line return false?
You likely have optimizations turned on. This time it's the opposite problem.
What happens if inlining is turned on?
id will be rewritten to an instance of idFuncClass <: FSharpFunc.
The whole expression will be rewritten to:
Object.ReferenceEquals(new fsharpfun1(), new fsharpfun1())
You can turning off inlining with:
[<MethodImpl(MethodImplOptions.NoInlining)>]
let f x = System.Object.ReferenceEquals(x,x)
You'll find that the comparison works again.
But the bigger take-away is this - comparing two functions in F# is undefined behavior. In fact a function type doesn't even implement equality.
let illegal = id = id //this won't compile
Here's the relevant section in the F# Spec:
6.9.24 Values with Underspecified Object Identity and Type Identity
The CLI and F# support operations that detect object identity — that is, whether two object references refer to the same “physical” object.
For example, System.Object.ReferenceEquals(obj1, obj2) returns true if the two object references refer to the same object. Similarly, GetHashCode() returns a hash code that is partly based on physical object identity ...
The results of these operations are underspecified when used with values of the following F# types:
Function types
Tuple types
Immutable record types
Union types
Boxed immutable value types
For two values of such types, the results of System.Object.ReferenceEquals and
System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode are underspecified; however, the operations terminate and do not raise exceptions.
An implementation of F# is not required to define the results of these
operations for values of these types.
What the spec advises is to treat the actual function-type and its CLR implementations as a black-box.

with source_gen package, how can I get initializer value?

I would like to get the initializer in the field corrected_time in code below. I found the field.initializer, but couldn't get much further. (the #Init annotation is temporary solution for now):
mixin PrerenderDoc on Doc implements AllowDelete {
#Init(init_int: 0)
int corrected_time = 0;
}
I'm guessing that field is an instance of FieldElement. Unfortunately, if that's the case, then the answer is that analyzer doesn't have a value for the initializer. The analyzer only computes values for (a subset of) expressions that are constant expressions. For field initializers, that means that the field needs to be declared to be const, and the one in the example isn't.
(Annotations are constants and hence have values, which is why your workaround works.)
If the field were declared const, then you could use VariableElement.constantValue to access a representation of the value (VariableElement is a superclass of FieldElement).
The other option available to you is to use the AST structure and examine the structure of the expression, but if you want / need to handle anything more than just simple literal values, that can be quite complex.

When are F# function calls evaluated; lazily or immediately?

Curried functions in F#. I get the bit where passing in a subset of parameters yields a function with presets. I just wondered if passing all of the parameters is any different. For example:
let addTwo x y = x + y
let incr a = addTwo 1
let added = addTwo 2 2
incr is a function taking one argument.
Is added an int or a function? I can imagine an implementation where "added" is evaluated lazily only on use (like Schroedinger's Cat on opening the box). Is there any guarantee of when the addition is performed?
added is not a function; it is just a value that is calculated and bound to the name on the spot. A function always needs at least one parameter; if there is nothing useful to pass, that would be the unit value ():
let added () = addTwo 2 2
F# is an eagerly evaluated language, so an expression like addTwo 2 2 will immediately be evaluated to a value of the int type.
Haskell, by contrast, is lazily evaluated. An expression like addTwo 2 2 will not be evaluated until the value is needed. The type of the expression would still be a single integer, though. Even so, such an expression is, despite its laziness, not regarded as a function; in Haskell, such an unevaluated expression is called a thunk. That basically just means 'an arbitrarily complex expression that's not yet evaluated'.
incr is a function taking one argument. Is added an int or a function?
added, in this case, is a named binding that evaluates to an int. It is not a function.
I can imagine an implementation where "added" is evaluated lazily only on use (like Schroedinger's Cat on opening the box). Is there any guarantee of when the addition is performed?
The addition will be performed immediately when the binding is generated. There is no laziness involved.
As explained by TeaDrivenDev, you can change added to be a bound function instead of a bound value by adding a parameter, which can be unit:
let added () = addTwo 2 2
In this case, it will be a function, so the addition wouldn't happen until you call it:
let result = added () // Call the function, bind output to result
No. But kind of yes. But really, no.
You can construct a pure functional language that only has functions and nothing else. Lambda calculus is a complete algebra, so the theory is there. In this model, added can be considered a parameter-less function (in contrast to e.g. random(), where there's one parameter of type unit).
But F# is different. Since it's a rather pragmatic mix of imperative and functional programming, the result is not a function[1]. Instead, it's a value, just like a local in C#. This is no implementation detail - it's actually part of the F# specification. This does have disadvantages - it means its possible to have an ambiguous definition, where a definition could be either a value or a function definition (14.6.1).
[1] - Though in a pure functional program, you can't tell the difference - it's the same as just doing a substitution of the function with a cached value, which is perfectly legal.

anonymous functions and overloaded methods in F#

So, if you want to write out a line to the console in F#, you do the following:
System.Console.WriteLine "foo"
Originally I thought the following was pretty much identical, just more verbose, but actually it gives the error "A unique overload for method 'WriteLine' could not be determined based on type information prior to this program point":
(fun line -> System.Console.WriteLine line) "foo"
It seems the second version is confused by the presence of overloaded WriteLine methods that take a string as well as other arguments. Is my assumption along the right lines?
Not exactly. In the first case, the function call knows that it's being applied to a string literal, so it can do overload resolution to find the string overload.
In the second case, line is an unsolved type variable to type inference at the point of the call to the overloaded WriteLine method, so it doesn't know which overload to pick, and it hasn't seen the string argument yet, as type inference is left-to-right.
Change it to
"foo" |> (fun line -> System.Console.WriteLine line)
and it will work, because the type inference variable for line will get unified with string from "foo" coming in, before it needs to determine the WriteLine call.
So they key is left-to-right type inference; in the absence of a solution to a type variable, it may not be possible to pick an overload yet.

Duh? help with f# option types

I am having a brain freeze on f#'s option types. I have 3 books and read all I can but I am not getting them.
Does someone have a clear and concise explanation and maybe a real world example?
TIA
Gary
Brian's answer has been rated as the best explanation of option types, so you should probably read it :-). I'll try to write a more concise explanation using a simple F# example...
Let's say you have a database of products and you want a function that searches the database and returns product with a specified name. What should the function do when there is no such product? When using null, the code could look like this:
Product p = GetProduct(name);
if (p != null)
Console.WriteLine(p.Description);
A problem with this approach is that you are not forced to perform the check, so you can easily write code that will throw an unexpected exception when product is not found:
Product p = GetProduct(name);
Console.WriteLine(p.Description);
When using option type, you're making the possibility of missing value explicit. Types defined in F# cannot have a null value and when you want to write a function that may or may not return value, you cannot return Product - instead you need to return option<Product>, so the above code would look like this (I added type annotations, so that you can see types):
let (p:option<Product>) = GetProduct(name)
match p with
| Some prod -> Console.WriteLine(prod.Description)
| None -> () // No product found
You cannot directly access the Description property, because the reuslt of the search is not Product. To get the actual Product value, you need to use pattern matching, which forces you to handle the case when a value is missing.
Summary. To summarize, the purpose of option type is to make the aspect of "missing value" explicit in the type and to force you to check whether a value is available each time you work with values that may possibly be missing.
See,
http://msdn.microsoft.com/en-us/library/dd233245.aspx
The intuition behind the option type is that it "implements" a null-value. But in contrast to null, you have to explicitly require that a value can be null, whereas in most other languages, references can be null by default. There is a similarity to SQLs NULL/NOT NULL if you are familiar with those.
Why is this clever? It is clever because the language can assume that no output of any expression can ever be null. Hence, it can eliminate all null-pointer checks from the code, yielding a lot of extra speed. Furthermore, it unties the programmer from having to check for the null-case all the same, should he or she want to produce safe code.
For the few cases where a program does require a null value, the option type exist. As an example, consider a function which asks for a key inside an .ini file. The key returned is an integer, but the .ini file might not contain the key. In this case, it does make sense to return 'null' if the key is not to be found. None of the integer values are useful - the user might have entered exactly this integer value in the file. Hence, we need to 'lift' the domain of integers and give it a new value representing "no information", i.e., the null. So we wrap the 'int' to an 'int option'. Now, if there is no integer value we will get 'None' and if there is an integer value, we will get 'Some(N)' where N is the integer value in question.
There are two beautiful consequences of the choice. One, we can use the general pattern match features of F# to discriminate the values in e.g., a case expression. Two, the framework of algebraic datatypes used to define the option type is exposed to the programmer. That is, if there were no option type in F# we could have created it ourselves!

Resources