what is the roles of function name that's Delphi does when compiling pas file.
for example the following code
unit Hellopas;
interface
function HelloFromPas():Integer; stdcall;
will preduce this function name #Hellopas#HelloFromPas$qqsv
so what is the Delphi roles for that?
This is a decorated or mangled name. The name encodes the full scope for the function, and its parameters. The unit name is included because that is part of the fully qualified name. The parameters, return value and calling convention are encoded also, here as qqsv.
Wikipedia explains the need for mangling like this:
In compiler construction, name mangling (also called name decoration)
is a technique used to solve various problems caused by the need to
resolve unique names for programming entities in many modern
programming languages.
It provides a way of encoding additional information in the name of a
function, structure, class or another datatype in order to pass more
semantic information from the compilers to linkers.
The need arises where the language allows different entities to be
named with the same identifier as long as they occupy a different
namespace (where a namespace is typically defined by a module, class,
or explicit namespace directive) or have different signatures (such as
function overloading).
Any object code produced by compilers is usually linked with other
pieces of object code (produced by the same or another compiler) by a
type of program called a linker. The linker needs a great deal of
information on each program entity. For example, to correctly link a
function it needs its name, the number of arguments and their types,
and so on.
Related
How can I access the typed abstract syntaxe tree for all source files in a f# project in order as descibed in "analysing a whole project". So, what I need is the specific Microsoft.FSharp.Compiler.Tast of all files in a project.
Accessing the untyped syntax tree is quite simple, as described in walking an untyped ast. So, I expect there to be a corresponding interface to the tast.
The purpose is to transpile code from F# to another typed language, in this case scala, which need type annotations. A whole project should be translated at once.
The first URL you link shows how to get an FSharpAssemblySignature, but doesn't explain much of what to do with such a value. That type, and the immediate types it contains, FSharpEntity & FSharpMemberOrFunctionOrValue, are defined in Symbols.fs. The typed AST itself is defined in tast.fs. I don't know of any docs explaining the various types, except the comments in these two files.
Is there any way to open a namespace of types provided by a type provider implementation? I ask, because some of the generated type name paths are very long and ugly in code. I have used type abbreviations to alleviate this, but obviously this is a manual process. The F# open keyword does not support this. Is there another way? Update: as pointed out in the answer and comments this is wrong. You can open a type provided namespace. I had not realised I was looking at deeply nested types, not a namespace.
This is tricky - parameterized type providers (like the standard SQL providers or the F# Data providers for XML and JSON) need to put all types that they generate (representing tables, XML nodes, etc) inside the main generated type. So all types that you might want to use are hidden somewhere as nested types of the main type (with parameters specified).
This makes sense - if you use the type provider with multiple parameters, the types generated for each configuration have to be separate.
As #kvb points out, you cannot open a nested type, but you can use type aliases to make this a bit less painful. For example, using F# Data, I can define an alias R that lets me access all the generated domain types with just two additional characters:
#r #"..\packages\FSharp.Data.1.1.10\lib\net40\FSharp.Data.dll"
open FSharp.Data
type RssFeed = XmlProvider<"http://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml">
type R = RssFeed.DomainTypes
let printTitle (itm:R.Item) = printfn "%A" itm.Title
What exactly is the difference between F#'s type augmentation and type extension, and do we really need both?
Are there situations where one is better than the other, and vice-versa?
I'm asking because I recently had a lecture in F# where the lecturer talked about both, and afterwards commented that he couldn't see the reason why both were included in the F# language.
Update:
Ok, so Vladislav Zorov links to a page with examples of using type augmentation both when defining your own types, and extending (or augmenting?) an external type.
pad links to an MSDN page where they call it intrinsic and optional type extension.
Both seem to illustrate the same thing. Can someone come with a concrete example of type extension and another concrete example of type augmentation perhaps, in order to explicitly clarify what the two things are exactly?
The following bits from MSDN's Type Extensions page are relevant (emphasis mine):
There are two forms of type extensions that have slightly different
syntax and behavior. An intrinsic extension is an extension that
appears in the same namespace or module, in the same source file, and
in the same assembly (DLL or executable file) as the type being
extended. An optional extension is an extension that appears outside
the original module, namespace, or assembly of the type being
extended. Intrinsic extensions appear on the type when the type is
examined by reflection, but optional extensions do not. Optional
extensions must be in modules, and they are only in scope when the
module that contains the extension is open.
The purpose of optional extension is clear. It helps you inject new functionalities to types not belonging to your assemblies. For examples, FSharpx uses it to create various helpers for parsing primitive types:
open System
type Boolean with
static member parse x =
match bool.TryParse(x) with
| true,v -> Some v
| _ -> None
Why do you need intrinsic extension then? The answer is its convenience. I find it useful to break down type definitions to multiple sections with clear purposes.
In many F# libraries, I saw the use of the following pattern: type definition -> utility functions -> intrinsic extension. In this way, you can define sophisticated utility functions on your types, make them available in modules and still can use them directly in your member definitions. You can look at Complex type in F# PowerPack to see the pattern.
EDIT:
To be honest, I often use type extension and type augmentation interchangeably. The thing that matters is whether they are intrinsic or optional.
They are different things. Type augmentations, when defined in the same namespace, module and source file, actually become part of the type when compiled. Type extensions (a.k.a. type augmentations for types outside of the module and source file) are implemented with .NET extension methods.
They both use the same syntax, the only difference is whether the type you mention is in the same namespace and assembly, i.e. you're augmenting your own code and the additional methods can be added to your type before compilation.
Source: http://tomasp.net/blog/fsharp-iii-oop.aspx
Edit:
This is a terminology mix-up, they are both referring to the same thing - intrinsic extensions are type augmentations of the first kind (i.e. same namespace and assembly), optional extensions are type augmentations of the second kind (i.e. 3rd party assembly, in the blog post this is the List<T> augmentation example).
I assume when your lecturer is talking about type augmentations, he's referring to intrinsic extensions, i.e. first kind type augmentations, and when he's talking about type extensions, he's talking about optional extensions, or second kind type augmentations.
This works
open System
let f = Action(fun () -> Unchecked.defaultof<_>)
But this
let f = System.Action(fun () -> Unchecked.defaultof<_>)
produces the compilation error
Multiple types exist called 'Action', taking different numbers of generic parameters. Provide a type instantiation to disambiguate the type resolution, e.g. 'Action<,,_,,,_,,,_>'.
I know I can fix it by adding a type parameter placeholder (System.Action<_>(...)), but any idea why they behave differently?
EDIT
Found this in the spec, section 14.1.9:
When a module or namespace declaration group F is opened, items are added to the name environment as follows:
Add the type to the TypeNames table. If the type has a CLI-mangled generic name such as List'1 then an entry is added under both List and List'1.
Is this behavior replicated for fully-qualified types (with omitted type parameters)? It doesn't appear so.
I agree with #James that this is related to the bug submitted on Connect, but I think it is a slightly different case. Anyway, I think this is not the intended behaviour. Could you report it to fsbugs at microsoft dot com?
Anyway - I did some debugging and here is what I found so far:
It seems that the compiler uses different code paths to resolve the name Action and the name System.Action. When resolving the other, it searches all loaded modules (i.e. assemblies) for a type named System.Action (see ResolveLongIndentAsModuleOrNamespaceThen function in the nameres.fs file of the open-source release).
This finds the two definitions of Action (one in mscorlib and another in System.Core). I think the issue comes from the fact that the name resolution simply iterates over the results - it finds the first one (from System.Core), which doesn't have a usable overload (because it ranges from Action<_,_,_,_,_> to a version with about 15 type parameters). After finding this type, it reports an error without even looking whether there is another type (in another assembly) that could be used.
If you don't reference system assemblies, then the F# compiler resolves the overload just fine. Running the compiler without parameters references the default assembly set, so this doesn't work:
fsc test.fs
but if I add the --noframework flag, then it compiles without issues:
fsc --noframework test.fs
I am using functions from an external .pas file. I can use some of the functions, but not others. As far as i can see the functions are declared the same way, I would like to post some of the file, but don't know ho to post large amounts of code.
You can use the functions that are declared in the interface section, that is the section of code before the implementation section.
You are probably trying to call functions that are defined only in the implementation section, that is that code that appears after the implementation keyword.
These different sections are how Delphi implements public and private visibility at the unit level.
Usually, in well written units, there will be a reason for functions being made private to the unit. But if you feel it reasonable to override the author's decision then you need to redeclare the function in the interface section. This will make it available to your code which uses the 3rd party unit.
The file is not properly linked and/or not included in your projects search path and/or shadowed by some other file with same function names and/or odd functions are within $IFDEF clauses.
Check spelling, uses clauses, working function location (Ctrl+click on function name in your code), $IFDEF clauses.
The file is not properly linked in Delphi environment options
The file could be located outside of project search path. Hence it's not linked.
The file path is typed wrongly in project (DPR file). E.g. you are referring to older path with olde version of a file.
In each of these cases some functions could be taken from other files if name fits. E.g. function gluUnproject can be taken both from OpenGL.pas and dglOpenGL.pas, if first unit is not linked properly I would get the same problem as you are having now - some functions work and some are missing. In any of the cases you should compile your project, Ctrl+Click on a working function name and see where it brings you, check file version location.
The functions could be inside of $IFDEF clauses. These are compiler directives and code within such clause will be invisible to compiler if certain condition is not met. E.g. {$IFDEF MSWindows} Func {$ENDIF} won't be accessible on Linux.