Skip to content
Snippets Groups Projects
Commit 20bb7c08 authored by Julien Lopez's avatar Julien Lopez
Browse files

Renaming and documentation for type systems

parent da0b0b25
No related branches found
No related tags found
No related merge requests found
......@@ -25,21 +25,23 @@ import qir.types.QIRStringType;
import qir.types.QIRType;
import qir.typing.QIRSpecificTypeSystem;
import qir.typing.QIRTypeErrorException;
import qir.typing.QIRTypeSystemVisitor;
public class QIRSQLTypeSystemVisitor extends QIRSpecificTypeSystem {
public QIRSQLTypeSystemVisitor() {
/**
* The {@link QIRSpecificTypeSystem} for SQL.
*/
public class QIRSQLTypeSystem extends QIRSpecificTypeSystem {
/**
* The {@link QIRSQLTypeSystem} can only have flat records (records containing constants), and
* lists can only contain flat records.
*/
public QIRSQLTypeSystem() {
this(QIRRecordType.anyRestrictedTo(QIRConstantType.ANY));
}
private QIRSQLTypeSystemVisitor(final QIRRecordType anyRelationalRecord) {
private QIRSQLTypeSystem(final QIRRecordType anyRelationalRecord) {
super(anyRelationalRecord, new QIRListType(anyRelationalRecord));
}
public QIRSQLTypeSystemVisitor(final QIRRecordType anyRecordType, final QIRListType anyListType, final QIRTypeSystemVisitor toAccept) {
super(anyRecordType, anyListType, toAccept);
}
@Override
public final QIRType visit(final QIRProject qirProject) {
return visit(qirProject, anyRecordType);
......
package qir.typing;
import qir.types.QIRListType;
import qir.types.QIRRecordType;
/**
* The default {@link QIRSpecificTypeSystem}. It uses the default rules of
* {@link QIRSpecificTypeSystem}.
*/
public class QIRDefaultTypeSystem extends QIRSpecificTypeSystem {
/**
* The {@link QIRDefaultTypeSystem} is a {@link QIRSpecificTypeSystem} working on any type of
* record and any type of list, and that calls the {@link QIRGenericTypeSystem} on
* subexpressions.
*/
private QIRDefaultTypeSystem() {
super(QIRRecordType.ANY, QIRListType.ANY, QIRGenericTypeSystem.getInstance());
}
/**
* The unique representation of the {@link QIRDefaultTypeSystem}.
*/
private static final QIRDefaultTypeSystem instance = new QIRDefaultTypeSystem();
public static final QIRDefaultTypeSystem getInstance() {
return instance;
}
}
package qir.typing;
import qir.types.QIRListType;
import qir.types.QIRRecordType;
public class QIRDefaultTypeSystemVisitor extends QIRSpecificTypeSystem {
private QIRDefaultTypeSystemVisitor() {
super(QIRRecordType.ANY, QIRListType.ANY, QIRGenericTypeSystemVisitor.getInstance());
}
private static final QIRDefaultTypeSystemVisitor instance = new QIRDefaultTypeSystemVisitor();
public static final QIRDefaultTypeSystemVisitor getInstance() {
return instance;
}
}
......@@ -45,19 +45,30 @@ import qir.ast.operator.QIRProject;
import qir.ast.operator.QIRRightJoin;
import qir.ast.operator.QIRScan;
import qir.ast.operator.QIRSortBy;
import qir.driver.sql.QIRSQLTypeSystemVisitor;
import qir.driver.sql.QIRSQLTypeSystem;
import qir.types.QIRType;
import qir.util.QIRException;
public final class QIRGenericTypeSystemVisitor extends QIRTypeSystemVisitor {
private static List<Class<? extends QIRSpecificTypeSystem>> specificTypeSystems = Arrays.asList(QIRSQLTypeSystemVisitor.class);
/**
* The generic {@link QIRTypeSystem} of QIR that can type any QIR expression. It makes use of
* {@link QIRSpecificTypeSystem}s as much as possible, then defaults to the
* {@link QIRDefaultTypeSystem}.
*/
public final class QIRGenericTypeSystem extends QIRTypeSystem {
/**
* The registered {@link QIRSpecificTypeSystem}s used by the {@link QIRGenericTypeSystem}.
*/
private static final List<Class<? extends QIRSpecificTypeSystem>> specificTypeSystems = Arrays.asList(QIRSQLTypeSystem.class);
private QIRGenericTypeSystemVisitor() {
private QIRGenericTypeSystem() {
}
private static final QIRGenericTypeSystemVisitor instance = new QIRGenericTypeSystemVisitor();
/**
* The unique representation of the {@link QIRGenericTypeSystem}.
*/
private static final QIRGenericTypeSystem instance = new QIRGenericTypeSystem();
public static final QIRGenericTypeSystemVisitor getInstance() {
public static final QIRGenericTypeSystem getInstance() {
return instance;
}
......@@ -70,173 +81,173 @@ public final class QIRGenericTypeSystemVisitor extends QIRTypeSystemVisitor {
throw new QIRException("Internal error: " + specificTypeSystem.getName() + " could not be instantiated.");
}
try {
return expr.setType(expr.accept(QIRDefaultTypeSystemVisitor.getInstance()), QIRDefaultTypeSystemVisitor.class);
return expr.setType(expr.accept(QIRDefaultTypeSystem.getInstance()), QIRDefaultTypeSystem.class);
} catch (final QIRTypeErrorException e) {
throw new QIRException("No type system could type " + expr);
}
}
public QIRType visit(QIRProject qirProject) {
public QIRType visit(final QIRProject qirProject) {
return tryTyping(qirProject);
}
public QIRType visit(QIRScan qirScan) {
public QIRType visit(final QIRScan qirScan) {
return tryTyping(qirScan);
}
public QIRType visit(QIRFilter qirFilter) {
public QIRType visit(final QIRFilter qirFilter) {
return tryTyping(qirFilter);
}
public QIRType visit(QIRGroupBy qirGroupBy) {
public QIRType visit(final QIRGroupBy qirGroupBy) {
return tryTyping(qirGroupBy);
}
public QIRType visit(QIRSortBy qirSortBy) {
public QIRType visit(final QIRSortBy qirSortBy) {
return tryTyping(qirSortBy);
}
public QIRType visit(QIRJoin qirJoin) {
public QIRType visit(final QIRJoin qirJoin) {
return tryTyping(qirJoin);
}
public QIRType visit(QIRLeftJoin qirJoin) {
public QIRType visit(final QIRLeftJoin qirJoin) {
return tryTyping(qirJoin);
}
public QIRType visit(QIRRightJoin qirJoin) {
public QIRType visit(final QIRRightJoin qirJoin) {
return tryTyping(qirJoin);
}
public QIRType visit(QIRLimit qirLimit) {
public QIRType visit(final QIRLimit qirLimit) {
return tryTyping(qirLimit);
}
public <DBRepr> QIRType visit(QIRDBNode<DBRepr> qirDBNode) {
public <DBRepr> QIRType visit(final QIRDBNode<DBRepr> qirDBNode) {
return tryTyping(qirDBNode);
}
public QIRType visit(QIRExternal qirExternal) {
public QIRType visit(final QIRExternal qirExternal) {
return tryTyping(qirExternal);
}
public QIRType visit(QIRVariable qirVariable) {
public QIRType visit(final QIRVariable qirVariable) {
return tryTyping(qirVariable);
}
public QIRType visit(QIRLambda qirLambda) {
public QIRType visit(final QIRLambda qirLambda) {
return tryTyping(qirLambda);
}
public QIRType visit(QIRApply qirApply) {
public QIRType visit(final QIRApply qirApply) {
return tryTyping(qirApply);
}
public QIRType visit(QIRIf qirIf) {
public QIRType visit(final QIRIf qirIf) {
return tryTyping(qirIf);
}
public QIRType visit(QIRPlus qirPlus) {
public QIRType visit(final QIRPlus qirPlus) {
return tryTyping(qirPlus);
}
public QIRType visit(QIRMinus qirMinus) {
public QIRType visit(final QIRMinus qirMinus) {
return tryTyping(qirMinus);
}
public QIRType visit(QIRStar qirStar) {
public QIRType visit(final QIRStar qirStar) {
return tryTyping(qirStar);
}
public QIRType visit(QIRDiv qirDiv) {
public QIRType visit(final QIRDiv qirDiv) {
return tryTyping(qirDiv);
}
public QIRType visit(QIRMod qirMod) {
public QIRType visit(final QIRMod qirMod) {
return tryTyping(qirMod);
}
public QIRType visit(QIRAnd qirAnd) {
public QIRType visit(final QIRAnd qirAnd) {
return tryTyping(qirAnd);
}
public QIRType visit(QIROr qirOr) {
public QIRType visit(final QIROr qirOr) {
return tryTyping(qirOr);
}
public QIRType visit(QIREqual qirEqual) {
public QIRType visit(final QIREqual qirEqual) {
return tryTyping(qirEqual);
}
public QIRType visit(QIRLowerOrEqual qirLowerOrEqual) {
public QIRType visit(final QIRLowerOrEqual qirLowerOrEqual) {
return tryTyping(qirLowerOrEqual);
}
public QIRType visit(QIRLowerThan qirLowerThan) {
public QIRType visit(final QIRLowerThan qirLowerThan) {
return tryTyping(qirLowerThan);
}
public QIRType visit(QIRNot qirNot) {
public QIRType visit(final QIRNot qirNot) {
return tryTyping(qirNot);
}
public QIRType visit(QIRTable qirTable) {
public QIRType visit(final QIRTable qirTable) {
return tryTyping(qirTable);
}
public QIRType visit(QIRLnil qirLnil) {
public QIRType visit(final QIRLnil qirLnil) {
return tryTyping(qirLnil);
}
public QIRType visit(QIRLcons qirLcons) {
public QIRType visit(final QIRLcons qirLcons) {
return tryTyping(qirLcons);
}
public QIRType visit(QIRLdestr qirLdestr) {
public QIRType visit(final QIRLdestr qirLdestr) {
return tryTyping(qirLdestr);
}
public QIRType visit(QIRRnil qirTnil) {
public QIRType visit(final QIRRnil qirTnil) {
return tryTyping(qirTnil);
}
public QIRType visit(QIRRcons qirTcons) {
public QIRType visit(final QIRRcons qirTcons) {
return tryTyping(qirTcons);
}
public QIRType visit(QIRRdestr qirTdestr) {
public QIRType visit(final QIRRdestr qirTdestr) {
return tryTyping(qirTdestr);
}
public QIRType visit(QIRString qirString) {
public QIRType visit(final QIRString qirString) {
return tryTyping(qirString);
}
public QIRType visit(QIRNumber qirNumber) {
public QIRType visit(final QIRNumber qirNumber) {
return tryTyping(qirNumber);
}
public QIRType visit(QIRBigNumber qirBigNumber) {
public QIRType visit(final QIRBigNumber qirBigNumber) {
return tryTyping(qirBigNumber);
}
public QIRType visit(QIRDouble qirDouble) {
public QIRType visit(final QIRDouble qirDouble) {
return tryTyping(qirDouble);
}
public QIRType visit(QIRBoolean qirBoolean) {
public QIRType visit(final QIRBoolean qirBoolean) {
return tryTyping(qirBoolean);
}
public QIRType visit(QIRNull qirNull) {
public QIRType visit(final QIRNull qirNull) {
return tryTyping(qirNull);
}
public QIRType visit(QIRExportableTruffleNode qirTruffleNode) {
public QIRType visit(final QIRExportableTruffleNode qirTruffleNode) {
return tryTyping(qirTruffleNode);
}
public QIRType visit(QIRUnexportableTruffleNode qirTruffleNode) {
public QIRType visit(final QIRUnexportableTruffleNode qirTruffleNode) {
return tryTyping(qirTruffleNode);
}
}
......@@ -58,40 +58,113 @@ import qir.types.QIRSomeType;
import qir.types.QIRStringType;
import qir.types.QIRType;
public abstract class QIRSpecificTypeSystem extends QIRTypeSystemVisitor {
/**
* A {@link QIRSpecificTypeSystem} is a {@link QIRTypeSystem} that types QIR expressions compatible
* with a specific database language.
*/
public abstract class QIRSpecificTypeSystem extends QIRTypeSystem {
/**
* An environment to store the {@link QIRType}s of variables in an expression.
*/
protected final Map<String, QIRType> env = new HashMap<>();
/**
* The generic {@link QIRType} of a record in the language.
*/
protected final QIRRecordType anyRecordType;
/**
* The generic {@link QIRType} of a list in the language.
*/
protected final QIRListType anyListType;
protected final QIRTypeSystemVisitor toAccept;
/**
* The {@link QIRTypeSystem} to call recursively on subexpressions.
*/
protected final QIRTypeSystem toAccept;
/**
* A {@link QIRSpecificTypeSystem} that calls itself recursively on subexpressions. This is the
* most usual type of {@link QIRSpecificTypeSystem}.
*
* @param anyRecordType The generic {@link QIRType} of a record for this
* {@link QIRSpecificTypeSystem}.
* @param anyListType The generic {@link QIRType} of a list for this
* {@link QIRSpecificTypeSystem}.
*/
public QIRSpecificTypeSystem(final QIRRecordType anyRecordType, final QIRListType anyListType) {
this.anyRecordType = anyRecordType;
this.anyListType = anyListType;
this.toAccept = this;
}
public QIRSpecificTypeSystem(final QIRRecordType anyRecordType, final QIRListType anyListType, final QIRTypeSystemVisitor toAccept) {
/**
* A {@link QIRSpecificTypeSystem} that calls another {@link QIRSpecificTypeSystem} recursively
* on subexpressions.
*
* @param anyRecordType The generic {@link QIRType} of a record for this
* {@link QIRSpecificTypeSystem}.
* @param anyListType The generic {@link QIRType} of a list for this
* {@link QIRSpecificTypeSystem}.
* @param toAccept The {@link QIRTypeSystem} to call recursively on subexpressions.
*/
public QIRSpecificTypeSystem(final QIRRecordType anyRecordType, final QIRListType anyListType, final QIRTypeSystem toAccept) {
this.anyRecordType = anyRecordType;
this.anyListType = anyListType;
this.toAccept = toAccept;
}
protected void checkSubtype(final QIRType actual, final QIRType expected) {
/**
* Throws a {@link QIRTypeErrorException} if the actual {@link QIRType} is not a subtype of the
* expected {@link QIRType} in the sense of {@link QIRType#isSubtypeOf(QIRType)}.
*
* @param actual The actual {@link QIRType} of the expression.
* @param expected The expected {@link QIRType} for the expression.
* @throws QIRTypeErrorException The expression thrown if the actual {@link QIRType} is not a
* subtype of the expected {@link QIRType}.
*/
protected void checkSubtype(final QIRType actual, final QIRType expected) throws QIRTypeErrorException {
if (!actual.isSubtypeOf(expected))
throw new QIRTypeErrorException(this.getClass(), expected, actual);
}
/**
* Returns the actual {@link QIRType} with the type of the expected {@link QIRType} if the
* actual {@link QIRType} is a subtype of the expected {@link QIRType} in the sense of
* {@link QIRType#isSubtypeOf(QIRType)}.
*
* @param actual The actual {@link QIRType} of the expression.
* @param expected The expected {@link QIRType} for the expression.
* @return The actual {@link QIRType} with the type of the expected {@link QIRType}.
*/
@SuppressWarnings("unchecked")
protected <U extends QIRType> U expectIfSubtype(final QIRType actual, final U expected) {
checkSubtype(actual, expected);
return (U) (actual instanceof QIRSomeType ? ((QIRSomeType) actual).getInferedType() : actual);
}
/**
* Throws a {@link QIRTypeErrorException} if the actual {@link QIRType} and the expected
* {@link QIRType} do not share a common subtype in the sense of
* {@link QIRType#isSubtypeOf(QIRType)}.
*
* @param actual The actual {@link QIRType} of the expression.
* @param expected The expected {@link QIRType} for the expression.
* @throws QIRTypeErrorException The expression thrown if the actual {@link QIRType} and the
* expected {@link QIRType} do not share a common subtype in the sense of
* {@link QIRType#isSubtypeOf(QIRType)}.
*/
protected void checkCommonType(final QIRType actual, final QIRType expected) {
if (!actual.isSubtypeOf(expected) && !expected.isSubtypeOf(actual))
throw new QIRTypeErrorException(this.getClass(), expected, actual);
}
/**
* Returns the actual {@link QIRType} with the type of the expected {@link QIRType} if the
* actual {@link QIRType} and the expected {@link QIRType} share a common subtype in the sense
* of {@link QIRType#isSubtypeOf(QIRType)}.
*
* @param actual The actual {@link QIRType} of the expression.
* @param expected The expected {@link QIRType} for the expression.
* @return The actual {@link QIRType} with the type of the expected {@link QIRType}.
*/
protected QIRType expectCommonType(final QIRType actual, final QIRType expected) {
if (actual.isSubtypeOf(expected))
return expected;
......
......@@ -9,26 +9,61 @@ import qir.types.QIRRecordType;
import qir.types.QIRType;
import qir.util.QIRException;
/**
* An exception that can be thrown by a {@link QIRTypeSystem}.
*/
public class QIRTypeErrorException extends QIRException {
private static final long serialVersionUID = 2089121923670702478L;
public QIRTypeErrorException(final Class<?> typer, final QIRType expected, final QIRType actual) {
/**
* A mismatch between an expected type and the actual type of an expression.
*
* @param typer The instance of {@link QIRTypeSystem} throwing the exception.
* @param expected The expected type for the expression.
* @param actual The actual type of the expression.
*/
public QIRTypeErrorException(final Class<? extends QIRTypeSystem> typer, final QIRType expected, final QIRType actual) {
super(typer.getName() + " type error. Expected: " + expected + ", got: " + actual);
}
public QIRTypeErrorException(final Class<?> typer, final QIRType[] expected, final QIRType actual) {
/**
* A mismatch between possible expected types and the actual type of an expression.
*
* @param typer The instance of {@link QIRTypeSystem} throwing the exception.
* @param expected The possible expected types for the expression.
* @param actual The actual type of the expression.
*/
public QIRTypeErrorException(final Class<? extends QIRTypeSystem> typer, final QIRType[] expected, final QIRType actual) {
super(typer.getName() + " type error. Expected: " + Arrays.stream(expected).map(Object::toString).collect(Collectors.joining(" or ")) + ", got: " + actual);
}
public QIRTypeErrorException(final Class<?> typer, final QIRNode unknown) {
/**
* An expression that cannot be typed.
*
* @param typer The instance of {@link QIRTypeSystem} throwing the exception.
* @param unknown The expression that cannot be typed.
*/
public QIRTypeErrorException(final Class<? extends QIRTypeSystem> typer, final QIRNode unknown) {
super(typer.getName() + " could not type unknown expression " + unknown);
}
public QIRTypeErrorException(final Class<?> typer, final QIRVariable freeVariable) {
/**
* A free variable that cannot be typed.
*
* @param typer The instance of {@link QIRTypeSystem} throwing the exception.
* @param unknown The free variable that cannot be typed.
*/
public QIRTypeErrorException(final Class<? extends QIRTypeSystem> typer, final QIRVariable freeVariable) {
super(typer.getName() + " could not type free variable " + freeVariable);
}
public QIRTypeErrorException(final Class<?> typer, final QIRRecordType recordType, final String unknownColName) {
super(typer.getName() + " could not type column name " + unknownColName + " in record type " + recordType);
/**
* A record field that cannot be typed.
*
* @param typer The instance of {@link QIRTypeSystem} throwing the exception.
* @param unknown The record field that cannot be typed.
*/
public QIRTypeErrorException(final Class<? extends QIRTypeSystem> typer, final QIRRecordType recordType, final String unknownField) {
super(typer.getName() + " could not type field " + unknownField + " in record type " + recordType);
}
}
......@@ -3,5 +3,8 @@ package qir.typing;
import qir.driver.IQIRVisitor;
import qir.types.QIRType;
public abstract class QIRTypeSystemVisitor implements IQIRVisitor<QIRType> {
/**
* {@link QIRTypeSystem} represents any type system on a QIR expression.
*/
public abstract class QIRTypeSystem implements IQIRVisitor<QIRType> {
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment