Skip to content

Commit

Permalink
Merge 90fcbbc into 5181051
Browse files Browse the repository at this point in the history
  • Loading branch information
PalumboN committed Dec 8, 2018
2 parents 5181051 + 90fcbbc commit 6693330
Show file tree
Hide file tree
Showing 10 changed files with 318 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,25 @@ class MethodTypeInferenceTestCase extends AbstractWollokTypeSystemTestCase {
assertMethodSignature("(Number) => Void", 'GolondrinaIneficiente.comer')
]
}

@Test
def void testMethodInferredFromSuperMethodWithSuperInvocation() {
'''
class Golondrina {
var energia = 100
method comer(gramos) {
energia = energia + gramos
}
}
class GolondrinaIneficiente inherits Golondrina {
override method comer(gramos) { super(gramos - 10) }
}
'''.parseAndInfer.asserting [
noIssues
assertMethodSignature("(Number) => Void", 'Golondrina.comer')
assertMethodSignature("(Number) => Void", 'GolondrinaIneficiente.comer')
]
}

// Method Calls
@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/* XPECT_SETUP org.uqbar.project.wollok.tests.typesystem.xpect.TypeSystemXpectTestCase END_SETUP */

class Ave {
// XPECT type at nombre --> String
var nombre
var energia = 100

// XPECT type at nom --> String
constructor(nom) {
nombre = nom
}

constructor() = self("") { }

// XPECT methodType at come --> (Number) => Void
method come(gramos) {
energia = energia + gramos
}

// XPECT methodType at energia --> () => Number
method energia() = energia
}

class Golondrina inherits Ave {

// XPECT type at e2 --> Number
constructor(e2) = super("pepita") {
self.vola()
}

constructor() = self(1) { }

// XPECT methodType at vola --> () => Void
method vola() {
energia = energia - 10
}

// XPECT methodType at come --> (Number) => Void
override method come(gramos) {
super(gramos + 10)
}
}

class GolondrinaMentirosa inherits Golondrina {

// XPECT type at e3 --> Number
constructor(e3) = super(e3) {
self.vola()
}

// XPECT methodType at energia --> () => Number
override method energia() = super() + 10
}



class EntrenadorChanta inherits EntrenadorDeGolondrinas {
// XPECT methodType at alimentar --> (Ave) => Void
override method alimentar(ave) {
super(new GolondrinaMentirosa(1))
}

// XPECT methodType at hacerQueVuele --> (Golondrina) => Void
override method hacerQueVuele(golondrina) {
// golondrina.come(1) TODO: Fix it! This can't be an Ave
super(golondrina)
}

// XPECT methodType at pajaro --> () => GolondrinaMentirosa
override method pajaro() {
// XPECT type at p --> Golondrina
const p = super()
return new GolondrinaMentirosa(1)
}
}

class EntrenadorDeGolondrinas inherits EntrenadorDeAves {

// XPECT type at g --> Golondrina
constructor(g) = super(g) {
g.vola()
}

// XPECT methodType at alimentar --> (Ave) => Void
override method alimentar(ave) {
super(new Golondrina())
}

// XPECT methodType at hacerQueVuele --> (Golondrina) => Void
method hacerQueVuele(golondrina) {
golondrina.vola()
}

// XPECT methodType at pajaro --> () => Golondrina
override method pajaro() {
// XPECT type at a --> Ave
const a = super()
return new Golondrina()
}

method hacerVolarGolondrina() { self.hacerQueVuele(new Golondrina()) }
}

class EntrenadorDeAves {
const ave

// XPECT type at a --> Ave
constructor(a) {
ave = a
}

// XPECT methodType at alimentar --> (Ave) => Void
method alimentar(ave) { ave.come(10) }

// XPECT methodType at pajaro --> () => Ave
method pajaro() = new Ave()

method alimentarAve() { self.alimentar(new Ave()) }

method alimentarFavorita() { ave.come(1) }
}

