Cappulada: What we've Learned
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Subtitle |
| |
Title of Series | ||
Number of Parts | 490 | |
Author | ||
License | CC Attribution 2.0 Belgium: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor. | |
Identifiers | 10.5446/47041 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
00:00
CodeKeyboard shortcutComputer animation
00:29
Link (knot theory)Kolmogorov complexitySubject indexingInheritance (object-oriented programming)Type theoryFunctional (mathematics)Generic programmingLatent heatComplete metric spaceKeyboard shortcutComplex (psychology)Standard deviationTemplate (C++)Extension (kinesiology)Overlay-NetzTypprüfungMultiplicationExpressionPoint (geometry)ImplementationOperator (mathematics)CASE <Informatik>Pointer (computer programming)Data structureAreaSocial classMultiplication signExterior algebraNatural languageGradientFormal languageService (economics)Web pageSource code
03:17
Generic programmingType theoryTemplate (C++)Generic programmingSymbol tableIntegerSet (mathematics)MappingFunctional (mathematics)Fluid staticsCompass (drafting)Computer animation
04:14
BriefträgerproblemConvex hullString (computer science)MereologyFunctional (mathematics)Symbol tableFluid staticsType theoryMultiplication signParameter (computer programming)Template (C++)Latent heatInformation overload
05:20
String (computer science)BriefträgerproblemConvex hull10 (number)Generic programmingInformation overloadType theoryComputer animation
05:45
String (computer science)Template (C++)BriefträgerproblemLetterpress printingConvex hullMountain passVector potentialHill differential equationComputer configurationControl flowProof theoryAdditionData conversionStandard deviationSocial classAddress spaceData structurePoint (geometry)Row (database)Web pageProcess (computing)Sinc functionUsabilitySemiconductor memoryArmPointer (computer programming)Game controllerFunctional (mathematics)CodeSoftware bugConstructor (object-oriented programming)Video gameType theoryLetterpress printingParameter (computer programming)Procedural programmingCoprocessorSymbol tableOperator (mathematics)Object (grammar)Preprocessor2 (number)MereologyStack (abstract data type)Computer animation
11:09
Euclidean vectorSoftware frameworkConnectivity (graph theory)BuildingKeyboard shortcutPhysical systemSoftware frameworkComponent-based software engineeringMikrokernelFrame problemComputer animation
11:53
CodePoint (geometry)Connectivity (graph theory)Limit (category theory)PressureMultiplication signType theoryMathematicsFormal languageState of matterPhysical systemExpressionConstructor (object-oriented programming)Integrated development environmentGoodness of fitShared memoryComputer configurationSemiconductor memoryData managementCASE <Informatik>Generic programmingRegular graphTheoryObservational studyMemory managementoutputGame controllerPointer (computer programming)Interface (computing)Template (C++)Lecture/Conference
15:37
Euclidean vectorSoftware frameworkSlide ruleType theoryFunctional (mathematics)MereologyComputer animationSource code
16:03
BriefträgerproblemTemplate (C++)Generic programmingHill differential equationCompilerFunctional (mathematics)Type theoryLimit (category theory)SubsetConstructor (object-oriented programming)Point (geometry)Multiplication signComputer programming
17:50
Software frameworkEuclidean vectorMikrokernelFacebookPoint cloudOpen sourceComputer animation
Transcript: English(auto-generated)
00:05
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
00:20
than any existing solution, and we tried hard, but it isn't. And I'm going to, 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.
00:44
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.
01:04
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, namespaces, functions, pointers, function pointers,
01:22
visibility like public, protected, and private. And also, at some point, we arrived at our own, probably not complete C++ name mangling implementation. So what are the things we didn't achieve?
01:41
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. Also, there are many things that we could have done with just more effort, like there are many edge cases
02:02
like typedefs on specific types, the auto keyword operator overlays function templates and so on. But there are also things we didn't even try to do until the point when we stopped, like destructors or multiple inheritance. So why is it hard in an overview?
02:22
Well, 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.
02:41
And at some points, they are 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, arrays, for example, in Ada,
03:01
they are a separate type. They have a specific index type, and in C++, the index is just, well, the array itself 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,
03:21
or what is really hard to get right? Templates in C++, they are static. So when you have a template, you're instantiated 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 an aesthetic, it generates its own symbol,
03:42
and this symbol is mangled to prevent overlapping symbols. So we instantiate this template with integers, or 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.
04:01
The things between are 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,
04:20
well, 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, 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,
04:40
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 in this,
05:00
no, well, not at this part, but in general 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,
05:21
we overload this function, and for each type, we return a specific symbol, but the other problem is, we can't overload a function, and then put a private type, if it 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,
05:40
and hope that the private type is integer, and it'll 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 preprocessor. We didn't want to have a preprocessor. First thing is, Ada doesn't have one in the first place,
06:02
and the second thing is, if we wanted to make the code as far comfortable as possible, and if we would make a preprocessor, it would be really hard to prove all the code, because depending on the preprocessor options, you would only prove the part that the preprocessor includes, and then you would have to make sure
06:20
that all the preprocessor options are proved also, and this would require some meta-prover that proves that all your code is proofed. Yeah, so that's why we don't want to have a preprocessor, and this is an option for us. The second is C++ supports pass-by value for anything, so you can just take a class
06:41
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,
07:01
which is a function that returns A, but has a pragma C++ constructor. The important thing here is that this function behaves like a, this construct behaves like a function, so that it can initialize the limited object, but it actually, it is a procedure where A is the first argument as an out-parameter.
07:22
So yeah, this is kind of a 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,
07:41
so it's just pass-by value. And well, okay, we just imported, 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 passed by reference.
08:02
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, well, a considered solution would be
08:23
that we can import print by the convention C pass-by copy, which explicitly tells print, okay, whatever goes into there must be passed by copy. Problem is, this is only allowed for the record type, and as soon as we make it limited,
08:42
and it's convention C++, so it is no longer a record type, but a C++ class type, which can at no point ever be passed by value. So we can just define an identical record and convert between both.
09:01
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 uncheck conversion between a limited and an unlimited type, and this is some kind of, you take an address and convert it to something
09:20
that is not an address, so this doesn't sound really safe. Yeah, things that are just not working, automatically called destructors. So I think we even wrote a ticket to Adacore, and they just told us this won't work. An option for this could be control types,
09:42
but to use a control 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
10:00
somehow into the control type, but if you have a point of the C++ class, it doesn't point anymore to the control type. So yeah, you see, this isn't going anywhere. Okay, yeah, we could call the destructor manually, but then we had to implement a solution in our binding generator that checks the scope
10:22
of any object we ever see in C++ and checks if it goes out of scope and automatically calls the generator at the destructor. This isn't really a feasible solution. So what have we learned? Well, even if anything would work,
10:40
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.
11:01
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.
11:23
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 component framework in Spark.
11:43
Talk tomorrow in the microkernel lab room. So you're all welcome to go there. Thank you. Are there any questions? Fabio?
12:06
Sorry, it was just, okay. Yeah, the question was if we can change things
12:20
in the Ada language to overcome some of those limitations. Well, 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.
12:41
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 const 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.
13:04
About the pass-by value thing, I'm not sure if this is ever going to work. I try to remember you. The interface of C++,
13:33
instead of going through some kind of wrapper, you have actually pure Ada types
13:42
that just contain in something private a pointer to then immediately locate C++ in so that you can actually manually forward the Ada and AD operations, such as copying in the control types to the copy constructors in C++.
14:05
I don't know if that's clear, but introducing an indirection, not to rely on if that's C++ interfacing aspects to work around the... Yeah, I tried to repeat it.
14:21
Well, the question was, if we can embed the C++ types as pointers into our Ada types, and then that we can forward the destructor and construct and copy constructor calls to C++ again. Our initial goal was also
14:40
for those component-based systems, and we don't have dynamic memory there. Our memory management solution for these systems is that all the memory resides in the BSS in our package. We have to know all exact C++ type layouts
15:03
to map them correctly to Ada. Yes. Yes, exactly. We have quite a limited environment.
15:22
With the limited runtime, 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. Ah, you.
15:41
I think this was slide three or so. Overloading, so the question was, somewhere on my slides was, overloading doesn't work with private types.
16:01
Ah, no, I know what you mean. So you see here that T is a private type, and the idea was that M is a function we implemented somewhere else for any possible type, and that whatever you put in T is automatically overloaded in M,
16:21
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 an M that accepts exactly T, and then you, again, you don't know what T is, but you want, at this point, you want to know what T is.
16:41
Yes. This is actually a restriction set by the, by the Knut,
17:00
ah, 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++, or there might be a copy constructor called, but if you copy something in Ada,
17:20
the copy constructor isn't called, so you're actually not allowed to copy it because it doesn't have the same behavior. You don't want to copy it in Ada, and the other limitation is Knut just says if you use this pragma, the type must be limited point, so it just doesn't compile. Any further questions?
17:44
Well then, thank you.