ooc-lang / rock

:ocean: self-hosted ooc compiler that generates c99
http://ooc-lang.org/
MIT License
404 stars 40 forks source link

Range as a for loop range #951

Closed davidhesselbom closed 8 years ago

davidhesselbom commented 8 years ago
range := 0 .. 5
for (i in range)
    println(i toString())

This doesn't build, because

No such function iterator() for `Range`

What if rock could pre-process this into

range := 0 .. 5
for (i in range min .. range max)
    println(i toString())

(which does work) so you wouldn't have to spell it out? As far as I can tell, a new Range is created with this syntax anyway.

fasterthanlime commented 8 years ago

ping @shamanas

alexnask commented 8 years ago

I'll take a look at this today (read the mailing list too)

davidhesselbom commented 8 years ago

On a somewhat unrelated note, it would be cool if you could make ranges run backwards, like this:

for (i in 5 .. 0)
    println(i toString())

but I suppose there are reasons why that would be a bad idea.

fasterthanlime commented 8 years ago

@davidhesselbom there's a bunch of stuff in the SDK to do backward/reverse iteration, cf. https://github.com/fasterthanlime/rock/blob/94362e9ee6f7cda1f8ffdcda5636c5ed0ad40c3d/sdk/lang/Iterators.ooc

davidhesselbom commented 8 years ago

Using iterators, yes, but I'd prefer not to use them (iirc, unfixable memory leaks when no gc, but not sure). Thanks for the suggestion, though.

alexnask commented 8 years ago

For loops only seem to handle range literal collections as an edge-case, changing this to any expression of type Range should be trivial (I think?).

fasterthanlime commented 8 years ago

should be trivial

famous last words :tm: but you're the maintainer :) go ahead.

alexnask commented 8 years ago

I've got a version that is 99% of the way there but for some reason it generates both a correct index variable vdecl and an incorrect one that makes rock choke T_T

davidhesselbom commented 8 years ago

They say 90% of the time is spent on the last 10% of the job, so by extension, that means 81% of the development time remains? :P

alexnask commented 8 years ago

Seems accurate to me, although the time I've spent so far is minimal anyway :)

I'll try to finish this off now, add a couple of tests and then move on to the cover member assignment bug.

refi64 commented 8 years ago

@davidhesselbom You beat me to say that by 10 minutes.

alexnask commented 8 years ago

For some reason a foreach loop adds it's index variable vdecl in a scope before it, so when I do my hackish replacement of a range collection with a range literal, I generate a secon vdecl and the first one is unresolvable.

The problem is the fact that I can't find the code that actually adds the vDecl before the for loop (although the code that generates the decl is obvious)

horasal commented 8 years ago

@shamanas I haven't read all the discussion, but if you mean Foreach variable, I think it is added to parent scope while being resolved.

In middle/VariableDecl.ooc: 230 ~

            if(!parent isScope() && !parent instanceOf?(TypeDecl) && !parent instanceOf?(FuncType)) {

This part try to unwrap variable decl to its parent scope. Maybe it is mainly designed for things like

while ( a := get_next() )

The debug loop information also shows than i is unwrapped while resolving

Resolving variable decl i: Int

For i: Int, resolving type Int, of type BaseType
Done resolving the type, ref = CoverDecl Int 

info wholeAgain 'because parent isn't scope nor typedecl, unwrapped' for i: Int (of type VariableDecl)
for (i in 0..10 ){

Response of statement [Foreach] for (i in RangeLiteral) = LOOP
response of body = LOOP
alexnask commented 8 years ago

@zhaihj
Thank you, I couldn't figure out where it was added to the parent scope (I assumed Foreach was doing it), this still leaves things a bit complicated but I suppose I can go up the trail and fetch the declaration :)

alexnask commented 8 years ago

That was going to be my solution anyway but it frustrated me too much I couldn't find where the variable was unwrapped, since it is done in VariableDecl.ooc I think it is the correct solution.

alexnask commented 8 years ago

By the way @fasterthanlime the C backend seems to be making the index variable iterate over the same range as the foreach variable (for range foreaches).

Here is some generated code:

// Should be:
// for (i = test__range.min, j = 0; i < test__range.max; i++, j++) {
for (i = test__range.min, j = test__range.min; i < test__range.max; i++, j++) {
}

From:

range := 10 .. 15
for ((j, i) in range) {
}