Tuesday, March 28, 2006

Indexers

I had postponed any decision on Freya indexers until I could find a better model for representing name overloading in the symbol table. The original data structure was borrowed from Blue, and it was based in a clever trick: each context table contained a "group symbol" entry, which associated a name like WriteLine to the list of overloaded methods. At the same time, each of these methods was included independently. Since the context table is a kind of hash dictionary, method names were "decorated" or mangled, adding information from the parameter types.
I started with a version of Blue without indexers, and that's the reason why the symbol table only considered overloading for methods, but not for properties. There was another problem with explicit and implicit user defined conversions. The raw op_Implicit and op_Explicit methods violate one important rule in Freya and C#: they cannot be distinguished by the parameters signature! Suppose you write this in C#:
public static operator explicit double(Complex);
public static operator explicit float(Complex);
They translate to something like this:
public static double op_Explicit(Complex);
public static float op_Explicit(Complex);
Both methods have identical parameter lists, and they only differ in their return types. Of course, this is forbidden in C# and Freya... but is supported by the CLR. But the decorated parameter trick was inappropiate for representing this situation.
I have solved the problem by only including the group name for user defined conversions and indexers. Probably, there's no reason for including decorated method names in the hash table, but I won't mess right now with such a far reaching change in the compiler.
Finally, Freya has full functional indexers, following Visual Basic.NET. The reason:
  1. The VB model is the most general.
  2. Surprisingly, you can access secondary indexers from a C# application.
  3. So far, I haven't discovered any important drawback in the VB model.
I have also added lifted operators to Freya: these are automatic extensions for predefined and user operators for dealing with nullable types, and they imitate the behavior of SQL operators when they act on null values.

Labels: ,

Tuesday, March 07, 2006

Operating with operators

Let's do a quick review of operators in Freya. Operators must be declared, as usual, in public static sections:
static public
method+(c1, c2: Complex): Complex;
operator-(c1, c2: Complex): Complex;
As you see, method and operator are equivalent when defining a "symbolic" operator. No syntax ambiguity arises in these cases, and the method keyword is friendlier, in my humble opinion.
However, operator is required when the operator name is a keyword or an identifier:
    operator True(c: Complex): Boolean;
Technically, True is an operator in Freya, following C#. We cannot proceed as in Pascal and consider True an enumerative constant, since in that case, both Freya and C# would require the class name as qualifier: Boolean.True.
Even when the operator name is a keyword, there's no syntactic ambiguity. The real reason for keeping the operator keyword is this:
    operator Explicit(c: Complex): Double;
operator Implicit(d: Double): Complex;
Though both explicit and implicit are C# keywords, they are not keywords in Freya. We could have allowed this:
   method Explicit(c: Complex): Double;
But I thought it would be dangerous, since you cannot tell whether the programmer intention was declaring a full featured operator or a regular method called Explicit.
Operator implementation is straightforward, as usual:
implementation for Complex is

operator Implicit(d: Double): Complex;
begin
Result := new Complex(d, 0.0);
end;

Labels: ,