object wollok {
method entrenadorDeAves() = new EntrenadorDeAves(new Ave())
method entrenadorDeGolondrinas() = new EntrenadorDeGolondrinas(new Golondrina())
}

Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import org.eclipse.emf.ecore.EObject
import org.uqbar.project.wollok.typesystem.WollokType
import org.uqbar.project.wollok.typesystem.constraints.variables.GenericTypeInfo
import org.uqbar.project.wollok.typesystem.constraints.variables.TypeVariablesRegistry
import org.uqbar.project.wollok.wollokDsl.Import
import org.uqbar.project.wollok.wollokDsl.WAssignment
import org.uqbar.project.wollok.wollokDsl.WBinaryOperation
import org.uqbar.project.wollok.wollokDsl.WBlockExpression
import org.uqbar.project.wollok.wollokDsl.WBooleanLiteral
import org.uqbar.project.wollok.wollokDsl.WCatch
import org.uqbar.project.wollok.wollokDsl.WClass
import org.uqbar.project.wollok.wollokDsl.WClosure
import org.uqbar.project.wollok.wollokDsl.WConstructor
Expand All @@ -19,14 +21,20 @@ import org.uqbar.project.wollok.wollokDsl.WListLiteral
import org.uqbar.project.wollok.wollokDsl.WMemberFeatureCall
import org.uqbar.project.wollok.wollokDsl.WMethodDeclaration
import org.uqbar.project.wollok.wollokDsl.WNamedObject
import org.uqbar.project.wollok.wollokDsl.WNullLiteral
import org.uqbar.project.wollok.wollokDsl.WNumberLiteral
import org.uqbar.project.wollok.wollokDsl.WParameter
import org.uqbar.project.wollok.wollokDsl.WPostfixOperation
import org.uqbar.project.wollok.wollokDsl.WProgram
import org.uqbar.project.wollok.wollokDsl.WReturnExpression
import org.uqbar.project.wollok.wollokDsl.WSelf
import org.uqbar.project.wollok.wollokDsl.WSelfDelegatingConstructorCall
import org.uqbar.project.wollok.wollokDsl.WSetLiteral
import org.uqbar.project.wollok.wollokDsl.WStringLiteral
import org.uqbar.project.wollok.wollokDsl.WSuperDelegatingConstructorCall
import org.uqbar.project.wollok.wollokDsl.WSuperInvocation
import org.uqbar.project.wollok.wollokDsl.WThrow
import org.uqbar.project.wollok.wollokDsl.WTry
import org.uqbar.project.wollok.wollokDsl.WUnaryOperation
import org.uqbar.project.wollok.wollokDsl.WVariableDeclaration
import org.uqbar.project.wollok.wollokDsl.WVariableReference
Expand All @@ -35,12 +43,6 @@ import static org.uqbar.project.wollok.sdk.WollokDSK.*

import static extension org.uqbar.project.wollok.model.WMethodContainerExtensions.*
import static extension org.uqbar.project.wollok.model.WollokModelExtensions.*
import static extension org.uqbar.project.wollok.visitors.ReturnFinderVisitor.containsReturnExpression
import org.uqbar.project.wollok.wollokDsl.Import
import org.uqbar.project.wollok.wollokDsl.WThrow
import org.uqbar.project.wollok.wollokDsl.WTry
import org.uqbar.project.wollok.wollokDsl.WCatch
import org.uqbar.project.wollok.wollokDsl.WNullLiteral

