[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Marst Algol 60 compiler
From: |
Andrew Makhorin |
Subject: |
Re: Marst Algol 60 compiler |
Date: |
Tue, 26 Jan 2016 15:44:48 +0300 |
> I believe I am making progress. I followed your suggestion and after a
> lot of studying! have successfully called three different procedures
> from gsl that take one, two and three real value inputs and deliver a
> real output. I've edited the algol.h header file to add #include
> statements for the gsl procedures. I notice the procedures I have
> called use odd sequence numbering ( ie E_1 for the first procedure
> declared , E_3 for the second declared and so on). It is safe to
> continue using this number sequencing?
>
> I guess I need to move onto how to deal with:
>
> 1) Integer arguments
> 2) Arrays
>
> Any tips?
>
> Also will this mechanism allow arrays to be returned - or does Algol
> 60 not support that capability?
>
Probably the most relevant way to call external C functions in your case
is to write a wrapper for each C function to be called as if it (the
wrapper) were produced by Marst. For example, let you need to call the
following C function:
int foo(int n, double a[], double x[]);
If you would write a wrapper in Algol 60, it could looks like follows
(it is assumed that it is a separately translated procedure, so in the
main Algol 60 program there should be its "code" declaration):
integer procedure foo(n, a, x);
value n;
integer n;
real array a, x;
begin
...
end
Marst would produce the following code (note that all formal parameters
are implemented as struct arg objects, and foo_0 means that procedure
foo is declared on level 0, i.e. outside any block):
struct desc foo_0 /* precompiled integer procedure */
( struct arg n_1 /* by value integer */,
struct arg a_1 /* by name real array */,
struct arg x_1 /* by name real array */
)
{
...
}
So, if you need to obtain the value of n, you could use the following
statement:
int n = get_int((global_dsa = n_1.arg2,
(*(struct desc (*)(void))n_1.arg1)()));
(global_dsa specifies a context, in which corresponding actual parameter
is evaluated, because it is considered an expression passed by name).
Similarly, if you need to obtain a[i,j] or x[j], you could write
struct dv *a = a_1.arg1;
struct dv *x = x_1.arg1;
where struct dv is the Algol array descriptor (so called dope vector),
declared in algol.h as follows:
struct dv
{ /* array dope vector */
void *base;
/* address of the first array element */
int n;
/* number of subscripts (1 <= n <= 9) */
struct
{ int lo;
/* lower bound of subscript */
int up;
/* upper bound of subscript (if lo > up, the array is empty
and in this case base is NULL) */
} d[9];
/* subscript bounds for each dimension (actually d[n] is used) */
};
This allows you performing all necessary checks and obtain a pointer to
a[i,j] or x[j].
To return an integer value from foo_0 you need to return the value of
struct desc (declared in algol.h) which is the return value descriptor.
Thus, finally, the wrapper could look like follows:
struct desc foo_0 /* precompiled void procedure */
( struct arg n_1 /* by value integer */,
struct arg a_1 /* by name real array */,
struct arg x_1 /* by name real array */
)
{ struct desc retv;
int n = get_int((global_dsa = n_1.arg2,
(*(struct desc (*)(void))n_1.arg1)()));
struct dv *a = a_1.arg1;
struct dv *x = x_1.arg1;
...prepare arguments and call C function...
retv.lval = 0;
retv.type = 0;
retv.u.int_val = ...return value...;
return retv;
}
To determine how formal parameters of an Algol 60 procedure can be
accessed/assigned, you may look at the output code produced by Marst.
Hope this helps.
Best regards,
Andrew Makhorin