 So, hello everyone. Last year I presented our binding generator for C++ code to ADA. We promised you that it's going to be better than any existing solution, and we tried hard, but it isn't. And now I'm going to explain why. So what did we say? We wanted to be better than existing solutions. We wanted to have to maintain the original C++ API layout. We wanted to have type safety. We wanted to have template support because this is what most of the existing solution were lacking. And for this we also had to implement things like C++ name mangling and so on. So how far did we get? Well, we got working template support to some extent. I showed a demo last year. We were able to bind these simple things like classes, name spaces, functions, pointers, function pointers, visibility like public, protected and private. So at some point we arrived at our own probably not complete C++ name mangling implementation. So what are the things we didn't achieve? Well, one great but also really complex feature of C++ are partial template specializations. So this is something that we didn't make to work. There are many things that we could have done with just more effort. Like there are many edge cases like type devs on specific types, the auto keyword operator overlates function templates and so on. But there are also things we didn't even try to do until the point when we stopped destructors or multiple inheritance. So why is it hard in an overview? They're both quite complex languages like Ada 2012 has 1,300 pages and C and C++ together have around 2,000 pages of standard. So to make a complete generator you have to understand it all and map it all one on another. And at some points they're also inherently different. So C++ templates can be used for meta programming. They're actually Turing complete. Ada generics are not that versatile, which in my mind is a good thing. Also Aries for example, in Ada they are a separate type. They have a specific index type and in C++ the index is just a built-in construct and the index is just a constant expression that is casted to whatever type is needed on compile time. So what doesn't work or what is really hard to get right? Templates in C++ they are static. So when you have a template you're instantiate with a type name T for example and then you use this type. So this is like an Ada generic with a private type. And as it is static it generates its own symbol and this symbol is mangled to prevent overlapping symbols. So we instantiate this template and we have with integer so we have the name A which maps to this name A in the symbol and the integer matches to this E in the symbol. The function name matches to this name in the symbol and the other integer matches to this I in the symbol. The things between our start and end points for the names and this set underscore set is like just this is a C++ mangled symbol. So we want to implement this as an Ada generic and we don't want to make this statically it's not statically in the sense of compile time but statically in the sense of binding but we want to generate our binding automatically. So what would we have to do? We have to generate the symbol in the external name where we can import symbols in Ada. We would have to generate the symbol at compile time. Well now we are running in a problem here when we call this function which generates the correct symbol part of our type which X is of, so X is of type T and we generate a string of X which is type specific and the problem is this isn't static and in general the Ada reference manual says well not at this part but in general it says that this part the template argument is never static so we will never be able to get the template argument be somewhere included in the symbol name so this just doesn't work. The idea behind this function initially was we overload this function and for each type you return a specific symbol but the other problem is we can't overload a function and then put a private type if you go back and we see that X is private and X is of a private type T so we can't just overload M with integer and hope that the private type is integer and it will be automatically resolved this just doesn't work. So yeah you can't just generate a symbol from code in Ada. The only solution would be a pre-processor. We didn't want to have a pre-processor. The first thing is the Ada doesn't have one in the first place and the second thing is if we wanted to make the code as far compatible as possible and if we would make a pre-processor it would be really hard to prove all the code because depending on the pre-processor options you would only prove the part that the pre-processor includes and then you would have to make sure that all the pre-processor options are proved also and this would require some meta-prover that proves that all your code is proof. Yeah so that's why we don't want to have a pre-processor and this is an option for us. The second is C++ supports pass-by value for anything so you can just take a class that is like a kilobyte large and you can just pass it by value. So how do we import a class in C++ in Ada? First the class itself is a record in Ada and it has the convention C++ and it must be limited. So if you don't add the limited you won't get the constructor which is a function that returns A but has a C++ constructor. The important thing here is that this construct behaves like a function so that it can initialize the limited object but actually it is a procedure where A is the first argument as an out parameter. So this is a kind of special construct we need for C++ classes so we can't omit this. But now we add a procedure print A so as we can see here this takes A without any pointer or reference addition so it just pass-by value and okay we just import it and we say it's an in parameter so it's potentially pass-by value but the problem is does anyone see the problem here? Exactly. Well A is limited and so A is always pass-by reference so what we do is we take the reference to A and pass it to print and print thinks oh this is already my class and for anything else then this simple thing it will just break and you have a stack overflow because print will just go deeper into the class and yeah this is your memory where the pointer is but not your class. So a considered solution would be that we can import print by the convention C pass-by copy and explicitly test print okay whatever goes into there must be pass-by copy problem is this is only allowed for the record type and as soon as we make it limited and convention C++ to it it is not longer a record type but a C++ class type which can at no point ever be pass-by value so we can just define an identical record and convert between both so yeah this is going to be on one point really really ugly because you always have to convert between usually identical things and the other thing is you would have to make an unchecked conversion between a limited and a non-limited type and this is some kind of you take an address and convert it to something that is not an address so this doesn't sound really safe things that are just not working automatically called destructors so I think we even wrote a ticket to Adakor and they just told us this won't work an option for this could be controlled types but to use a controlled type you have to inherit from it so you already have the controlled type in your class but then it's not any more identical to the C++ class you actually want to use so you probably have to embed the C++ class somehow into the controlled type but if you have a point of the C++ class it doesn't point any more to the controlled type so yeah we see this isn't going any better we could call the destructor manually but then we had to implement a solution in our binding generator that checks the scope of any object we ever see in C++ and checks if it goes out of scope and automatically calls then the generator at the destructor this isn't really a feasible solution so what have you learned well even if anything would work we would still have to implement 2,000 pages of standard and yeah there are things that might work with really high effort with a preprocessor but there are also things that just never will work really good or at the high cost of a bad usability or really really bad safety and since we are going to target Spark as our language we are not going to make any compromises in safety last year someone asked this question do you fear that you import the weirdness of C++ into Ada and well now we have our answer it is yes yes well we didn't make the binding generator for no purpose but the purpose was to build safe components for component-based systems so since we don't have a binding generator we had to write our bindings ourselves and I will talk about those bindings and the solutions in my nice a nice component framework in Spark talk tomorrow in the microkernel left room so you are all welcome to go there thank you are there any questions Fabian sorry it was just the question was if we can change things in the Ada language to overcome some of those limitations but at some point what we really thought would be useful would be a static the option to make generics completely static so the problem is that generics are never considered static even if all inputs are actually static because you just write them into the code so this would be a great option for those things another one would I don't know if it's something you want to have in the language but maybe some kind of constant expression so like an expression function but you say it's always static and you can evaluate it at compile time this would probably make templates in generics work about the pass-by-value thing I'm not sure if this is going if this is ever going to work I'll try to remember you I don't know if operations such as compiling in the control types to the two decoupling constructors in C++ I don't know if that's there but introducing an indirection not to rely on that C++ interfacing aspects to work around the I tried to repeat it but the question was if we can embed the C++ types as pointers into our data types and then that we can forward the destructor and construct and copy constructor calls to C++ again our initial goal was also for those component-based systems and we don't have dynamic memory there and our memory management solution for these systems is that all the memory resides in the BSS in our package so we have to to know all exact C++ type layouts to map them correctly to ADA yes yes exactly so we have a quite limited quite a limited environment so with a limited runtime so we really have to make our memory management ourselves and then we have to know the exact type layout for any C++ type we want to use I think this was slide 3 so the question was somewhere on my slides was overloading doesn't work with private types I know what you mean so you see here that T is a private type and the idea was M is a function we implemented somewhere else for any possible type and that whatever you put in T is automatically overloaded in M but if you do a construct like this the compiler just tells you okay well M does not accept T but M wants integer or whatever so you have to implement in M that accepts exactly T and then again you don't know what T is but you want at this point you want to know what T is this is actually a restriction set by the Knot sorry yeah why are we using limited types for C++ classes and why nothing is limited in C++ well one thing is we are not in C++ and when you copy some things in C++ there might be a copy constructor called but if you copy something the copy constructor isn't called so you're actually not allowed to copy it because it doesn't have the same behavior so you don't want to copy it in Ada and the other limitation is not just sales if you use the spragma the type must be limited point so it just doesn't compile any further questions well then thank you