magic-lang / rock

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

Check override signatures #37

Closed horasal closed 8 years ago

horasal commented 8 years ago

Summary

This pull request allow rock check if there exists any incompatible definition between derived and base classes (covers). If there are any incompatible definitons, a warning is generated. The rules for checking is summarized as follows:

  1. super function call vs definition
    • Number of the arguments provided in super should match the best matched definitoin.
  2. derived function vs base function
    • Number of the arguments provided should match.
    • Return type should match (i.e. the match score is larger than 0)
    • Type of each argument should match (i.e. the match score is larger than 0)
    • NumberTypes only match when they are definitely the same..

      Implementation Details

    • super call is unwrapped in middle/FunctionCall.ooc. When resolving a function call, rock checks if its name equals to super. Once a super call is found, rock will perform a search the best definition in the meta class (which contains all the functions). The auto-fordwarding of arguments also happens here. A extra check on the number of arguments is added after the definition is got.
    • In magic-lang/rock, every function derived from the base class should have the override property. Override functions are guaranteed to only derived from abstract/virtual function by TypeDecl.ooc:checkOverrideFuncs. Checking of compatiblity is also performed in checkOverrideFuncs. One thing should be point out is that it is necessary to unwrap This before checking because getScore can not match This agaist its actural definition.
thomasfanell commented 8 years ago

@zhaihj Big thanks for submitting a fix! We are currently testing and reviewing this. :+1:

thomasfanell commented 8 years ago

Overall, we're quite happy with this PR. One thing we found is that rock accepts this without warning (gcc fails, however). We would request that since gcc fails, rock should produce an error in this case:

Base: abstract class {
    init: func
    increase: virtual func {
        this value += 1
    }
}
Derived: class extends Base{
    init: func { super() }
    // rock seems to ignore that increase() is returning void in the base class
    // instead, this should cause rock to produce an error (not warning)
    increase: override func -> Int {
        this value + 1
    }
}
thomasfanell commented 8 years ago

@zhaihj almost there, however:

Base: abstract class {
    value: Int
    init: func { this value = 0 }
    increaseByN: abstract func (n: Int) -> Int
    increaseByThree: virtual func -> Int {
        this value += 3
    }
}
Derived: class extends Base {
    init: func { super() }
    increaseByN: override func (n: Float) -> Float {
        this value += n
    }
    increaseByThree: override func -> Float {
        this value += 3.0f
    }
}

Here, rock ignores that the type is Int in the base, and Float in the derived class.

horasal commented 8 years ago

Hmm, this is because that current rock allow matching different types of numbers -- so it can allow you return a Int in something like func->Float. I don't want to touch the getScoreImpl function because it will breaks too many things. As the result, I make the definition-check follows the following rule:

  1. if numbers of arguments are different, fail.
  2. if there doesn't exist a common root (i.e. score < -1), fail.
  3. if both side is number and they have different type, fail.
alexnask commented 8 years ago

rock is really relaxed with what you can override indeed.

It should get stricter at some point but I'm pretty sure a lot of things in the core Number type declarations would break :p

horasal commented 8 years ago

@shamanas

Rock even allow define default parameter before the normal ones :laughing:

marcusnaslund commented 8 years ago

Well, when it comes to numbers, this seems logical. We do want stuff like myFloat: Float = myInt to work, so this seems like a good solution.

How about if you change Int to Float of an argument type? We should do the same thing then.

thomasfanell commented 8 years ago

@zhaihj do you have additional commits coming? Otherwise, as far as I'm concerned, this is a done deal. Now it's up to @fredrikbryntesson to sign off on it.

horasal commented 8 years ago

@thomasfanell currently that's all!

fredrikbryntesson commented 8 years ago

@zhaihj It would be good if you could write a short explanation about how you reasoned when you created the solution as stated in the bounty repository. "Your pull request's description should contain a brief summary of what has been done, how it works and how the solution was found. " A simple writeup about how you solved the problem.

horasal commented 8 years ago

Update pull request description (I'm not good at writing :(

fredrikbryntesson commented 8 years ago

@zhaihj We accept it, send me a mail at fredrik.bryntesson@vidhance.com to collect the reward.

marcusnaslund commented 8 years ago

@zhaihj Very nicely done, and very quick responses, thank you. :)