Hi everyone,
These last few days, I've been busy fixing bugs to make rock compile
itself. Things have been going pretty smoothly, as it now parses 57
files (see log http://gist.github.com/316144 ) before choking, out
of the 137 that rock+sdk consist of.
But now I've reached a point where I have to make choices that might
differ from j/ooc's behavior. Here are my ideas/plans, I'd love to
hear your comments on it.
Arrays
=====
Literals
How to determine the type of [1, 2, 3.14] ? Several cases.
If we're in a var-decl, take the 'largest' type, e.g. one in which
all values fit (in this case, Float). In the case of [animal, dog],
it would be 'Animal'
In the case [1, 2, dog], an error should be thrown.
If we're not in a var-decl, chances are there are 'outer
requirements', e.g. a function's signature, an outer cast, etc. as
in the following cases:
a := [1, 2, 3] as Float[]
a : Float[] = [1, 2, 3]
call: func (f: Float[])
call([1, 2, 3])
In all these cases, the array type can be easily deduced (and
verified, and an error thrown if an incompatible element is in.)
Types
structs/Array should be gone. It provides no advantage over
ArrayList (neither in size nor speed), and we want no redundancy,
right?
a := [1, 2, 3]
..should be an ArrayList<Int>
a : Int[3]
should be a shortcut for
a := ArrayList<Int> new(3)
call: func (f: Float[])
..should be an alias for:
call: func (f: List<Float>)
This means we'll move structs/ArrayList and structs/List to lang/,
where it'll get imported implicitly in every source file. This is,
imho, a small cost to pay for classes that are used in 83% of the
ooc code out there anyway. (Yes, that's an HIMYM reference.)
C arrays (aka raw arrays)
You can still use gc_malloc() anywhere, handle them as pointers:
a := gc_malloc(3 * Int size) as Int*
for(i in 0..3) a[i] = i
C arrays will now always have to be defined with the 'char**' style,
never 'char[][]', cause '[]' will be reserved to ArrayList
Stack allocation
We've been over this numerous times on IRC, and there were heated
debates. Of course, allocating on the stack is faster. And it's also
more dangerous (you have to be careful not to leak references to it
to outer functions, and it's hard to keep an eye on the stack usage,
which size may vary from platform to platform, and in case you
allocate too much you have a difficult-to-debug problem on your
hands).
I've always thought that memory allocation is almost always a job
best left to the compiler (hence the choice of a GC). rock will be
an amazing playground to implement stack-allocation, capture-into-
the-heap etc. Application developers should have time to concentrate
on cleaner code instead!
Optimizations
It is well known that sometimes C is slower than, say, Fortran
because of pointer aliasing. Making pure ooc arrays would allow
optimizations in an assembly backend for rock, that the C backend
wouldn't allow (except maybe with the use of the http://en.wikipedia.org/wiki/Restrict
keyword).
That's assuming we're willing to heavily inline functions of
ArrayList, of course. But there are fascinating perspectives for an
asm backend that I'm looking forward to explore.
Constructors
==========
In j/ooc, constructors (e.g. the init method) couldn't be
overloaded. You had to use different prefixes in each subclass. This
behavior, is not desirable.
In rock, currently, init methods can be overriden, but this also
means you can do
Animal: class {
init: func { "New animal created!" println() }
}
Dog: class extends Animal {
init: func ~withName (=name) { "New dog %s created!" format(name)
println() }
}
d := Dog new("Dogbert") // creates a dog alright
d2 := Dog new() // whoops, d2 is an Animal, not a dog :/
In Java, calling 'Dog new()' would be illegal. Should we forbid it
in ooc too? (Based on the name of the method, even if it's user-
defined).
I think it's a wise choice, except it will maybe require more
boilerplate code in some classes.
On the other hand, I'd still like to keep init()/new() as close as
possible to 'normal' methods, the only trickery involved being that
defining an init() instance method generates a corresponding new()
static method.
Maybe we should simply forbid to call static functions defined in
parent classes, for *all* static methods? That would solve the
problem and be consistent. Besides, who does that anyway?
That's it for tonight, I guess. In the absence of comments, I'll
follow the plan I have outlined here, but I'd love to hear your
thoughts!
Amos Wenger, aka nddrylliog
_______________________________________________
Mailing list: https://launchpad.net/~ooc-dev
Post to : ooc-dev@xxxxxxxxxxxxxxxxxxx
Unsubscribe : https://launchpad.net/~ooc-dev
More help : https://help.launchpad.net/ListHelp