diff --git a/src/qir/ast/QIRLambda.java b/src/qir/ast/QIRLambda.java index b7f27bdd89c8c24aa8044941e3e46b29633c9f92..48c9046a5bd7c5056b8a3aea799384063d15a271 100644 --- a/src/qir/ast/QIRLambda.java +++ b/src/qir/ast/QIRLambda.java @@ -8,7 +8,7 @@ import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.source.SourceSection; import qir.driver.IQIRVisitor; -import qir.types.QIRConstantType; +import qir.types.QIRAnyType; import qir.types.QIRType; import qir.util.QIRAny; @@ -45,7 +45,7 @@ public final class QIRLambda extends QIRNode { } public QIRLambda(final SourceSection source, final String funName, final QIRVariable var, final QIRNode body, final FrameDescriptor frameDescr) { - this(source, funName, QIRConstantType.ANY, var, body, frameDescr); + this(source, funName, QIRAnyType.getInstance(), var, body, frameDescr); } public final String getFunName() { diff --git a/src/qir/ast/data/QIRRdestr.java b/src/qir/ast/data/QIRRdestr.java index 5752f1aa2ce66c57ab8ffa2f333eea11f50dea9e..70a26a85b2783b111224f84cf506c898316df80b 100644 --- a/src/qir/ast/data/QIRRdestr.java +++ b/src/qir/ast/data/QIRRdestr.java @@ -15,20 +15,20 @@ public final class QIRRdestr extends QIRNode { /** * The {@link QIRRecord} to access. */ - @Child private QIRNode tuple; + @Child private QIRNode record; /** * The name of the field to look for in the {@link QIRRecord}. */ private final String colName; - public QIRRdestr(final SourceSection source, final QIRNode tuple, final String colName) { + public QIRRdestr(final SourceSection source, final QIRNode record, final String colName) { super(source); - this.tuple = tuple; + this.record = record; this.colName = colName; } - public final QIRNode getTuple() { - return tuple; + public final QIRNode getRecord() { + return record; } public final String getColName() { @@ -37,7 +37,7 @@ public final class QIRRdestr extends QIRNode { @Override public final String toString() { - return tuple + "." + colName; + return record + "." + colName; } @Override @@ -46,12 +46,12 @@ public final class QIRRdestr extends QIRNode { return true; if (!(other instanceof QIRRdestr)) return false; - return tuple.equals(((QIRRdestr) other).tuple) && colName.equals(((QIRRdestr) other).colName); + return record.equals(((QIRRdestr) other).record) && colName.equals(((QIRRdestr) other).colName); } @Override public QIRNode executeGeneric(VirtualFrame frame) { - QIRNode t = tuple.executeGeneric(frame); + QIRNode t = record.executeGeneric(frame); // TODO: Should we allow this in QIR? if (t instanceof QIRLcons && ((QIRLcons) t).getTail() == QIRLnil.getInstance()) diff --git a/src/qir/ast/operator/QIRSortBy.java b/src/qir/ast/operator/QIRSortBy.java index 2d3c9bf77627fe4038f1528d97a0cdbfbf273b4b..2b012f03a72b9d12fdb2b7c3187b9be4e2013a3b 100644 --- a/src/qir/ast/operator/QIRSortBy.java +++ b/src/qir/ast/operator/QIRSortBy.java @@ -13,11 +13,11 @@ import qir.util.QIRException; */ public final class QIRSortBy extends QIROperator { /** - * The list of ordering rows. + * The list of sorting rows. */ - private final QIRNode order; + private final QIRNode sort; /** - * A list of booleans telling for every row of {@link QIRSortBy#order} if it is ascending. + * A list of booleans telling for every row of {@link QIRSortBy#sort} if it is ascending. */ private final QIRNode isAscending; /** @@ -25,15 +25,15 @@ public final class QIRSortBy extends QIROperator { */ private final QIRNode child; - public QIRSortBy(final SourceSection source, final QIRNode order, final QIRNode isAscending, final QIRNode child) { + public QIRSortBy(final SourceSection source, final QIRNode sort, final QIRNode isAscending, final QIRNode child) { super(source); - this.order = order; + this.sort = sort; this.isAscending = isAscending; this.child = child; } - public final QIRNode getOrder() { - return order; + public final QIRNode getSort() { + return sort; } public final QIRNode getIsAscending() { @@ -46,7 +46,7 @@ public final class QIRSortBy extends QIROperator { @Override public final String toString() { - return "SortBy(" + order + ", " + isAscending + ", " + child + ")"; + return "SortBy(" + sort + ", " + isAscending + ", " + child + ")"; } @Override @@ -55,7 +55,7 @@ public final class QIRSortBy extends QIROperator { return true; if (!(other instanceof QIRSortBy)) return false; - return order.equals(((QIRSortBy) other).order) && isAscending.equals(((QIRSortBy) other).isAscending) && child.equals(((QIRSortBy) other).child); + return sort.equals(((QIRSortBy) other).sort) && isAscending.equals(((QIRSortBy) other).isAscending) && child.equals(((QIRSortBy) other).child); } @Override diff --git a/src/qir/driver/IQIRVisitor.java b/src/qir/driver/IQIRVisitor.java index 5eef74d3ac92009b45385f712b49f9f207f85a37..ad6cdf4c2e6f488a95d7e16b2b4eeb8d69d15b51 100644 --- a/src/qir/driver/IQIRVisitor.java +++ b/src/qir/driver/IQIRVisitor.java @@ -22,9 +22,9 @@ public interface IQIRVisitor<T> { public abstract T visit(final QIRFilter qirFilter); - public abstract T visit(final QIRGroupBy qirGroup); + public abstract T visit(final QIRGroupBy qirGroupBy); - public abstract T visit(final QIRSortBy qirOrder); + public abstract T visit(final QIRSortBy qirSortBy); public abstract T visit(final QIRJoin qirJoin); diff --git a/src/qir/driver/QIRDriver.java b/src/qir/driver/QIRDriver.java index cbc67eac1fa84b46f91eddb665afec721ca3d3d4..980de17b3b371d4d531fdb70695008d7cd1b6361 100644 --- a/src/qir/driver/QIRDriver.java +++ b/src/qir/driver/QIRDriver.java @@ -14,16 +14,18 @@ import qir.ast.QIRVariable; */ public class QIRDriver { /** - * Executes a QIR query. First, the query is normalized using the {@link QIRGreedyNormalizationVisitor} - * module, then the query is translated by the {@link QIRGenericTranslationVisitor} module into a query written - * in the different languages understandable by the different data providers, finally it is run by - * the {@link QIREvaluationVisitor} module. + * Executes a QIR query. First, the query is normalized using the + * {@link QIRGreedyNormalizationVisitor} module, then the query is translated by the + * {@link QIRGenericTranslationVisitor} module into a query written in the different languages + * understandable by the different data providers, finally it is run by the + * {@link QIREvaluationVisitor} module. * * @param query The QIR query to execute * @return The results of the query */ public static final QIRNode run(final QIRNode query) { - return query.accept(new QIRGreedyNormalizationVisitor()).accept(QIRGenericTranslationVisitor.instance).executeGeneric(Truffle.getRuntime().createVirtualFrame(new Object[]{}, new FrameDescriptor())); + return query.accept(new QIRGreedyNormalizationVisitor()).accept(QIRGenericTranslationVisitor.instance).executeGeneric( + Truffle.getRuntime().createVirtualFrame(new Object[]{}, new FrameDescriptor())); } /** diff --git a/src/qir/driver/QIRFreeVarsVisitor.java b/src/qir/driver/QIRFreeVarsVisitor.java index 9ec947751f167501e64d1b4c692ba96b37b5e3e8..f33c814d94f38a7903f2f8cfee7ebe7b77091dc1 100644 --- a/src/qir/driver/QIRFreeVarsVisitor.java +++ b/src/qir/driver/QIRFreeVarsVisitor.java @@ -37,16 +37,16 @@ final class QIRFreeVarsVisitor implements IQIRVisitor<Map<String, QIRVariable>> } @Override - public final Map<String, QIRVariable> visit(final QIRGroupBy qirGroup) { - qirGroup.getGroup().accept(this); - return qirGroup.getChild().accept(this); + public final Map<String, QIRVariable> visit(final QIRGroupBy qirGroupBy) { + qirGroupBy.getGroup().accept(this); + return qirGroupBy.getChild().accept(this); } @Override - public final Map<String, QIRVariable> visit(final QIRSortBy qirOrder) { - qirOrder.getOrder().accept(this); - qirOrder.getIsAscending().accept(this); - return qirOrder.getChild().accept(this); + public final Map<String, QIRVariable> visit(final QIRSortBy qirSortBy) { + qirSortBy.getSort().accept(this); + qirSortBy.getIsAscending().accept(this); + return qirSortBy.getChild().accept(this); } @Override @@ -212,7 +212,7 @@ final class QIRFreeVarsVisitor implements IQIRVisitor<Map<String, QIRVariable>> @Override public final Map<String, QIRVariable> visit(final QIRRdestr qirTdestr) { - return qirTdestr.getTuple().accept(this); + return qirTdestr.getRecord().accept(this); } @Override diff --git a/src/qir/driver/QIRGenericTranslationVisitor.java b/src/qir/driver/QIRGenericTranslationVisitor.java index 0f4cfa3d0448fdc71b487ce8d14c91a8f7f096a8..bfc522df6f27497ad3c238d8674a5d5db1057e6c 100644 --- a/src/qir/driver/QIRGenericTranslationVisitor.java +++ b/src/qir/driver/QIRGenericTranslationVisitor.java @@ -10,7 +10,8 @@ import qir.ast.operator.*; import qir.util.QIRException; /** - * {@link QIRGenericTranslationVisitor} represents the translation from QIR to an executable QIR tree. + * {@link QIRGenericTranslationVisitor} represents the translation from QIR to an executable QIR + * tree. */ final class QIRGenericTranslationVisitor implements IQIRVisitor<QIRNode> { private QIRGenericTranslationVisitor() { @@ -53,27 +54,28 @@ final class QIRGenericTranslationVisitor implements IQIRVisitor<QIRNode> { } @Override - public final QIRNode visit(final QIRGroupBy qirGroup) { - final QIRNode child = qirGroup.getChild().accept(this); + public final QIRNode visit(final QIRGroupBy qirGroupBy) { + final QIRNode child = qirGroupBy.getChild().accept(this); if (child instanceof QIRDBNode) try { - return new QIRDBNode<>(child.getSourceSection(), ((QIRDBNode<?>) child).getDriver(), new QIRGroupBy(qirGroup.getSourceSection(), qirGroup.getGroup(), child)); + return new QIRDBNode<>(child.getSourceSection(), ((QIRDBNode<?>) child).getDriver(), new QIRGroupBy(qirGroupBy.getSourceSection(), qirGroupBy.getGroup(), child)); } catch (QIRException e) { } - return new QIRGroupBy(qirGroup.getSourceSection(), qirGroup.getGroup().accept(this), child); + return new QIRGroupBy(qirGroupBy.getSourceSection(), qirGroupBy.getGroup().accept(this), child); } @Override - public final QIRNode visit(final QIRSortBy qirOrder) { - final QIRNode child = qirOrder.getChild().accept(this); + public final QIRNode visit(final QIRSortBy qirSortBy) { + final QIRNode child = qirSortBy.getChild().accept(this); if (child instanceof QIRDBNode) try { - return new QIRDBNode<>(child.getSourceSection(), ((QIRDBNode<?>) child).getDriver(), new QIRSortBy(qirOrder.getSourceSection(), qirOrder.getOrder(), qirOrder.getIsAscending(), child)); + return new QIRDBNode<>(child.getSourceSection(), ((QIRDBNode<?>) child).getDriver(), + new QIRSortBy(qirSortBy.getSourceSection(), qirSortBy.getSort(), qirSortBy.getIsAscending(), child)); } catch (QIRException e) { } - return new QIRSortBy(qirOrder.getSourceSection(), qirOrder.getOrder().accept(this), qirOrder.getIsAscending().accept(this), child); + return new QIRSortBy(qirSortBy.getSourceSection(), qirSortBy.getSort().accept(this), qirSortBy.getIsAscending().accept(this), child); } @Override @@ -245,7 +247,7 @@ final class QIRGenericTranslationVisitor implements IQIRVisitor<QIRNode> { @Override public final QIRNode visit(final QIRRdestr qirTdestr) { - return new QIRRdestr(qirTdestr.getSourceSection(), qirTdestr.getTuple().accept(this), qirTdestr.getColName()); + return new QIRRdestr(qirTdestr.getSourceSection(), qirTdestr.getRecord().accept(this), qirTdestr.getColName()); } @Override diff --git a/src/qir/driver/QIRGreedyNormalizationVisitor.java b/src/qir/driver/QIRGreedyNormalizationVisitor.java index 53abed5fc7f38c80f000ad76b3058300912a3295..a6888a341f422194ff05dd81d6ac766be6b990e8 100644 --- a/src/qir/driver/QIRGreedyNormalizationVisitor.java +++ b/src/qir/driver/QIRGreedyNormalizationVisitor.java @@ -11,8 +11,8 @@ import qir.ast.expression.relational.*; import qir.ast.operator.*; /** - * {@link QIRGreedyNormalizationVisitor} is the QIR greedy normalization module. TODO: Check behavior if - * reduction fails, especially in ldestr. + * {@link QIRGreedyNormalizationVisitor} is the QIR greedy normalization module. TODO: Check + * behavior if reduction fails, especially in ldestr. */ final class QIRGreedyNormalizationVisitor implements IQIRVisitor<QIRNode> { private final HashMap<String, QIRNode> env = new HashMap<>(); @@ -33,13 +33,13 @@ final class QIRGreedyNormalizationVisitor implements IQIRVisitor<QIRNode> { } @Override - public final QIRNode visit(final QIRGroupBy qirGroup) { - return new QIRGroupBy(qirGroup.getSourceSection(), qirGroup.getGroup().accept(this), qirGroup.getChild().accept(this)); + public final QIRNode visit(final QIRGroupBy qirGroupBy) { + return new QIRGroupBy(qirGroupBy.getSourceSection(), qirGroupBy.getGroup().accept(this), qirGroupBy.getChild().accept(this)); } @Override - public final QIRNode visit(final QIRSortBy qirOrder) { - return new QIRSortBy(qirOrder.getSourceSection(), qirOrder.getOrder().accept(this), qirOrder.getIsAscending().accept(this), qirOrder.getChild().accept(this)); + public final QIRNode visit(final QIRSortBy qirSortBy) { + return new QIRSortBy(qirSortBy.getSourceSection(), qirSortBy.getSort().accept(this), qirSortBy.getIsAscending().accept(this), qirSortBy.getChild().accept(this)); } @Override @@ -235,7 +235,7 @@ final class QIRGreedyNormalizationVisitor implements IQIRVisitor<QIRNode> { @Override public final QIRNode visit(final QIRRdestr qirTdestr) { - final QIRNode tuple = qirTdestr.getTuple().accept(this); + final QIRNode tuple = qirTdestr.getRecord().accept(this); final String colName = qirTdestr.getColName(); for (QIRNode current = tuple; current instanceof QIRRcons; current = ((QIRRcons) current).getTail()) diff --git a/src/qir/driver/QIRTranslator.java b/src/qir/driver/QIRTranslator.java index 8bc3539c7f59361d89cbb9ca7b77375b17b0d4cd..e89b1707a10ee647074c5bbefaaf3dc74ee32523 100644 --- a/src/qir/driver/QIRTranslator.java +++ b/src/qir/driver/QIRTranslator.java @@ -32,13 +32,13 @@ public abstract class QIRTranslator<T> implements IQIRVisitor<T> { } @Override - public T visit(final QIRGroupBy qirGroup) { - throw new QIRException(this.getClass().getSimpleName() + " error: unsupported QIR node " + qirGroup.getClass().getSimpleName() + "."); + public T visit(final QIRGroupBy qirGroupBy) { + throw new QIRException(this.getClass().getSimpleName() + " error: unsupported QIR node " + qirGroupBy.getClass().getSimpleName() + "."); } @Override - public T visit(final QIRSortBy qirOrder) { - throw new QIRException(this.getClass().getSimpleName() + " error: unsupported QIR node " + qirOrder.getClass().getSimpleName() + "."); + public T visit(final QIRSortBy qirSortBy) { + throw new QIRException(this.getClass().getSimpleName() + " error: unsupported QIR node " + qirSortBy.getClass().getSimpleName() + "."); } @Override diff --git a/src/qir/driver/hbase/QIRHBaseQueryVisitor.java b/src/qir/driver/hbase/QIRHBaseQueryVisitor.java index 5bd5cc90ac799314109fd8e1aef48ffb3ebb36cd..44e859b221e5e4e4bf642cbdd8914c893a60310e 100644 --- a/src/qir/driver/hbase/QIRHBaseQueryVisitor.java +++ b/src/qir/driver/hbase/QIRHBaseQueryVisitor.java @@ -78,12 +78,12 @@ final class QIRHBaseQueryVisitor extends QIRTranslator<HBaseQuery> { } @Override - public final HBaseQuery visit(QIRGroupBy qirGroup) { - if (!(qirGroup.getGroup() instanceof QIRLambda)) - throw new QIRException("QIR HBase Group not implemented for group type: " + qirGroup.getGroup().getClass()); - if (!(qirGroup.getChild() instanceof QIRProject)) + public final HBaseQuery visit(QIRGroupBy qirGroupBy) { + if (!(qirGroupBy.getGroup() instanceof QIRLambda)) + throw new QIRException("QIR HBase Group not implemented for group type: " + qirGroupBy.getGroup().getClass()); + if (!(qirGroupBy.getChild() instanceof QIRProject)) throw new QIRException("Invalid QIR HBase Group"); - final HBaseQuery child = qirGroup.getChild().accept(this); + final HBaseQuery child = qirGroupBy.getChild().accept(this); final Job job; try { job = Job.getInstance(conf); diff --git a/src/qir/driver/sql/QIRHiveStringVisitor.java b/src/qir/driver/sql/QIRHiveStringVisitor.java index 0260ae5f796ad813672ab9287e99f01a109a313d..17ef16fcadda0acaa1784f4ea0e28b12e926b613 100644 --- a/src/qir/driver/sql/QIRHiveStringVisitor.java +++ b/src/qir/driver/sql/QIRHiveStringVisitor.java @@ -84,7 +84,7 @@ public class QIRHiveStringVisitor extends QIRSQLStringVisitor { @Override public final String visit(final QIRRdestr qirTdestr) { - QIRNode tuple = qirTdestr.getTuple(); + QIRNode tuple = qirTdestr.getRecord(); if (tuple instanceof QIROperator) throw new QIRException("Invalid subquery in Hive."); diff --git a/src/qir/driver/sql/QIRSQLStringVisitor.java b/src/qir/driver/sql/QIRSQLStringVisitor.java index 33f1a42beed765dab369ef4e5da886a01c6f9199..61557dbcda8b18e5fa9d605666b06a9cc1a19d66 100644 --- a/src/qir/driver/sql/QIRSQLStringVisitor.java +++ b/src/qir/driver/sql/QIRSQLStringVisitor.java @@ -83,25 +83,25 @@ class QIRSQLStringVisitor extends QIRTranslator<String> { } @Override - public final String visit(final QIRGroupBy qirGroup) { - if (qirGroup.getGroup() instanceof QIRLambda) - return qirGroup.getChild().accept(this) + " group by " + ((QIRLambda) qirGroup.getGroup()).getBody().accept(this); - throw new QIRException("QIR SQL GroupBy not implemented for group type: " + qirGroup.getGroup().getClass()); + public final String visit(final QIRGroupBy qirGroupBy) { + if (qirGroupBy.getGroup() instanceof QIRLambda) + return qirGroupBy.getChild().accept(this) + " group by " + ((QIRLambda) qirGroupBy.getGroup()).getBody().accept(this); + throw new QIRException("QIR SQL GroupBy not implemented for group type: " + qirGroupBy.getGroup().getClass()); } @Override - public final String visit(final QIRSortBy qirOrder) { - if (qirOrder.getOrder() instanceof QIRLambda && ((QIRLambda) qirOrder.getOrder()).getBody() instanceof QIRLcons && qirOrder.getIsAscending() instanceof QIRLambda && - ((QIRLambda) qirOrder.getIsAscending()).getBody() instanceof QIRLcons) { - QIRNode rows = ((QIRLambda) qirOrder.getOrder()).getBody(); - QIRNode ascs = ((QIRLambda) qirOrder.getIsAscending()).getBody(); + public final String visit(final QIRSortBy qirSortBy) { + if (qirSortBy.getSort() instanceof QIRLambda && ((QIRLambda) qirSortBy.getSort()).getBody() instanceof QIRLcons && qirSortBy.getIsAscending() instanceof QIRLambda && + ((QIRLambda) qirSortBy.getIsAscending()).getBody() instanceof QIRLcons) { + QIRNode rows = ((QIRLambda) qirSortBy.getSort()).getBody(); + QIRNode ascs = ((QIRLambda) qirSortBy.getIsAscending()).getBody(); String o = ((QIRLcons) rows).getValue().accept(this) + (((QIRLcons) ascs).getValue().equals(QIRBoolean.TRUE) ? "" : " desc"); for (rows = ((QIRLcons) rows).getTail(), ascs = ((QIRLcons) ascs).getTail(); rows instanceof QIRLcons; rows = ((QIRLcons) rows).getTail(), ascs = ((QIRLcons) ascs).getTail()) o += ", " + ((QIRLcons) rows).getValue().accept(this) + (((QIRLcons) ascs).getValue().equals(QIRBoolean.TRUE) ? "" : " desc"); - return "select * from (" + qirOrder.getChild().accept(this) + ") as " + ((QIRLambda) qirOrder.getOrder()).getVar().accept(this) + " order by " + o; + return "select * from (" + qirSortBy.getChild().accept(this) + ") as " + ((QIRLambda) qirSortBy.getSort()).getVar().accept(this) + " order by " + o; } - throw new QIRException("QIR SQL OrderBy not implemented for: " + qirOrder.getOrder().getClass() + " and " + qirOrder.getIsAscending().getClass()); + throw new QIRException("QIR SQL SortBy not implemented for: " + qirSortBy.getSort().getClass() + " and " + qirSortBy.getIsAscending().getClass()); } @Override @@ -332,7 +332,7 @@ class QIRSQLStringVisitor extends QIRTranslator<String> { @Override public String visit(final QIRRdestr qirTdestr) { - QIRNode tuple = qirTdestr.getTuple(); + QIRNode tuple = qirTdestr.getRecord(); if (tuple instanceof QIRVariable) return qirTdestr.toString(); diff --git a/src/qir/parser/Parser.frame b/src/qir/parser/Parser.frame index d66a70ae4b57f7e74c2baf26133e515c707af9a8..aa301329d98cae04157ba26ff93b32a4ef60ff29 100644 --- a/src/qir/parser/Parser.frame +++ b/src/qir/parser/Parser.frame @@ -32,7 +32,6 @@ import java.util.List; import java.util.ArrayList; import java.util.Map; import java.util.HashMap; -import java.util.Arrays; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.source.Source; diff --git a/src/qir/parser/Parser.java b/src/qir/parser/Parser.java index cfc86b4228880a60f4634edca0257ff83dddf07e..74920a97a7e89b2dddf3cceae1bc708e0b1b0a62 100644 --- a/src/qir/parser/Parser.java +++ b/src/qir/parser/Parser.java @@ -5,7 +5,6 @@ import java.util.List; import java.util.ArrayList; import java.util.Map; import java.util.HashMap; -import java.util.Arrays; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.source.Source; @@ -26,7 +25,7 @@ public class Parser { public static final int _stringLiteral = 2; public static final int _numberLiteral = 3; public static final int _doubleLiteral = 4; - public static final int maxT = 59; + public static final int maxT = 58; static final boolean _T = true; static final boolean _x = false; @@ -283,32 +282,32 @@ public class Parser { res = result; break; } - case 40: { + case 39: { QIRList result = Listcons(); res = result; break; } - case 42: { + case 41: { QIRLdestr result = Listdestr(); res = result; break; } - case 45: { + case 44: { QIRExternal result = External(); res = result; break; } - case 46: { + case 45: { QIRTable result = Table(); res = result; break; } - case 47: { + case 46: { QIRBigNumber result = Bignumber(); res = result; break; } - case 48: case 49: { + case 47: case 48: { QIRBoolean result = Boolean(); res = result; break; @@ -323,7 +322,7 @@ public class Parser { res = result; break; } - case 50: { + case 49: { QIRNull result = Null(); res = result; break; @@ -352,42 +351,42 @@ public class Parser { res = new ExternalOperator(srcFromToken(srcToken), opName.val, args); break; } - case 51: { + case 50: { QIRProject result = Project(); res = result; break; } - case 52: { + case 51: { QIRScan result = Scan(); res = result; break; } - case 53: { + case 52: { QIRFilter result = Filter(); res = result; break; } - case 54: { + case 53: { QIRGroupBy result = Groupby(); res = result; break; } - case 55: { + case 54: { QIRSortBy result = Sortby(); res = result; break; } - case 56: { + case 55: { QIRJoin result = Join(); res = result; break; } - case 57: { + case 56: { QIRLeftJoin result = Leftjoin(); res = result; break; } - case 58: { + case 57: { QIRRightJoin result = Rightjoin(); res = result; break; @@ -398,7 +397,7 @@ public class Parser { Expect(20); break; } - default: SynErr(60); break; + default: SynErr(59); break; } return res; } @@ -415,7 +414,7 @@ public class Parser { Expect(21); final Token srcToken = t; Token funName = null; - QIRType type = new QIRFunctionType(Arrays.asList(QIRConstantType.ANY, QIRConstantType.ANY)); + QIRType type = new QIRFunctionType(new QIRType[]{QIRAnyType.getInstance()}, QIRAnyType.getInstance()); if (la.kind == 22) { Get(); Expect(1); @@ -451,7 +450,7 @@ public class Parser { res = QIRRnil.getInstance(); final Token srcToken = t; Token idToken; - QIRType type = QIRConstantType.ANY; + QIRType type = QIRAnyType.getInstance(); if (la.kind == 1) { Get(); idToken = t; @@ -478,9 +477,9 @@ public class Parser { QIRList Listcons() { QIRList res; - Expect(40); + Expect(39); res = QIRLnil.getInstance(); - QIRType type = QIRConstantType.ANY; + QIRType type = QIRAnyType.getInstance(); final Token srcToken = t; if (StartOf(1)) { QIRNode value = QIR(); @@ -491,7 +490,7 @@ public class Parser { res = new QIRLcons(srcFromToken(srcToken), value, res); } } - Expect(41); + Expect(40); if (la.kind == 23) { Get(); type = ListType(); @@ -502,11 +501,11 @@ public class Parser { QIRLdestr Listdestr() { QIRLdestr res; - Expect(42); + Expect(41); final Token srcToken = t; QIRNode list = QIR(); + Expect(42); Expect(43); - Expect(44); Expect(24); QIRNode ifEmpty = QIR(); Expect(27); @@ -519,7 +518,7 @@ public class Parser { QIRExternal External() { QIRExternal res; - Expect(45); + Expect(44); final Token srcToken = t; Expect(1); final Token eName = t; @@ -530,7 +529,7 @@ public class Parser { QIRTable Table() { QIRTable res; - Expect(46); + Expect(45); final Token srcToken = t; QIRNode tableName = QIR(); Expect(19); @@ -546,7 +545,7 @@ public class Parser { QIRBigNumber Bignumber() { QIRBigNumber res; - Expect(47); + Expect(46); final Token srcToken = t; Expect(3); final Token number = t; @@ -558,13 +557,13 @@ public class Parser { QIRBoolean Boolean() { QIRBoolean res; res = null; - if (la.kind == 48) { + if (la.kind == 47) { Get(); res = QIRBoolean.TRUE; - } else if (la.kind == 49) { + } else if (la.kind == 48) { Get(); res = QIRBoolean.FALSE; - } else SynErr(61); + } else SynErr(60); return res; } @@ -584,7 +583,7 @@ public class Parser { QIRNull Null() { QIRNull res; - Expect(50); + Expect(49); res = QIRNull.getInstance(); return res; } @@ -598,7 +597,7 @@ public class Parser { QIRProject Project() { QIRProject res; - Expect(51); + Expect(50); final Token srcToken = t; QIRNode formatter = QIR(); Expect(19); @@ -610,7 +609,7 @@ public class Parser { QIRScan Scan() { QIRScan res; - Expect(52); + Expect(51); final Token srcToken = t; QIRNode child = QIR(); Expect(20); @@ -620,7 +619,7 @@ public class Parser { QIRFilter Filter() { QIRFilter res; - Expect(53); + Expect(52); final Token srcToken = t; QIRNode filter = QIR(); Expect(19); @@ -632,7 +631,7 @@ public class Parser { QIRGroupBy Groupby() { QIRGroupBy res; - Expect(54); + Expect(53); final Token srcToken = t; QIRNode group = QIR(); Expect(19); @@ -644,21 +643,21 @@ public class Parser { QIRSortBy Sortby() { QIRSortBy res; - Expect(55); + Expect(54); final Token srcToken = t; - QIRNode order = QIR(); + QIRNode sort = QIR(); Expect(19); QIRNode isAscending = QIR(); Expect(19); QIRNode child = QIR(); Expect(20); - res = new QIRSortBy(srcFromToken(srcToken), order, isAscending, child); + res = new QIRSortBy(srcFromToken(srcToken), sort, isAscending, child); return res; } QIRJoin Join() { QIRJoin res; - Expect(56); + Expect(55); final Token srcToken = t; QIRNode filter = QIR(); Expect(19); @@ -672,7 +671,7 @@ public class Parser { QIRLeftJoin Leftjoin() { QIRLeftJoin res; - Expect(57); + Expect(56); final Token srcToken = t; QIRNode filter = QIR(); Expect(19); @@ -686,7 +685,7 @@ public class Parser { QIRRightJoin Rightjoin() { QIRRightJoin res; - Expect(58); + Expect(57); final Token srcToken = t; QIRNode filter = QIR(); Expect(19); @@ -709,7 +708,7 @@ public class Parser { QIRType type = NonFunctionType(); types.add(type); } - res = types.size() == 1 ? first : new QIRFunctionType(types); + res = types.size() == 1 ? first : new QIRFunctionType(types.subList(0, types.size() - 1).toArray(new QIRType[types.size() - 1]), types.get(types.size() - 1)); return res; } @@ -744,13 +743,13 @@ public class Parser { res = ConstantType(); } else if (la.kind == 28) { res = RecordType(); - } else if (la.kind == 39) { + } else if (la.kind == 38) { res = ListType(); } else if (la.kind == 18) { Get(); res = Type(); Expect(20); - } else SynErr(62); + } else SynErr(61); return res; } @@ -760,50 +759,45 @@ public class Parser { switch (la.kind) { case 32: { Get(); - res = QIRConstantType.ANY; + res = QIRAnyType.getInstance(); break; } case 33: { Get(); - res = QIRConstantType.NUMBER; + res = QIRNumberType.getInstance(); break; } case 34: { Get(); - res = QIRConstantType.BIG_NUMBER; + res = QIRBigNumberType.getInstance(); break; } case 35: { Get(); - res = QIRConstantType.DOUBLE; + res = QIRDoubleType.getInstance(); break; } case 36: { Get(); - res = QIRConstantType.BOOLEAN; + res = QIRBooleanType.getInstance(); break; } case 37: { Get(); - res = QIRConstantType.STRING; - break; - } - case 38: { - Get(); - res = QIRConstantType.NULL; + res = QIRStringType.getInstance(); break; } - default: SynErr(63); break; + default: SynErr(62); break; } return res; } QIRListType ListType() { QIRListType res; + Expect(38); Expect(39); - Expect(40); QIRType type = Type(); - Expect(41); + Expect(40); res = new QIRListType(type); return res; } @@ -822,9 +816,9 @@ public class Parser { } private static final boolean[][] set = { - {_T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x}, - {_x,_T,_T,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_T, _x,_x,_T,_x, _x,_T,_x,_x, _x,_T,_x,_x, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _T,_x,_T,_x, _x,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_x, _x}, - {_x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _T,_T,_T,_T, _T,_T,_T,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x} + {_T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x}, + {_x,_T,_T,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_T, _x,_x,_T,_x, _x,_T,_x,_x, _x,_T,_x,_x, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _x,_T,_x,_x, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_x,_x}, + {_x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _T,_T,_T,_T, _T,_T,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x} }; @@ -895,32 +889,31 @@ class Errors { case 35: s = "\"double\" expected"; break; case 36: s = "\"bool\" expected"; break; case 37: s = "\"string\" expected"; break; - case 38: s = "\"null\" expected"; break; - case 39: s = "\"list\" expected"; break; - case 40: s = "\"[\" expected"; break; - case 41: s = "\"]\" expected"; break; - case 42: s = "\"match\" expected"; break; - case 43: s = "\"with\" expected"; break; - case 44: s = "\"empty\" expected"; break; - case 45: s = "\"External(\" expected"; break; - case 46: s = "\"Table(\" expected"; break; - case 47: s = "\"BigNumber(\" expected"; break; - case 48: s = "\"true\" expected"; break; - case 49: s = "\"false\" expected"; break; - case 50: s = "\"NULL\" expected"; break; - case 51: s = "\"%Project(\" expected"; break; - case 52: s = "\"%Scan(\" expected"; break; - case 53: s = "\"%Filter(\" expected"; break; - case 54: s = "\"%GroupBy(\" expected"; break; - case 55: s = "\"%SortBy(\" expected"; break; - case 56: s = "\"%Join(\" expected"; break; - case 57: s = "\"%LeftJoin(\" expected"; break; - case 58: s = "\"%RightJoin(\" expected"; break; - case 59: s = "??? expected"; break; - case 60: s = "invalid Expression"; break; - case 61: s = "invalid Boolean"; break; - case 62: s = "invalid NonFunctionType"; break; - case 63: s = "invalid ConstantType"; break; + case 38: s = "\"list\" expected"; break; + case 39: s = "\"[\" expected"; break; + case 40: s = "\"]\" expected"; break; + case 41: s = "\"match\" expected"; break; + case 42: s = "\"with\" expected"; break; + case 43: s = "\"empty\" expected"; break; + case 44: s = "\"External(\" expected"; break; + case 45: s = "\"Table(\" expected"; break; + case 46: s = "\"BigNumber(\" expected"; break; + case 47: s = "\"true\" expected"; break; + case 48: s = "\"false\" expected"; break; + case 49: s = "\"NULL\" expected"; break; + case 50: s = "\"%Project(\" expected"; break; + case 51: s = "\"%Scan(\" expected"; break; + case 52: s = "\"%Filter(\" expected"; break; + case 53: s = "\"%GroupBy(\" expected"; break; + case 54: s = "\"%SortBy(\" expected"; break; + case 55: s = "\"%Join(\" expected"; break; + case 56: s = "\"%LeftJoin(\" expected"; break; + case 57: s = "\"%RightJoin(\" expected"; break; + case 58: s = "??? expected"; break; + case 59: s = "invalid Expression"; break; + case 60: s = "invalid Boolean"; break; + case 61: s = "invalid NonFunctionType"; break; + case 62: s = "invalid ConstantType"; break; default: s = "error " + n; break; } printMsg(line, col, s); diff --git a/src/qir/parser/Scanner.java b/src/qir/parser/Scanner.java index ae6983c1eaa22f5dd26566dc6a1f13a0cde62390..e379b5987a5cb12a3ecb8a8be1232efc6f385523 100644 --- a/src/qir/parser/Scanner.java +++ b/src/qir/parser/Scanner.java @@ -253,8 +253,8 @@ class StartStates { public class Scanner { static final char EOL = '\n'; static final int eofSym = 0; - static final int maxT = 59; - static final int noSym = 59; + static final int maxT = 58; + static final int noSym = 58; public Buffer buffer; // scanner buffer @@ -323,14 +323,13 @@ public class Scanner { literals.put("double", new Integer(35)); literals.put("bool", new Integer(36)); literals.put("string", new Integer(37)); - literals.put("null", new Integer(38)); - literals.put("list", new Integer(39)); - literals.put("match", new Integer(42)); - literals.put("with", new Integer(43)); - literals.put("empty", new Integer(44)); - literals.put("true", new Integer(48)); - literals.put("false", new Integer(49)); - literals.put("NULL", new Integer(50)); + literals.put("list", new Integer(38)); + literals.put("match", new Integer(41)); + literals.put("with", new Integer(42)); + literals.put("empty", new Integer(43)); + literals.put("true", new Integer(47)); + literals.put("false", new Integer(48)); + literals.put("NULL", new Integer(49)); } @@ -554,15 +553,15 @@ public class Scanner { case 33: {t.kind = 31; break loop;} case 34: - {t.kind = 40; break loop;} + {t.kind = 39; break loop;} case 35: - {t.kind = 41; break loop;} + {t.kind = 40; break loop;} case 36: - {t.kind = 45; break loop;} + {t.kind = 44; break loop;} case 37: - {t.kind = 46; break loop;} + {t.kind = 45; break loop;} case 38: - {t.kind = 47; break loop;} + {t.kind = 46; break loop;} case 39: if (ch == 'r') {AddCh(); state = 40; break;} else {state = 0; break;} @@ -585,7 +584,7 @@ public class Scanner { if (ch == '(') {AddCh(); state = 46; break;} else {state = 0; break;} case 46: - {t.kind = 51; break loop;} + {t.kind = 50; break loop;} case 47: if (ch == 'a') {AddCh(); state = 48; break;} else {state = 0; break;} @@ -596,7 +595,7 @@ public class Scanner { if (ch == '(') {AddCh(); state = 50; break;} else {state = 0; break;} case 50: - {t.kind = 52; break loop;} + {t.kind = 51; break loop;} case 51: if (ch == 'i') {AddCh(); state = 52; break;} else {state = 0; break;} @@ -616,7 +615,7 @@ public class Scanner { if (ch == '(') {AddCh(); state = 57; break;} else {state = 0; break;} case 57: - {t.kind = 53; break loop;} + {t.kind = 52; break loop;} case 58: if (ch == 'r') {AddCh(); state = 59; break;} else {state = 0; break;} @@ -639,7 +638,7 @@ public class Scanner { if (ch == '(') {AddCh(); state = 65; break;} else {state = 0; break;} case 65: - {t.kind = 54; break loop;} + {t.kind = 53; break loop;} case 66: if (ch == 'r') {AddCh(); state = 67; break;} else {state = 0; break;} @@ -656,7 +655,7 @@ public class Scanner { if (ch == '(') {AddCh(); state = 71; break;} else {state = 0; break;} case 71: - {t.kind = 55; break loop;} + {t.kind = 54; break loop;} case 72: if (ch == 'o') {AddCh(); state = 73; break;} else {state = 0; break;} @@ -670,7 +669,7 @@ public class Scanner { if (ch == '(') {AddCh(); state = 76; break;} else {state = 0; break;} case 76: - {t.kind = 56; break loop;} + {t.kind = 55; break loop;} case 77: if (ch == 'e') {AddCh(); state = 78; break;} else {state = 0; break;} @@ -696,7 +695,7 @@ public class Scanner { if (ch == '(') {AddCh(); state = 85; break;} else {state = 0; break;} case 85: - {t.kind = 57; break loop;} + {t.kind = 56; break loop;} case 86: if (ch == 'i') {AddCh(); state = 87; break;} else {state = 0; break;} @@ -725,7 +724,7 @@ public class Scanner { if (ch == '(') {AddCh(); state = 95; break;} else {state = 0; break;} case 95: - {t.kind = 58; break loop;} + {t.kind = 57; break loop;} case 96: recEnd = pos; recKind = 11; if (ch >= '1' && ch <= '9') {AddCh(); state = 12; break;} diff --git a/src/qir/parser/qir.atg b/src/qir/parser/qir.atg index b9e35ee272ad9aad91c9b2b5a45cd5f1e42d55cc..2934101c9ef59ace663d3a7751d17ee16306a35d 100644 --- a/src/qir/parser/qir.atg +++ b/src/qir/parser/qir.atg @@ -153,7 +153,7 @@ identifier (. res = new QIRVariable(srcFromToken(t), t.val); .) Lambda<out QIRLambda res> = "fun" (. final Token srcToken = t; Token funName = null; - QIRType type = new QIRFunctionType(Arrays.asList(QIRConstantType.ANY, QIRConstantType.ANY)); .) + QIRType type = new QIRFunctionType(new QIRType[]{QIRAnyType.getInstance()}, QIRAnyType.getInstance()); .) [ "#" identifier (. funName = t; .) ] [ ":" Type<out type> ] Variable<out QIRVariable var> "->" QIR<out QIRNode body> (. res = new QIRLambda(srcFromToken(srcToken), funName == null ? null : funName.val, type, var, body, new FrameDescriptor()); .) @@ -169,7 +169,7 @@ Tuplecons<out QIRRecord res> = "{" (. res = QIRRnil.getInstance(); final Token srcToken = t; Token idToken; - QIRType type = QIRConstantType.ANY; .) + QIRType type = QIRAnyType.getInstance(); .) [ identifier (. idToken = t; .) "=" QIR<out QIRNode value> (. res = new QIRRcons(srcFromToken(srcToken), idToken.val, value, res); .) @@ -184,7 +184,7 @@ Type<out QIRType res> = (. res = null; .) NonFunctionType<out QIRType first> (. final List<QIRType> types = new ArrayList<>(); types.add(first); .) { "->" NonFunctionType<out QIRType type> (. types.add(type); .) -} (. res = types.size() == 1 ? first : new QIRFunctionType(types); .) +} (. res = types.size() == 1 ? first : new QIRFunctionType(types.subList(0, types.size() - 1).toArray(new QIRType[types.size() - 1]), types.get(types.size() - 1)); .) ) . @@ -199,13 +199,12 @@ ConstantType<out res> ConstantType<out QIRType res> = (. res = null; .) ( -"any" (. res = QIRConstantType.ANY; .) -| "int" (. res = QIRConstantType.NUMBER; .) -| "big_int" (. res = QIRConstantType.BIG_NUMBER; .) -| "double" (. res = QIRConstantType.DOUBLE; .) -| "bool" (. res = QIRConstantType.BOOLEAN; .) -| "string" (. res = QIRConstantType.STRING; .) -| "null" (. res = QIRConstantType.NULL; .) +"any" (. res = QIRAnyType.getInstance(); .) +| "int" (. res = QIRNumberType.getInstance(); .) +| "big_int" (. res = QIRBigNumberType.getInstance(); .) +| "double" (. res = QIRDoubleType.getInstance(); .) +| "bool" (. res = QIRBooleanType.getInstance(); .) +| "string" (. res = QIRStringType.getInstance(); .) ) . @@ -226,7 +225,7 @@ ListType<out QIRListType res> = Listcons<out QIRList res> = "[" (. res = QIRLnil.getInstance(); - QIRType type = QIRConstantType.ANY; + QIRType type = QIRAnyType.getInstance(); final Token srcToken = t; .) [ QIR<out QIRNode value> (. res = new QIRLcons(srcFromToken(srcToken), value, res); .) @@ -305,8 +304,8 @@ QIR<out QIRNode group> "," QIR<out QIRNode child> ')' (. res = new QIRGroup Sortby<out QIRSortBy res> = "%SortBy(" (. final Token srcToken = t; .) -QIR<out QIRNode order> "," QIR<out QIRNode isAscending> -"," QIR<out QIRNode child> ')' (. res = new QIRSortBy(srcFromToken(srcToken), order, isAscending, child); .) +QIR<out QIRNode sort> "," QIR<out QIRNode isAscending> +"," QIR<out QIRNode child> ')' (. res = new QIRSortBy(srcFromToken(srcToken), sort, isAscending, child); .) . Join<out QIRJoin res> = diff --git a/src/qir/types/QIRAnyType.java b/src/qir/types/QIRAnyType.java new file mode 100644 index 0000000000000000000000000000000000000000..962ccd597a1c06505d1d951dd6e41ea605caeee8 --- /dev/null +++ b/src/qir/types/QIRAnyType.java @@ -0,0 +1,22 @@ +package qir.types; + +public class QIRAnyType extends QIRType { + protected QIRAnyType() { + } + + private static final QIRAnyType instance = new QIRAnyType(); + + public static final QIRAnyType getInstance() { + return instance; + } + + @Override + public String toString() { + return "Any"; + } + + @Override + protected boolean isSubtypeOfSpecific(final QIRType other) { + return other == instance; + } +} diff --git a/src/qir/types/QIRBigNumberType.java b/src/qir/types/QIRBigNumberType.java new file mode 100644 index 0000000000000000000000000000000000000000..892d596ea6e82136f0b852d15d80b82f515d8f23 --- /dev/null +++ b/src/qir/types/QIRBigNumberType.java @@ -0,0 +1,17 @@ +package qir.types; + +public class QIRBigNumberType extends QIRConstantType { + private QIRBigNumberType() { + } + + private static final QIRBigNumberType instance = new QIRBigNumberType(); + + public static final QIRBigNumberType getInstance() { + return instance; + } + + @Override + public String toString() { + return "BigNumber"; + } +} diff --git a/src/qir/types/QIRBooleanType.java b/src/qir/types/QIRBooleanType.java new file mode 100644 index 0000000000000000000000000000000000000000..7105515a05989cf0e2509df102371b86be40bf38 --- /dev/null +++ b/src/qir/types/QIRBooleanType.java @@ -0,0 +1,17 @@ +package qir.types; + +public class QIRBooleanType extends QIRConstantType { + private QIRBooleanType() { + } + + private static final QIRBooleanType instance = new QIRBooleanType(); + + public static final QIRBooleanType getInstance() { + return instance; + } + + @Override + public String toString() { + return "Boolean"; + } +} diff --git a/src/qir/types/QIRBottomType.java b/src/qir/types/QIRBottomType.java new file mode 100644 index 0000000000000000000000000000000000000000..1e7e8083e245b890b1280f5f548dc537d7ddbe20 --- /dev/null +++ b/src/qir/types/QIRBottomType.java @@ -0,0 +1,22 @@ +package qir.types; + +public class QIRBottomType extends QIRType { + private QIRBottomType() { + } + + private static final QIRBottomType instance = new QIRBottomType(); + + public static final QIRBottomType getInstance() { + return instance; + } + + @Override + public String toString() { + return "Bottom"; + } + + @Override + protected boolean isSubtypeOfSpecific(final QIRType other) { + return true; + } +} diff --git a/src/qir/types/QIRConstantType.java b/src/qir/types/QIRConstantType.java index 38e2f67541847a6ba9a66dea16180979f31c5e9a..52142c029084c91ca4314014d129eee188d92c22 100644 --- a/src/qir/types/QIRConstantType.java +++ b/src/qir/types/QIRConstantType.java @@ -1,11 +1,8 @@ package qir.types; -public enum QIRConstantType implements QIRType { - ANY, - NUMBER, - BIG_NUMBER, - DOUBLE, - BOOLEAN, - STRING, - NULL +public abstract class QIRConstantType extends QIRType { + @Override + protected final boolean isSubtypeOfSpecific(final QIRType other) { + return this == other; + } } diff --git a/src/qir/types/QIRDoubleType.java b/src/qir/types/QIRDoubleType.java new file mode 100644 index 0000000000000000000000000000000000000000..6852b979c55731014ea1d2157a28917a11acee08 --- /dev/null +++ b/src/qir/types/QIRDoubleType.java @@ -0,0 +1,17 @@ +package qir.types; + +public class QIRDoubleType extends QIRConstantType { + private QIRDoubleType() { + } + + private static final QIRDoubleType instance = new QIRDoubleType(); + + public static final QIRDoubleType getInstance() { + return instance; + } + + @Override + public String toString() { + return "Double"; + } +} diff --git a/src/qir/types/QIRFunctionType.java b/src/qir/types/QIRFunctionType.java index d48fea9f06307a20b2cde018ab833d184172821b..3104e5a3953d4c0194c66623d266aa8f99f9758b 100644 --- a/src/qir/types/QIRFunctionType.java +++ b/src/qir/types/QIRFunctionType.java @@ -1,22 +1,46 @@ package qir.types; -import java.util.ArrayList; -import java.util.List; +import java.util.Arrays; import java.util.stream.Collectors; -public final class QIRFunctionType implements QIRType { - private final List<QIRType> types; +public final class QIRFunctionType extends QIRType { + private final QIRType[] domain; + private final QIRType returnType; - public QIRFunctionType(final List<QIRType> types) { - this.types = types; + public QIRFunctionType(final QIRType[] domain, final QIRType returnType) { + this.domain = domain; + this.returnType = returnType; } - public final List<QIRType> getDomain() { - return types.size() > 0 ? types.subList(0, types.size() - 1) : new ArrayList<>(); + public static final QIRFunctionType ANY(final int domainSize) { + QIRType[] domain = new QIRType[domainSize]; + Arrays.fill(domain, QIRAnyType.getInstance()); + return new QIRFunctionType(domain, QIRAnyType.getInstance()); + } + + public final QIRType[] getDomain() { + return domain; + } + + public final QIRType getReturnType() { + return returnType; } @Override public final String toString() { - return types.stream().map(Object::toString).collect(Collectors.joining(" -> ")); + return Arrays.stream(domain).map(Object::toString).collect(Collectors.joining(" -> ")) + " -> " + returnType; + } + + @Override + protected final boolean isSubtypeOfSpecific(final QIRType other) { + if (!(other instanceof QIRFunctionType)) + return false; + final QIRFunctionType o = (QIRFunctionType) other; + if (domain.length != o.domain.length) + return false; + for (int i = 0; i < domain.length; i++) + if (!domain[i].isSubtypeOf(o.domain[i])) + return false; + return returnType.isSubtypeOf(o.returnType); } } diff --git a/src/qir/types/QIRListType.java b/src/qir/types/QIRListType.java index 8db46f2b4288ed4f142aedb1f208567e1d4a6475..e8fdaaa82eb356e78edc0c974228f1dc47d2b7c4 100644 --- a/src/qir/types/QIRListType.java +++ b/src/qir/types/QIRListType.java @@ -1,14 +1,25 @@ package qir.types; -public class QIRListType implements QIRType { - private QIRType type; +public class QIRListType extends QIRType { + private QIRType elementType; - public QIRListType(final QIRType type) { - this.type = type; + public QIRListType(final QIRType elementType) { + this.elementType = elementType; + } + + public static final QIRListType ANY = new QIRListType(QIRAnyType.getInstance()); + + public final QIRType getElementType() { + return elementType; } @Override public final String toString() { - return type + " list"; + return elementType + " list"; + } + + @Override + protected boolean isSubtypeOfSpecific(final QIRType other) { + return other instanceof QIRListType && elementType.isSubtypeOf(((QIRListType) other).elementType); } } diff --git a/src/qir/types/QIRNumberType.java b/src/qir/types/QIRNumberType.java new file mode 100644 index 0000000000000000000000000000000000000000..00b4e7899d8017459c6adc163997c181760e8f5b --- /dev/null +++ b/src/qir/types/QIRNumberType.java @@ -0,0 +1,17 @@ +package qir.types; + +public class QIRNumberType extends QIRConstantType { + private QIRNumberType() { + } + + private static final QIRNumberType instance = new QIRNumberType(); + + public static final QIRNumberType getInstance() { + return instance; + } + + @Override + public String toString() { + return "Number"; + } +} diff --git a/src/qir/types/QIRRecordType.java b/src/qir/types/QIRRecordType.java index 21ae6a0a97a8901192b23cdde668d2cc947a6056..1f6f7fd1d6d3323bffccb15076e9adfd8f928bd6 100644 --- a/src/qir/types/QIRRecordType.java +++ b/src/qir/types/QIRRecordType.java @@ -1,17 +1,38 @@ package qir.types; +import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; -public class QIRRecordType implements QIRType { - private Map<String, QIRType> types; +public class QIRRecordType extends QIRType { + private Map<String, QIRType> fieldTypes; - public QIRRecordType(final Map<String, QIRType> types) { - this.types = types; + public QIRRecordType(final Map<String, QIRType> fieldTypes) { + this.fieldTypes = fieldTypes; + } + + public static final QIRRecordType ANY = new QIRRecordType(new HashMap<>()); + public static final QIRRecordType BOTTOM = new QIRRecordType(new HashMap<>()); + + public final Map<String, QIRType> getFieldTypes() { + return fieldTypes; } @Override public final String toString() { - return "{ " + types.entrySet().stream().map(e -> e.getKey() + " : " + e.getValue()).collect(Collectors.joining(" ; ")) + " }"; + return "{ " + fieldTypes.entrySet().stream().map(e -> e.getKey() + " : " + e.getValue()).collect(Collectors.joining(" ; ")) + " }"; + } + + @Override + protected boolean isSubtypeOfSpecific(QIRType other) { + if (this == BOTTOM) + return true; + if (!(other instanceof QIRRecordType)) + return false; + final Map<String, QIRType> otherTypes = ((QIRRecordType) other).fieldTypes; + for (String key : otherTypes.keySet()) + if (!fieldTypes.containsKey(key) || !otherTypes.get(key).isSubtypeOf(fieldTypes.get(key))) + return false; + return true; } } diff --git a/src/qir/types/QIRSomeType.java b/src/qir/types/QIRSomeType.java new file mode 100644 index 0000000000000000000000000000000000000000..a4f3133aa576dc41e26d5231698f0b8634a18c83 --- /dev/null +++ b/src/qir/types/QIRSomeType.java @@ -0,0 +1,31 @@ +package qir.types; + +import java.util.Optional; + +public class QIRSomeType extends QIRType { + private static int idGen = 0; + + private final int id; + private Optional<QIRType> infered = Optional.empty(); + + public QIRSomeType() { + this.id = idGen++; + } + + public QIRType getInferedType() { + return infered.isPresent() ? infered.get() : this; + } + + @Override + public String toString() { + return infered.isPresent() ? infered.get() + "('a" + id + ")" : "'a" + id; + } + + @Override + protected boolean isSubtypeOfSpecific(final QIRType other) { + if (infered.isPresent() && !other.isSubtypeOf(infered.get())) + return false; + infered = Optional.of(other); + return true; + } +} diff --git a/src/qir/types/QIRStringType.java b/src/qir/types/QIRStringType.java new file mode 100644 index 0000000000000000000000000000000000000000..8f12160d2d11858d740e261077adfae7c65c8d49 --- /dev/null +++ b/src/qir/types/QIRStringType.java @@ -0,0 +1,17 @@ +package qir.types; + +public class QIRStringType extends QIRConstantType { + private QIRStringType() { + } + + private static final QIRStringType instance = new QIRStringType(); + + public static final QIRStringType getInstance() { + return instance; + } + + @Override + public String toString() { + return "String"; + } +} diff --git a/src/qir/types/QIRType.java b/src/qir/types/QIRType.java index 6f004382fc74cca4cfe5db2494a0ec1692a71755..17e4b1b8b8e69415c780670c5e502ecd7a1a8883 100644 --- a/src/qir/types/QIRType.java +++ b/src/qir/types/QIRType.java @@ -1,4 +1,9 @@ package qir.types; -public interface QIRType { +public abstract class QIRType { + protected abstract boolean isSubtypeOfSpecific(final QIRType other); + + public final boolean isSubtypeOf(final QIRType other) { + return other == QIRAnyType.getInstance() || isSubtypeOfSpecific(other); + } } diff --git a/src/qir/typing/QIRDefaultTypeSystemVisitor.java b/src/qir/typing/QIRDefaultTypeSystemVisitor.java new file mode 100644 index 0000000000000000000000000000000000000000..e2ca78accc0e774960445883d91adb840be3805e --- /dev/null +++ b/src/qir/typing/QIRDefaultTypeSystemVisitor.java @@ -0,0 +1,267 @@ +package qir.typing; + +import java.util.HashMap; +import java.util.Map; + +import qir.ast.QIRApply; +import qir.ast.QIRDBNode; +import qir.ast.QIRExportableTruffleNode; +import qir.ast.QIRExternal; +import qir.ast.QIRIf; +import qir.ast.QIRLambda; +import qir.ast.QIRUnexportableTruffleNode; +import qir.ast.QIRVariable; +import qir.ast.data.QIRLcons; +import qir.ast.data.QIRLdestr; +import qir.ast.data.QIRLnil; +import qir.ast.data.QIRRcons; +import qir.ast.data.QIRRdestr; +import qir.ast.data.QIRRnil; +import qir.ast.data.QIRTable; +import qir.ast.expression.QIRBigNumber; +import qir.ast.expression.QIRBinaryNode; +import qir.ast.expression.QIRBoolean; +import qir.ast.expression.QIRDouble; +import qir.ast.expression.QIRNull; +import qir.ast.expression.QIRNumber; +import qir.ast.expression.QIRString; +import qir.ast.expression.arithmetic.QIRDiv; +import qir.ast.expression.arithmetic.QIRMinus; +import qir.ast.expression.arithmetic.QIRMod; +import qir.ast.expression.arithmetic.QIRPlus; +import qir.ast.expression.arithmetic.QIRStar; +import qir.ast.expression.logic.QIRAnd; +import qir.ast.expression.logic.QIRNot; +import qir.ast.expression.logic.QIROr; +import qir.ast.expression.relational.QIREqual; +import qir.ast.expression.relational.QIRLowerOrEqual; +import qir.ast.expression.relational.QIRLowerThan; +import qir.ast.operator.QIRFilter; +import qir.ast.operator.QIRGroupBy; +import qir.ast.operator.QIRJoin; +import qir.ast.operator.QIRLeftJoin; +import qir.ast.operator.QIRLimit; +import qir.ast.operator.QIRProject; +import qir.ast.operator.QIRRightJoin; +import qir.ast.operator.QIRScan; +import qir.ast.operator.QIRSortBy; +import qir.types.QIRAnyType; +import qir.types.QIRBigNumberType; +import qir.types.QIRBooleanType; +import qir.types.QIRDoubleType; +import qir.types.QIRFunctionType; +import qir.types.QIRListType; +import qir.types.QIRNumberType; +import qir.types.QIRRecordType; +import qir.types.QIRSomeType; +import qir.types.QIRStringType; +import qir.types.QIRType; + +public class QIRDefaultTypeSystemVisitor extends QIRTypeSystemVisitor<QIRType> { + public final QIRType visit(final QIRProject qirProject) { + final QIRListType childType = expectIfSubtype(qirProject.getChild().accept(this), QIRListType.ANY); + final QIRFunctionType formatterType = expectIfSubtype(qirProject.getFormatter().accept(this), new QIRFunctionType(new QIRType[]{childType.getElementType()}, QIRAnyType.getInstance())); + + return new QIRListType(formatterType.getReturnType()); + } + + public final QIRType visit(final QIRScan qirScan) { + throw new QIRTypeErrorException(this.getClass(), qirScan); + } + + public final QIRType visit(final QIRFilter qirFilter) { + final QIRListType childType = expectIfSubtype(qirFilter.getChild().accept(this), QIRListType.ANY); + + checkSubtype(qirFilter.getFilter().accept(this), new QIRFunctionType(new QIRType[]{childType.getElementType()}, QIRBooleanType.getInstance())); + return new QIRListType(childType.getElementType()); + } + + public final QIRType visit(final QIRGroupBy qirGroupBy) { + throw new QIRTypeErrorException(this.getClass(), qirGroupBy); + } + + public final QIRType visit(final QIRSortBy qirSortBy) { + throw new QIRTypeErrorException(this.getClass(), qirSortBy); + } + + public final QIRType visit(final QIRJoin qirJoin) { + throw new QIRTypeErrorException(this.getClass(), qirJoin); + } + + public final QIRType visit(final QIRLeftJoin qirJoin) { + throw new QIRTypeErrorException(this.getClass(), qirJoin); + } + + public final QIRType visit(final QIRRightJoin qirJoin) { + throw new QIRTypeErrorException(this.getClass(), qirJoin); + } + + public final QIRType visit(final QIRLimit qirLimit) { + throw new QIRTypeErrorException(this.getClass(), qirLimit); + } + + public final <DBRepr> QIRType visit(final QIRDBNode<DBRepr> qirDBNode) { + throw new QIRTypeErrorException(this.getClass(), qirDBNode); + } + + public final QIRType visit(final QIRExternal qirExternal) { + throw new QIRTypeErrorException(this.getClass(), qirExternal); + } + + public final QIRType visit(final QIRVariable qirVariable) { + if (env.containsKey(qirVariable.id)) + return env.get(qirVariable.id); + throw new QIRTypeErrorException(this.getClass(), qirVariable); + } + + public final QIRType visit(final QIRLambda qirLambda) { + final QIRType varType = new QIRSomeType(); + env.put(qirLambda.getVar().id, varType); + return new QIRFunctionType(new QIRType[]{varType}, qirLambda.getBody().accept(this)); + } + + public final QIRType visit(final QIRApply qirApply) { + final QIRType rightType = qirApply.getRight().accept(this); + return expectIfSubtype(qirApply.getLeft().accept(this), new QIRFunctionType(new QIRType[]{rightType}, QIRAnyType.getInstance())).getReturnType(); + } + + public final QIRType visit(final QIRIf qirIf) { + checkSubtype(qirIf.getCondition().accept(this), QIRBooleanType.getInstance()); + + return expectCommonType(qirIf.getThenNode().accept(this), qirIf.getElseNode().accept(this)); + } + + private final QIRType visitBinaryArithmetic(final QIRBinaryNode qirBinary) { + final QIRType left = qirBinary.getLeft().accept(this); + + if (!left.isSubtypeOf(QIRNumberType.getInstance()) && !left.isSubtypeOf(QIRBigNumberType.getInstance()) && !left.isSubtypeOf(QIRDoubleType.getInstance())) + throw new QIRTypeErrorException(this.getClass(), new QIRType[]{QIRNumberType.getInstance(), QIRBigNumberType.getInstance(), QIRDoubleType.getInstance()}, left); + return expectCommonType(left, qirBinary.getRight().accept(this)); + } + + private final QIRType visitBinaryLogic(final QIRBinaryNode qirBinary) { + checkCommonType(qirBinary.getLeft().accept(this), qirBinary.getRight().accept(this)); + return QIRBooleanType.getInstance(); + } + + public final QIRType visit(final QIRPlus qirPlus) { + return visitBinaryArithmetic(qirPlus); + } + + public final QIRType visit(final QIRMinus qirMinus) { + return visitBinaryArithmetic(qirMinus); + } + + public final QIRType visit(final QIRStar qirStar) { + return visitBinaryArithmetic(qirStar); + } + + public final QIRType visit(final QIRDiv qirDiv) { + return visitBinaryArithmetic(qirDiv); + } + + public final QIRType visit(final QIRMod qirMod) { + return visitBinaryArithmetic(qirMod); + } + + public final QIRType visit(final QIRAnd qirAnd) { + return visitBinaryLogic(qirAnd); + } + + public final QIRType visit(final QIROr qirOr) { + return visitBinaryLogic(qirOr); + } + + public final QIRType visit(final QIREqual qirEqual) { + return visitBinaryLogic(qirEqual); + } + + public final QIRType visit(final QIRLowerOrEqual qirLowerOrEqual) { + return visitBinaryLogic(qirLowerOrEqual); + } + + public final QIRType visit(final QIRLowerThan qirLowerThan) { + return visitBinaryLogic(qirLowerThan); + } + + public final QIRType visit(final QIRNot qirNot) { + final QIRType exprType = qirNot.getExpr().accept(this); + checkSubtype(exprType, QIRBooleanType.getInstance()); + return exprType; + } + + public final QIRType visit(final QIRTable qirTable) { + throw new QIRTypeErrorException(this.getClass(), qirTable); + } + + public final QIRType visit(final QIRLnil qirLnil) { + return QIRListType.ANY; + } + + public final QIRType visit(final QIRLcons qirLcons) { + final QIRListType tailType = expectIfSubtype(qirLcons.getTail().accept(this), QIRListType.ANY); + + return new QIRListType(expectIfSubtype(qirLcons.getValue().accept(this), tailType.getElementType())); + } + + public final QIRType visit(final QIRLdestr qirLdestr) { + final QIRListType listType = expectIfSubtype(qirLdestr.getList().accept(this), QIRListType.ANY); + final QIRType returnType = qirLdestr.getIfEmpty().accept(this); + + checkSubtype(qirLdestr.getHandler().accept(this), new QIRFunctionType(new QIRType[]{listType.getElementType(), listType}, returnType)); + return returnType; + } + + public final QIRType visit(final QIRRnil qirRnil) { + return QIRRecordType.ANY; + } + + public final QIRType visit(final QIRRcons qirRcons) { + final QIRRecordType tailType = expectIfSubtype(qirRcons.getTail().accept(this), QIRRecordType.ANY); + + final Map<String, QIRType> fieldTypes = new HashMap<>(); + tailType.getFieldTypes().entrySet().forEach(e -> fieldTypes.put(e.getKey(), e.getValue())); + fieldTypes.put(qirRcons.getId(), qirRcons.getValue().accept(this)); + return new QIRRecordType(fieldTypes); + } + + public final QIRType visit(final QIRRdestr qirRdestr) { + final String colName = qirRdestr.getColName(); + final Map<String, QIRType> expectedRecordFields = new HashMap<>(); + + expectedRecordFields.put(colName, new QIRSomeType()); + return expectIfSubtype(qirRdestr.getRecord().accept(this), new QIRRecordType(expectedRecordFields)).getFieldTypes().get(colName); + } + + public final QIRType visit(final QIRString qirString) { + return QIRStringType.getInstance(); + } + + public final QIRType visit(final QIRNumber qirNumber) { + return QIRNumberType.getInstance(); + } + + public final QIRType visit(final QIRBigNumber qirBigNumber) { + return QIRBigNumberType.getInstance(); + } + + public final QIRType visit(final QIRDouble qirDouble) { + return QIRDoubleType.getInstance(); + } + + public final QIRType visit(final QIRBoolean qirBoolean) { + return QIRBooleanType.getInstance(); + } + + public final QIRType visit(final QIRNull qirNull) { + return QIRAnyType.getInstance(); + } + + public final QIRType visit(final QIRExportableTruffleNode qirTruffleNode) { + throw new QIRTypeErrorException(this.getClass(), qirTruffleNode); + } + + public final QIRType visit(final QIRUnexportableTruffleNode qirTruffleNode) { + throw new QIRTypeErrorException(this.getClass(), qirTruffleNode); + } +} diff --git a/src/qir/typing/QIRTypeErrorException.java b/src/qir/typing/QIRTypeErrorException.java new file mode 100644 index 0000000000000000000000000000000000000000..b52718adf4d1d0476d8da7bef89a35d18412aaf9 --- /dev/null +++ b/src/qir/typing/QIRTypeErrorException.java @@ -0,0 +1,34 @@ +package qir.typing; + +import java.util.Arrays; +import java.util.stream.Collectors; + +import qir.ast.QIRNode; +import qir.ast.QIRVariable; +import qir.types.QIRRecordType; +import qir.types.QIRType; +import qir.util.QIRException; + +public class QIRTypeErrorException extends QIRException { + private static final long serialVersionUID = 2089121923670702478L; + + public QIRTypeErrorException(final Class<?> 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) { + 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) { + super(typer.getName() + " could not type unknown expression " + unknown); + } + + public QIRTypeErrorException(final Class<?> 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); + } +} diff --git a/src/qir/typing/QIRTypeSystemVisitor.java b/src/qir/typing/QIRTypeSystemVisitor.java new file mode 100644 index 0000000000000000000000000000000000000000..390fea25b36db31f1950943ead3835ea6269fb16 --- /dev/null +++ b/src/qir/typing/QIRTypeSystemVisitor.java @@ -0,0 +1,36 @@ +package qir.typing; + +import java.util.HashMap; +import java.util.Map; + +import qir.driver.IQIRVisitor; +import qir.types.QIRSomeType; +import qir.types.QIRType; + +public abstract class QIRTypeSystemVisitor<T> implements IQIRVisitor<T> { + protected final Map<String, QIRType> env = new HashMap<>(); + + protected void checkSubtype(final QIRType actual, final QIRType expected) { + if (!actual.isSubtypeOf(expected)) + throw new QIRTypeErrorException(this.getClass(), expected, actual); + } + + @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); + } + + protected void checkCommonType(final QIRType actual, final QIRType expected) { + if (!actual.isSubtypeOf(expected) && !expected.isSubtypeOf(actual)) + throw new QIRTypeErrorException(this.getClass(), expected, actual); + } + + protected QIRType expectCommonType(final QIRType actual, final QIRType expected) { + if (actual.isSubtypeOf(expected)) + return expected; + if (expected.isSubtypeOf(actual)) + return actual; + throw new QIRTypeErrorException(this.getClass(), expected, actual); + } +} diff --git a/src/qir/util/QIRException.java b/src/qir/util/QIRException.java index 19fcf7980d8bce8d17202679e2c99a4df37710e5..294642ffceb6a571d3676f3e7c61ead4a6c137d7 100644 --- a/src/qir/util/QIRException.java +++ b/src/qir/util/QIRException.java @@ -3,11 +3,10 @@ package qir.util; /** * {@link QIRException} can be thrown by any module of QIR. */ -public final class QIRException extends RuntimeException { +public class QIRException extends RuntimeException { private static final long serialVersionUID = -8609737632453908968L; public QIRException(final String message) { super(message); - initCause(new Throwable("Java stack trace")); } }