/**
* @author npasserini
Expand All @@ -51,12 +53,16 @@ class ConstraintGenerator {

OverridingConstraintsGenerator overridingConstraintsGenerator
ConstructorConstraintsGenerator constructorConstraintsGenerator
SuperInvocationConstraintsGenerator superInvocationConstraintsGenerator
DelegatingConstructorCallConstraintsGenerator delegatingConstructorCallConstraintsGenerator

new(ConstraintBasedTypeSystem typeSystem) {
this.typeSystem = typeSystem
this.registry = typeSystem.registry
this.overridingConstraintsGenerator = new OverridingConstraintsGenerator(registry)
this.constructorConstraintsGenerator = new ConstructorConstraintsGenerator(registry)
this.superInvocationConstraintsGenerator = new SuperInvocationConstraintsGenerator(registry)
this.delegatingConstructorCallConstraintsGenerator = new DelegatingConstructorCallConstraintsGenerator(registry)
}

// ************************************************************************
Expand Down Expand Up @@ -89,7 +95,7 @@ class ConstraintGenerator {
def void generateVariables(EObject it) {
try {
generate
} catch(Exception e) {
} catch (Exception e) {
addFatalError(e)
}
}
Expand Down Expand Up @@ -125,21 +131,20 @@ class ConstraintGenerator {
// TODO Process superconstructor information.
parameters.forEach[generateVariables]
expression?.generateVariables
delegatingConstructorCall?.generateVariables
}

def dispatch void generate(WMethodDeclaration it) {
newTypeVariable
parameters.forEach[generateVariables]

if(!abstract) {
if (!abstract) {
expression?.generateVariables
if(expression.containsReturnExpression // Method contains at least one return expression
|| expressionReturns // Compact method, no return required.
) beSupertypeOf(expression) // Return type is taken from the body
if(hasReturnType) beSupertypeOf(expression) // Return type is taken from the body
else beVoid // Otherwise, method is void.
}

if(overrides) overridingConstraintsGenerator.addMethodOverride(it)
if(overrides) overridingConstraintsGenerator.add(it)
}

def dispatch void generate(WClosure it) {
Expand All @@ -161,7 +166,7 @@ class ConstraintGenerator {
expressions.forEach[generateVariables]

val containsReturn = !tvar.subtypes.empty
if(!containsReturn)
if (!containsReturn)
if(!expressions.empty) beSupertypeOf(expressions.last) else beVoid
}

Expand Down Expand Up @@ -189,7 +194,7 @@ class ConstraintGenerator {
leftOperand.generateVariables
rightOperand.generateVariables

if(isMultiOpAssignment) {
if (isMultiOpAssignment) {
// Handling something of the form "a += b"
newTypeVariable => [beVoid]
val operator = feature.substring(0, 1)
Expand All @@ -202,7 +207,7 @@ class ConstraintGenerator {
}

def dispatch void generate(WUnaryOperation it) {
if(feature.equals("!")) {
if (feature.equals("!")) {
newTypeVariable.beSealed(classType(BOOLEAN))
}
operand.generateVariables
Expand All @@ -220,7 +225,7 @@ class ConstraintGenerator {
def dispatch void generate(WConstructorCall it) {
arguments.forEach[arg|arg.generateVariables]
beSealed(typeOrFactory(classRef).instanceFor(newTypeVariable))
constructorConstraintsGenerator.addConstructorCall(it)
constructorConstraintsGenerator.add(it)
}

def dispatch void generate(WInitializer it) {
Expand All @@ -237,7 +242,7 @@ class ConstraintGenerator {
def dispatch void generate(WVariableDeclaration it) {
variable.newTypeVariable.beNonVoid

if(right !== null) {
if (right !== null) {
right.generateVariables
variable.beSupertypeOf(right)
}
Expand All @@ -260,7 +265,7 @@ class ConstraintGenerator {

then.generateVariables

if(getElse !== null) {
if (getElse !== null) {
getElse.generateVariables

// If there is a else branch, if can be an expression
Expand Down Expand Up @@ -290,7 +295,7 @@ class ConstraintGenerator {

def dispatch void generate(WCatch it) {
exceptionVarName.newTypeVariable => [ tvar |
if(exceptionType !== null)
if (exceptionType !== null)
tvar.beSealed(classType(exceptionType))
else
tvar.beNonVoid
Expand Down Expand Up @@ -336,7 +341,7 @@ class ConstraintGenerator {
}

def dispatch void generate(WVariableReference it) {
if(ref.eIsProxy) {
if (ref.eIsProxy) {
// Reference could not be resolved, we can't add constraint with the referenced element.
// So we know almost nothing, but a variable reference can not be void.
newTypeVariable.beNonVoid
Expand All @@ -348,11 +353,30 @@ class ConstraintGenerator {
def dispatch void generate(WSelf it) {
asOwner.newSealed(declaringContext.asWollokType)
}

def dispatch void generate(WNullLiteral it) {
// Now only generate ANY variable.
// Maybe we'll want another kind of variable for nullable types implementation.
newTypeVariable
newTypeVariable
}

def dispatch void generate(WSuperInvocation it) {
newTypeVariable
memberCallArguments.forEach[generateVariables]
superInvocationConstraintsGenerator.add(it)
}


def dispatch void generate(WSelfDelegatingConstructorCall it) {
newTypeVariable
arguments.forEach[generateVariables]
delegatingConstructorCallConstraintsGenerator.add(it)
}

def dispatch void generate(WSuperDelegatingConstructorCall it) {
newTypeVariable
arguments.forEach[generateVariables]
delegatingConstructorCallConstraintsGenerator.add(it)
}

// ************************************************************************
Expand All @@ -361,6 +385,8 @@ class ConstraintGenerator {
def addCrossReferenceConstraints() {
overridingConstraintsGenerator.run()
constructorConstraintsGenerator.run()
superInvocationConstraintsGenerator.run()
delegatingConstructorCallConstraintsGenerator.run()
}

// ************************************************************************
Expand Down
Loading

0 comments on commit 6693330

Please sign in to comment.