I have a problem understanding how the UFCS (Universal Function Call Syntax) works in Ada.
Let's say I have a type, like:
package People
type Person is tagged private;
-- This procedure is a primitive operation:
procedure Say_Name (Person_Object : in Person);
private
type Person is tagged record
Name : String;
end record;
end People;
then I can call the procedure as if it actually belonged to the Person type:
Some_Person_Instance.Say_Name;
Now that works, but in my particular instance it doesn't make sense to have a record, and a subtype would suffice.
subtype Person is String;
At this point (assuming I changed the procedure's workings), it fails to compile and I get the error:
invalid prefix in selected component "Person".
Why? It doesn't even help if I do:
type Person is new String;
Does UFCS only work for records?
I apologize if this is an inane question, but I've no study materials for Ada (apart for couple of e-books) and the textbook I ordered hasn't arrived yet.
UFCS is a full feature of the D language. For historical reasons, Ada has mixed approaches to calls in different parts of the language.
Ordinary subprogram calls are dealt with in ARM 6.4, and look like Subprogram_Name (Parameters) (or just Subprogram_Name if there are no parameters).
Protected subprogram calls (ARM 9.5.1) and entry calls (ARM 9.5.3) look like Object.Subprogram_Or_Entry_Name (Parameters).
Primitive subprograms of tagged types, however, can be called either way; either as an ordinary call, or, if the tagged parameter is the first parameter, using the prefix notation (ARM 4.1.3(9.1)).
There is discussion of this design in AI95-00252; apparently the designers did consider allowing both call forms for all types, but there were too many complications and too few benefits. A shame, I think we all agree, though perhaps it can be taken too far; the D example (from here)
values.multiply(10).divide(3).evens.writeln;
might be a case in point!
With regard to learning Ada and Web resources, have a look at the Ada Resource Association’s resource list.
Related
I have been trying to understand the type system for Julialang but some design aspects are still confusing me. I was hoping someone could clarify.
So the question here is about Abstract Types and their concrete implementations. From what I understand Julia Abstract types do not enforce any constraints on their concrete implementations. So there is no guarantee that a method that works on the Abstract type will work on a concrete implementation of that type.
I get that Julia does not use classes or follow inheritance. But I just want to avoid generating all sorts of bugs in my code. If there is a different design paradigm, then could someone please answer question 2 below.
So I have 2 questions.
Is this still the way that the language works? Just to confirm nothing has changed since the blog post.
How do users design their software around this seeming vulnerability?
And example of the issue from the linked post:
abstract type AbstractPerson end
abstract type AbstractStudent <: AbstractPerson end
abstract type AbstractTeacher <: AbstractPerson end
struct Person <: AbstractPerson
name::String
end
struct Student <: AbstractStudent
name::String
grade::Int
hobby::String
end
struct MusicStudent <: AbstractStudent
grade::Int
end
Now if I create some methods on the abstract type.
get_name(x::AbstractPerson) = x.name
p1 = Person("elroy")
get_name(p1)
>"elroy"
So even if MusicStudent is a subtype of AbstractPerson, the MusicStudent DOES NOT have a name attribute. That means that to following behavior is observed.
m1 = MusicStudent(10)
get_name(m1)
ERROR: type MusicStudent has no field name
Stacktrace:
[1] getproperty(::Any, ::Symbol) at ./sysimg.jl:18
[2] get_name(::MusicStudent) at ./In[2]:1
[3] top-level scope at In[13]:2
So the problem here is that Julia allows me to instantiate the type variable m1 with essentially an incomplete constructor. And it only gives me an error when I try to run that function.
So that means if I write a function for the Abstract Type, I can't guarantee every concrete implementation of that type has the same interface. That seems like it will make very fragile code as the developer won't know which types implement which attributes and methods.
Isn't this kind of behavior just a bug in the implementation of the Persons? If you really want the behavior to go without exception you can define a default method:
julia> get_name(p::AbstractPerson) = try return p.name catch y return "" end
get_name (generic function with 1 method)
julia> m1 = MusicStudent(10)
MusicStudent(10)
julia> get_name(m1)
""
I think the underlying struggle may be that in Julia you cannot inherit the data field called "name" as part of the object hierarchy. There is a nice discussion of that genuine issue here (see the mention of the #forward macro):
https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231
The basic answer is that in julia the interface of a method is thought of as the methods that are defined to take an element of that type. AbstractArray for example specifies that implementations should implement getIndex and size. The reason to not make fields part of the interface is that not doing so allows for memory efficient code, since each type can define the methods in the most sensible way. For example if I want to make a type called Bob that is a subtype for all people named bob, I don't want to store his name every time. by using methods, Julia allows much more potential for future expansion in unexpected ways.
Technically this approach loses "safety", but the only way it does is if you write code using fields that might not exist, in which case you will get an error. This type of safety isn't that useful since it just gives you a compile error that slows down development.
I am refactoring some code originally written using access types, but not yet tested. I found access types to be troublesome in Ada because they can only refer to dynamically allocated items, and referring to items defined at compile time is apparently not allowed. (This is Ada83.)
But now I come to a function like this one:
function Get_Next(stateInfo : State_Info_Access_Type) return integer;
I know that I can easily pass parameter "contents" of an access type rather than the access pointer itself, so I am considering writing this as
function Get_Next(stateInfoPtr : State_Info_Type) return integer;
where State_Info_Type is the type that State_Info_Access_Type refers to.
With this refactor, for all intents and purposes I think I'm still really passing what amounts to an implicit pointer back to the contents (using the .all) syntax).
I want to refactor and test starting with the lowest level functions, working my way up the call chains. My goal is to push the access types out of the code as I go.
Am I understanding this correctly or am I missing something?
I think original author(s), and possibly OP are missing a point, that is, how Ada parameter modes work.
To quote #T.E.D
Every Ada compiler I know of under the hood passes objects larger than fit in a machine register by reference. It is the compiler, not the details of your parameter passing mechanisim, that enforces not writing data back out of the routine.
Ada does this automatically, and leaves the parameter modes as a way of describing the flow of information (Its NOT the C style reference / value conundrum). See the useful wikibook.
What worries me is that the code you have inherited looks like the author has used the explicit access parameter type as a way of getting functions to have side effects (usually considered a bad thing in Ada - World).
My recommendation is to change your functions to:
function Get_Next(State_Info : in State_Info_Type) return Integer;
and see if the compiler tells you if you are trying to modify State_Info. If so, you may need to change your functions to procedures like this:
procedure Get_Next(State_Info : in out State_Info_Type;
Result : out Integer);
This explicitly shows the flow of information without needing to know the register size or the size of State_Info_Type.
As an aside Ada 2012 Will allow you to have functions that have in out parameters.
To quote #T.E.D,
Every Ada compiler I know of under the hood passes objects larger than fit in a machine register by reference. It is the compiler, not the details of your parameter passing mechanisim, that enforces not writing data back out of the routine.
Since this code hasn’t yet been tested, I think you are completely right to rework what looks like code written with a C mindset. But, you oughtn’t to mention pointers at all; you suggested
function Get_Next(stateInfoPtr : State_Info_Type) return integer;
but this would be better as
function Get_Next(stateInfo : State_Info_Type) return integer;
or even (IMO) as
function Get_Next(State_Info : State_Info_Type) return Integer;
to use more standard Ada styling! My editor (Emacs, but GPS can do this too) will change state_info into State_Info on the fly.
As an afterthought, you might be able to get rid of State_Info_Type_Pointer altogether. You mention .all, so I guess you’ve got
SITP : State_Info_Type_Pointer := new State_Info_Type;
... set up components
Next := Get_Next (SITP.all);
but what about
SIT : State_Info_Type;
... set up components
Next := Get_Next (SIT);
I wouldn't recommend this, but you can get pointers to variables in Ada 83 by using 'Address.
You can then use overlays (again this is all Ada83 stuff) to achieve access...
function something(int_address : Address) return integer
is
x : integer;
for x'address use int_address;
begin
-- play with x as you will.
Somewhat embarassed to ask this, but I know it's for the best. I've been programming in Ada for many years now, and understand nearly every part of the language fluently. However, I've never seemed able to wrap my head around T'Class. To borrow from others, can someone "explain it like I'm five?".
Edit: I bought it just to have, but contained within is a great description of, and example use of, T'Class; I refer to “Software Construction and Data Structures with Ada 95” by Michael B. Feldman.
If you start with
package P1 is
type T is tagged private;
procedure Method (Self : T);
end P1;
package P2 is
procedure Proc (Self : T); -- not a primitive
procedure Proc2 (Self : T'Class);
end P2;
In the case of Proc, you are telling the compiler that the parameter should always be considered precisely as of type T (remember that a tagged type is always passed by reference, so the actual type could be derived from T of course, you would not lose the extra data). In particular, that means that within the body of Proc, all calls to Method will be exactly calls to P1.Method, never a call to an overriding Method.
In the case of Proc2, you are telling the compiler that you do not know the exact type statically, so it will need to insert extra code to resolve things at run time. A call to Method, within the body of Proc2, could be call to P1.Method, or to another overriding Method.
Basically: with 'Class, things are resolved at runtime.
Well, if you were five, I would say that T'Class represents the whole family of T.
By family, we mean children and grand-children and grand-grand-children.
As you're not five, it means that this special type represents every tagged type which is in the inheritance tree of T. This way, if you use this type as a parameter, you can use every parameter which has T as ancestor directly or not.
For more information, you can read the wikibooks on this.
I'm a fairly new Ada programmer. I have read the book by Barnes (twice I might add) and even managed to write a fair terminal program in Ada. My main language is C++ though.
I am currently wondering if there is a way to "protect" subroutine calls in Ada, perhaps in Ada 2012 (of which I know basically nothing). Let me explain what I mean (although in C++ terms).
Suppose you have a class Secret like this:
class Secret
{
private:
int secret_int;
public:
Set_Secret_Value( int i );
}
Now this is the usual stuff, dont expose secret_int, manipulate it only through access functions. However, the problem is that anybody with access to an object of type Secret can manipulate the value, whether that particular code section is supposed to do it or not. So the danger of rogue altering of secret_int has been reduced to anybody altering secret_int through the permitted functions, even if it happens in a code section that's not supposed to manipulate it.
To remedy that I came up with the following construct
class Secret
{
friend class Secret_Interface;
private:
int secret_int;
Set_Secret_Value( int i );
Super_Secret_Function();
};
class Secret_Interface
{
friend class Client;
private:
static Set_Secret_Value( Secret &rc_secret_object, int i )
{
rc_secret_object.Set_Secret( i );
}
};
class Client
{
Some_Function()
{
...
Secret_Interface::Set_Secret_Value( c_object, some-value );
...
}
}
Now the class Secret_Interface can determine which other classes can use it's private functions and by doing so, indirectly, the functions of class Secret that are exposed to Secret_Interface. This way class Secret still has private functions that can not be called by anybody outside the class, for instance function Super_Secret_Function().
Well I was wondering if anything of this sort is possible in Ada. Basically my desire is to be able to say:
Code A may only be executed by code B but not by anybody else
Thanks for any help.
Edit:
I add a diagram here with a program structure like I have in mind that shows that what I mean here is a transport of a data structure across a wide area of the software, definition, creation and use of a record should happen in code sections that are otherwise unrleated
I think the key is to realize that, unlike C++ and other languages, Ada's primary top-level unit is the package, and visibility control (i.e. public vs. private) is on a per-package basis, not a per-type (or per-class) basis. I'm not sure I'm saying that correctly, but hopefully things will be explained below.
One of the main purposes of friend in C++ is so that you can write two (or more) closely related classes that both take part in implementing one concept. In that case, it makes sense that the code in one class would be able to have more direct access to the code in another class, since they're working together. I assume that in your C++ example, Secret and Client have that kind of close relationship. If I understand C++ correctly, they do all have to be defined in the same source file; if you say friend class Client, then the Client class has to be defined somewhere later in the same source file (and it can't be defined earlier, because at that point the methods in Secret or Secret_Interface haven't yet been declared).
In Ada, you can simply define the types in the same package.
package P is
type Secret is tagged private;
type Client is tagged private;
-- define public operations for both types
private
type Secret is tagged record ... end record;
type Client is tagged record ... end record;
-- define private operations for either or both types
end P;
Now, the body of P will contain the actual code for the public and private operations of both types. All code in the package body of P has access to those things defined in P's private part, regardless of which type they operate on. And, in fact, all code has access to the full definitions of both types. This means that a procedure that operates on a Client can call a private operation that operates on a Secret, and in fact it can read and write a Secret's record components directly. (And vice versa.) This may seem bizarre to programmers used to the class paradigm used by most other OOP languages, but it works fine in Ada. (In fact, if you don't need Secret to be accessible to anything else besides the implementation of Client, the type and its operations can be defined in the private part of P, or the package body.) This arrangement doesn't violate the principles behind OOP (encapsulation, information hiding), as long as the two types are truly two pieces of the implementation of one coherent concept.
If that isn't what you want, i.e. if Secret and Client aren't that closely related, then I would need to see a larger example to find out just what kind of use case you're trying to implement.
MORE THOUGHTS: After looking over your diagram, I think that the way you're trying to solve the problem is inferior design--an anti-pattern, if you will. When you write a "module" (whatever that means--a class or package, or in some cases two or more closely related classes or packages cooperating with each other), the module defines how other modules may use it--what public operations it provides on its objects, and what those operations do.
But the module (let's call it M1) should work the same way, according to its contract, regardless of what other module calls it, and how. M1 will get a sequence of "messages" instructing it to perform certain tasks or return certain information; M1 should not care where those messages are coming from. In particular, M1 should not be making decisions about the structure of the clients that use it. By having M1 decree that "procedure XYZ can only be called from package ABC", M1 is imposing structural requirements on the clients that use it. This, I believe, causes M1 to be too tightly coupled to the rest of the program. It is not good design.
However, it may make sense for the module that uses M1 to exercise some sort of control like that, internally. Suppose we have a "module" M2 that actually uses a number of packages as part of its implementation. The "main" package in M2 (the one that clients of M2 use to get M2 to perform its task) uses M1 to create a new object, and then passes that object to several other packages that do the work. It seems like a reasonable design goal to find a way that M2 could pass that object to some packages or subprograms without giving them the ability to, say, update the object, but pass it to other packages or subprograms that would have that ability.
There are some solutions that would protect against most accidents. For example:
package M1 is
type Secret is tagged private;
procedure Harmless_Operation (X : in out Secret);
type Secret_With_Updater is new Secret with null record;
procedure Dangerous_Operation (X : in out Secret_With_Updater);
end M1;
Now, the packages that could take a "Secret" object but should not have the ability to update it would have procedures defined with Secret'Class parameters. M2 would create a Secret_With_Updater object; since this object type is in Secret'Class, it could be passed as a parameter to procedures with Secret'Class parameters. However, those procedures would not be able to call Dangerous_Operation on their parameters; that would not compile.
A package with a Secret'Class parameter could still call the dangerous operation with a type conversion:
procedure P (X : in out Secret'Class) is
begin
-- ...
M1.Secret_With_Updater(X).Dangerous_Operation;
-- ...
end P;
The language can't prevent this, because it can't make Secret_With_Updater visible to some packages but not others (without using a child package hierarchy). But it would be harder to do this accidentally. If you really wish to go further and prevent even this (if you think there will be a programmer whose understanding of good design principles is so poor that they'd be willing to write code like this), then you could go a little further:
package M1 is
type Secret is tagged private;
procedure Harmless_Operation (X : in out Secret);
type Secret_Acc is access all Secret;
type Secret_With_Updater is tagged private;
function Get_Secret (X : Secret_With_Updater) return Secret_Acc;
-- this will be "return X.S"
procedure Dangerous_Operation (X : in out Secret_With_Updater);
private
-- ...
type Secret_With_Updater is tagged record
S : Secret_Acc;
end record;
-- ...
end M1;
Then, to create a Secret, M2 would call something that creates a Secret_With_Updater that returns a record with an access to a Secret. It would then pass X.Get_Secret to those procedures which would not be allowed to call Dangerous_Operation, but X itself to those that would be allowed. (You might also be able to declare S : aliased Secret, declare Get_Secret to return access Secret, and implement it with return X.S'access. This may avoid a potential memory leak, but it may also run into accessibility-check issues. I haven't tried this.)
Anyway, perhaps some of these ideas could help accomplish what you want to accomplish without introducing unnecessary coupling by forcing M1 to know about the structure of the application that uses it. It's hard to tell because your description of the problem, even with the diagram, is still at too abstract a level for me to see what you really want to do.
You could do this by using child packages:
package Hidden is
private
A : Integer;
B : Integer;
end Hidden;
and then
package Hidden.Client_A_View is
function Get_A return Integer;
procedure Set_A (To : Integer);
end Hidden.Client_A_View;
Then, Client_A can write
with Hidden.Client_A_View;
procedure Client_A is
Tmp : Integer;
begin
Tmp := Hidden.Client_A_View.Get_A;
Hidden.Client_A_View.Set_A (Tmp + 1);
end Client_A;
Your question is extremely unclear (and all the C++ code doesn't help explaining what you need), but if your point is that you want a type to have some publicly accessible operations, and some private operations, then it is easily done:
package Example is
type Instance is private;
procedure Public_Operation (Item : in out Instance);
private
procedure Private_Operation (Item : in out Instance);
type Instance is ... -- whatever you need it to be
end Example;
The procedure Example.Private_Operation is accessible to children of Example. If you want an operation to be purely internal, you declare it only in the package body:
package body Example is
procedure Internal_Operation (Item : in out Instance);
...
end Example;
Well I was wondering if anything of this sort is possible in Ada. Basically my desire is to be able to say:
Code A may only be executed by code B but not by anybody else
If limited to language features, no.
Programmatically, code execution can be protected if the provider must be provided an approved "key" to allow execution of its services, and only authorized clients are supplied with such keys.
Devising the nature, generation, and security of such keys is left as an exercise for the reader.
Support for generics (currently only Vector.<*>, and called 'postfix type parameters' by Adobe) was added in Flash Player 10, but the only AVM2 documentation does not describe how these objects are accessed.
Specifically, I noticed a new opcode (0x53) and a new multiname kind (0x1D) that seem relevant, but their usage is not documented.
NB: This question was created with the answer already known as it is more easily found here than on my blog or the Adobe Bug DB.
The reverse engineering work I did on this did not include declaring your own generic types, though it's very likely possible.
References to the declaring (parameterless) generic type (Vector) are made through a regular qualified name (though any multiname should do).
References to a typed generic type (Vector.<int> as opposed to Vector.<>) are made by a new multiname kind (0x1D), which I call GenericName. GenericName has a format like so:
[Kind] [TypeDefinition] [ParamCount] [Param1] [Param2] [ParamN]
Where:
[TypeDefinition] is a U30 into the multiname table
[ParamCount] is a U8 (U30?) of how many type parameters there are
[ParamX] is a U30 into the multiname table.
Obviously generics are not generally supported yet, so ParamCount will always be 1 (for Vector.<*>).
The other interesting thing is how instances of the class are created. A new opcode was added in Flash 10 (0x53), which I will call MakeGenericType. MakeGenericType is declared with the following stack:
TypeDefinition, ParameterType1, ParameterTypeN -> GenericType
It also has one parameter, a U8 (U30?) specifying how many parameters are on the stack. You will generally see MakeGenericType being used like this:
GetLex [TypeDefinitionMultiname]
GetLex [ParameterTypeMultiname]
MakeGeneric [ParamCount]
Coerce [GenericNameMultiname]
Construct [ConstructorParamCount]
So if you had the following...
GetLex __AS3__.vec::Vector
GetLex int
MakeGeneric 1
Coerce __AS3__.vec::Vector.<int>
Construct 0
You would now have an instance of Vector.<int>