operators
The core operators in this language are the period, used for substructure access, and the parentheses, used to pass parameters to a function call.
Every object embodies a namespace of components and methods. These are accessed by following the object by a period and the name.
Methods can be called by following the name by a (possibly empty) list of parameters enclosed in parentheses. All operations can be called this way, though there are often easier means, such as as infix operators. So for example
Integer.add(a, b)
might be the same as
a + b
Note that this is not necessarily a.add(b). Infix operators are defined as operation in a type, not methods of an object.
When finding which operation to use for an infix operator we look through the operations in the class of the left hand operand which have been associated with the given operator, and choose one for which the types of both sides are correct. Of these, the operation for which the first parameter is lowest in the type lattice is perferred. If choices still remain, the lowest inf the second parameter is chosen.
Thus the virtual class "Number" might declare the "+" infix operator. Then Integer32 might refine Number to a concrete class and define "add(Interger32, Interger32)" which adds two integers. Also Float might refine Number and define "add(Float, Float)" and also "addint(Float, Int)" and "addtoint(Int, Float)" all of which return Float. Then a + b would clearly resolve to one of these providing each of a and b were either Int or Float.
No automatic coersion is done. If another class "BigNum" were defined that defined addition within bignums and between bignums and integers, then an addition of a bignum and a float would fail.
In general, automatic coersion is frowned upon as lack of precission is likely.
Note that classes can define operations and methods for other classes. For example, Float might define a method for the Integer32 class which converts the integer into a floating point number. This is done by declaring the name in the Number class, and defining it for various subclasses.
For this reason, it is good for an abstract class to declare a number of representatons for subclasses to work with. Thus "Number" might declare the names Integer32, Integer64, Float, Double, BigNum, BigInt, Complex, Guassian (Is that what complex integers are called?) Duplex (Complex doubles?) so that different classes can make use of each other representations.
Question: Is this only useful for numbers? Numbers are clearly a fairly special case, but the less special we can make them, the cleaner the language.