On Thu, Jun 18, 2009 at 3:28 PM, john
skaller<skal...@users.sourceforge.net> wrote:
>
> still not sure what to do about this. This cannot work now:
>
>        x.[i] += 1;
>
> where x is a C-array, because the subscript function cannot return
> an lvalue (since they don't exist). It could return a pointer, and we could
> make it so
>
>        p + 1
>
> actually means
>
>        *p + 1
>
> Normally deref and store are the only operations allowed on pointers,
> addition (as in C) isn't allowed. At present
>
>        a.[i] = 1;
>
> only works because of a hack: Felix doesn't bother to actually check
> the LHS here is legal. This should mean
>
>        &a.[i] <- 1;
>
> which would fail, but assignment is simply delegated to C.

Oiy, isn't this a big can of worms? So starting off, I still think
it's a good idea that we got rid of lvalues. There are a bunch of
things at work here. I think the main question is if arrays are
special. In C/C++, we can limit pointers through const-ing. It has 4
types of pointers:

int i[] = { 1, 2, 3 };
int j[] = { 3, 4, 5 };

int* p = i;
p[0] = 0;
p = j;

const int* p = i;
p[0] = 0;  <- type error
p = j;

int* const p = i;
p[0] = 0;
p = j; <- type error

const int* const p = i;
p[0] = 0; <- type error
p = j; <- type error

However, they don't transmit immutability. It's pretty simple to take
a `const foo* const` and modify it:

struct P { int x; int y };
const P const p[] = ...
p[0].x = 5;

This means it's easy to create a data structure that is only sort-of immutable.

OCaml, on the other hand, treats it's arrays as always mutable. With
references, OCaml essentially provides "int*" and "int* const"
semantics:

# let f a = a.(0) <- 5;;
# let a = [|1;2;3|];;
# f a;;
# a;;
- : int array = [|5; 2; 3|]

Scala works the same way. Felix currently works the same way by default:

# proc foo[N] (x:array[int,N]) { x.[0] = 5; }
# val x = 1,2,3;
# foo x;
# println x;
-: (5, 2, 3)

However, we can limit this by using the "var" keyword:

# proc foo[N] (var x:array[int,N]) { x.[0] = 5; }
# val x = 1,2,3;
# foo x;
# println x;
-: (1, 2, 3)

But there's no way to say "it's a type error to modify this array"
like C/C++ does. So, is this something we'd want? I personally think
something like this would be useful, and I'd bet it'd help with
optimization. We'd probably want something like this to work beyond
just arrays and pointers.

One way we could limit this a little bit is to make value arrays
immutable, where these would be type errors:

# val x = 1,2,3;
# x.[0] = 5; <- type error
# proc foo[N] (x:array[int,N]) { x.[0] = 5; } <- type error

Then, if we modified the "ref" reference to work like this:

# proc foo[N] (ref x:array[int,N]) { x.[0] = 5; }
# var x = 1,2,3;
# foo x;
# println x;
-: (5, 2, 3)

This then pretty much provides the "int*" and "const int* const"
semantics. (I wonder if there's any way to achieve "const int*" or
"int* const"...). This would also mean that we'd change the store (and
all other mutation functions) to be written as:

fun store[T,N]: ref array[T,N] * int * T

And would allow us to use the pointer semantics for something else.
Maybe OCaml-esque non-nullable reference types? Maybe we could write:

# var x = ref 1,2,3;
# *x = 4,5,6;
# (*x).[0] = 0; <- type error

That'd get "int* const". I'm not sure if that makes much sense though...

------------------------------------------------------------------------------
Crystal Reports - New Free Runtime and 30 Day Trial
Check out the new simplified licensing option that enables unlimited
royalty-free distribution of the report engine for externally facing 
server and web deployment.
http://p.sf.net/sfu/businessobjects
_______________________________________________
Felix-language mailing list
Felix-language@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/felix-language

Reply via email to