How to use put from private part from spec? - private

How to use put from private part from spec? i am unable to use put please help to fix below is my code
p.ads(spec)
package p is
type t is private;
give_public_acess:constant t;
private
type t is range 1..10;
give_public_acess:Constant t:=9;
end p;
private_acc.adb
with ada.Text_IO,ada.Integer_Text_IO;
with p;
procedure private_acc is
package my_type is new ada.Text_IO.Integer_IO(p.t);
v:p.t;
begin
v:=p.give_public_acess;
my_type.put(v); -- How to print every thing? Is it ok just put is not good here. please help me to fix?
end private_acc;

Your type t is private, so there is no way that procedure private_acc can know whether it is an integer, or float, or anything (this is the whole point of private types).
If you want to be able to display them then you need to export a Put method from your package p that other subprograms can call.
So
package p is
type t is private;
procedure Put (Item : T);
...
This will probably mean that the package body of P will need to instantiate Ada.Text_IO.Integer_IO;
Alternatively you could instantiate it into a private child package of package P which the package body would then perform call throughs to Put.
Edit: package body added...
with Ada.Text_IO.Integer_IO;
package body P is
package T_IO is new Ada.Text_IO.Integer_IO(T);
procedure Put(Item : T) is
begin
T_IO.Put(Item); -- call through.
end;
end P;

Related

ESQL InputLocalEnvironment data type

I want to be able to access the InputLocalEnvironment within a Procedure call.
CREATE FUNCTION Main() RETURNS BOOLEAN
BEGIN
SET OutputLocalEnvironment = InputLocalEnvironment;
--Call Procedure doStuff
END
CREATE PROCEDURE doStuff ( IN inputLocalEnvironment ) RETURNS BOOLEAN
BEGIN
--Do Stuff with the inputLocalEnvironment
END
What is the data type I should use to pass InputLocalEnvironment as the above procedure will obviously through an error.
CREATE PROCEDURE doStuff ( IN inputLocalEnvironment DataType)
If someone has a better suggestion I'm open to the idea but I need to be able to get information out of the local variables and then place them into an output.
Many thanks.
It should work with the REFERENCE data type:
CREATE PROCEDURE doStuff (IN inputLocalEnvironment REFERENCE)

Assign an existing method by its name from one Unit to a generic TMethod in another unit

