Implement quantified variables in type assumptions

see issue #1
This commit is contained in:
Arne Keller 2021-06-17 08:45:28 +02:00
parent 7736a12b8d
commit b55c63acc0
3 changed files with 28 additions and 5 deletions

View File

@ -52,7 +52,11 @@ public class Tree implements TermVisitorTree {
this.typeVarFactory = typeVariableFactory; this.typeVarFactory = typeVariableFactory;
this.constraints = new ArrayList<>(); this.constraints = new ArrayList<>();
this.stepFactory = lambdaTerm.hasLet() || partOfLetTerm ? new StepFactoryWithLet() : new StepFactoryDefault(); // quantified type assumptions have the same effect as let terms
// (both require VarStepWithLet)
this.stepFactory = typeAssumptions.entrySet().stream()
.anyMatch(entry -> entry.getValue().hasQuantifiedVariables())
|| lambdaTerm.hasLet() || partOfLetTerm ? new StepFactoryWithLet() : new StepFactoryDefault();
this.failedSubInference = false; this.failedSubInference = false;

View File

@ -36,7 +36,7 @@ public class TypeAssumptionParser {
return new Result<>(null, ParseError.UNEXPECTED_CHARACTER); return new Result<>(null, ParseError.UNEXPECTED_CHARACTER);
} }
VarTerm var = new VarTerm(typeName); VarTerm var = new VarTerm(typeName);
Result<TypeAbstraction, ParseError> typeAbs = parseType(entry.getValue()); Result<TypeAbstraction, ParseError> typeAbs = parseTypeDefinition(entry.getValue());
if (typeAbs.isError()) { if (typeAbs.isError()) {
return new Result<>(typeAbs); return new Result<>(typeAbs);
} }
@ -45,14 +45,33 @@ public class TypeAssumptionParser {
return new Result<>(typeAssumptions); return new Result<>(typeAssumptions);
} }
public Result<TypeAbstraction, ParseError> parseType(String type) { /**
* Parse a type definition that may use the all quantor.
* @param definition type definition
* @return parsed type
*/
public Result<TypeAbstraction, ParseError> parseTypeDefinition(String definition) {
Set<TypeVariable> allQuantified = new HashSet<>();
// TODO: clarify syntax, this just (barely) accepts a comma separated list of t<number>
if (definition.startsWith("")) {
String[] parts = definition.split(":", 2);
for (String quantified : parts[0].substring(1).split(",")) {
int i = Integer.parseInt(quantified.trim().substring(1));
allQuantified.add(new TypeVariable(TypeVariableKind.USER_INPUT, i));
}
definition = parts[1];
}
return parseType(definition, allQuantified);
}
private Result<TypeAbstraction, ParseError> parseType(String type, Set<TypeVariable> allQuantified) {
// this parser is using the same lexer as the LambdaParser (to avoid types named "let" etc.) // this parser is using the same lexer as the LambdaParser (to avoid types named "let" etc.)
LambdaLexer lexer = new LambdaLexer(type); LambdaLexer lexer = new LambdaLexer(type);
Result<Pair<Type, Integer>, ParseError> parsedType = parseType(lexer, 0); Result<Pair<Type, Integer>, ParseError> parsedType = parseType(lexer, 0);
if (parsedType.isError()) { if (parsedType.isError()) {
return new Result<>(null, parsedType.unwrapError()); return new Result<>(null, parsedType.unwrapError());
} }
return new Result<>(new TypeAbstraction(parsedType.unwrap().getLeft())); return new Result<>(new TypeAbstraction(parsedType.unwrap().getLeft(), allQuantified));
} }
private Result<Pair<Type, Integer>, ParseError> parseType(LambdaLexer lexer, int parenCount) { private Result<Pair<Type, Integer>, ParseError> parseType(LambdaLexer lexer, int parenCount) {

View File

@ -109,7 +109,7 @@ public class TypeAssumptionField extends HorizontalLayout implements LocaleChang
* @return true if the type matches the syntax, false if not * @return true if the type matches the syntax, false if not
*/ */
protected boolean hasCorrectType(String type) { protected boolean hasCorrectType(String type) {
return parser.parseType(parseBackType(type)).isOk(); return parser.parseTypeDefinition(parseBackType(type)).isOk();
} }
private void addValidator() { private void addValidator() {