This commit is contained in:
ucrhh 2021-02-11 15:35:47 +01:00
commit cab3fcc4aa
8 changed files with 190 additions and 22 deletions

View File

@ -103,14 +103,14 @@ public class Tree implements TermVisitorTree {
public InferenceStep visit(AppTerm appTerm, Map<VarTerm, TypeAbstraction> typeAssumptions, Type conclusionType) { public InferenceStep visit(AppTerm appTerm, Map<VarTerm, TypeAbstraction> typeAssumptions, Type conclusionType) {
Type leftType = typeVarFactory.nextTypeVariable(); Type leftType = typeVarFactory.nextTypeVariable();
Type rightType = typeVarFactory.nextTypeVariable(); Type rightType = typeVarFactory.nextTypeVariable();
InferenceStep leftPremise = appTerm.getFunction().accept(this, typeAssumptions, leftType);
InferenceStep rightPremise = appTerm.getParameter().accept(this, typeAssumptions, rightType);
Type function = new FunctionType(rightType, conclusionType); Type function = new FunctionType(rightType, conclusionType);
Constraint newConstraint = new Constraint(leftType, function); Constraint newConstraint = new Constraint(leftType, function);
constraints.add(newConstraint); constraints.add(newConstraint);
InferenceStep leftPremise = appTerm.getFunction().accept(this, typeAssumptions, leftType);
InferenceStep rightPremise = appTerm.getParameter().accept(this, typeAssumptions, rightType);
Conclusion conclusion = new Conclusion(typeAssumptions, appTerm, conclusionType); Conclusion conclusion = new Conclusion(typeAssumptions, appTerm, conclusionType);
return stepFactory.createAppStep(leftPremise, rightPremise, conclusion, newConstraint); return stepFactory.createAppStep(leftPremise, rightPremise, conclusion, newConstraint);
} }
@ -123,12 +123,13 @@ public class Tree implements TermVisitorTree {
extendedTypeAssumptions.put(absTerm.getVariable(), assAbs); extendedTypeAssumptions.put(absTerm.getVariable(), assAbs);
Type premiseType = typeVarFactory.nextTypeVariable(); Type premiseType = typeVarFactory.nextTypeVariable();
InferenceStep premise = absTerm.getInner().accept(this, extendedTypeAssumptions, premiseType);
Type function = new FunctionType(assType, premiseType); Type function = new FunctionType(assType, premiseType);
Constraint newConstraint = new Constraint(conclusionType, function); Constraint newConstraint = new Constraint(conclusionType, function);
constraints.add(newConstraint); constraints.add(newConstraint);
InferenceStep premise = absTerm.getInner().accept(this, extendedTypeAssumptions, premiseType);
Conclusion conclusion = new Conclusion(typeAssumptions, absTerm, conclusionType); Conclusion conclusion = new Conclusion(typeAssumptions, absTerm, conclusionType);
return stepFactory.createAbsStep(premise, conclusion, newConstraint); return stepFactory.createAbsStep(premise, conclusion, newConstraint);
} }
@ -159,10 +160,10 @@ public class Tree implements TermVisitorTree {
typeInfererLet.getType().orElseThrow(IllegalStateException::new), extendedTypeAssumptions); typeInfererLet.getType().orElseThrow(IllegalStateException::new), extendedTypeAssumptions);
extendedTypeAssumptions.put(letTerm.getVariable(), newTypeAbstraction); extendedTypeAssumptions.put(letTerm.getVariable(), newTypeAbstraction);
premise = letTerm.getInner().accept(this, extendedTypeAssumptions, premiseType);
constraints.add(newConstraint); constraints.add(newConstraint);
constraints.addAll(typeInfererLet.getLetConstraints()); constraints.addAll(typeInfererLet.getLetConstraints());
premise = letTerm.getInner().accept(this, extendedTypeAssumptions, premiseType);
} else { } else {
premise = new EmptyStep(); premise = new EmptyStep();
failedSubInference = true; failedSubInference = true;
@ -196,4 +197,22 @@ public class Tree implements TermVisitorTree {
Conclusion conclusion = new Conclusion(typeAssumptions, varTerm, conclusionType); Conclusion conclusion = new Conclusion(typeAssumptions, varTerm, conclusionType);
return stepFactory.createVarStep(premiseAbs, instantiation, conclusion, newConstraint); return stepFactory.createVarStep(premiseAbs, instantiation, conclusion, newConstraint);
} }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Tree tree = (Tree) o;
return failedSubInference == tree.failedSubInference && firstTypeVariable.equals(tree.firstTypeVariable)
&& firstInferenceStep.equals(tree.firstInferenceStep) && constraints.equals(tree.constraints);
}
@Override
public int hashCode() {
return Objects.hash(firstTypeVariable, firstInferenceStep, constraints, failedSubInference);
}
} }

View File