Basically, I have an application which will retrieve information out of an INI file and part of this process includes extracting the names -stored in the INI- of some procedures declared at global scope inside another unit.
I use the following to get the SQL method:
MyIni.ReadString('SQL', SubStr + '_Insert, '');
SubStr is the type of data I want, for example "titles", this is prefixed with the type of SQL procedure I want, in this case "_Insert" therefore, my request here could be seen as:
MyIni.ReadString('SQL', 'titles_Insert', '');
This would then retrieve the appropriate SQL procedure name "InsertTitlesSql" which is displayed inside the INI thus:
[SQL]
titles_Insert=InsertTitlesSql
I have a unit which lists the SQL procedures we use.
Like so:
unit uSqlLibrary;
interface
function InsertTitlesSql: string;
implementation
function InsertTitlesSql: string;
begin
{
INSERT INTO TITLES (ENGLISH, AFRIKAANS, KEY)
VALUES (:english,
:afrikaans,
:key)
}
Result := ''
+'INSERT INTO TITLES (ENGLISH, AFRIKAANS, KEY) '
+'VALUES (:english, '
+' :afrikaans, '
+' :key) ';
end;
end.
I've tried TGenericContainer without any success, I've also tried MethodAddress but I don't know how to tell MethodAddress to look at the other unit without an Object to reference (Form1.MethodAddress() for example) my best result so far is this:
type
TExec = procedure of object;
procedure TForm1.Button1Click(Sender: TObject);
var
M : TMethod ;
E : TExec ;
begin
M.Code := #Test; // Where "Test" is a procedure inside a secondary Unit.
E := TExec(M);
E;
end;
What I'm trying to do is get the SQL procedure by name that I want ( function InsertTitlesSql : string;) and assign it to a generic method that behaves in the same way.
My team lead has said that he doesn't want to edit the uSqlLibrary; so I can't do it that way and have thought to go by the method's name instead. Any other suggestions are welcome.
Hope this is clear. Sorry if it's not ( my use of terminology is not so good xD ). I'll try to elaborate on your queries to the best of my knowledge if I can.
You cannot use RTTI to enumerate procedures with global scope. You can enumerate methods, so you could convert your global procedures to be static class methods.
However, you also state that your team lead does not want you to change uSqlLibrary. This seems a little short sighted in my opinion. Feel free to tell him/her that I said so.
Anyway, if you cannot change uSqlLibrary then you cannot use RTTI. So you'll need to construct your own lookup table. Use a generic dictionary:
uses
System.Generics.Collections;
var
ProcTable: TDictionary<string, TProc>;
Instantiate it in the usual way. Add your functions at program startup:
....
ProcTable.Add('InsertTitlesSql', InsertTitlesSql);
....
When you need to look one up and call it do this:
var
Proc: TProc;
....
if not ProcTable.TryGetValue(ProcName, Proc) then
raise EProcNotFound.CreateFmt(...);
Proc();
The default equality comparer used for the key is case-sensitive by default. So you may elect to supply a custom equality comparer that compares keys without case sensitivity.

Calling package's procedure from another procedure

Trying to search but i couldn't find it.
I have a package name package_1 and in that I have multiple procedures/functions. Now I want to call one of these functions from another procedure, which is not part of this package. I can't put this code in that package (both are on same schema).
I am trying this
package_1.function_1(varchar_var_1, varchar_var_2, varchar_var_3);
But it is giving me error.
QUESTION2
The above functions return an object which is a record type defined in package. How can I declare an object of that type in my procedure so that I can assign response in my procedure ?
If the function returns a record type, you'd need to declare a local variable in the caller of that record type. Something like
CREATE OR REPLACE PROCEDURE your_procedure_name( <<parameters>> )
AS
l_rec package_1.record_type;
...
BEGIN
...
l_rec := package_1.function_name( p1, p2, p3 );
...
END;
Of course, this assumes that both the record type and the function are defined in the package spec so that they are public rather than merely being defined as private members of the package that are defined only in the package body.
Check if it is declared in the package header/specification. If it is you
will have access to it.
Function must return a value:
a_value := package_1.function_1(varchar_var_1, varchar_var_2, varchar_var_3);
Check if the package is valid. If it is invalidated then there is not
much you can do (until it is fixed).

GetItem on TDictionary eleminated by linker

I am using a TDictionary of <string, string>. But for some reason, the linker decides that I do not want to get items out of it.
I have the following code:
function TSheet.GetFieldName(Field: string; Default: string): string;
begin
Result := Default;
if FFieldNames[Field] = '' then
Result := Field
else
Result := FFieldNames[Field];
end;
FFieldNames is a TDictionary<string, string>. On line 2 (if FFieldNames[Field] = '' then), it throws a 'File not found' exception. Adding FFieldNames[Field] to my watch tells me that Function to be called, {System.Generics.Collections}TDictionary.GetItem, was eliminated by linker.
Someone asked here on a similar issue on how to avoid the linker eliminating functions during debugging. From this I gathered, that the compiler/linker assumes that I am not using it. Someone suggested - during conversation - that I should try using it more.
So I created the following code:
FFieldNames.Add(Name, S);
V := FFieldNames.Items[Name];
Where S, Name and V are strings. This is from the code where FFieldNames is filled with data. V's only purpose is to obtain the just inserted S; it does nothing else.
Strangely, while the debugger tells me the same thing (i.e. GetItem being eliminated), V does get set to the expected value. But it does not in my TSheet.GetFieldName function. :|
What am I missing?
The same problem applies to TList<>. Even if the code is using a method in the class it is not accessible from the debugger ("xxx on TList eliminated by linker"). I guess this is a problem with generics in general.
If you make a descendent class it will not have this problem
type
TMyList = class(TList<TMyObject>)
end;
var
List : TMyList;
begin
...
end;

need help with interesting call to JCL's TEvaluator

i'm using JCL's expression evaluator TEvaluator (a marvelous creation donated by barry kelly). (THANK YOU barry!)
background
i've used the AddFunc method.
function MyFunc:double;
begin
// calculations here
Result:=1;
end;
you can use the AddFunc method to make the function available:
AddFunc('MyFunc', MyFunc);
here's the problem...
i need to call a method on an object instead of a standalone routine.
the reason is that i have a list of objects that provide the values.
say we have a list of vehicle objects. each object has a Weight function. i want to be able to make available each object's weight available for use in the formula.
a silly example but it's easy to explain:
type
TVehicle=class
private
public
function Weight:double;
end;
function StrangeCalculation:double;
var
vehicle:TVehicle;
begin
for iVehicle = 0 to Count - 1 do
begin
vehicle:=GetVehicle(iVehicle);
// E2250 There is no overloaded version of 'AddFunc' that can be called with these arguments
eval.AddFunc(vehicle.Name, vehicle.Weight);
end;
Result:=eval.Evaluate('JeepTJWeight + FordF150Weight * 2');
end;
my options:
AddVar( ) or AddConst( ) -- but that isn't so great because i need to be able to raise an exception if the value is not available.
AddFunc( ) with standalone functions. can't do that because the names of (and number of) variables is unknown until runtime.
modify the object to add a callback if the variable isn't found. i have actually done this but needed to edit a copy of the source to call back to make it do this.
make an AddFunc( ) that's able to use method functions.
option #3 is actually built but an additional AddFunc would be nicer. the trouble is i don't know what method prototype to provide. i thought TMethod would be the way but my knowledge is too limited here... here was my unsuccessful attempt but i still get "E2250 There is no overloaded version of 'AddFunc' that can be called with these arguments" at the eval.AddFunc() call like before.
TFloat64MethodFunc = function(c:pointer): TFloat64;
procedure TEasyEvaluator.AddFunc(const AName: string; AFunc: TFloat64MethodFunc);
begin
FOwnContext.Add(TExprFloat64MethodFuncSym.Create(AName, AFunc));
end;
TExprFloat64MethodFuncSym = class(TExprAbstractFuncSym)
private
FFunc: TFloat64MethodFunc;
public
constructor Create(const AIdent: string; AFunc: TFloat64MethodFunc);
function Evaluate: TFloat; override;
// not using function Compile: TExprNode; override;
end;
thank you for your help!
mp
figured it out...
TFloat64MethodFunc = function: TFloat of object;
Long time ago (2004), I have faced this problem. My solution then was to use the Turbo Power SysTools evaluator, that accepts methods.

Resources