Just An Application

November 1, 2014

So Swift Then: The Curried Function Type Encoding Mystery Continued

Compiling the curried function

    public func plusN(n: Int)(i: Int) -> Int
    {
        return i + n
    }

on its own in the module xper gives us the symbol

    __TF4xper5plusNfSiFT1iSi_Si

All the examples of mangled names of vanilla functions we have seen to date have been in the format.

    "__TF" 'function name' "F" 'parameter encoding' 'return type encoding' 'suffix'?

The format of the symbol for the curried function is identical to this except that there is a lower-case ‘f’ rather than an upper case ‘F’

We have been assuming that the upper case ‘F’ immediately following the function name in the symbol for a vanilla function is the prefix for a ‘function type’.

If this is true than the lower case ‘f’ is presumably the prefix for a different kind of function type.

The obvious candidate is the ‘curried function type’ but why is it necessary to distinguish between a ‘function type’ and a ‘curried function type’ in the mangled name of the function ?

The compiler does not distinguish between a curried function and the vanilla version of the curried function at compile time but it does ensure that it is possible to identify which one was compiled to produce the object code.

This implies that a caller would have to be linked against either one or the other despite calls to both functions being identical.

Here is a function which calls plusN and then immediately calls the function that was returned

    import xper
    
    func cod(x: Int, y:Int) -> Int
    {
        return xper.plusN(x)(i:y) // ignore the 'external name' its not really there
    }

This call works whether it is the curried function or the vanilla function equivalent that is being called.

Here is a function that does the same thing as the function cod with an intermediate step just to make it clear what is going
on.

    import xper
    
    func saithe(x: Int, y:Int) -> Int
    {
        let plusX = xper.plusN(x)

        return plusX(i:y) // ignore the 'external name' its not really there
    }

This call also works whether it is the curried function or the vanilla function equivalent that is being called.

This is not surprising since they are obviously both doing the same thing, that is

  • calling the function xper.plusN with the argument x

  • calling the function returned from the call to xper.plusN with the argument y

In saithe the function returned from the call to xper.plusN is explicitly referenced but the only thing done with it is to call it. It does not ‘escape’ from the function at any point so the two functions are effectively identical.

If we compile the function cod on its own in the module caller linking against the module xper containing the curried function plusN we get the symbol

    __TF6caller3codFTSiSi_Si

for the function itself, and the undefined symbol

  __TF4xper5plusNfSiFT1iSi_Si

which is the symbol for the curried function xper.plusN.

If we compile the function saithe on its own in the module caller linking against the module xper containing the curried function plusN then, as before, we get the symbol

    __TF6caller6saitheFTSiSi_Si

for the function itself, the undefined symbol

  __TF4xper5plusNfSiFT1iSi_Si

which is the symbol for the curried function xper.plusN, as before, and quite unexpectedly the symbols for two local
functions.

    __TF4xper5plusNFSiFT1iSi_Si

and

    __TPA__TF4xper5plusNfSiFT1iSi_Si

Who ordered those ?

The function type encoded in the first symbol is

    (Int) -> (i: Int) -> Int

which looks strangely familiar.

The only place in the function saithe that it could be called is here.

    let plusX = xper.plusN(x)

If we assume that the compiler knows what it is doing then that must be what it is for.

The symbol for the second function

    __TPA__TF4xper5plusNfSiFT1iSi_Si

looks like the symbol for the curried function xper.plusN with the prefix

    __TPA

We have never seen anything like this before so it is a bit difficult to say what this kind of function might be for.

Continuing with the hypothesis that the compiler knows what it is doing we have to assume that it needs this function for something, and given that is has already generated a function to return a function then presumably this is the function that gets returned.

If this is true then the reading of the function type in the mangled name has to be something other than the type apparently encoded.

The function type needs to be

    (i: Int) -> Int

and that is not what is encoded according to the vanilla function type reading.

If the compiler really has had to generate a function to do this

    let plusX = xper.plusN(x)

then the implication is that the function plusN in the module xper cannot be called at that point.

It must be possible to call it since the first example works and the compiler did not need to generate any additional functions to make it work.

If the function plusN in the module xper cannot be called in saithe but it can be called in cod then we can infer both

  • what its function type is not, and

  • what it must be

which explains both why the generated local functions are needed and what they do.

It also confirms that the reading of ‘curried function’ types is not the same as the reading of ‘vanilla function’ types when they appear in mangled function names.


Copyright (c) 2014 By Simon Lewis. All Rights Reserved.

Unauthorized use and/or duplication of this material without express and written permission from this blog’s author and owner Simon Lewis is strictly prohibited.

Excerpts and links may be used, provided that full and clear credit is given to Simon Lewis and justanapplication.wordpress.com with appropriate and specific direction to the original content.

Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: