mirror of
https://gitlab.kit.edu/uskyk/typicalc.git
synced 2024-11-08 18:30:42 +00:00
Correctly scope variables in type assumptions
This commit is contained in:
parent
394b5a3d23
commit
1b70e374ac
@ -213,7 +213,7 @@ public class TypeAssumptionParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// attempt to parse as type
|
// attempt to parse as type
|
||||||
ParserResult<Type> result = new ParseTypeState1().handle(t);
|
ParserResult<Type> result = new ParseTypeState1(alreadyParsed.size()).handle(t);
|
||||||
if (result.isError()) {
|
if (result.isError()) {
|
||||||
return result.castError();
|
return result.castError();
|
||||||
}
|
}
|
||||||
@ -254,6 +254,15 @@ public class TypeAssumptionParser {
|
|||||||
private int parenthesisInitial = 0;
|
private int parenthesisInitial = 0;
|
||||||
private int openParens = 0;
|
private int openParens = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attached to any parsed type variables.
|
||||||
|
*/
|
||||||
|
private final int typeVariableUniqueIndex;
|
||||||
|
|
||||||
|
ParseTypeState1(int typeVariableUniqueIndex) {
|
||||||
|
this.typeVariableUniqueIndex = typeVariableUniqueIndex;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ParserResult<Type> handle(Token t) {
|
public ParserResult<Type> handle(Token t) {
|
||||||
switch (t.getType()) {
|
switch (t.getType()) {
|
||||||
@ -284,7 +293,7 @@ public class TypeAssumptionParser {
|
|||||||
.withToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
.withToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||||
}
|
}
|
||||||
// parse function type
|
// parse function type
|
||||||
state = Optional.of(new ParseTypeStateExpectArrow().handle(t).getState());
|
state = Optional.of(new ParseTypeStateExpectArrow(typeVariableUniqueIndex).handle(t).getState());
|
||||||
return new ParserResult<>(this);
|
return new ParserResult<>(this);
|
||||||
case LEFT_PARENTHESIS:
|
case LEFT_PARENTHESIS:
|
||||||
openParens += 1;
|
openParens += 1;
|
||||||
@ -294,7 +303,7 @@ public class TypeAssumptionParser {
|
|||||||
if (stateParenthesis.isPresent()) {
|
if (stateParenthesis.isPresent()) {
|
||||||
return handleInnerParenthesis(t);
|
return handleInnerParenthesis(t);
|
||||||
}
|
}
|
||||||
stateParenthesis = Optional.of(new ParseTypeState1());
|
stateParenthesis = Optional.of(new ParseTypeState1(typeVariableUniqueIndex));
|
||||||
parenthesisInitial = openParens - 1;
|
parenthesisInitial = openParens - 1;
|
||||||
return new ParserResult<>(this);
|
return new ParserResult<>(this);
|
||||||
case RIGHT_PARENTHESIS:
|
case RIGHT_PARENTHESIS:
|
||||||
@ -372,11 +381,13 @@ public class TypeAssumptionParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Type parseLiteral(String text) {
|
private Type parseLiteral(String text) {
|
||||||
Matcher typeVariableMatcher = TYPE_VARIABLE_PATTERN.matcher(text);
|
Matcher typeVariableMatcher = TYPE_VARIABLE_PATTERN.matcher(text);
|
||||||
if (typeVariableMatcher.matches()) {
|
if (typeVariableMatcher.matches()) {
|
||||||
int typeVariableIndex = Integer.parseInt(typeVariableMatcher.group(1));
|
int typeVariableIndex = Integer.parseInt(typeVariableMatcher.group(1));
|
||||||
return new TypeVariable(TypeVariableKind.USER_INPUT, typeVariableIndex);
|
TypeVariable var = new TypeVariable(TypeVariableKind.USER_INPUT, typeVariableIndex);
|
||||||
|
var.setUniqueIndex(typeVariableUniqueIndex);
|
||||||
|
return var;
|
||||||
} else {
|
} else {
|
||||||
return new NamedType(text);
|
return new NamedType(text);
|
||||||
}
|
}
|
||||||
@ -386,13 +397,22 @@ public class TypeAssumptionParser {
|
|||||||
private static class ParseTypeStateExpectArrow implements ParserState<Type> {
|
private static class ParseTypeStateExpectArrow implements ParserState<Type> {
|
||||||
private Optional<ParserState<Type>> state = Optional.empty();
|
private Optional<ParserState<Type>> state = Optional.empty();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attached to any parsed type variables.
|
||||||
|
*/
|
||||||
|
private final int typeVariableUniqueIndex;
|
||||||
|
|
||||||
|
ParseTypeStateExpectArrow(int typeVariableUniqueIndex) {
|
||||||
|
this.typeVariableUniqueIndex = typeVariableUniqueIndex;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ParserResult<Type> handle(Token t) {
|
public ParserResult<Type> handle(Token t) {
|
||||||
switch (t.getType()) {
|
switch (t.getType()) {
|
||||||
case ARROW:
|
case ARROW:
|
||||||
if (state.isEmpty()) {
|
if (state.isEmpty()) {
|
||||||
// try parsing remainder as type
|
// try parsing remainder as type
|
||||||
state = Optional.of(new ParseTypeState1());
|
state = Optional.of(new ParseTypeState1(typeVariableUniqueIndex));
|
||||||
return new ParserResult<>(this);
|
return new ParserResult<>(this);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -446,6 +466,7 @@ public class TypeAssumptionParser {
|
|||||||
return new ParserResult<>(ParseError.UNEXPECTED_TOKEN
|
return new ParserResult<>(ParseError.UNEXPECTED_TOKEN
|
||||||
.withToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
.withToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||||
}
|
}
|
||||||
|
variable.setUniqueIndex(alreadyParsed.size());
|
||||||
variables.add(variable);
|
variables.add(variable);
|
||||||
expectCommaOrDot = true;
|
expectCommaOrDot = true;
|
||||||
return new ParserResult<>(this);
|
return new ParserResult<>(this);
|
||||||
|
@ -13,6 +13,11 @@ public class TypeVariable extends Type implements Comparable<TypeVariable> {
|
|||||||
private final TypeVariableKind kind;
|
private final TypeVariableKind kind;
|
||||||
private final int index;
|
private final int index;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The same type variable can be universally quantified multiple times, but this index will differ.
|
||||||
|
*/
|
||||||
|
private int uniqueIndex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a new TypeVariable with the given index.
|
* Initializes a new TypeVariable with the given index.
|
||||||
*
|
*
|
||||||
@ -42,6 +47,14 @@ public class TypeVariable extends Type implements Comparable<TypeVariable> {
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setUniqueIndex(int uniqueIndex) {
|
||||||
|
this.uniqueIndex = uniqueIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUniqueIndex() {
|
||||||
|
return uniqueIndex;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether some type occurs in this type.
|
* Checks whether some type occurs in this type.
|
||||||
*
|
*
|
||||||
|
@ -239,6 +239,24 @@ class TypeAssumptionParserTest {
|
|||||||
assertEquals(10, error.getCause().get().getPos());
|
assertEquals(10, error.getCause().get().getPos());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void correctlyScopesQuantifiedTypeVariables() {
|
||||||
|
TypeAssumptionParser parser = new TypeAssumptionParser();
|
||||||
|
Result<Map<VarTerm, TypeAbstraction>, ParseError> type =
|
||||||
|
parser.parse("id: ∀ t1 . t1 -> t1, fun: ∀t1,t2.t1->t2 ");
|
||||||
|
assertTrue(type.isOk());
|
||||||
|
Map<VarTerm, TypeAbstraction> res = type.unwrap();
|
||||||
|
TypeAbstraction id = res.get(new VarTerm("id"));
|
||||||
|
TypeVariable[] idVariables = id.getQuantifiedVariables().toArray(new TypeVariable[0]);
|
||||||
|
assertEquals(0, idVariables[0].getUniqueIndex());
|
||||||
|
TypeAbstraction fun = res.get(new VarTerm("fun"));
|
||||||
|
TypeVariable[] funVariables = fun.getQuantifiedVariables().toArray(new TypeVariable[0]);
|
||||||
|
assertEquals(1, funVariables[0].getUniqueIndex());
|
||||||
|
assertEquals(1, funVariables[1].getUniqueIndex());
|
||||||
|
assertEquals(1, ((TypeVariable) ((FunctionType) fun.getInnerType()).getParameter()).getUniqueIndex());
|
||||||
|
assertEquals(1, ((TypeVariable) ((FunctionType) fun.getInnerType()).getOutput()).getUniqueIndex());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void errors() {
|
void errors() {
|
||||||
Map<String, ParseError> tests = new HashMap<>();
|
Map<String, ParseError> tests = new HashMap<>();
|
||||||
|
Loading…
Reference in New Issue
Block a user