@ -6,6 +6,7 @@ import edu.kit.typicalc.model.type.TypeVariable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Objects;
/** /**
* Models the final result of the type inference with the most general unifier (mgu) and * Models the final result of the type inference with the most general unifier (mgu) and
@ -85,4 +86,21 @@ public class TypeInferenceResult {
protected Type getType() { protected Type getType() {
return finalType; return finalType;
} }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TypeInferenceResult that = (TypeInferenceResult) o;
return mgu.equals(that.mgu) && finalType.equals(that.finalType);
}
@Override
public int hashCode() {
return Objects.hash(mgu, finalType);
}
} }

View File

@ -87,4 +87,22 @@ public class TypeInferer implements TypeInfererInterface {
public Optional<Type> getType() { public Optional<Type> getType() {
return typeInfResult.map(TypeInferenceResult::getType); return typeInfResult.map(TypeInferenceResult::getType);
} }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TypeInferer that = (TypeInferer) o;
return tree.equals(that.tree) && unification.equals(that.unification)
&& typeInfResult.equals(that.typeInfResult);
}
@Override
public int hashCode() {
return Objects.hash(tree, unification, typeInfResult);
}
} }

View File

@ -6,11 +6,7 @@ import edu.kit.typicalc.model.term.VarTerm;
import edu.kit.typicalc.model.type.Type; import edu.kit.typicalc.model.type.Type;
import edu.kit.typicalc.model.type.TypeAbstraction; import edu.kit.typicalc.model.type.TypeAbstraction;
import java.util.ArrayDeque; import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
/** /**
* Instances of this implementation of TypeInfererInterface are used to execute the sub-inference starting in let steps. * Instances of this implementation of TypeInfererInterface are used to execute the sub-inference starting in let steps.
@ -92,4 +88,22 @@ public class TypeInfererLet implements TypeInfererInterface {
public Optional<Type> getType() { public Optional<Type> getType() {
return typeInfResult.map(TypeInferenceResult::getType); return typeInfResult.map(TypeInferenceResult::getType);
} }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TypeInfererLet that = (TypeInfererLet) o;
return tree.equals(that.tree) && unification.equals(that.unification)
&& typeInfResult.equals(that.typeInfResult);
}
@Override
public int hashCode() {
return Objects.hash(tree, unification, typeInfResult);
}
} }

View File

@ -4,12 +4,7 @@ import edu.kit.typicalc.model.type.Type;
import edu.kit.typicalc.model.type.UnificationActions; import edu.kit.typicalc.model.type.UnificationActions;
import edu.kit.typicalc.util.Result; import edu.kit.typicalc.util.Result;
import java.util.ArrayDeque; import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.List;
import java.util.Optional;
/** /**
* Models the unification of a type inference with its individual steps. * Models the unification of a type inference with its individual steps.
@ -82,4 +77,20 @@ public class Unification {
return substitutionsResult; return substitutionsResult;
} }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Unification that = (Unification) o;
return steps.equals(that.steps) && substitutionsResult.equals(that.substitutionsResult);
}
@Override
public int hashCode() {
return Objects.hash(steps, substitutionsResult);
}
} }

View File

@ -8,8 +8,7 @@ import org.junit.jupiter.api.Test;
import java.util.*; import java.util.*;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertThrows;
class TreeTest { class TreeTest {
@ -74,9 +73,9 @@ class TreeTest {
assertEquals(expectedStep, tree.getFirstInferenceStep()); assertEquals(expectedStep, tree.getFirstInferenceStep());
List<Constraint> constraints = new ArrayList<>(); List<Constraint> constraints = new ArrayList<>();
constraints.add(appConstraint);
constraints.add(varLeftConstraint); constraints.add(varLeftConstraint);
constraints.add(varRightConstraint); constraints.add(varRightConstraint);
constraints.add(appConstraint);
assertEquals(constraints, tree.getConstraints()); assertEquals(constraints, tree.getConstraints());
} }
@ -101,8 +100,8 @@ class TreeTest {
assertEquals(expectedStep, tree.getFirstInferenceStep()); assertEquals(expectedStep, tree.getFirstInferenceStep());
List<Constraint> constraints = new ArrayList<>(); List<Constraint> constraints = new ArrayList<>();
constraints.add(varConstraint);
constraints.add(absConstraint); constraints.add(absConstraint);
constraints.add(varConstraint);
assertEquals(constraints, tree.getConstraints()); assertEquals(constraints, tree.getConstraints());
} }
@ -125,4 +124,44 @@ class TreeTest {
assertEquals(expectedStep, tree.getFirstInferenceStep()); assertEquals(expectedStep, tree.getFirstInferenceStep());
assertEquals(Collections.singletonList(constraint), tree.getConstraints()); assertEquals(Collections.singletonList(constraint), tree.getConstraints());
} }
@Test
void visitLet() {
VarTerm x = new VarTerm("x");
VarTerm f = new VarTerm("f");
TypeVariable generated1 = new TypeVariable(TypeVariableKind.GENERATED_TYPE_ASSUMPTION, 1);
TypeVariable variable2 = new TypeVariable(TypeVariableKind.TREE, 2);
TypeVariable variable3 = new TypeVariable(TypeVariableKind.TREE, 3);
TypeAbstraction generated1Abs = new TypeAbstraction(generated1);
Map<VarTerm, TypeAbstraction> typeAssumptions = new LinkedHashMap<>();
typeAssumptions.put(x, generated1Abs);
LetTerm letTerm = new LetTerm(f, x, f);
Tree tree = new Tree(typeAssumptions, letTerm);
TypeVariableFactory refFac = new TypeVariableFactory(TypeVariableKind.TREE);
refFac.nextTypeVariable();
TypeInfererLet typeInfererLet = new TypeInfererLet(x, typeAssumptions, refFac);
Map<VarTerm, TypeAbstraction> varRightTypeAss = new LinkedHashMap<>(typeAssumptions);
varRightTypeAss.put(f, generated1Abs);
Conclusion varRightConclusion = new Conclusion(varRightTypeAss, f, variable3);
Constraint varRightConstraint = new Constraint(variable3, generated1);
InferenceStep varRightStep = new VarStepWithLet(generated1Abs, generated1,
varRightConclusion, varRightConstraint);
Conclusion conclusion = new Conclusion(typeAssumptions, letTerm, tree.getFirstTypeVariable());
Constraint letConstraint = new Constraint(tree.getFirstTypeVariable(), variable3);
InferenceStep expectedStep = new LetStepDefault(conclusion, letConstraint, varRightStep, typeInfererLet);
assertEquals(expectedStep, tree.getFirstInferenceStep());
List<Constraint> constraints = new ArrayList<>();
constraints.add(letConstraint);
constraints.add(new Constraint(variable2, generated1));
constraints.add(varRightConstraint);
assertEquals(constraints, tree.getConstraints());
}
} }

View File

@ -0,0 +1,48 @@
package edu.kit.typicalc.model;
import edu.kit.typicalc.model.step.InferenceStep;
import edu.kit.typicalc.model.step.VarStepWithLet;
import edu.kit.typicalc.model.term.VarTerm;
import edu.kit.typicalc.model.type.TypeAbstraction;
import edu.kit.typicalc.model.type.TypeVariable;
import edu.kit.typicalc.model.type.TypeVariableKind;
import org.junit.jupiter.api.Test;
import java.util.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
class TypeInfererLetTest {
@Test
void createTypeInfererLet() {
VarTerm x = new VarTerm("x");
TypeVariable generated1 = new TypeVariable(TypeVariableKind.GENERATED_TYPE_ASSUMPTION, 1);
TypeVariable variable2 = new TypeVariable(TypeVariableKind.TREE, 2);
TypeAbstraction generated1Abs = new TypeAbstraction(generated1);
Map<VarTerm, TypeAbstraction> typeAssumptions = new LinkedHashMap<>();
typeAssumptions.put(x, generated1Abs);
TypeVariableFactory refFac = new TypeVariableFactory(TypeVariableKind.TREE);
refFac.nextTypeVariable();
TypeInfererLet typeInfererLet = new TypeInfererLet(x, typeAssumptions, refFac);
Conclusion varLeftConclusion = new Conclusion(typeAssumptions, x, variable2);
Constraint varLeftConstraint = new Constraint(variable2, generated1);
InferenceStep varLeftStep = new VarStepWithLet(generated1Abs, generated1,
varLeftConclusion, varLeftConstraint);
assertEquals(varLeftStep, typeInfererLet.getFirstInferenceStep());
assertTrue(typeInfererLet.getType().isPresent());
assertEquals(generated1, typeInfererLet.getType().get());
List<Substitution> expectedMGU
= new ArrayList<>(Collections.singletonList(new Substitution(variable2, generated1)));
assertTrue(typeInfererLet.getMGU().isPresent());
assertEquals(expectedMGU, typeInfererLet.getMGU().get());
List<Constraint> expectedLetConstraints
= new ArrayList<>(Collections.singletonList(new Constraint(variable2, generated1)));
assertEquals(expectedLetConstraints, typeInfererLet.getLetConstraints());
}
}

View File

@ -25,7 +25,8 @@ class LatexCreatorTypeTest {
@Test @Test
void generatedTypeTest() { void generatedTypeTest() {
typeInferer = model.getTypeInferer("x", new HashMap<>()).unwrap(); typeInferer = model.getTypeInferer("x", new HashMap<>()).unwrap();
assertEquals(GENERATED_ASSUMPTION_VARIABLE + "_{1}", new LatexCreatorType(typeInferer.getType().get()).getLatex()); assertEquals(GENERATED_ASSUMPTION_VARIABLE + "_{1}",
new LatexCreatorType(typeInferer.getType().get()).getLatex());
} }
@Test @Test