[sac-user] SaC beginner: modularization, declaration

Scholz, Sven-Bodo s.scholz at herts.ac.uk
Wed Dec 8 20:00:42 CET 2010


Hi David,


On 08/12/2010 13:50, "Juhasz David" <juhda at inf.elte.hu> wrote:

> Hi,
> 
> I'm participant of a project in Eötvös Loránd University, Hungary. In this
> project we want to develop a general programming language for multicore
> and distributed systems, wich is not hardware-specific, but can make an
> effective code from the source. My actual assignment is to write a summary

that sounds interesting; is it a follow up on the feldspar work?
What architectures are you targeting?
In Sac, we have now backends for SMPs, GPUs, and MicroGrids.

However, the latter two are not yet publically available. If you want to
play around with our prototypes, we can make our pre-alpha version
available....

> about SaC and its compiling issues. There are useful papers on SAC
> homepage. But as I can see, the module subsystem section doesn't reflect
> the current syntax for modularization. So I have two questions about this
> topic:
> * What is the difference between the use and the import instructions?

That has something to do with steering function overloading.

Each module has its own namespace. Within such a namespace you can have
several definitions for one function, provided that these differ in their
argument types. For example:

int f( int x) {...}
double f( double x) {...}

If you overload with the same element type, you have to ensure COVARIANCE,
e.g., you could add yet another definition for f of the form:

double[*] f( double[*] x) {...}

Now, whenever you call f in that namespace, you can only see exactly those
three instances.


Now, let us assume we have two different modules; a module A and a module B.
Both define an overloaded function f. A may contain the three versions
defined above, and B has two versions of the form:

double[.] f( double[.] a) {...}
double[.,.] f( double[.,.] b) {...}


Now, we want to be able to control exactly, which of these versions can be
seen.

If we want to use the three version from A, we can simply say

A::f([3.2])

alternatively, we may not want to prefix all functions from A with the
namespace, so we can use A:

use A:{f};


and then it suffices to write

f([3.2])

The only problem arises when we use A and B, for example, as in

use A: all;
use B: all;

Now, if we write f([3.2]) it is not clear which version of f we are
referring to. Therefore, the compiler will complain about f being provided
by both modules. One way to resolve this is to exclude f from the use
mechanism, e.g.:

use A: all except {f};
use B: all except {f};

Now we can even write:
A::f([3.2]) + B::f([3.2])

where the first call to f will chose one instance from A and the second will
choose an instance from B.

However, sometimes, you want to actually combine all 5 instances into one
symbol f. The way this can be done in SaC is not to *use* the existing
versions of f but to *import* their definitions into the current namespace.
If you do that, your current namespace contains an f that dispatches between
all 5 instances:

import A: {f};
import B: {f};

f([3.2])


you can even export this new f by saying

export {f};


You may also have noticed that we have provide and export. These are
complements to use and export, i.e., you can only import things that have
been exported. If a symbol is being provided only, all you can do is to use
it as is; a later "extension" of an overloading in the way described above
is NOT possible.





> * How is it possible to define uniqueness type explicitly? Classtypes are
>   uniqueness, but I'd like to define uniqueness types on a general way.

The entire idea is to hide uniqueness types from the user. Instead, we talk
about state-full objects. A class introduces a state-full data type which is
guaranteed to be used single threaded-ly (even if you use our
non-determinism feature as explained in
http://doi.acm.org/10.1145/1481839.1481847). Then, uniqueness types serve as
an implementation vehicle only. We even mimick the touch and feel of
side-effects by supporting reference parameters and global objects, both of
which lead to compiler inserted extra parameters to ensure proper
single-threadedness.

> 
> And one more question about variable declaration. I don't know that it's a
> bug or just I don't understand the impact of declarations. Consider the
> following example:
> 
> import Array: all;
> import StdIO: all;
> 
> typedef int[1] array;
> 
> int main()
> {
>         array x;
>         x = 10;
> 
> #ifndef EXCLUDE_ERRORS
>         print(x);
> #endif
> 
>         return(0);
> }
> 
> Without the print there is no error, but with the print there is a typing
> error for the assignment. I wonder, why succeed the compiling without the
> print. What's the matter in this case? If this is actually a bug, I'll
> report it more detailed in SaC-Zilla.

There you have hit an ugly spot :-) It has something to do with the way we
use the type system to infer array shapes. We only propagate type errors to
the user, if we can guarantee that the type error will be hit, e.g., if you
write:

if ( ... ) {
    res = 1;
} else {
    res = 2 + true;
}

return( res)


this is being accepted and transformed into

if ( ... ) {
    res = 1;
} else {
    res = type_error( "....");
}

return( res)

so it may yield a runtime type error. The way we deal with this formally is
by introducing bottom types within our subtype hierarchy. And here, we have
lub( int, bottom) = int which is ok.

We decide whether a type error is guaranteed to happen by simply looking at
the return type! So, in a sense, our type system is lazy!
As a consequence, if you have a type error in dead code, it is not
statically detected. If you furthermore have all opts enabled Dead Code
Removal than will also eliminate the potential runtime type error.

The reason why the print propagates the error is the uniqueness typing.

In essence, you get something like:

int main( world)
{
    array x;
    x = 10;

    world' = print( x, world);

    return(0, world');
}

Subsequent type checking reveals that x is bottom
hence world' is bottom
hence we statically know bottom will show up
=> static error

HTH,
  Bodo
> 
> Thanks for any advice!
> 
> Best regards,
> David 




More information about the sac-user mailing list