← Back to team overview

ooc-dev team mailing list archive

Re: Request for comments - Arrays (Literals, Types, C Arrays, Stack allocation, Optimizations), and Constructors

 

Regarding arrays, it would be nice to not have the var: Type[#] syntax become var:=ArrayList<Type> new(#), and instead remain as a static C array. This becomes crutial for covering C structures and speed- crutial functions. Besides, if a person is using var: Type[#] syntax, they more than likely already know what size the array is supposed to be, negating the usefulness of having it as a resizable ArrayList.

As far as the tidbit on stack-allocation in rock, does that mean we'll see alloca'd objects eventually? If so, that might actually remove the need for a GC in many parts of the sdk. Even more interesting would be methods added to the cover of the Pointer, such as copyToStack: func->This, or copyToHeap: func->This.

PS: I'm not exactly sure if this mail was sent right, it's been a while since I've touched a mailing list.

On Feb 26, 2010, at 4:36 PM, Amos Wenger <amoswenger@xxxxxxxxx> wrote:

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

Follow ups

References