OpenVMS initialization of record types - initialization

I have some legacy code that I am trying to improve... one approach I like to take is using structures to organize data rather than equivalence operations.... shudder. This is on OpenVMS Fortran 6.4 which I understand to be Fortran77 plus some stuff (might be wrong).
I want to initialize a record variable like so:
structure /my_data/
integer*2 var1
integer*2 var2
character*5 NameTag
end structure
record /my_data/ OrganizedData
data OrganizedData /1, 2, 'Fred '/
I know the data statement is an error, the compiler told me so. Checking in the help files, it appears that DATA does not support record variables in this version. Can anyone confirm? Any suggestions to initialize something like this other than direct assignments?

I have only the Oracle (Sun) manual here, not from OpenVMS, but it implements the same VAX extension (completely non-standard!). There is no structure constructor described there, that you could use for creating values of structure in single expression.
It also says:
Record fields are not allowed in COMMON statements.
Records and record fields are not allowed in DATA,EQUIVALENCE, or NAMELISTstatements.
Record fields are not allowed in SAVE statement.
If you can use a compiler which accepts Fortran 90 you could use
type my_data
integer*2 var1
integer*2 var2
character*5 NameTag
end type
type(my_data) :: OrganizedData
OrganizedData = my_data(1, 2, 'Fred')
(I left the also non-standard * notation there.)

This is how you do it in DEC Fortran:
structure /my_data/
integer*2 var1 /1/
integer*2 var2 /2/
character*5 NameTag /'Fred'/
end structure
record /my_data/ OrganizedData
end
Note that the initializations are on the type - this will give the same initial values for all variables of that type.

For that version of DEC FORTRAN, if you want different values for each instance, I think you need to initialize the record fields at run time.
OrganizedData.var1 = 1 ! etc.
There are tricks, like using a COMMON and making a MACRO Assembler PSECT that initializes the values at compile time, but I'm guessing that's not what you are looking for. (Let me know if you are).
Also, I forget if it's 6.4 or not, but receiving a passed argument that has static initialization would cause a compiler error or warning.

Related

How and why is a GNAT.Strings.String_List use clause disallowed? How can you use System.Strings.String_List."&" with infix notation?

