Felix currently has 3 kinds of native products:

tuples
structs
records

And also cstructs.

I'm thinking to unify them into a single anonymous type:

product sname { f1name: f1type; ... }

The way to do this is:

A record is just a struct with name "".
A tuple is just a record with field names 0,1,2 etc.

Now you can also have a named tuple too: 

product tname { 0:T0; 1:T1; ...}

That's the theory. In the compiler only one combinator is used:

BTYP_product of string * (string * btype) list

Now you can do:

typedef A1 = product A1 { .. };

Note the second A1 isn't a type name, its just a tag like a field name.
The type name is "product A1 { ... }" i.e. the whole expression.

A synonym for the above is:

struct A1 { ... };

so we have recovered the struct notation, with the same meaning,
but now it is no longer a type put into the symbol table requiring lookup.

Field tags can be identifiers or integers.. the integers are implicit
from position:

struct X { a:int; long; b:int; }

The padding long has a name: 1.

Field access is by

   field value

That is, the field name is an ordinary production function.

Now, the notation

  value . field

is just reverse application. The only hassle is this:

struct X { x:int; };
fun x: X -> int = "1";

var a: X = X (x=1;);

println$ a . x; // which x?

There are some other details, such as struct constructors: that's a special 
isomorphism
from a tuple to a struct in which field and tag names are changed from the 
"default"
ones (empty, integer sequence) to the named ones of the struct.

I expect a similar thing can be done with variants..

Now there's an interesting quirk here. Consider:

var a: X ...

a.x

That's a projection function. Now consider:

(&a) . x

What could that do? Well, it should return a pointer to the x field of a,
right? So now we get our store operation:

  (&a). x <- 42;
  x (&a) <- 42;

If the struct is on the heap and pa is a pointer to it then 

  pa . x <- 42;

but we need to use

  (*pa) . x 

to get the value. Note that

  *(pa . x) == (*pa) . x

On the other hand

  & ( a . x )

is nonsense because a is a value. If a is a variable we allow (&a) however,
so we should also allow & ( a. x). 

However, if we have a Cstruct, it is different:

A Cstruct is just a collection of projection functions:

cstruct X { x: int; };

is shorthand for

type X = "X";
fun x: X -> int = "$1.x";

An *abstract struct* can be given by:

type X = "X";
fun x: X -> int = "Whatever you like goes here";

In this case we can't allow & ( a . x) because it is an int value.
However what if we have this:

fun x: &X -> &int = " ... ";

pa .x <- 42; // works!
(&a) . x <- 42; // works! (if a is a variable)

So actually, we're close to also allowing a choice of whether a field
is mutable: clearly you can't store calculated fields. Note that
a struct with calculated fields is NOT a product!! (Products requires
all the fields to be independent).

Now, we can actually get rid of the "&" operator altogether if we decide
a variable type "int" is actually a pointer. In that case given

var px : int =  1;
px <- *px;

In other words instead of addressing and lvalues, we have pointers
and deref only.

Getting rid of lvalues is pretty cool. Note we STILL have variables we
can store stuff in. The calculus is functional upto the assignment operation:

        LHS <- RHS

Hmmm.. any thoughts?


--
john skaller
skal...@users.sourceforge.net





------------------------------------------------------------------------------
Free Software Download: Index, Search & Analyze Logs and other IT data in 
Real-Time with Splunk. Collect, index and harness all the fast moving IT data 
generated by your applications, servers and devices whether physical, virtual
or in the cloud. Deliver compliance at lower cost and gain new business 
insights. http://p.sf.net/sfu/splunk-dev2dev 
_______________________________________________
Felix-language mailing list
Felix-language@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/felix-language

Reply via email to