magic-lang / rock

ooc compiler written in ooc
http://ooc-lang.org/
MIT License
14 stars 4 forks source link

methods-on-tuple #40

Closed horasal closed 8 years ago

horasal commented 8 years ago

Description

This pull request add the ability of caling functions/accessing variable/accessing property on Tuples. For example, the following expression:

(c,d,e) := (a, b, c) memberVariable
(a, b, c) free()

will be unwrapped to:

(c, d, e) := (a memberVariable, b memberVariable, c memberVariabel)
a free()
b free()
c free()

Implementation Details

The unwrap process only happes in two module: VariableAccess and FunctionCall.

VariableAccess handles the member variable/property access. If the expr is a Tuple, it is necessary to do the unwrap. In current rock, tuple-tuple assignment is already able to be unwrapped. Thus, the only work is to turn Tuple method to (TupleElements method(), ...).

FunctionCall handlse the member function call access. Similar with VariableAccess, we just "move" the method call into the tuple. One thing needed to be noticed is that because Tuple is an expression, so to make the following codes work, modification is also done in the return type check.

free: func {}
(a, b, c) free()

Current rock do not write standalone tuple to the c sources but just put a null. Such as the example given in FunctionCall, if the unwrapped tuple is just replaced with a NULL, the memory of a, b,c leaks. Thus, a visitTuple method is added into the Visitor to allow backend write each element of tuples.

thomasfanell commented 8 years ago
Base: class {
    value: Int
    init: func (=value)
    print: func { "Value: #{this value}" printfln() }
}
A: class extends Base { init: func (.value) { super(value) } }
B: class extends Base { init: func (.value) { super(value) } }
C: class extends Base { init: func (.value) { super(value) } }
// this works fine
(A new(10), B new(20), C new(30)) print()
// error Unsupported expression type VariableAccess for VariableDeclTuple.
(av, bv, cv) := (A new(1), B new(2), C new(3)) value

// Note: It works if av, bv and cv are pre-defined:
av, bv, cv: Int
(av, bv, cv) = (A new(1), B new(2), C new(3)) value

I'm not sure if this is strictly required by the bounty, but it would be nice to be able to do a one-liner like in the first case. @fredrikbryntesson and @marcusnaslund what do you say?

horasal commented 8 years ago

@thomasfanell member variable access in variabledecl is supposed to be supported in this implementation. I will fix it when I get back to workplace.

thomasfanell commented 8 years ago

@zhaihj :+1:

horasal commented 8 years ago

Fixed. If the replacing happens after expr resolve, compiler will finall loop back to resolve variabledecl. So just move the replacement before expr resolve.

thomasfanell commented 8 years ago

@zhaihj Nice job! Contact @fredrikbryntesson as per bounty instructions.

horasal commented 8 years ago

I'm wondering should I contact @fredrikbryntesson each time when a pr is merged, or just wait from the second time?

fredrikbryntesson commented 8 years ago

No it is not necessary, I got your contact information now so I will contact you when needed.