Posting for two reasons: (1) I was stuck on unhelpful compiler errors for far too long for such a simple issue and I want the next person to google those messages to come upon my (or other) answers, and (2) I still don't understand disallowing a use clause, so my own answer is really incomplete.
In order to call a program in two places with mostly the same arguments, I want to use the '&' to append to a default list inline:
declare
Exit_Code : constant Integer := GNAT.OS_Lib.Spawn (Program_Name => "gprbuild", Args => (Default_GPR_Arguments & new String'(File_Name_Parameter)));
begin
if Exit_Code /= 0 then
raise Program_Error with "Exit code:" & Exit_Code'Image;
end if;
end;
However, the compiler complains that System.Strings.String_List needs a use clause:
operator for type "System.Strings.String_List" is not directly visible
use clause would make operation legal
But inserting use System.Strings.String_List yields:
"System.Strings.String_List" is not allowed in a use clause
I also got this warning:
warning: "System.Strings" is an internal GNAT unit
warning: use "GNAT.Strings" instead
So I substituted GNAT for System in the with and the use clause and got an extra error in addition to the original 'you need a use clause for System.Strings.String_List' one:
"GNAT.Strings.String_List" is not allowed in a use clause
Why is GNAT.Strings.String_List not allowed in a use clause? Section 8.5 on use clauses doesn't seem to state anything on disallowed packages, so is this a compiler bug? Is it possible to define a new package that cannot have a use clause?
In a use clause of the form
use Name;
Name must be a package name. GNAT.Strings.String_List is a subtype name, not a package name.
There are a number of ways to invoke "&" for String_List. The simplest is to use the full name:
GNAT.Strings."&" (Left, Right)
but presumably you want to be able to use it as an operator in infix notation, Left & Right. Ways to achieve this, in decreasing specificity:
function "&" (Left : GNAT.Strings.String_List; Right : GNAT.Strings.String_List) return GNAT.Strings.String_List renames GNAT.Strings."&"; This makes this specific function directly visible.
use type GNAT.Strings.String_List; This makes all primitive operators of the type directly visible.
use all type GNAT.Strings.String_List; This makes all primitive operations of the type (including non-operator operations) directly visible.
use GNAT.Strings; This makes everything in the package directly visible.
Looks like it is a design decision. And many other packages in System follows this rule. From the s-string.ads (package specification for System.String):
-- Note: this package is in the System hierarchy so that it can be directly
-- be used by other predefined packages. User access to this package is via
-- a renaming of this package in GNAT.String (file g-string.ads).
My guess why this is done in that way: because it isn't in the Ada specification, but extension from GNAT.

Rocket Universe Dictionary passing VM attribute value to subroutine

Okay this might get a tad complex or not.
Have a file with a multivalues in attribute 4
I want to write another dictionary item that loops through the multivalue list, calls a subroutine and returns calculated values for each item in attribute 4.
somthing like
<4> a]b]c]d]e
New attribute
#RECORD<4>;SUBR("SUB.CALC.AMT", #1)
Result
<4> AMT
a 5.00
b 15.00
c 13.50
d 3.25
Not quite sure how to pass in the values from RECORD<4>, had a vague notion of a #CNT system variable, but that's not working, which might mean it was from SB+ or one of the other 4GLs.
You might be over thinking this.
You should just be able to reference it without out doing the ";" and #1 thing (I am not familiar with that convention). Using an I-Descriptor this should do the trick, though I have traditionally used the actual dictionary names instead of the #RECORD thing.
SUBR("SUB.CALC.AMT", #RECORD<4>)
This should work provided your subroutine is compiled, cataloged and returns your desired value with the same value/subvalue structure as #RECORD<4> in the first parameter of the Subroutine.
SUBROUTINE SUB.CALC.AMT(RETURN.VALUE,JUICY.BITS)
JBC = DCOUNT(JUICY.BITS<1>,#VM)
FOR X=1 TO JBC
RETURN.VALUE<1,X> = JUICY.BITS<1,X>:" or something else"
NEXT X
RETURN
END
Good luck.

Ada Source code modifications using ASIS(Ada Semantics interface specifications)

i am developing a tool for finding sub type range overflow problems in Ada source code.for this purpose i am using ASIS for finding assignment statements in Ada source code and finding type of the variables on the right side of the assignment
expression.now i want to replace the variables(not of record type) of the assignment expression with 'first, 'last values of the variable type in the assignment statement so that i will get compilation error if any range overflow happens.below is an example what i am trying to convey.
procedure Example is
subtype A_Type is integer 1 .. 10;
subtype B_Type is integer -5 .. 5;
subtype C_Type is integer 1 .. 12;
A : A_Type;
B : B_Type;
C : C_Type;
begin
C := A + B;
end Example;
I want modify C := A + B; with C := A_Type'Last + B_Type'Last in the source code. C := A_Type'Last + B_Type'Last assignment statement will get warning at compile time or Constraint error during run time.
Is it possible do above modifications with ASIS?
For your purpose, you shouldn't rewrite the source text you are processing. You should rather write a new program, which only contains exactly the required declarations and assignments.
So the output should be something like:
with Type_Declarations;
procedure Test_Driver is
begin
declare
C : Type_Declarations.C_Type;
begin
C := Type_Declarations."+" (Type_Declarations.A_Type'First, Type_Declarations.B_Type'First);
C := Type_Declarations."+" (Type_Declarations.A_Type'First, Type_Declarations.B_Type'Last);
C := Type_Declarations."+" (Type_Declarations.A_Type'Last, Type_Declarations.B_Type'First);
C := Type_Declarations."+" (Type_Declarations.A_Type'Last, Type_Declarations.B_Type'Last);
end;
end Test_Driver;
ASIS was not designed to make modifications like that. You can, however take a look at libadalang from AdaCore, which supports this (and works on partial sources, so you won't have to precompile your sources)
GNAT includes utilities gnat2xml and xml2gnat; gnat2xml generates a representation of the source based on ASIS, and xml2gnat converts it back to Ada. You could maybe modify the XML output of the first and feed it back to the second.
Not that I’m recommending this; the XML schema isn’t documented, and is complicated.
If you want a tool that can apply modifications to Ada source code, you might be interested in our DMS Software Reengineering Toolkit with its Ada front end.
DMS parses source code to ASTs, and makes those ASTs available for modification using DMS's Abstract Syntax Tree procedural interface (direct hacking at the tree nodes) and/or DMS's rewrite rules (source-to-source transformations "if you see this replace it by that" written in [Ada] language surface syntax, that directly manipulates the trees. After your changes are made, DMS can prettyprint the source to regenerate valid Ada source code, even preserving comments and formatting in those places that have not been modified.

How to suppress function return

Suppose I have a function that has multiple returned values (shown below). However, this output is not informative as users do not know what each value stands for unless they look up the function definition. So I would like to use println() to print the results with appropriate names to the screen, while suppressing the the actual returned values from being printed on the screen. In R, the function invisible() does that, but how do you do the same thing in Julia?
function trimci(x::Array; tr=0.2, alpha=0.05, nullvalue=0)
se=sqrt(winvar(x,tr=tr))./((1-2.*tr)*sqrt(length(x)))
ci=cell(2)
df=length(x)-2.*floor(tr.*length(x))-1
ci=[tmean(x, tr=tr)-qt(1-alpha./2, df).*se, tmean(x, tr=tr)+qt(1-alpha./2, df).*se]
test=(tmean(x,tr=tr)-nullvalue)./se
sig=2.*(1-pt(abs(test),df))
return ci, tmean(x, tr=tr), test, se, sig
end
In addition to what Harlan and Stefan said, let me share an example from the ODBC.jl package (source here).
One of my favorite features of Julia over other languages is how dead simple it is to create custom types (and without performance issues either!). Here's a custom type, Metadata, that simply holds several fields of data that describe an executed query. This doesn't necessarily need its own type, but it makes it more convenient passing all this data between functions as well as allowing custom formatting of its output by overloading the Base.show() function.
type Metadata
querystring::String
cols::Int
rows::Int
colnames::Array{ASCIIString}
coltypes::Array{(String,Int16)}
colsizes::Array{Int}
coldigits::Array{Int16}
colnulls::Array{Int16}
end
function show(io::IO,meta::Metadata)
if meta == null_meta
print(io,"No metadata")
else
println(io,"Resultset metadata for executed query")
println(io,"------------------------------------")
println(io,"Columns: $(meta.cols)")
println(io,"Rows: $(meta.rows)")
println(io,"Column Names: $(meta.colnames)")
println(io,"Column Types: $(meta.coltypes)")
println(io,"Column Sizes: $(meta.colsizes)")
println(io,"Column Digits: $(meta.coldigits)")
println(io,"Column Nullable: $(meta.colnulls)")
print(io,"Query: $(meta.querystring)")
end
end
Again, nothing fancy, but illustrates how easy it really is to define a custom type and produce custom output along with it.
Cheers.
One thing you could do would be to define a new type for the return value for this function, call it TrimCIResult or something. Then you could define appropriate methods to show that object in the REPL. Or you may be able to generalize that solution with a type hierarchy that could be used for storing the results from and displaying any statistical test.
The value nothing is how you return a value that won't print: the repl specifically checks for the value nothing and prints nothing if that's the value returned by an expression. What you're looking to do is to return a bunch of values and not print them, which strikes me as rather odd. If a function returns some stuff, I want to know about it – having the repl lie to users seems like a bad idea. Harlan's suggesting would work though: define a type for this value with the values you don't want to expose to the user as fields and customize its printing so that the fields you don't want to show people aren't printed.

Variable Names in SWI Prolog

I have been using the chr library along with the jpl interface. I have a general inquiry though. I send the constraints from SWI Prolog to an instance of a java class from within my CHR program. The thing is if the input constraint is leq(A,B) for example, the names of the variables are gone, and the variable names that appear start with _G. This happens even if I try to print leq(A,B) without using the interface at all. It appears that whenever the variable is processed the name is replaced with a fresh one. My question is whether there is a way to do the mapping back. For example whether there is a way to know that _G123 corresponds to A and so on.
Thank you very much.
(This question has nothing to do with CHR nor is it specific to SWI).
The variable names you use when writing a Prolog program are discarded completely by the Prolog system. The reason is that this information cannot be used to print variables accurately. There might be several independent instances of that variable. So one would need to add some unique identifier to the variable name. Also, maintaining that information at runtime would incur significant overheads.
To see this, consider a predicate mylist/1.
?- [user].
|: mylist([]).
|: mylist([_E|Es]) :- mylist(Es).
|: % user://2 compiled 0.00 sec, 4 clauses
true.
Here, we have used the variable _E for each element of the list. The toplevel now prints all those elements with a unique identifier:
?- mylist(Fs).
Fs = [] ;
Fs = [_G295] ;
Fs = [_G295, _G298] .
Fs = [_G295, _G298, _G301] .
The second answer might be printed as Fs = [_E] instead. But what about the third? It cannot be printed as Fs = [_E,_E] since the elements are different variables. So something like Fs = [_E_295,_E_298] is the best we could get. However, this would imply a lot of extra book keeping.
But there is also another reason, why associating source code variable names with runtime variables would lead to extreme complexities: In different places, that variable might have a different name. Here is an artificial example to illustrate this:
p1([_A,_B]).
p2([_B,_A]).
And the query:
?- p1(L), p2(L).
L = [_G337, _G340].
What names, would you like, these two elements should have? The first element might have the name _A or _B or maybe even better: _A_or_B. Or, even _Ap1_and_Bp2. For whom will this be a benefit?
Note that the variable names mentioned in the query at the toplevel are retained:
?- Fs = [_,F|_], mylist(Fs).
Fs = [_G231, F] ;
Fs = [_G231, F, _G375] ;
Fs = [_G231, F, _G375, _G378]
So there is a way to get that information. On how to obtain the names of variables in SWI and YAP while reading a term, please refer to this question.

Resources