|
@@ -1,60 +1,158 @@
|
|
|
import { Types } from './../ast/types';
|
|
|
import { Operators } from './../ast/operators';
|
|
|
|
|
|
-const InfixCompatibilityTable = Object.freeze([
|
|
|
- [Types.INTEGER, Types.REAL, Types.STRING],
|
|
|
- [Types.INTEGER, Types.REAL],
|
|
|
- [Types.INTEGER, Types.REAL],
|
|
|
- [Types.INTEGER, Types.REAL],
|
|
|
- [Types.INTEGER],
|
|
|
- [Types.INTEGER, Types.REAL],
|
|
|
- [Types.INTEGER, Types.REAL],
|
|
|
- [Types.INTEGER, Types.REAL],
|
|
|
- [Types.INTEGER, Types.REAL],
|
|
|
- [Types.INTEGER, Types.REAL, Types.STRING, Types.BOOLEAN],
|
|
|
- [Types.INTEGER, Types.REAL, Types.STRING, Types.BOOLEAN],
|
|
|
- [Types.BOOLEAN],
|
|
|
- [Types.BOOLEAN],
|
|
|
- null,
|
|
|
-]);
|
|
|
-
|
|
|
-const UnaryCompatibilityTable = Object.freeze([
|
|
|
- [Types.INTEGER, Types.REAL],
|
|
|
- [Types.INTEGER, Types.REAL],
|
|
|
- null,
|
|
|
- null,
|
|
|
- null,
|
|
|
- null,
|
|
|
- null,
|
|
|
- null,
|
|
|
- null,
|
|
|
- null,
|
|
|
- null,
|
|
|
- null,
|
|
|
- null,
|
|
|
- [Types.BOOLEAN],
|
|
|
-]);
|
|
|
-
|
|
|
-export function canApplyUnaryOp (op, a) {
|
|
|
- const list = UnaryCompatibilityTable[op];
|
|
|
- if (!!!list) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- const type = list.find(t => t === a.type);
|
|
|
- if (!!!type) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- return true
|
|
|
+function buildInfixAddTable () {
|
|
|
+ const table = [[], [], [], []];
|
|
|
+
|
|
|
+ table[Types.INTEGER.ord][Types.INTEGER.ord] = Types.INTEGER;
|
|
|
+ table[Types.INTEGER.ord][Types.REAL.ord] = Types.REAL;
|
|
|
+ table[Types.INTEGER.ord][Types.STRING.ord] = Types.STRING;
|
|
|
+
|
|
|
+ table[Types.REAL.ord][Types.INTEGER.ord] = Types.REAL;
|
|
|
+ table[Types.REAL.ord][Types.REAL.ord] = Types.REAL;
|
|
|
+ table[Types.REAL.ord][Types.STRING.ord] = Types.STRING;
|
|
|
+
|
|
|
+ table[Types.STRING.ord][Types.INTEGER.ord] = Types.STRING;
|
|
|
+ table[Types.STRING.ord][Types.REAL.ord] = Types.STRING;
|
|
|
+ table[Types.STRING.ord][Types.STRING.ord] = Types.STRING;
|
|
|
+ table[Types.STRING.ord][Types.BOOLEAN.ord] = Types.STRING;
|
|
|
+
|
|
|
+ return table;
|
|
|
+}
|
|
|
+
|
|
|
+function buildInfixMultiSubTable () {
|
|
|
+ const table = [[], [], [], []];
|
|
|
+
|
|
|
+ table[Types.INTEGER.ord][Types.INTEGER.ord] = Types.INTEGER;
|
|
|
+ table[Types.INTEGER.ord][Types.REAL.ord] = Types.REAL;
|
|
|
+
|
|
|
+ table[Types.REAL.ord][Types.INTEGER.ord] = Types.REAL;
|
|
|
+ table[Types.REAL.ord][Types.REAL.ord] = Types.REAL;
|
|
|
+
|
|
|
+ return table;
|
|
|
}
|
|
|
|
|
|
-export function canApplyInfixOp (op, a, b) {
|
|
|
- const list = InfixCompatibilityTable[op];
|
|
|
- if (!!!list) {
|
|
|
- return false;
|
|
|
+function buildInfixDivTable () {
|
|
|
+ const table = [[], [], [], []];
|
|
|
+
|
|
|
+ table[Types.INTEGER.ord][Types.INTEGER.ord] = Types.REAL;
|
|
|
+ table[Types.INTEGER.ord][Types.REAL.ord] = Types.REAL;
|
|
|
+
|
|
|
+ table[Types.REAL.ord][Types.INTEGER.ord] = Types.REAL;
|
|
|
+ table[Types.REAL.ord][Types.REAL.ord] = Types.REAL;
|
|
|
+
|
|
|
+ return table;
|
|
|
+}
|
|
|
+
|
|
|
+function buildInfixEqualityInequalityTable () {
|
|
|
+ const table = [[], [], [], []];
|
|
|
+
|
|
|
+ table[Types.INTEGER.ord][Types.INTEGER.ord] = Types.BOOLEAN;
|
|
|
+
|
|
|
+ table[Types.REAL.ord][Types.REAL.ord] = Types.BOOLEAN;
|
|
|
+
|
|
|
+ table[Types.BOOLEAN.ord][Types.BOOLEAN.ord] = Types.BOOLEAN;
|
|
|
+
|
|
|
+ table[Types.STRING.ord][Types.STRING.ord] = Types.BOOLEAN;
|
|
|
+
|
|
|
+ return table;
|
|
|
+}
|
|
|
+
|
|
|
+function buildInfixRelationalTable () {
|
|
|
+ const table = [[], [], [], []];
|
|
|
+
|
|
|
+ table[Types.INTEGER.ord][Types.INTEGER.ord] = Types.BOOLEAN;
|
|
|
+
|
|
|
+ table[Types.REAL.ord][Types.REAL.ord] = Types.BOOLEAN;
|
|
|
+
|
|
|
+ table[Types.STRING.ord][Types.STRING.ord] = Types.BOOLEAN;
|
|
|
+
|
|
|
+ return table;
|
|
|
+}
|
|
|
+
|
|
|
+function buildInfixAndOrTable () {
|
|
|
+ const table = [[], [], [], []];
|
|
|
+
|
|
|
+ table[Types.BOOLEAN.ord][Types.BOOLEAN.ord] = Types.BOOLEAN;
|
|
|
+
|
|
|
+ return table;
|
|
|
+}
|
|
|
+
|
|
|
+function buildInfixModTable () {
|
|
|
+ const table = [[], [], [], []];
|
|
|
+
|
|
|
+ table[Types.INTEGER.ord][Types.INTEGER.ord] = Types.INTEGER;
|
|
|
+
|
|
|
+ return table;
|
|
|
+}
|
|
|
+
|
|
|
+function buildUnarySumSubList () {
|
|
|
+ const list = [];
|
|
|
+
|
|
|
+ list[Types.INTEGER.ord] = Types.INTEGER;
|
|
|
+
|
|
|
+ list[Types.REAL.ord] = Types.REAL;
|
|
|
+
|
|
|
+ return list;
|
|
|
+}
|
|
|
+
|
|
|
+function buildUnaryNegList () {
|
|
|
+ const list = [];
|
|
|
+
|
|
|
+ list[Types.BOOLEAN.ord] = Types.BOOLEAN;
|
|
|
+
|
|
|
+ return list;
|
|
|
+}
|
|
|
+
|
|
|
+function buildInfixCompatibilityTable () {
|
|
|
+ const compatibilityMap = new WeakMap();
|
|
|
+ compatibilityMap.set(Operators.ADD, buildInfixAddTable());
|
|
|
+ compatibilityMap.set(Operators.SUB, buildInfixMultiSubTable());
|
|
|
+ compatibilityMap.set(Operators.MULT, buildInfixMultiSubTable());
|
|
|
+ compatibilityMap.set(Operators.DIV, buildInfixDivTable());
|
|
|
+ compatibilityMap.set(Operators.EQ, buildInfixEqualityInequalityTable());
|
|
|
+ compatibilityMap.set(Operators.NEQ, buildInfixEqualityInequalityTable());
|
|
|
+ compatibilityMap.set(Operators.GE, buildInfixRelationalTable());
|
|
|
+ compatibilityMap.set(Operators.GT, buildInfixRelationalTable());
|
|
|
+ compatibilityMap.set(Operators.LE, buildInfixRelationalTable());
|
|
|
+ compatibilityMap.set(Operators.LT, buildInfixRelationalTable());
|
|
|
+ compatibilityMap.set(Operators.OR, buildInfixAndOrTable());
|
|
|
+ compatibilityMap.set(Operators.AND, buildInfixAndOrTable());
|
|
|
+ compatibilityMap.set(Operators.MOD, buildInfixModTable());
|
|
|
+ return compatibilityMap;
|
|
|
+}
|
|
|
+
|
|
|
+function buildUnaryCompatibilityTable () {
|
|
|
+ const compatibilityMap = new WeakMap();
|
|
|
+ compatibilityMap.set(Operators.ADD, buildUnarySumSubList());
|
|
|
+ compatibilityMap.set(Operators.SUB, buildUnarySumSubList());
|
|
|
+ compatibilityMap.set(Operators.NOT, buildUnaryNegList());
|
|
|
+ return compatibilityMap;
|
|
|
+}
|
|
|
+
|
|
|
+const infixMap = buildInfixCompatibilityTable();
|
|
|
+const unaryMap = buildUnaryCompatibilityTable();
|
|
|
+
|
|
|
+export function resultTypeAfterInfixOp (operator, leftExpressionType, rightExpressionType) {
|
|
|
+ try {
|
|
|
+ return infixMap.get(operator)[leftExpressionType.ord][rightExpressionType.ord];
|
|
|
+ } catch (e) {
|
|
|
+ if (e instanceof TypeError) {
|
|
|
+ return Types.UNDEFINED;
|
|
|
+ } else {
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
}
|
|
|
- const type = list.find(t => t === a.type);
|
|
|
- if (!!!type) {
|
|
|
- return false;
|
|
|
+}
|
|
|
+
|
|
|
+export function resultTypeAfterUnaryOp (operator, leftExpressionType) {
|
|
|
+ try {
|
|
|
+ return unaryMap.get(operator)[leftExpressionType.ord];
|
|
|
+ } catch (e) {
|
|
|
+ if (e instanceof TypeError) {
|
|
|
+ return Types.UNDEFINED;
|
|
|
+ } else {
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
}
|
|
|
- return type === b.type;
|
|
|
}
|