diff --git a/pom.xml b/pom.xml index 64d94ac..feb78c6 100644 --- a/pom.xml +++ b/pom.xml @@ -28,12 +28,6 @@ - - com.nitta-lab - dtram - 1.0 - - diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 1738ff9..b692f74 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,325 +1,33 @@ -import java.util.List; +import java.util.HashMap; +import java.util.Map; -import inference.rewrite.Position; -import inference.rewrite.ResourceTree; -import inference.rewrite.RewriteInferenceSystem; -import lombok.SneakyThrows; +import constants.Types; +import models.algebra.Constant; import models.algebra.Expression; import models.algebra.Type; -import models.dataConstraintModel.DataConstraintModel; -import models.dataFlowModel.DataTransferModel; -import models.formulas.EquationFormula; -import models.formulas.Then; -import models.terms.DependencyTerm; -import models.terms.PrimedTerm; -import models.terms.Resource; -import parser.Parser; -import parser.Parser.TokenStream; +import models.algebra.Variable; public class Main { - static TokenStream stream = new Parser.TokenStream(); - static Parser parser = new Parser(stream); - static DataTransferModel model = new DataTransferModel(); - - static Type INT = DataConstraintModel.typeInt; + static Type INT = Types.typeInt; public static void main(String[] args) { -// sandbox4(); -// System.out.println("================================================================="); -// System.out.println("================================================================="); -// System.out.println("================================================================="); -// sandbox5(); - sandbox9(); - } - - static void sandbox1() { - Resource A = new Resource("A", INT, 1); - Resource B = new Resource("B", INT, 1); - Resource C = new Resource("C", INT, 1); - Resource D = new Resource("D", INT, 1); - Resource E = new Resource("E", INT, 1); - Resource F = new Resource("F", INT, 1); - Resource G = new Resource("G", INT, 1); - DependencyTerm t1 = new DependencyTerm(A, B, C, D, E); - DependencyTerm t2 = new DependencyTerm(t1, F, G); - System.out.println(t2); - ResourceTree rt = new ResourceTree(t2); - System.out.println(rt); - rt.debug(new Position(List.of(0))); - } - - static void sandbox2() { - Resource A = new Resource("A", INT, 1); - Resource B = new Resource("B", INT, 1); - Resource C = new Resource("C", INT, 1); - Resource D = new Resource("D", INT, 1); - Resource E = new Resource("E", INT, 1); - Resource F = new Resource("F", INT, 1); - Resource G = new Resource("G", INT, 1); - Resource H = new Resource("H", INT, 1); - Resource I = new Resource("I", INT, 1); - Resource J = new Resource("J", INT, 1); - Resource K = new Resource("K", INT, 1); - Resource L = new Resource("L", INT, 1); - Resource M = new Resource("M", INT, 1); - Resource N = new Resource("N", INT, 1); - Resource O = new Resource("O", INT, 1); - Resource P = new Resource("P", INT, 1); - Resource Q = new Resource("Q", INT, 1); - - DependencyTerm t1 = new DependencyTerm(A, B, C, D, E); - DependencyTerm t2 = new DependencyTerm(G, H, I, J, K); - DependencyTerm t3 = new DependencyTerm(M, N, O, P, Q); - DependencyTerm t4 = new DependencyTerm(t1, F, t2, L, t3); - System.out.println(t4); - ResourceTree rt = new ResourceTree(t4); - System.out.println(rt); - rt.debug(new Position()); - rt.debugAllPath(); - - } - - static void sandbox3() { - Resource A = new Resource("A", INT, 1); - Resource B = new Resource("B", INT, 1); - Resource C = new Resource("C", INT, 1); - Resource D = new Resource("D", INT, 1); - Resource x = new Resource("x", INT, 0); - Resource y = new Resource("y", INT, 1); - DependencyTerm t1 = new DependencyTerm(A, B, C); - DependencyTerm t2 = new DependencyTerm(B, C, D); - EquationFormula f1 = new EquationFormula(t1, x); - EquationFormula f2 = new EquationFormula(y, t2); - RewriteInferenceSystem ris = new RewriteInferenceSystem(List.of(f1, f2), null); - ris.inference(); - - } - - static void sandbox4() { - Resource uadd = new Resource("uadd", INT, 1); - Resource add = new Resource("add", INT, 1); - Resource cid = new Resource("cid", INT, 1); - Resource org = new Resource("org", INT, 1); - Resource uid = new Resource("uid", INT, 1); - Resource x = new Resource("x", INT, 0); - Resource y = new Resource("y", INT, 0); - DependencyTerm t1 = new DependencyTerm(add, cid, org); - DependencyTerm t2 = new DependencyTerm(org, uid, x); - DependencyTerm t3 = new DependencyTerm(uadd, uid, x); - DependencyTerm t4 = new DependencyTerm(add, cid, y); - EquationFormula f1 = new EquationFormula(uadd, t1); - EquationFormula f2 = new EquationFormula(t2, y); - EquationFormula f3 = new EquationFormula(t3, t4); - - - RewriteInferenceSystem ris = new RewriteInferenceSystem(List.of(f1, f2), f3); - ris.debug(); - ris.inference(); - - } - - static void sandbox5() { - Resource uadd = new Resource("uadd", INT, 1); - Resource add = new Resource("add", INT, 1); - Resource cid = new Resource("cid", INT, 1); - Resource org = new Resource("org", INT, 1); - Resource uid = new Resource("uid", INT, 1); - Resource x = new Resource("x", INT, 0); - Resource y = new Resource("y", INT, 0); - Resource z = new Resource("z", INT, 0); - DependencyTerm t1 = new DependencyTerm(add, cid, org); - DependencyTerm t2 = new DependencyTerm(add, cid, x); - DependencyTerm t3 = new DependencyTerm(org, uid, z); - DependencyTerm t4 = new DependencyTerm(uadd, uid, z); - - EquationFormula f1 = new EquationFormula(uadd, t1); - EquationFormula f2 = new EquationFormula(t2, y); - EquationFormula f3 = new EquationFormula(t3, x); - EquationFormula f4 = new EquationFormula(t4, y); - Then f5 = new Then(f3, f4); - - RewriteInferenceSystem ris = new RewriteInferenceSystem(List.of(f1, f2), f5); - ris.debug(); - ris.inference(); - - } - - static void sandbox6() { - Resource add = new Resource("add", INT, 1); - Resource cid = new Resource("cid", INT, 1); - Resource org = new Resource("org", INT, 1); - Resource uid = new Resource("uid", INT, 1); - Resource x = new Resource("x", INT, 0); - Resource y = new Resource("y", INT, 0); - Resource z = new Resource("z", INT, 0); - - DependencyTerm t1 = new DependencyTerm(add, cid, x); - DependencyTerm t2 = new DependencyTerm(cid, uid, z); - DependencyTerm t3 = new DependencyTerm(add, cid, t2); - EquationFormula f1 = new EquationFormula(t1, y); - EquationFormula f2 = new EquationFormula(t2, x); - EquationFormula f3 = new EquationFormula(t3, y); - Then f4 = new Then(f2, f3); - RewriteInferenceSystem ris = new RewriteInferenceSystem(List.of(f1), f4); - ris.inference(); - + sandbox(); } - static void sandbox7() { - Resource A = new Resource("A", INT, 1); - Resource B = new Resource("B", INT, 1); - Resource C = new Resource("C", INT, 1); - Resource D = new Resource("D", INT, 1); - Resource E = new Resource("E", INT, 1); - Resource F = new Resource("F", INT, 1); - Resource G = new Resource("G", INT, 1); - Resource H = new Resource("H", INT, 1); - Resource I = new Resource("I", INT, 1); - Resource J = new Resource("J", INT, 1); - Resource K = new Resource("K", INT, 1); - Resource L = new Resource("L", INT, 1); - Resource M = new Resource("M", INT, 1); - Resource N = new Resource("N", INT, 1); - Resource O = new Resource("O", INT, 1); + static void sandbox() { + Expression tmp = utils.ExpressionUitls.parse("x"); + System.out.println(tmp); + tmp = utils.ExpressionUitls.parse("(x + 5) * 3"); + Map nums = new HashMap<>(); + int a = utils.ExpressionUitls.getCoefficientAndConstantsFromExpression(tmp, nums, 1); + System.out.println(tmp); + System.out.println(a); + System.out.println(nums); - DependencyTerm t1 = new DependencyTerm(A, B, C); - DependencyTerm t2 = new DependencyTerm(I, J, K); - DependencyTerm t3 = new DependencyTerm(M, N, O); - DependencyTerm t4 = new DependencyTerm(E, F, G, H, t2); - DependencyTerm t5 = new DependencyTerm(t1, D, t4, L, t3); - - ResourceTree rt = new ResourceTree(t5); -// System.out.println(rt); - rt.debug(new Position(List.of(0))); + int b = utils.ExpressionUitls.getConstantValue(new Constant("3")); + System.out.println(b); } - static void sandbox8() { - Resource A = new Resource("A", INT, 1); - Resource B = new Resource("B", INT, 1); - Resource C = new Resource("C", INT, 1); - DependencyTerm te = new DependencyTerm(A, B, C); - EquationFormula eq1 = new EquationFormula(A, te); - RewriteInferenceSystem ris = new RewriteInferenceSystem(List.of(eq1), eq1); - ris.inference(); - } - - static void sandbox9() { - Resource totalAmount = new Resource("totalAmount", INT, 1); - Resource quantity = new Resource("quantity", INT, 1); - Resource unitPrice = new Resource("unitPrice", INT, 1); - Resource productId = new Resource("productID", INT, 1); - Resource productName = new Resource("productName", INT, 1); - Resource soledProductId = new Resource("soledProductId", INT, 1); - PrimedTerm totalAmountP = new PrimedTerm(totalAmount); - PrimedTerm quantityP = new PrimedTerm(quantity); - PrimedTerm unitPriceP = new PrimedTerm(unitPrice); - PrimedTerm productIdP = new PrimedTerm(productId); - PrimedTerm productNameP = new PrimedTerm(productName); - PrimedTerm soledProductIdP = new PrimedTerm(soledProductId); - Resource a = new Resource("a", INT, 0); - Resource b = new Resource("b", INT, 0); - Resource c = new Resource("c", INT, 0); - Resource d = new Resource("d", INT, 0); - Resource e = new Resource("e", INT, 0); - Resource salesId = new Resource("salesId", INT, 1); - PrimedTerm salesIdP = new PrimedTerm(salesId); - Resource mul = new Resource("mul", INT, 1); - Resource mul1= new Resource("mul1", INT, 1); - Resource mul2 = new Resource("mul2", INT, 1); - - // reference1 - DependencyTerm te1 = new DependencyTerm(unitPrice, productId, soledProductId); - DependencyTerm te2 = new DependencyTerm(mul, mul1, quantity, mul2, te1); - EquationFormula eq1 = new EquationFormula(totalAmount, te2); - - //reference2 - DependencyTerm te3 = new DependencyTerm(unitPriceP, productIdP, soledProductIdP); - DependencyTerm te4 = new DependencyTerm(mul, mul1, quantityP, mul2, te3); - EquationFormula eq2 = new EquationFormula(totalAmountP, te4); - - //input1 - DependencyTerm te5 = new DependencyTerm(soledProductIdP, salesIdP, a); - EquationFormula eq3 = new EquationFormula(te5, b); - - //input2 - DependencyTerm te6 = new DependencyTerm(quantityP, salesIdP, a); - EquationFormula eq4 = new EquationFormula(te6, c); - - //input3, 4, 5 - EquationFormula eq5 = new EquationFormula(productIdP, productId); - EquationFormula eq6 = new EquationFormula(productNameP, productName); - EquationFormula eq7 = new EquationFormula(unitPriceP, unitPrice); - - // value copy - DependencyTerm te7 = new DependencyTerm(totalAmountP, salesIdP, a); - DependencyTerm te8 = new DependencyTerm(unitPriceP, productIdP, b); - DependencyTerm te9 = new DependencyTerm(mul, mul1, c, mul2, te8); - EquationFormula eq8 = new EquationFormula(te7, te9); - - - //----------------------change value------------------- - //input6 - DependencyTerm te10 = new DependencyTerm(unitPriceP, productIdP, d); - EquationFormula eq9 = new EquationFormula(te10, e); - - //input7, 8, 9, 10 - EquationFormula eq10 = new EquationFormula(productNameP, productName); - EquationFormula eq11 = new EquationFormula(salesIdP, salesId); - EquationFormula eq12 = new EquationFormula(soledProductIdP, soledProductId); - EquationFormula eq13 = new EquationFormula(quantityP, quantity); - - //value copy - EquationFormula eq14 = new EquationFormula(totalAmountP, totalAmount); - - //value copy conclusion - DependencyTerm te11 = new DependencyTerm(totalAmountP, salesIdP, a); - DependencyTerm te12 = new DependencyTerm(totalAmount, salesId, a); - EquationFormula eq15 = new EquationFormula(te11, te12); -// RewriteInferenceSystem ris = new RewriteInferenceSystem(List.of(eq3, eq4, eq5, eq6, eq7, eq8, eq9, eq10, eq11, eq12, eq13, eq14), eq15); -// RewriteInferenceSystem ris = new RewriteInferenceSystem(List.of(), List.of(), List.of(eq3, eq4, eq5, eq6, eq7, eq8, eq9, eq10, eq11, eq12, eq13, eq14), eq15); - - //value copy new sales -// RewriteInferenceSystem ris = new RewriteInferenceSystem(List.of(eq3, eq4, eq5, eq6, eq7, eq8), eq15); - - //value copy change value - RewriteInferenceSystem ris = new RewriteInferenceSystem(List.of(eq9, eq10, eq11, eq12, eq13, eq14), eq15); - ris.debug(); - ris.inference(); -// - System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); - System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); - System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); - - //reference conclusion - DependencyTerm te13 = new DependencyTerm(soledProductId, salesId, a); - EquationFormula eq16 = new EquationFormula(d, te13); - Then th1 = new Then(eq16, eq15); - - -// RewriteInferenceSystem ris2 = new RewriteInferenceSystem(List.of(eq3, eq4, eq5, eq6, eq7, eq1, eq9, eq10, eq11, eq12, eq13, eq2), th1); -// RewriteInferenceSystem ris2 = new RewriteInferenceSystem(List.of(eq1, eq2), List.of(), List.of(eq3, eq4, eq5, eq6, eq7,eq9, eq10, eq11, eq12, eq13), th1); - - //reference new sales -// RewriteInferenceSystem ris2 = new RewriteInferenceSystem(List.of(eq1, eq2, eq3, eq4, eq5, eq6, eq7), th1); - - //reference change value - RewriteInferenceSystem ris2 = new RewriteInferenceSystem(List.of(eq1, eq2, eq9, eq10, eq11, eq12, eq13), th1); - - ris2.debug(); - ris2.inference(); - - } - - - - - @SneakyThrows - static Expression parse(String expr) { - stream.addLine(expr); - return parser.parseTerm(stream, model); - } - - } diff --git a/src/main/java/constants/Symbols.java b/src/main/java/constants/Symbols.java new file mode 100644 index 0000000..b2dba87 --- /dev/null +++ b/src/main/java/constants/Symbols.java @@ -0,0 +1,513 @@ +package constants; + +import java.util.List; + +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.Symbol; +import models.algebra.Type; +import parser.Parser; + +public class Symbols { + + public static final Symbol null_ = new Symbol("null", 0, Symbol.Type.PREFIX, "null", Symbol.Type.PREFIX); + public static final Symbol true_ = new Symbol("true", 0, Symbol.Type.PREFIX, "true", Symbol.Type.PREFIX); + public static final Symbol false_ = new Symbol("false", 0, Symbol.Type.PREFIX, "false", Symbol.Type.PREFIX); + + public static final Symbol add = new Symbol(Parser.ADD, 2, Symbol.Type.INFIX, new Symbol.ICalculator() { + @Override + public Expression calculate(List args) { + if (!(args.get(0).getClass() == Constant.class)) { + return null; + } + if (!(args.get(1).getClass() == Constant.class)) { + return null; + } + Constant arg0 = (Constant) args.get(0); + Constant arg1 = (Constant) args.get(1); + String sArg0 = arg0.getSymbol().toString(); + String sArg1 = arg1.getSymbol().toString(); + if (arg0.getType() != null && arg1.getType() != null) { + if (arg0.getType().equals(Types.typeDouble) || arg1.getType().equals(Types.typeDouble)) { + return new Constant(Double.toString(Double.parseDouble(sArg0) + Double.parseDouble(sArg1)), Types.typeDouble); + } else if (arg0.getType().equals(Types.typeFloat) || arg1.getType().equals(Types.typeFloat)) { + return new Constant(Float.toString(Float.parseFloat(sArg0) + Float.parseFloat(sArg1)), Types.typeFloat); + } else if (arg0.getType().equals(Types.typeLong) || arg1.getType().equals(Types.typeLong)) { + return new Constant(Long.toString(Long.parseLong(sArg0) + Long.parseLong(sArg1)), Types.typeLong); + } else if (arg0.getType().equals(Types.typeInt) || arg1.getType().equals(Types.typeInt)) { + return new Constant(Integer.toString(Integer.parseInt(sArg0) + Integer.parseInt(sArg1)), Types.typeInt); + } else if (arg0.getType().equals(Types.typeString) || arg1.getType().equals(Types.typeString)) { + return new Constant((String) arg0.getValue() + (String) arg1.getValue(), Types.typeString); + } + } + if (sArg0.contains(Parser.DOT) || sArg1.contains(Parser.DOT)) { + return new Constant(Double.toString(Double.parseDouble(sArg0) + Double.parseDouble(sArg1)), Types.typeDouble); + } else { + return new Constant(Integer.toString(Integer.parseInt(sArg0) + Integer.parseInt(sArg1)), Types.typeInt); + } + } + }); + public static final Symbol mul = new Symbol(Parser.MUL, 2, Symbol.Type.INFIX, new Symbol.ICalculator() { + @Override + public Expression calculate(List args) { + if (!(args.get(0).getClass() == Constant.class)) { + return null; + } + if (!(args.get(1).getClass() == Constant.class)) { + return null; + } + Constant arg0 = (Constant) args.get(0); + Constant arg1 = (Constant) args.get(1); + String sArg0 = arg0.getSymbol().toString(); + String sArg1 = arg1.getSymbol().toString(); + if (arg0.getType() != null && arg1.getType() != null) { + if (arg0.getType().equals(Types.typeDouble) || arg1.getType().equals(Types.typeDouble)) { + return new Constant(Double.toString(Double.parseDouble(sArg0) * Double.parseDouble(sArg1)), Types.typeDouble); + } else if (arg0.getType().equals(Types.typeFloat) || arg1.getType().equals(Types.typeFloat)) { + return new Constant(Float.toString(Float.parseFloat(sArg0) * Float.parseFloat(sArg1)), Types.typeFloat); + } else if (arg0.getType().equals(Types.typeLong) || arg1.getType().equals(Types.typeLong)) { + return new Constant(Long.toString(Long.parseLong(sArg0) * Long.parseLong(sArg1)), Types.typeLong); + } else if (arg0.getType().equals(Types.typeInt) || arg1.getType().equals(Types.typeInt)) { + return new Constant(Integer.toString(Integer.parseInt(sArg0) * Integer.parseInt(sArg1)), Types.typeInt); + } + } + if (sArg0.contains(Parser.DOT) || sArg1.contains(Parser.DOT)) { + return new Constant(Double.toString(Double.parseDouble(sArg0) * Double.parseDouble(sArg1)), Types.typeDouble); + } else { + return new Constant(Integer.toString(Integer.parseInt(sArg0) * Integer.parseInt(sArg1)), Types.typeInt); + } + } + }); + public static final Symbol sub = new Symbol(Parser.SUB, 2, Symbol.Type.INFIX, new Symbol.ICalculator() { + @Override + public Expression calculate(List args) { + if (!(args.get(0).getClass() == Constant.class)) { + return null; + } + if (!(args.get(1).getClass() == Constant.class)) { + return null; + } + Constant arg0 = (Constant) args.get(0); + Constant arg1 = (Constant) args.get(1); + String sArg0 = arg0.getSymbol().toString(); + String sArg1 = arg1.getSymbol().toString(); + if (arg0.getType() != null && arg1.getType() != null) { + if (arg0.getType().equals(Types.typeDouble) || arg1.getType().equals(Types.typeDouble)) { + return new Constant(Double.toString(Double.parseDouble(sArg0) - Double.parseDouble(sArg1)), Types.typeDouble); + } else if (arg0.getType().equals(Types.typeFloat) || arg1.getType().equals(Types.typeFloat)) { + return new Constant(Float.toString(Float.parseFloat(sArg0) - Float.parseFloat(sArg1)), Types.typeFloat); + } else if (arg0.getType().equals(Types.typeLong) || arg1.getType().equals(Types.typeLong)) { + return new Constant(Long.toString(Long.parseLong(sArg0) - Long.parseLong(sArg1)), Types.typeLong); + } else if (arg0.getType().equals(Types.typeInt) || arg1.getType().equals(Types.typeInt)) { + return new Constant(Integer.toString(Integer.parseInt(sArg0) - Integer.parseInt(sArg1)), Types.typeInt); + } + } + if (sArg0.contains(Parser.DOT) || sArg1.contains(Parser.DOT)) { + return new Constant(Double.toString(Double.parseDouble(sArg0) - Double.parseDouble(sArg1)), Types.typeDouble); + } else { + return new Constant(Integer.toString(Integer.parseInt(sArg0) - Integer.parseInt(sArg1)), Types.typeInt); + } + } + }); + public static final Symbol div = new Symbol(Parser.DIV, 2, Symbol.Type.INFIX, new Symbol.ICalculator() { + @Override + public Expression calculate(List args) { + if (!(args.get(0).getClass() == Constant.class)) { + return null; + } + if (!(args.get(1).getClass() == Constant.class)) { + return null; + } + Constant arg0 = (Constant) args.get(0); + Constant arg1 = (Constant) args.get(1); + String sArg0 = arg0.getSymbol().toString(); + String sArg1 = arg1.getSymbol().toString(); + if (arg0.getType() != null && arg1.getType() != null) { + if (arg0.getType().equals(Types.typeDouble) || arg1.getType().equals(Types.typeDouble)) { + return new Constant(Double.toString(Double.parseDouble(sArg0) / Double.parseDouble(sArg1)), Types.typeDouble); + } else if (arg0.getType().equals(Types.typeFloat) || arg1.getType().equals(Types.typeFloat)) { + return new Constant(Float.toString(Float.parseFloat(sArg0) / Float.parseFloat(sArg1)), Types.typeFloat); + } else if (arg0.getType().equals(Types.typeLong) || arg1.getType().equals(Types.typeLong)) { + return new Constant(Long.toString(Long.parseLong(sArg0) / Long.parseLong(sArg1)), Types.typeLong); + } else if (arg0.getType().equals(Types.typeInt) || arg1.getType().equals(Types.typeInt)) { + return new Constant(Integer.toString(Integer.parseInt(sArg0) / Integer.parseInt(sArg1)), Types.typeInt); + } + } + if (sArg0.contains(Parser.DOT) || sArg1.contains(Parser.DOT)) { + return new Constant(Double.toString(Double.parseDouble(sArg0) / Double.parseDouble(sArg1)), Types.typeDouble); + } else { + return new Constant(Integer.toString(Integer.parseInt(sArg0) / Integer.parseInt(sArg1)), Types.typeInt); + } + } + }); + public static final Symbol mod = new Symbol(Parser.MOD, 2, Symbol.Type.INFIX, "%", Symbol.Type.INFIX, new Symbol.ICalculator() { + @Override + public Expression calculate(List args) { + if (!(args.get(0).getClass() == Constant.class)) { + return null; + } + if (!(args.get(1).getClass() == Constant.class)) { + return null; + } + Constant arg0 = (Constant) args.get(0); + Constant arg1 = (Constant) args.get(1); + String sArg0 = arg0.getSymbol().toString(); + String sArg1 = arg1.getSymbol().toString(); + if (arg0.getType() != null && arg1.getType() != null) { + if (arg0.getType().equals(Types.typeLong) || arg1.getType().equals(Types.typeLong)) { + return new Constant(Long.toString(Long.parseLong(sArg0) % Long.parseLong(sArg1)), Types.typeLong); + } else if (arg0.getType().equals(Types.typeInt) || arg1.getType().equals(Types.typeInt)) { + return new Constant(Integer.toString(Integer.parseInt(sArg0) % Integer.parseInt(sArg1)), Types.typeInt); + } + } + return new Constant(Integer.toString(Integer.parseInt(sArg0) % Integer.parseInt(sArg1))); + } + }); + public static final Symbol minus = new Symbol(Parser.MINUS, 1, new Symbol.ICalculator() { + @Override + public Expression calculate(List args) { + if (!(args.get(0).getClass() == Constant.class)) { + return null; + } + Constant arg = (Constant) args.get(0); + String sArg = arg.getSymbol().toString(); + if (arg.getType() != null) { + if (arg.getType().equals(Types.typeDouble)) { + return new Constant(Double.toString(-Double.parseDouble(sArg)), Types.typeDouble); + } else if (arg.getType().equals(Types.typeFloat)) { + return new Constant(Float.toString(-Float.parseFloat(sArg)), Types.typeFloat); + } else if (arg.getType().equals(Types.typeLong)) { + return new Constant(Long.toString(-Long.parseLong(sArg)), Types.typeLong); + } else if (arg.getType().equals(Types.typeInt)) { + return new Constant(Integer.toString(-Integer.parseInt(sArg)), Types.typeInt); + } + } + if (sArg.contains(Parser.DOT)) { + return new Constant(Double.toString(-Double.parseDouble(sArg)), Types.typeDouble); + } else { + return new Constant(Integer.toString(-Integer.parseInt(sArg)), Types.typeInt); + } + } + }); + public static final Symbol eq = new Symbol(Parser.EQ, 2, Symbol.Type.INFIX, new Symbol.IImplGenerator() { + @Override + public String generate(Type type, Type[] childrenTypes, String[] children, String[] childrenSideEffects, String[] sideEffect) { + for (String s: childrenSideEffects) { + sideEffect[0] += s; + } + if (childrenTypes[0] != null && childrenTypes[0].equals(Types.typeString) + && childrenTypes[1] != null && childrenTypes[1].equals(Types.typeString)) { + return children[0] + ".equals(" + children[1] + ")"; + } + return "(" + children[0] + "==" + children[1] + ")"; + } + }, new Symbol.ICalculator() { + @Override + public Expression calculate(List args) { + if (!(args.get(0).getClass() == Constant.class)) { + return null; + } + if (!(args.get(1).getClass() == Constant.class)) { + return null; + } + Constant arg0 = (Constant) args.get(0); + Constant arg1 = (Constant) args.get(1); + String sArg0 = arg0.getSymbol().toString(); + String sArg1 = arg1.getSymbol().toString(); + boolean result = false; + if (arg0.getType() == null || arg1.getType() == null) { + if (sArg0.contains(Parser.DOT) || sArg1.contains(Parser.DOT)) { + result = Double.parseDouble(sArg0) == Double.parseDouble(sArg1); + } else { + result = Integer.parseInt(sArg0) == Integer.parseInt(sArg1); + } + } + if (arg0.getType().equals(Types.typeDouble) || arg1.getType().equals(Types.typeDouble)) { + result = (Double.parseDouble(sArg0) == Double.parseDouble(sArg1)); + } else if (arg0.getType().equals(Types.typeFloat) || arg1.getType().equals(Types.typeFloat)) { + result = (Float.parseFloat(sArg0) == Float.parseFloat(sArg1)); + } else if (arg0.getType().equals(Types.typeLong) || arg1.getType().equals(Types.typeLong)) { + result = (Long.parseLong(sArg0) == Long.parseLong(sArg1)); + } else if (arg0.getType().equals(Types.typeInt) || arg1.getType().equals(Types.typeInt)) { + result = (Integer.parseInt(sArg0) == Integer.parseInt(sArg1)); + } else if (arg0.getType().equals(Types.typeString) || arg1.getType().equals(Types.typeString)) { + result = sArg0.toString().equals(sArg1.toString()); + } + if (result) { + return new Constant(true_); + } else { + return new Constant(false_); + } + } + }); + public static final Symbol neq = new Symbol(Parser.NEQ, 2, Symbol.Type.INFIX, new Symbol.IImplGenerator() { + @Override + public String generate(Type type, Type[] childrenTypes, String[] children, String[] childrenSideEffects, String[] sideEffect) { + for (String s: childrenSideEffects) { + sideEffect[0] += s; + } + if (childrenTypes[0] != null && childrenTypes[0].equals(Types.typeString) + && childrenTypes[1] != null && childrenTypes[1].equals(Types.typeString)) { + return "!" + children[0] + ".equals(" + children[1] + ")"; + } + return "(" + children[0] + "!=" + children[1] + ")"; + } + }, new Symbol.ICalculator() { + @Override + public Expression calculate(List args) { + if (!(args.get(0).getClass() == Constant.class)) { + return null; + } + if (!(args.get(1).getClass() == Constant.class)) { + return null; + } + Constant arg0 = (Constant) args.get(0); + Constant arg1 = (Constant) args.get(1); + String sArg0 = arg0.getSymbol().toString(); + String sArg1 = arg1.getSymbol().toString(); + boolean result = false; + if (arg0.getType() == null || arg1.getType() == null) { + if (sArg0.contains(Parser.DOT) || sArg1.contains(Parser.DOT)) { + result = Double.parseDouble(sArg0) != Double.parseDouble(sArg1); + } else { + result = Integer.parseInt(sArg0) != Integer.parseInt(sArg1); + } + } + if (arg0.getType().equals(Types.typeDouble) || arg1.getType().equals(Types.typeDouble)) { + result = (Double.parseDouble(sArg0) != Double.parseDouble(sArg1)); + } else if (arg0.getType().equals(Types.typeFloat) || arg1.getType().equals(Types.typeFloat)) { + result = (Float.parseFloat(sArg0) != Float.parseFloat(sArg1)); + } else if (arg0.getType().equals(Types.typeLong) || arg1.getType().equals(Types.typeLong)) { + result = (Long.parseLong(sArg0) != Long.parseLong(sArg1)); + } else if (arg0.getType().equals(Types.typeInt) || arg1.getType().equals(Types.typeInt)) { + result = (Integer.parseInt(sArg0) != Integer.parseInt(sArg1)); + } else if (arg0.getType().equals(Types.typeString) || arg1.getType().equals(Types.typeString)) { + result = !(sArg0.toString().equals(sArg1.toString())); + } + if (result) { + return new Constant(true_); + } else { + return new Constant(false_); + } + } + }); + public static final Symbol gt = new Symbol(Parser.GT, 2, Symbol.Type.INFIX, ">", Symbol.Type.INFIX, new Symbol.ICalculator() { + @Override + public Expression calculate(List args) { + if (!(args.get(0).getClass() == Constant.class)) { + return null; + } + if (!(args.get(1).getClass() == Constant.class)) { + return null; + } + Constant arg0 = (Constant) args.get(0); + Constant arg1 = (Constant) args.get(1); + String sArg0 = arg0.getSymbol().toString(); + String sArg1 = arg1.getSymbol().toString(); + boolean result = false; + if (arg0.getType() == null || arg1.getType() == null) { + if (sArg0.contains(Parser.DOT) || sArg1.contains(Parser.DOT)) { + result = Double.parseDouble(sArg0) > Double.parseDouble(sArg1); + } else { + result = Integer.parseInt(sArg0) > Integer.parseInt(sArg1); + } + } + if (arg0.getType().equals(Types.typeDouble) || arg1.getType().equals(Types.typeDouble)) { + result = (Double.parseDouble(sArg0) > Double.parseDouble(sArg1)); + } else if (arg0.getType().equals(Types.typeFloat) || arg1.getType().equals(Types.typeFloat)) { + result = (Float.parseFloat(sArg0) > Float.parseFloat(sArg1)); + } else if (arg0.getType().equals(Types.typeLong) || arg1.getType().equals(Types.typeLong)) { + result = (Long.parseLong(sArg0) > Long.parseLong(sArg1)); + } else if (arg0.getType().equals(Types.typeInt) || arg1.getType().equals(Types.typeInt)) { + result = (Integer.parseInt(sArg0) > Integer.parseInt(sArg1)); + } + if (result) { + return new Constant(true_); + } else { + return new Constant(false_); + } + } + }); + public static final Symbol lt = new Symbol(Parser.LT, 2, Symbol.Type.INFIX, "<", Symbol.Type.INFIX, new Symbol.ICalculator() { + @Override + public Expression calculate(List args) { + if (!(args.get(0).getClass() == Constant.class)) { + return null; + } + if (!(args.get(1).getClass() == Constant.class)) { + return null; + } + Constant arg0 = (Constant) args.get(0); + Constant arg1 = (Constant) args.get(1); + String sArg0 = arg0.getSymbol().toString(); + String sArg1 = arg1.getSymbol().toString(); + boolean result = false; + if (arg0.getType() == null || arg1.getType() == null) { + if (sArg0.contains(Parser.DOT) || sArg1.contains(Parser.DOT)) { + result = Double.parseDouble(sArg0) < Double.parseDouble(sArg1); + } else { + result = Integer.parseInt(sArg0) < Integer.parseInt(sArg1); + } + } + if (arg0.getType().equals(Types.typeDouble) || arg1.getType().equals(Types.typeDouble)) { + result = (Double.parseDouble(sArg0) < Double.parseDouble(sArg1)); + } else if (arg0.getType().equals(Types.typeFloat) || arg1.getType().equals(Types.typeFloat)) { + result = (Float.parseFloat(sArg0) < Float.parseFloat(sArg1)); + } else if (arg0.getType().equals(Types.typeLong) || arg1.getType().equals(Types.typeLong)) { + result = (Long.parseLong(sArg0) < Long.parseLong(sArg1)); + } else if (arg0.getType().equals(Types.typeInt) || arg1.getType().equals(Types.typeInt)) { + result = (Integer.parseInt(sArg0) < Integer.parseInt(sArg1)); + } + if (result) { + return new Constant(true_); + } else { + return new Constant(false_); + } + } + }); + public static final Symbol ge = new Symbol(Parser.GE, 2, Symbol.Type.INFIX, ">=", Symbol.Type.INFIX, new Symbol.ICalculator() { + @Override + public Expression calculate(List args) { + if (!(args.get(0).getClass() == Constant.class)) { + return null; + } + if (!(args.get(1).getClass() == Constant.class)) { + return null; + } + Constant arg0 = (Constant) args.get(0); + Constant arg1 = (Constant) args.get(1); + String sArg0 = arg0.getSymbol().toString(); + String sArg1 = arg1.getSymbol().toString(); + boolean result = false; + if (arg0.getType() == null || arg1.getType() == null) { + if (sArg0.contains(Parser.DOT) || sArg1.contains(Parser.DOT)) { + result = Double.parseDouble(sArg0) >= Double.parseDouble(sArg1); + } else { + result = Integer.parseInt(sArg0) >= Integer.parseInt(sArg1); + } + } + if (arg0.getType().equals(Types.typeDouble) || arg1.getType().equals(Types.typeDouble)) { + result = (Double.parseDouble(sArg0) >= Double.parseDouble(sArg1)); + } else if (arg0.getType().equals(Types.typeFloat) || arg1.getType().equals(Types.typeFloat)) { + result = (Float.parseFloat(sArg0) >= Float.parseFloat(sArg1)); + } else if (arg0.getType().equals(Types.typeLong) || arg1.getType().equals(Types.typeLong)) { + result = (Long.parseLong(sArg0) >= Long.parseLong(sArg1)); + } else if (arg0.getType().equals(Types.typeInt) || arg1.getType().equals(Types.typeInt)) { + result = (Integer.parseInt(sArg0) >= Integer.parseInt(sArg1)); + } + if (result) { + return new Constant(true_); + } else { + return new Constant(false_); + } + } + }); + public static final Symbol le = new Symbol(Parser.LE, 2, Symbol.Type.INFIX, "<=", Symbol.Type.INFIX, new Symbol.ICalculator() { + @Override + public Expression calculate(List args) { + if (!(args.get(0).getClass() == Constant.class)) { + return null; + } + if (!(args.get(1).getClass() == Constant.class)) { + return null; + } + Constant arg0 = (Constant) args.get(0); + Constant arg1 = (Constant) args.get(1); + String sArg0 = arg0.getSymbol().toString(); + String sArg1 = arg1.getSymbol().toString(); + boolean result = false; + if (arg0.getType() == null || arg1.getType() == null) { + if (sArg0.contains(Parser.DOT) || sArg1.contains(Parser.DOT)) { + result = Double.parseDouble(sArg0) <= Double.parseDouble(sArg1); + } else { + result = Integer.parseInt(sArg0) <= Integer.parseInt(sArg1); + } + } + if (arg0.getType().equals(Types.typeDouble) || arg1.getType().equals(Types.typeDouble)) { + result = (Double.parseDouble(sArg0) <= Double.parseDouble(sArg1)); + } else if (arg0.getType().equals(Types.typeFloat) || arg1.getType().equals(Types.typeFloat)) { + result = (Float.parseFloat(sArg0) <= Float.parseFloat(sArg1)); + } else if (arg0.getType().equals(Types.typeLong) || arg1.getType().equals(Types.typeLong)) { + result = (Long.parseLong(sArg0) <= Long.parseLong(sArg1)); + } else if (arg0.getType().equals(Types.typeInt) || arg1.getType().equals(Types.typeInt)) { + result = (Integer.parseInt(sArg0) <= Integer.parseInt(sArg1)); + } + if (result) { + return new Constant(true_); + } else { + return new Constant(false_); + } + } + }); + public static final Symbol and = new Symbol(Parser.AND, 2, Symbol.Type.INFIX, "&&", Symbol.Type.INFIX, new Symbol.ICalculator() { + @Override + public Expression calculate(List args) { + if (!(args.get(0).getClass() == Constant.class)) { + return null; + } + if (!(args.get(1).getClass() == Constant.class)) { + return null; + } + Constant arg0 = (Constant) args.get(0); + Constant arg1 = (Constant) args.get(1); + String sArg0 = arg0.getSymbol().toString(); + String sArg1 = arg1.getSymbol().toString(); + boolean result = false; + if (arg0.getType() == null || arg1.getType() == null) return null; + if (arg0.getType().equals(Types.typeBoolean) || arg1.getType().equals(Types.typeBoolean)) { + result = (Boolean.parseBoolean(sArg0) && Boolean.parseBoolean(sArg1)); + } + if (result) { + return new Constant(true_); + } else { + return new Constant(false_); + } + } + }); + public static final Symbol or = new Symbol(Parser.OR, 2, Symbol.Type.INFIX, "||", Symbol.Type.INFIX, new Symbol.ICalculator() { + @Override + public Expression calculate(List args) { + if (!(args.get(0).getClass() == Constant.class)) { + return null; + } + if (!(args.get(1).getClass() == Constant.class)) { + return null; + } + Constant arg0 = (Constant) args.get(0); + Constant arg1 = (Constant) args.get(1); + String sArg0 = arg0.getSymbol().toString(); + String sArg1 = arg1.getSymbol().toString(); + boolean result = false; + if (arg0.getType() == null || arg1.getType() == null) return null; + if (arg0.getType().equals(Types.typeBoolean) || arg1.getType().equals(Types.typeBoolean)) { + result = (Boolean.parseBoolean(sArg0) || Boolean.parseBoolean(sArg1)); + } + if (result) { + return new Constant(true_); + } else { + return new Constant(false_); + } + } + }); + public static final Symbol neg = new Symbol(Parser.NEG, 1, Symbol.Type.PREFIX, "!", Symbol.Type.PREFIX, new Symbol.ICalculator() { + @Override + public Expression calculate(List args) { + if (!(args.get(0).getClass() == Constant.class)) { + return null; + } + Constant arg0 = (Constant) args.get(0); + String sArg0 = arg0.getSymbol().toString(); + boolean result = false; + if (arg0.getType() == null) return null; + if (arg0.getType().equals(Types.typeBoolean)) { + result = !Boolean.parseBoolean(sArg0); + } + if (result) { + return new Constant(true_); + } else { + return new Constant(false_); + } + } + }); + +} diff --git a/src/main/java/constants/Types.java b/src/main/java/constants/Types.java new file mode 100644 index 0000000..ccaa4fe --- /dev/null +++ b/src/main/java/constants/Types.java @@ -0,0 +1,27 @@ +package constants; +import models.algebra.Type; +import parser.Parser; + +public class Types { + + public static final Type typeInt = new Type("Int", "int"); + public static final Type typeLong = new Type("Long", "long", typeInt); + public static final Type typeFloat = new Type("Float", "float", typeInt); + public static final Type typeDouble = new Type("Double", "double", typeFloat); + public static final Type typeBoolean = new Type("Bool", "boolean"); + public static final Type typeString = new Type("Str", "String") { + public String valueToRepresentation(Object value) { + if (value instanceof String) { + return Parser.DOUBLE_QUOT + (String) value + Parser.DOUBLE_QUOT; + } + return value.toString(); + } + public Object representationToValue(String representation) { + if (representation.startsWith(Parser.DOUBLE_QUOT) && representation.endsWith(Parser.DOUBLE_QUOT)) { + return representation.substring(1, representation.length() - 1); + } + return representation; + } + }; + +} diff --git a/src/main/java/models/algebra/Constant.java b/src/main/java/models/algebra/Constant.java new file mode 100644 index 0000000..2e55f0a --- /dev/null +++ b/src/main/java/models/algebra/Constant.java @@ -0,0 +1,51 @@ +package models.algebra; + +import java.util.ArrayList; + +public class Constant extends Term { + + public Constant(String value) { + super(new Symbol(value, 0), new ArrayList()); + } + + public Constant(String value, Type type) { + super(new Symbol((type == null ? value: type.valueToRepresentation(value)), 0), new ArrayList()); + symbol.setSignature(new Type[] {type}); + } + + public Constant(Symbol symbol) { + super(symbol); + } + + @Override + public boolean equals(Object another) { + if (!(another instanceof Constant)) return false; + return symbol.equals(((Constant) another).symbol); + } + + @Override + public Object clone() { + Constant c = new Constant(symbol); + c.setType(type); + return c; + } + + public String toString() { + return symbol.getName(); + } + + public Object getValue() { + if (getType() != null) { + return getType().representationToValue(symbol.getName()); + } + return symbol.getName(); + } + + public String toImplementation(String[] sideEffects) { + if (symbol.isImplGenerative()) { + String exp = symbol.generate(getType(), new Type[] {}, new String[] {}, new String[] {}, sideEffects); + return exp; + } + return symbol.getImplName(); + } +} diff --git a/src/main/java/models/algebra/Expression.java b/src/main/java/models/algebra/Expression.java new file mode 100644 index 0000000..ba4ce79 --- /dev/null +++ b/src/main/java/models/algebra/Expression.java @@ -0,0 +1,36 @@ +package models.algebra; + +import java.util.HashMap; + +public abstract class Expression implements Cloneable { + public abstract Expression getSubTerm(Position pos); + /** + * Get the unification between this expression and another expression. + * @param another another expression + * @return unified expression + */ + public abstract Expression unify(Expression another); + /** + * Get the inverse map to obtain a sub-term of a given output value back from the output value itself. + * @param outputValue an output value (usually a term) + * @param targetPos a position in outputValue + * @return inverse map + */ + public abstract Expression getInverseMap(Expression outputValue, Position targetPos); + public abstract boolean contains(Expression exp); + public abstract Object clone(); + public abstract HashMap getSubTerms(Class clazz); + + public HashMap getVariables() { + return getSubTerms(Variable.class); + } + + /** + * Get the implementation of this expression. + * @param sideEffects an array with an optional implementation that should be written before the evaluation of this expression + * @return the implementation to represent the value of this expression + */ + public String toImplementation(String[] sideEffects) { + return toString(); + } +} diff --git a/src/main/java/models/algebra/Field.java b/src/main/java/models/algebra/Field.java new file mode 100644 index 0000000..b82f0fa --- /dev/null +++ b/src/main/java/models/algebra/Field.java @@ -0,0 +1,46 @@ +package models.algebra; + +import java.util.ArrayList; + +/** + * A field in the implementation (regarded as a constant in the algebraic system) + * @author Nitta + * + */ +public class Field extends Constant { + + public Field(String name) { + super(name); + } + + public Field(String name, Type type) { + super(name); + symbol.setSignature(new Type[] {type}); + } + + public Field(Symbol symbol) { + super(symbol); + } + + public Type getType() { + if (symbol.getSignature() != null && symbol.getSignature().length >= 1) { + return symbol.getSignature()[0]; + } + return null; + } + + @Override + public boolean equals(Object another) { + if (!(another instanceof Field)) return false; + return symbol.equals(((Field) another).symbol); + } + + @Override + public Object clone() { + return new Field(symbol); + } + + public String toImplementation(String[] sideEffects) { + return "this." + super.toImplementation(sideEffects); + } +} diff --git a/src/main/java/models/algebra/FutureWorkException.java b/src/main/java/models/algebra/FutureWorkException.java new file mode 100644 index 0000000..0dad4bb --- /dev/null +++ b/src/main/java/models/algebra/FutureWorkException.java @@ -0,0 +1,5 @@ +package models.algebra; + +public class FutureWorkException extends Exception { + +} diff --git a/src/main/java/models/algebra/InvalidMessage.java b/src/main/java/models/algebra/InvalidMessage.java new file mode 100644 index 0000000..de909e5 --- /dev/null +++ b/src/main/java/models/algebra/InvalidMessage.java @@ -0,0 +1,5 @@ +package models.algebra; + +public class InvalidMessage extends Exception { + +} diff --git a/src/main/java/models/algebra/LambdaAbstraction.java b/src/main/java/models/algebra/LambdaAbstraction.java new file mode 100644 index 0000000..9898224 --- /dev/null +++ b/src/main/java/models/algebra/LambdaAbstraction.java @@ -0,0 +1,30 @@ +package models.algebra; + +import java.util.ArrayList; +import java.util.List; + +public class LambdaAbstraction extends Symbol { + private List variables = null; + private Term term = null; + + public LambdaAbstraction(Variable variable, Term term) { + super("($" + variable.getName() + ")->" + term.toString(), 1, Type.LAMBDA); + this.variables = new ArrayList<>(); + this.variables.add(variable); + this.term = term; + } + + public LambdaAbstraction(List variables, Term term) { + super("($" + variables + ")->" + term.toString(), variables.size(), Type.LAMBDA); + this.variables = variables; + this.term = term; + } + + public List getVariables() { + return variables; + } + + public Term getTerm() { + return term; + } +} diff --git a/src/main/java/models/algebra/Parameter.java b/src/main/java/models/algebra/Parameter.java new file mode 100644 index 0000000..5403bc1 --- /dev/null +++ b/src/main/java/models/algebra/Parameter.java @@ -0,0 +1,40 @@ +package models.algebra; + +/** + * A parameter in the implementation (regarded as a constant in the algebraic system) + * @author Nitta + * + */ +public class Parameter extends Constant { + + public Parameter(String name) { + super(name); + } + + public Parameter(String name, Type type) { + super(name); + symbol.setSignature(new Type[] {type}); + } + + public Parameter(Symbol symbol) { + super(symbol); + } + + public Type getType() { + if (symbol.getSignature() != null && symbol.getSignature().length >= 1) { + return symbol.getSignature()[0]; + } + return null; + } + + @Override + public boolean equals(Object another) { + if (!(another instanceof Parameter)) return false; + return symbol.equals(((Parameter) another).symbol); + } + + @Override + public Object clone() { + return new Parameter(symbol); + } +} diff --git a/src/main/java/models/algebra/ParameterizedIdentifierIsFutureWork.java b/src/main/java/models/algebra/ParameterizedIdentifierIsFutureWork.java new file mode 100644 index 0000000..3a58863 --- /dev/null +++ b/src/main/java/models/algebra/ParameterizedIdentifierIsFutureWork.java @@ -0,0 +1,5 @@ +package models.algebra; + +public class ParameterizedIdentifierIsFutureWork extends FutureWorkException { + +} diff --git a/src/main/java/models/algebra/Position.java b/src/main/java/models/algebra/Position.java new file mode 100644 index 0000000..243e274 --- /dev/null +++ b/src/main/java/models/algebra/Position.java @@ -0,0 +1,52 @@ +package models.algebra; + +import java.util.ArrayList; +import java.util.List; + +public class Position implements Cloneable { + private ArrayList orders = new ArrayList(); + + public Position() { + } + + public Position(ArrayList orders) { + this.orders = orders; + } + + public void addHeadOrder(int order) { + orders.add(0, order); + } + + public int removeHeadOrder() { + return orders.remove(0); + } + + public List getOrders() { + return orders; + } + + public boolean isEmpty() { + return (orders == null || orders.size() == 0); + } + + public boolean isAncestorOf(Position another) { + if (another.orders.size() < this.orders.size()) return false; + for (int i = 0; i < orders.size(); i++) { + if (this.orders.get(i) != another.orders.get(i)) return false; + } + return true; + } + + public Object clone() { + return new Position((ArrayList) orders.clone()); + } + + public boolean equals(Object another) { + if (!(another instanceof Position)) return false; + return orders.equals(((Position) another).orders); + } + + public int hashCode() { + return orders.hashCode(); + } +} diff --git a/src/main/java/models/algebra/Symbol.java b/src/main/java/models/algebra/Symbol.java new file mode 100644 index 0000000..6d6ac02 --- /dev/null +++ b/src/main/java/models/algebra/Symbol.java @@ -0,0 +1,295 @@ +package models.algebra; + +import java.util.List; + +public class Symbol { + protected String name; + protected String implName; + protected int arity = 0; // -1: variable number + protected Type operatorType = Type.PREFIX; + protected Type implOperatorType = Type.PREFIX; + protected Symbol[] inverses = null; + protected models.algebra.Type[] signature = null; + protected int[] implParamOrder = null; + protected IImplGenerator generator = null; + protected ICalculator calculator = null; + + public Symbol(String name) { + this.name = name; + this.implName = name; + this.arity = 0; + } + + public Symbol(String name, int arity) { + this.name = name; + this.implName = name; + this.arity = arity; + } + + public Symbol(String name, int arity, Type operatorType) { + this(name, arity); + this.operatorType = operatorType; + this.implOperatorType = operatorType; + } + + public Symbol(String name, int arity, Type operatorType, String implName, Type implOperatorType) { + this.name = name; + this.implName = implName; + this.arity = arity; + this.operatorType = operatorType; + this.implOperatorType = implOperatorType; + } + + public Symbol(String name, int arity, Type operatorType, String implName, Type implOperatorType, int[] implParamOrder) { + this.name = name; + this.implName = implName; + this.arity = arity; + this.operatorType = operatorType; + this.implOperatorType = implOperatorType; + this.implParamOrder = implParamOrder; + } + + public Symbol(String name, int arity, Type operatorType, IImplGenerator generator) { + this.name = name; + this.implName = name; + this.arity = arity; + this.operatorType = operatorType; + this.generator = generator; + this.implOperatorType = Type.GENERATIVE; + } + + public Symbol(String name, int arity, Type operatorType, IImplGenerator generator, boolean bSideEffect) { + this.name = name; + this.implName = name; + this.arity = arity; + this.operatorType = operatorType; + this.generator = generator; + if (!bSideEffect) { + this.implOperatorType = Type.GENERATIVE; + } else { + this.implOperatorType = Type.GENERATIVE_WITH_SIDE_EFFECT; + } + } + + public Symbol(String name, int arity, ICalculator calculator) { + this.name = name; + this.implName = name; + this.arity = arity; + this.calculator = calculator; + } + + public Symbol(String name, int arity, Type operatorType, ICalculator calculator) { + this.name = name; + this.implName = name; + this.arity = arity; + this.operatorType = operatorType; + this.implOperatorType = operatorType; + this.calculator = calculator; + } + + public Symbol(String name, int arity, Type operatorType, IImplGenerator generator, ICalculator calculator) { + this.name = name; + this.implName = name; + this.arity = arity; + this.operatorType = operatorType; + this.generator = generator; + this.implOperatorType = Type.GENERATIVE; + this.calculator = calculator; + } + + public Symbol(String name, int arity, Type operatorType, String implName, Type implOperatorType, ICalculator calculator) { + this.name = name; + this.implName = implName; + this.arity = arity; + this.operatorType = operatorType; + this.implOperatorType = implOperatorType; + this.calculator = calculator; + } + + public void setArity(int arity) { + this.arity = arity; + } + + public int getArity() { + return arity; + } + + public String getName() { + return name; + } + + public void changeName(String name) { + this.name = name; + this.implName = name; + } + + public Type getOperatorType() { + return operatorType; + } + + public boolean isInfix() { + return (operatorType == Type.INFIX); + } + + public boolean isMethod() { + return (operatorType == Type.METHOD || operatorType == Type.METHOD_WITH_SIDE_EFFECT); + } + + public boolean isLambda() { + return (operatorType == Type.LAMBDA); + } + + public Symbol[] getInverses() { + return inverses; + } + + public void setInverses(Symbol[] inverses) { + this.inverses = inverses; + } + + public models.algebra.Type[] getSignature() { + return signature; + } + + public void setSignature(models.algebra.Type[] signature) { + this.signature = signature; + } + + public String getImplName() { + return implName; + } + + public void setImplName(String implName) { + this.implName = implName; + } + + public Type getImplOperatorType() { + return implOperatorType; + } + + public boolean isImplInfix() { + return (implOperatorType == Type.INFIX); + } + + public boolean isImplMethod() { + return (implOperatorType == Type.METHOD || implOperatorType == Type.METHOD_WITH_SIDE_EFFECT); + } + + public boolean isImplLambda() { + return (implOperatorType == Type.LAMBDA || implOperatorType == Type.LAMBDA_WITH_SIDE_EFFECT); + } + + public boolean isImplGenerative() { + return (implOperatorType == Type.GENERATIVE || implOperatorType == Type.GENERATIVE_WITH_SIDE_EFFECT); + } + + public boolean isImplWithSideEffect() { + return (implOperatorType == Type.METHOD_WITH_SIDE_EFFECT + || implOperatorType == Type.LAMBDA_WITH_SIDE_EFFECT + || implOperatorType == Type.GENERATIVE_WITH_SIDE_EFFECT); + } + + public void setImplOperatorType(Type implOperatorType) { + this.implOperatorType = implOperatorType; + } + + public int[] getImplParamOrder() { + return implParamOrder; + } + + public void setGenerator(IImplGenerator generator) { + this.generator = generator; + } + + /** + * Generate the implementation of this symbol + * @param type the type of this symbol + * @param childrenTypes + * @param childrenImpl the implementations of the children + * @param childrenSideEffects (input) an array of the side effects of the children + * @param sideEffect (output) an array of the side effect of this symbol + * @return the implementation + */ + public String generate(models.algebra.Type type, models.algebra.Type[] childrenTypes, String[] childrenImpl, String[] childrenSideEffects, String[] sideEffect) { + if (generator != null) { + return generator.generate(type, childrenTypes, childrenImpl, childrenSideEffects, sideEffect); + } + return null; + } + + public boolean isCalculatable() { + return (calculator != null); + } + + public Expression calculate(List args) { + if (calculator != null) { + return calculator.calculate(args); + } + return null; + } + + public boolean equals(Object another) { + if (!(another instanceof Symbol)) return false; + return name.equals(((Symbol) another).name) && arity == ((Symbol) another).arity; + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + public String toString() { + return name; + } + + public String toImplementation() { + return implName; + } + + public enum Type { + PREFIX, + INFIX, + METHOD, + METHOD_WITH_SIDE_EFFECT, + LAMBDA, + LAMBDA_WITH_SIDE_EFFECT, + GENERATIVE, + GENERATIVE_WITH_SIDE_EFFECT + } + + public Memento createMemento() { + return new Memento(implName, implOperatorType); + } + + public void setMemento(Memento memento) { + this.implName = memento.implName; + this.implOperatorType = memento.implOperatorType; + } + + public static class Memento { + private String implName; + private Type implOperatorType = Type.PREFIX; + + public Memento(String implName, Type implOperatorType) { + this.implName = implName; + this.implOperatorType = implOperatorType; + } + } + + public interface IImplGenerator { + /** + * Generate the implementation + * @param type the type of this expression + * @param childrenTypes + * @param children the implementations of the children + * @param childrenSideEffects (input) an array of the side effects of the children + * @param sideEffect (output) an array of the side effect of this generator + * @return the generated implementation + */ + public String generate(models.algebra.Type type, models.algebra.Type[] childrenTypes, String children[], String[] childrenSideEffects, String[] sideEffect); + } + + public interface ICalculator { + public Expression calculate(List args); + } +} diff --git a/src/main/java/models/algebra/Term.java b/src/main/java/models/algebra/Term.java new file mode 100644 index 0000000..06c906c --- /dev/null +++ b/src/main/java/models/algebra/Term.java @@ -0,0 +1,448 @@ +package models.algebra; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map.Entry; + +public class Term extends Expression { + protected Symbol symbol = null; + protected List children = new ArrayList<>(); + protected Type type = null; + + public Term(Symbol symbol) { + super(); + this.symbol = symbol; + } + + public Term(Symbol symbol, List children) { + super(); + this.symbol = symbol; + this.children = children; + } + + public Term(Symbol symbol, Expression[] children) { + super(); + this.symbol = symbol; + this.children = new ArrayList<>(Arrays.asList(children)); + } + + public Symbol getSymbol() { + return symbol; + } + + public int getArity() { + return symbol.getArity(); + } + + public void setType(Type type) { + this.type = type; + } + + public Type getType() { + if (type == null) { + if (symbol.getSignature() == null) return null; + return symbol.getSignature()[0]; + } + return type; + } + + public boolean addChild(Expression child) { + if (getArity() != -1 && children.size() >= getArity()) return false; + children.add(child); + return true; + } + + public boolean setChild(int n, Expression child) { + if (getArity() != -1 && n >= getArity()) return false; + children.set(n, child); + return true; + } + + public void addChild(Expression child, boolean bForced) { + if (!bForced && getArity() != -1 && children.size() >= getArity()) return; + children.add(child); + } + + public void addChild(int n, Expression child, boolean bForced) { + if (!bForced && getArity() != -1 && children.size() >= getArity()) return; + children.add(n, child); + } + + public Expression getChild(int n) { + return children.get(n); + } + + public List getChildren() { + return children; + } + + public HashMap getSubTerms(Class clazz) { + HashMap subTerms = new HashMap<>(); + Class thisClass = this.getClass(); + while (thisClass != null) { + if (clazz == thisClass) { + subTerms.put(new Position(), (T) this); + break; + } + thisClass = thisClass.getSuperclass(); + } + for (int i = 0; i < children.size(); i++) { + if (children.get(i) != null) { + HashMap terms = children.get(i).getSubTerms(clazz); + for (Entry term: terms.entrySet()) { + Position pos = term.getKey(); + pos.addHeadOrder(i); + subTerms.put(pos, term.getValue()); + } + } + } + return subTerms; + } + + public Expression getSubTerm(Position pos) { + if (pos.isEmpty()) return this; + pos = (Position) pos.clone(); + int i = pos.removeHeadOrder(); + if (i >= children.size()) return null; + if (children.get(i) == null) return null; + return children.get(i).getSubTerm(pos); + } + + public Term substitute(Variable variable, Expression value) { + Term newTerm = (Term) this.clone(); + HashMap variables = getVariables(); + for (Entry varEnt: variables.entrySet()) { + if (varEnt.getValue().equals(variable)) { + newTerm.replaceSubTerm(varEnt.getKey(), value); + } + } + return newTerm; + } + + public void replaceSubTerm(Position pos, Expression newSubTerm) { + if (pos.isEmpty()) return; + pos = (Position) pos.clone(); + int i = pos.removeHeadOrder(); + if (pos.isEmpty()) { + children.set(i, newSubTerm); + } else { + if (!(children.get(i) instanceof Term)) return; + ((Term) children.get(i)).replaceSubTerm(pos, newSubTerm); + } + } + + @Override + public Expression unify(Expression another) { + if (another instanceof Variable) return (Expression) this.clone(); + if (this instanceof Constant) return (Expression) this.clone(); + if (another instanceof Constant) return (Expression) another.clone(); + if (another instanceof Term) { + Term anotherTerm = (Term) another; + if (!symbol.equals(anotherTerm.symbol)) return null; + if (children.size() != anotherTerm.children.size()) return null; + Term unifiedTerm = new Term(symbol); + for (int i = 0; i < children.size(); i++) { + if (children.get(i) != null) { + unifiedTerm.addChild(children.get(i).unify(anotherTerm.children.get(i))); + } else { + unifiedTerm.addChild(anotherTerm.children.get(i)); + } + } + return unifiedTerm; + } else { + return null; + } + } + + public Expression reduce() { + if (symbol.isLambda()) { + // Lambda beta-reduction + LambdaAbstraction newSymbol = ((LambdaAbstraction) symbol); + Term newTerm = newSymbol.getTerm(); + List newVariables = newSymbol.getVariables(); + List newChildren = children; + while (newVariables.size() > 0 && newChildren.size() > 0) { + newTerm = newTerm.substitute(newVariables.get(0), newChildren.get(0)); + newVariables = newVariables.subList(1, newVariables.size()); + newChildren = newChildren.subList(1, newChildren.size()); + newSymbol = new LambdaAbstraction(newVariables, newTerm); + } + if (newSymbol.arity == 0 && newChildren.size() == 0) { + return newTerm; + } else { + return new Term(newSymbol, newChildren); + } + } else if (symbol.isCalculatable()) { + List newChildren = new ArrayList<>(); + for (Expression child: children) { + if (child instanceof Term) { + child = ((Term) child).reduce(); + } + newChildren.add(child); + } + Expression newTerm = symbol.calculate(newChildren); + if (newTerm == null) return this; + return newTerm; + } else { + // Calculate inverse map + List newChildren = new ArrayList<>(); + boolean bReduced = false; + for (Expression child: children) { + if (child instanceof Term && !(child instanceof Constant)) { + Expression newChild = ((Term) (child)).reduce(); + if (newChild != child) { + bReduced = true; + child = newChild; + } + } + newChildren.add(child); + } + if (symbol.arity == 1 && newChildren.size() == 1) { + Expression child = newChildren.get(0); + if (child instanceof Term && !(child instanceof Constant)) { + Symbol childSymbol = ((Term) child).getSymbol(); + if (childSymbol.getInverses() != null) { + for (int i = 0; i < childSymbol.getInverses().length; i++) { + if (symbol.equals(childSymbol.getInverses()[i])) { + return ((Term) child).getChild(i); + } + } + } + } + } + if (!bReduced) return this; + Term newTerm = (Term) this.clone(); + newTerm.children = newChildren; + return newTerm; + } + } + + @Override + public Expression getInverseMap(Expression outputValue, Position targetPos) { + if (targetPos.isEmpty()) return outputValue; + targetPos = (Position) targetPos.clone(); + int i = targetPos.removeHeadOrder(); + Symbol[] inverseSymbols = symbol.getInverses(); + if (inverseSymbols == null || i >= inverseSymbols.length || inverseSymbols[i] == null) return null; + Term inverseMap = new Term(inverseSymbols[i]); + inverseMap.addChild(outputValue); + for (int n = 0; n < inverseSymbols[i].getArity(); n++) { + if (n != i) { + inverseMap.addChild(children.get(n)); + } + } + return children.get(i).getInverseMap(inverseMap, targetPos); + } + + @Override + public boolean contains(Expression exp) { + if (equals(exp)) return true; + for (Expression e: children) { + if (e.contains(exp)) return true; + } + return false; + } + + @Override + public boolean equals(Object another) { + if (!(another instanceof Term)) return false; + if (this == another) return true; + Term anotherTerm = (Term) another; + if (!symbol.equals(anotherTerm.symbol)) return false; + if (children.size() != anotherTerm.children.size()) return false; + if (type != anotherTerm.type) return false; + for (int i = 0; i < children.size(); i++) { + Expression e = children.get(i); + Expression e2 = anotherTerm.children.get(i); + if (!e.equals(e2)) return false; + } + return true; + } + + @Override + public int hashCode() { + return symbol.hashCode(); + } + + + @Override + public Object clone() { + Term newTerm = new Term(symbol); + for (Expression e: children) { + if (e != null) { + newTerm.addChild((Expression) e.clone()); + } else { + newTerm.addChild(null); + } + } + newTerm.type = type; + return newTerm; + } + + public String toString() { + if (getArity() == 2 && symbol.isInfix()) { + return "(" + children.get(0) + symbol.toString() + children.get(1) + ")"; + } + if ((getArity() >= 1 || getArity() == -1) && symbol.isMethod()) { + String exp = children.get(0).toString() + "." + symbol.toString() + "("; + String delimiter = ""; + for (int i = 1; i < children.size(); i++) { + Expression e = children.get(i); + exp += (delimiter + e.toString()); + delimiter = ","; + } + return exp + ")"; + } else { + String exp = symbol.toString() + "("; + String delimiter = ""; + for (Expression e: children) { + if (e != null) { + exp += (delimiter + e.toString()); + } else { + exp += (delimiter + "null"); + } + delimiter = ","; + } + return exp + ")"; + } + } + + + public String toImplementation(String[] sideEffects) { + int[] implParamOrder = symbol.getImplParamOrder(); + if (symbol.isImplLambda()) { + String[] components = symbol.getImplName().split("->"); + String component0 = components[0].replace("(", "").replace(")", ""); + String[] params = component0.split(","); + String exp = components[1]; + String receiver = ""; + if (implParamOrder == null) { + receiver = children.get(0).toImplementation(sideEffects); + exp = exp.replace(params[0], receiver); + for (int i = 1; i < params.length; i++) { + exp = exp.replace(params[i], children.get(i).toImplementation(sideEffects)); + } + } else { + receiver = children.get(implParamOrder[0]).toImplementation(sideEffects); + exp = exp.replace(params[0], receiver); + for (int i = 1; i < params.length; i++) { + exp = exp.replace(params[i], children.get(implParamOrder[i]).toImplementation(sideEffects)); + } + } + if (symbol.isImplWithSideEffect()) { + sideEffects[0] = sideEffects[0] + exp + ";\n"; + exp = receiver; + } + return exp; + } + if (symbol.isImplGenerative()) { + Type childrenTypes[] = new Type[children.size()]; + String childrenImpl[] = new String[children.size()]; + String childrenSideEffects[] = new String[children.size()]; + if (implParamOrder == null) { + for (int i = 0; i < children.size(); i++) { + Expression child = children.get(i); + if (child instanceof Variable) { + childrenTypes[i] = ((Variable) child).getType(); + } else if (child instanceof Term) { + childrenTypes[i] = ((Term) child).getType(); + } + String childSideEffect[] = new String[] {""}; + childrenImpl[i] = child.toImplementation(childSideEffect); + childrenSideEffects[i] = childSideEffect[0]; + } + String exp = symbol.generate(getType(), childrenTypes, childrenImpl, childrenSideEffects, sideEffects); + if (symbol.isImplWithSideEffect()) { + sideEffects[0] = sideEffects[0] + exp; + exp = childrenImpl[0]; // the value of this term + } + return exp; + } else { + for (int i = 0; i < children.size(); i++) { + Expression child = children.get(implParamOrder[i]); + if (child instanceof Variable) { + childrenTypes[i] = ((Variable) child).getType(); + } else if (child instanceof Term) { + childrenTypes[i] = ((Term) child).getType(); + } + String childSideEffect[] = new String[] {""}; + childrenImpl[i] = child.toImplementation(childSideEffect); + childrenSideEffects[i] = childSideEffect[0]; + } + String exp = symbol.generate(getType(), childrenTypes, childrenImpl, childrenSideEffects, sideEffects); + if (symbol.isImplWithSideEffect()) { + sideEffects[0] = sideEffects[0] + exp; + exp = childrenImpl[0]; // the value of this term + } + return exp; + } + } + if (getArity() == 2 && symbol.isImplInfix()) { + if (implParamOrder == null) { + return "(" + children.get(0).toImplementation(sideEffects) + symbol.toImplementation() + children.get(1).toImplementation(sideEffects) + ")"; + } else { + return "(" + children.get(implParamOrder[0]).toImplementation(sideEffects) + symbol.toImplementation() + children.get(implParamOrder[1]).toImplementation(sideEffects) + ")"; + } + } + if ((getArity() >= 1 || getArity() == -1) && symbol.isImplMethod()) { + if (implParamOrder == null) { + String exp = null; + String receiver = ""; + if (children.size() > 0 && children.get(0) != null) { + receiver = children.get(0).toImplementation(sideEffects); + exp = receiver + "." + symbol.toImplementation() + "("; + } else { + exp = symbol.toImplementation() + "("; + } + String delimiter = ""; + for (int i = 1; i < children.size(); i++) { + Expression e = children.get(i); + exp += (delimiter + e.toImplementation(sideEffects)); + delimiter = ","; + } + exp += ")"; + if (symbol.isImplWithSideEffect()) { + sideEffects[0] = sideEffects[0] + exp + ";\n"; + exp = receiver; + } + return exp; + } else { + String receiver = children.get(implParamOrder[0]).toImplementation(sideEffects); + String exp = receiver + "." + symbol.toImplementation() + "("; + String delimiter = ""; + for (int i = 1; i < children.size(); i++) { + Expression e = children.get(implParamOrder[i]); + exp += (delimiter + e.toImplementation(sideEffects)); + delimiter = ","; + } + exp += ")"; + if (symbol.isImplWithSideEffect()) { + sideEffects[0] = sideEffects[0] + exp + ";\n"; + exp = receiver; + } + return exp; + } + } else { + if (implParamOrder == null) { + String exp = symbol.toImplementation() + "("; + String delimiter = ""; + for (Expression e: children) { + exp += (delimiter + e.toImplementation(sideEffects)); + delimiter = ","; + } + return exp + ")"; + } else { + String exp = symbol.toImplementation() + "("; + String delimiter = ""; + for (int i = 0; i < children.size(); i++) { + Expression e = children.get(implParamOrder[i]); + exp += (delimiter + e.toImplementation(sideEffects)); + delimiter = ","; + } + return exp + ")"; + } + } + } +} diff --git a/src/main/java/models/algebra/Type.java b/src/main/java/models/algebra/Type.java new file mode 100644 index 0000000..207cb6c --- /dev/null +++ b/src/main/java/models/algebra/Type.java @@ -0,0 +1,124 @@ +package models.algebra; + +import java.util.ArrayList; +import java.util.List; + +public class Type { + private String typeName; + private String implementationTypeName; + private String interfaceTypeName; + private List parentTypes = new ArrayList<>(); + + public Type(String typeName, String implementationTypeName) { + this.typeName = typeName; + this.implementationTypeName = implementationTypeName; + this.interfaceTypeName = implementationTypeName; + } + + public Type(String typeName, String implementationTypeName, String interfaceTypeName) { + this.typeName = typeName; + this.implementationTypeName = implementationTypeName; + this.interfaceTypeName = interfaceTypeName; + } + + public Type(String typeName, String implementationTypeName, Type parentType) { + this.typeName = typeName; + this.implementationTypeName = implementationTypeName; + this.interfaceTypeName = implementationTypeName; + this.parentTypes.add(parentType); + } + + public Type(String typeName, String implementationTypeName, String interfaceTypeName, Type parentType) { + this.typeName = typeName; + this.implementationTypeName = implementationTypeName; + this.interfaceTypeName = interfaceTypeName; + this.parentTypes.add(parentType); + } + + public String getTypeName() { + return typeName; + } + + public void setTypeName(String typeName) { + this.typeName = typeName; + } + + public String getImplementationTypeName() { + return implementationTypeName; + } + + public void setImplementationTypeName(String implementastionTypeName) { + this.implementationTypeName = implementastionTypeName; + } + + public String getInterfaceTypeName() { + return interfaceTypeName; + } + + public void setInterfaceTypeName(String interfaceTypeName) { + this.interfaceTypeName = interfaceTypeName; + } + + public List getParentTypes() { + return parentTypes; + } + + public void addParentType(Type parentType) { + parentTypes.add(parentType); + } + + public void replaceParentType(Type oldParentType, Type newParentType) { + parentTypes.set(parentTypes.indexOf(oldParentType), newParentType); + } + + public boolean isAncestorOf(Type another) { + if (this.equals(another)) return true; + if (another == null || another.getParentTypes() == null) return false; + for (Type anothersParentType: another.getParentTypes()) { + if (isAncestorOf(anothersParentType)) return true; + } + return false; + } + + public String valueToRepresentation(Object value) { + if (value instanceof String) return (String) value; + return value.toString(); + } + + public Object representationToValue(String representation) { + return representation; + } + + @Override + public boolean equals(Object another) { + if (this == another) return true; + if (another == null) return false; + if (!(another instanceof Type)) return false; + if (!typeName.equals(((Type) another).typeName)) return false; + if (!implementationTypeName.equals(((Type) another).implementationTypeName)) return false; + if (!interfaceTypeName.equals(((Type) another).interfaceTypeName)) return false; + return true; + } + + public Memento createMemento() { + return new Memento(implementationTypeName, interfaceTypeName, parentTypes); + } + + public void setMemento(Memento memento) { + this.implementationTypeName = memento.implementationTypeName; + this.interfaceTypeName = memento.interfaceTypeName; + this.parentTypes = memento.parentTypes; + } + + public static class Memento { + private String implementationTypeName; + private String interfaceTypeName; + private List parentTypes; + + public Memento(String implementationTypeName, String interfaceTypeName, List parentTypes) { + this.implementationTypeName = implementationTypeName; + this.interfaceTypeName = interfaceTypeName; + this.parentTypes = parentTypes; + } + } +} diff --git a/src/main/java/models/algebra/UnificationFailed.java b/src/main/java/models/algebra/UnificationFailed.java new file mode 100644 index 0000000..46e06a7 --- /dev/null +++ b/src/main/java/models/algebra/UnificationFailed.java @@ -0,0 +1,5 @@ +package models.algebra; + +public class UnificationFailed extends Exception { + +} diff --git a/src/main/java/models/algebra/ValueUndefined.java b/src/main/java/models/algebra/ValueUndefined.java new file mode 100644 index 0000000..61dab0e --- /dev/null +++ b/src/main/java/models/algebra/ValueUndefined.java @@ -0,0 +1,5 @@ +package models.algebra; + +public class ValueUndefined extends Exception { + +} diff --git a/src/main/java/models/algebra/Variable.java b/src/main/java/models/algebra/Variable.java new file mode 100644 index 0000000..a3161a9 --- /dev/null +++ b/src/main/java/models/algebra/Variable.java @@ -0,0 +1,87 @@ +package models.algebra; + +import java.util.HashMap; + +public class Variable extends Expression { + private String name; + private Type type = null; + + public Variable(String name) { + super(); + this.name = name; + } + + public Variable(String name, Type type) { + super(); + this.name = name; + this.type = type; + } + + public String getName() { + return name; + } + + public Type getType() { + return type; + } + + public void setType(Type type) { + this.type = type; + } + + @Override + public HashMap getSubTerms(Class clazz) { + HashMap subTerms = new HashMap<>(); + if (clazz == this.getClass()) { + subTerms.put(new Position(), (T) this); + } + return subTerms; + } + + @Override + public Expression getSubTerm(Position pos) { + if (pos.isEmpty()) return this; + return null; + } + + @Override + public Expression unify(Expression another) { + return (Expression) another.clone(); + } + + @Override + public Expression getInverseMap(Expression outputValue, Position targetPos) { + if (targetPos.isEmpty()) return outputValue; + return null; + } + + @Override + public boolean contains(Expression exp) { + return equals(exp); + } + + @Override + public boolean equals(Object another) { + if (!(another instanceof Variable)) return false; + return name.equals(((Variable) another).name); + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public Object clone() { + return new Variable(name, type); + } + + public String toString() { + if (type == null) return name; + return name + ":" + type.getTypeName(); + } + + public String toImplementation(String[] sideEffects) { + return name; + } +} diff --git a/src/main/java/parser/Parser.java b/src/main/java/parser/Parser.java new file mode 100644 index 0000000..aa61b9c --- /dev/null +++ b/src/main/java/parser/Parser.java @@ -0,0 +1,429 @@ +package parser; + +import java.io.BufferedReader; +import java.io.IOException; + +import java.util.ArrayList; +import java.util.List; + +import constants.Symbols; +import constants.Types; +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.Symbol; +import models.algebra.Term; +import models.algebra.Variable; +import parser.exceptions.ExpectedDoubleQuotation; +import parser.exceptions.ExpectedRightBracket; + +public class Parser { + protected TokenStream stream; + + public static final String LEFT_BRACKET = "("; + public static final String RIGHT_BRACKET = ")"; + public static final String LEFT_BRACKET_REGX = "\\("; + public static final String RIGHT_BRACKET_REGX = "\\)"; + public static final String ADD = "+"; + public static final String MUL = "*"; + public static final String SUB = "-"; + public static final String DIV = "/"; + public static final String MOD = "%"; + public static final String MINUS = "-"; + public static final String EQ = "=="; + public static final String NEQ = "!="; + public static final String GT = ">"; + public static final String LT = "<"; + public static final String GE = ">="; + public static final String LE = "<="; + public static final String AND = "&&"; + public static final String OR = "||"; + public static final String NEG = "!"; + public static final String ADD_REGX = "\\+"; + public static final String MUL_REGX = "\\*"; + public static final String SUB_REGX = "\\-"; + public static final String DIV_REGX = "/"; + public static final String OR_REGX = "\\|\\|"; + public static final String EQUALS = "="; + public static final String ASSIGNMENT = "="; + public static final String COMMA = ","; + public static final String COLON = ":"; + public static final String DOT = "."; + public static final String DOT_REGX = "\\."; + public static final String DOUBLE_QUOT = "\""; + + public Parser(final TokenStream stream) { + this.stream = stream; + } + + public Parser(final BufferedReader reader) { + this.stream = new TokenStream(); + try { + String line; + while ((line = reader.readLine()) != null) { + stream.addLine(line); + } + reader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public Expression parseTerm(TokenStream stream) throws ExpectedRightBracket, ExpectedDoubleQuotation { + ArrayList expressions = new ArrayList<>(); + ArrayList operators = new ArrayList<>(); + String operator = null; + for (;;) { + String leftBracketOrMinusOrNeg = stream.next(); + if (leftBracketOrMinusOrNeg.equals(LEFT_BRACKET)) { + Expression exp = parseTerm(stream); + String rightBracket = stream.next(); + if (!rightBracket.equals(RIGHT_BRACKET)) throw new ExpectedRightBracket(stream.getLine()); + expressions.add(exp); + } else { + Symbol minusOrNeg = null; + String symbolName = null; + if (leftBracketOrMinusOrNeg.equals(MINUS)) { + minusOrNeg = Symbols.minus; // not sub + symbolName = stream.next(); + } else if (leftBracketOrMinusOrNeg.equals(NEG)) { + minusOrNeg = Symbols.neg; + symbolName = stream.next(); + } else if (leftBracketOrMinusOrNeg.equals(DOUBLE_QUOT)) { + symbolName = DOUBLE_QUOT + stream.next() + DOUBLE_QUOT; + String doubleQuot = stream.next(); + if (!doubleQuot.equals(DOUBLE_QUOT)) throw new ExpectedDoubleQuotation(stream.getLine()); + } else { + symbolName = leftBracketOrMinusOrNeg; + } + Expression exp = null; + if (Character.isDigit(symbolName.charAt(0))) { + // maybe a numerical value + if (stream.checkNext() != null && stream.checkNext().equals(DOT)) { + // Because tokens are separated by a DOT. + stream.next(); + symbolName += DOT + stream.next(); // decimal fraction + } + Double d = Double.parseDouble(symbolName); + // a numerical value + if (symbolName.contains(DOT)) { + exp = new Constant(symbolName, Types.typeDouble); + } else { + exp = new Constant(symbolName, Types.typeInt); + } + } else if (symbolName.startsWith(DOUBLE_QUOT) && symbolName.endsWith(DOUBLE_QUOT)) { + // a string value + exp = new Constant(symbolName.substring(1, symbolName.length() - 1), Types.typeString); + } else { + // a variable + exp = parseVariable(stream, symbolName); + } + + if (minusOrNeg != null) { + Term minusOrNegTerm = new Term(minusOrNeg); + minusOrNegTerm.addChild(exp); + expressions.add(minusOrNegTerm); + } else { + expressions.add(exp); + } + } + operator = stream.checkNext(); + if (operator == null) { + break; + } else if (operator.equals(ADD)) { + operators.add(Symbols.add); + stream.next(); + } else if (operator.equals(MUL)) { + operators.add(Symbols.mul); + stream.next(); + } else if (operator.equals(SUB)) { + operators.add(Symbols.sub); // not minus + stream.next(); + } else if (operator.equals(DIV)) { + operators.add(Symbols.div); + stream.next(); + } else if (operator.equals(MOD)) { + operators.add(Symbols.mod); + stream.next(); + } else if (operator.equals(EQ)) { + operators.add(Symbols.eq); + stream.next(); + } else if (operator.equals(NEQ)) { + operators.add(Symbols.neq); + stream.next(); + } else if (operator.equals(GT)) { + operators.add(Symbols.gt); + stream.next(); + } else if (operator.equals(LT)) { + operators.add(Symbols.lt); + stream.next(); + } else if (operator.equals(GE)) { + operators.add(Symbols.ge); + stream.next(); + } else if (operator.equals(LE)) { + operators.add(Symbols.le); + stream.next(); +// } else if (operator.equals(AND)) { +// operators.add(Symbols.and); +// stream.next(); +// } else if (operator.equals(OR)) { +// operators.add(Symbols.or); +// stream.next(); + } else { + break; + } + } + if (expressions.size() == 1) { + // no arithmetic operators + return expressions.get(0); + } + ArrayList monomials = new ArrayList<>(); + ArrayList addSubs = new ArrayList<>(); + Expression first = expressions.get(0); + int i = 1; + Term rootTerm = null; + for (Symbol op: operators) { + Expression second = expressions.get(i); + if (op.getName().equals(MUL) || op.getName().equals(DIV) || op.getName().equals(MOD)) { + // higher priority than add and sub + Term term = new Term(op); + term.addChild(first); + term.addChild(second); + first = term; + } else if (op.getName().equals(EQ) || op.getName().equals(NEQ) || op.getName().equals(GT) || op.getName().equals(LT) + || op.getName().equals(GE) || op.getName().equals(LE) || op.getName().equals(AND) || op.getName().equals(OR)) { + // lower priority than add and sub + if (first != null) monomials.add(first); + Expression firstMonomial = monomials.get(0); + int j = 1; + for (Symbol op2: addSubs) { + Expression secondMonomial = monomials.get(j); + Term term = new Term(op2); + term.addChild(firstMonomial); + term.addChild(secondMonomial); + firstMonomial = term; + j++; + } + if (rootTerm == null) { + rootTerm = new Term(op); + rootTerm.addChild(firstMonomial); + } else { + rootTerm.addChild(firstMonomial); + firstMonomial = rootTerm; + rootTerm = new Term(op); + rootTerm.addChild(firstMonomial); + } + monomials.clear(); + addSubs.clear(); + first = second; + } else { + // add or sub ==> new monomial + monomials.add(first); + addSubs.add(op); + first = second; + } + i++; + } + if (first != null) monomials.add(first); + Expression firstMonomial = monomials.get(0); + i = 1; + for (Symbol op: addSubs) { + Expression secondMonomial = monomials.get(i); + Term term = new Term(op); + term.addChild(firstMonomial); + term.addChild(secondMonomial); + firstMonomial = term; + i++; + } + if (rootTerm == null) { + return firstMonomial; + } else { + rootTerm.addChild(firstMonomial); + return rootTerm; + } + } + + public Variable parseVariable(TokenStream stream, String symbolName) { + return new Variable(symbolName); + } + + + protected Boolean doesMatchToKeyword(final String token, final String specificTokenName) { + if(token == null) return false; + if(specificTokenName == null) return false; + return token.equals(specificTokenName); + } + + public static class TokenStream { + private ArrayList> tokens = new ArrayList<>(); + private ArrayList lines = new ArrayList<>(); + private int line = 0; + private int n = 0; + + public TokenStream() { + line = 0; + n = 0; + } + + public void addLine(String line) { + lines.add(line); + line = line.trim(); + ArrayList tokenList = splitByDoubleQuotation(line); + tokenList = splitBy(tokenList, ADD, ADD_REGX); + tokenList = splitBy(tokenList, MUL, MUL_REGX); + tokenList = splitBy(tokenList, SUB, SUB_REGX); + tokenList = splitBy(tokenList, DIV, DIV_REGX); + tokenList = splitBy(tokenList, MOD, MOD); + tokenList = splitBy(tokenList, EQ, EQ); + tokenList = splitBy(tokenList, NEQ, NEQ); + tokenList = splitBy(tokenList, GE, GE); + tokenList = splitBy(tokenList, LE, LE); + tokenList = splitBy(tokenList, GT, GT); + tokenList = splitBy(tokenList, LT, LT); + tokenList = splitBy(tokenList, AND, AND); + tokenList = splitBy(tokenList, OR, OR_REGX); + tokenList = splitBy(tokenList, NEG, NEG); + tokenList = splitBy(tokenList, DOT, DOT_REGX); + tokenList = splitBy(tokenList, COMMA, COMMA); + tokenList = splitBy(tokenList, COLON, COLON); + tokenList = splitBy(tokenList, LEFT_BRACKET, LEFT_BRACKET_REGX); + tokenList = splitBy(tokenList, RIGHT_BRACKET, RIGHT_BRACKET_REGX); + tokenList = splitBy(tokenList, EQUALS, EQUALS); + tokens.add(tokenList); + } + + private ArrayList splitBy(final List tokens, final String delimiter, final String delimiterRegx) { + ArrayList newTokens = new ArrayList<>(); + for (Token token: tokens) { + if (token.isAtomic()) { + newTokens.add(token); + } else { + String[] splitTokens = token.split(delimiterRegx); + boolean fFirstToken = true; + for (String t: splitTokens) { + if (!fFirstToken) { + newTokens.add(new Token(delimiter, true)); + } + if (t.length() > 0) { + newTokens.add(new Token(t)); + } + fFirstToken = false; + } + while (token.endsWith(delimiter)) { + newTokens.add(new Token(delimiter, true)); + token = token.substring(0, token.length() - 1); + } + } + } + return newTokens; + } + + private ArrayList splitByDoubleQuotation(String line) { + ArrayList newTokens = new ArrayList<>(); + String[] tokens = line.split(DOUBLE_QUOT); + boolean fFirstToken = true; + for (int i = 0; i < tokens.length; i++) { + String token = tokens[i]; + if (!fFirstToken) { + newTokens.add(new Token(DOUBLE_QUOT, true)); + } + if (!fFirstToken || token.length() > 0) { + if (i % 2 == 0) { + for (String t: token.split("[ \t]")) { + newTokens.add(new Token(t)); + } + } else { + // string literal + newTokens.add(new Token(token, true)); + } + } + fFirstToken = false; + } + if (line.endsWith(DOUBLE_QUOT)) { + newTokens.add(new Token(DOUBLE_QUOT, true)); + } + return newTokens; + } + + public String next() { + if (line >= tokens.size()) return null; + while (n >= tokens.get(line).size()) { + line++; + n = 0; + if (line >= tokens.size()) return null; + } + String token = tokens.get(line).get(n).getTokenStr(); + n++; + return token; + } + + public String checkNext() { + if (line >= tokens.size()) return null; + while (n >= tokens.get(line).size()) { + line++; + n = 0; + if (line >= tokens.size()) return null; + } + return tokens.get(line).get(n).getTokenStr(); + } + + public boolean hasNext() { + if (line >= tokens.size()) return false; + while (n >= tokens.get(line).size()) { + line++; + n = 0; + if (line >= tokens.size()) return false; + } + return true; + } + + public int getLine() { + return line; + } + + public String getSourceText(int from, int to) { + String text = ""; + for (int l = from; l <= to; l++) { + text += lines.get(l) + "\n"; + } + return text; + } + } + + public static class Token { + String token; + boolean isAtomic = false; + + public Token(String token) { + this.token = token; + } + + public Token(String token, boolean isAtomic) { + this.token = token; + this.isAtomic = isAtomic; + } + + public String getTokenStr() { + return token; + } + + public boolean isAtomic() { + return isAtomic; + } + + public String[] split(String delimiterRegx) { + return token.split(delimiterRegx); + } + + public boolean endsWith(String delimiter) { + return token.endsWith(delimiter); + } + + public int length() { + return token.length(); + } + + public Token substring(int beginIdx, int endIdx) { + return new Token(token.substring(beginIdx, endIdx)); + } + } +} diff --git a/src/main/java/parser/exceptions/ExpectedDoubleQuotation.java b/src/main/java/parser/exceptions/ExpectedDoubleQuotation.java new file mode 100644 index 0000000..434bec3 --- /dev/null +++ b/src/main/java/parser/exceptions/ExpectedDoubleQuotation.java @@ -0,0 +1,8 @@ +package parser.exceptions; + +public class ExpectedDoubleQuotation extends ParseException { + + public ExpectedDoubleQuotation(int line) { + super(line); + } +} diff --git a/src/main/java/parser/exceptions/ExpectedRightBracket.java b/src/main/java/parser/exceptions/ExpectedRightBracket.java new file mode 100644 index 0000000..6d99d81 --- /dev/null +++ b/src/main/java/parser/exceptions/ExpectedRightBracket.java @@ -0,0 +1,9 @@ +package parser.exceptions; + +public class ExpectedRightBracket extends ParseException { + + public ExpectedRightBracket(int line) { + super(line); + } + +} diff --git a/src/main/java/parser/exceptions/ParseException.java b/src/main/java/parser/exceptions/ParseException.java new file mode 100644 index 0000000..b28550d --- /dev/null +++ b/src/main/java/parser/exceptions/ParseException.java @@ -0,0 +1,10 @@ +package parser.exceptions; + +public class ParseException extends RuntimeException { + protected int line; + + public ParseException(int line) { + super("at line " + (line + 1)); + this.line = line; + } +} diff --git a/src/main/java/utils/ExpressionUitls.java b/src/main/java/utils/ExpressionUitls.java index c6313a4..d223bcf 100644 --- a/src/main/java/utils/ExpressionUitls.java +++ b/src/main/java/utils/ExpressionUitls.java @@ -2,20 +2,15 @@ import java.util.Map; +import constants.Symbols; import exceptions.NonLinearExpressionException; import models.algebra.Constant; import models.algebra.Expression; import models.algebra.Symbol; import models.algebra.Term; import models.algebra.Variable; -import models.dataConstraintModel.DataConstraintModel; -import models.dataFlowModel.DataTransferModel; import parser.Parser; import parser.Parser.TokenStream; -import parser.exceptions.ExpectedColon; -import parser.exceptions.ExpectedDoubleQuotation; -import parser.exceptions.ExpectedRightBracket; -import parser.exceptions.WrongJsonExpression; public class ExpressionUitls { @@ -30,17 +25,17 @@ } Term term = (Term) expression; Symbol symbol = term.getSymbol(); - if(symbol.equals(DataConstraintModel.add)) { + if(symbol.equals(Symbols.add)) { Expression c1 = term.getChild(0); Expression c2 = term.getChild(1); res += getCoefficientAndConstantsFromExpression(c1, coefficients, curWeight); res += getCoefficientAndConstantsFromExpression(c2, coefficients, curWeight); - } else if(symbol.equals(DataConstraintModel.sub)) { + } else if(symbol.equals(Symbols.sub)) { Expression c1 = term.getChild(0); Expression c2 = term.getChild(1); res += getCoefficientAndConstantsFromExpression(c1, coefficients, curWeight); res += getCoefficientAndConstantsFromExpression(c2, coefficients, -curWeight); - } else if(symbol.equals(DataConstraintModel.mul)) { + } else if(symbol.equals(Symbols.mul)) { Expression c1 = term.getChild(0); Expression c2 = term.getChild(1); if(c1.getVariables().size() == 0 && c2.getVariables().size() == 0) { @@ -61,7 +56,7 @@ } else { throw new NonLinearExpressionException("Order expression must be linear expression."); } - } else if(symbol.equals(DataConstraintModel.minus)) { + } else if(symbol.equals(Symbols.minus)) { Expression c1 = term.getChild(0); res += getCoefficientAndConstantsFromExpression(c1, coefficients, -curWeight); } else { @@ -77,16 +72,10 @@ private static TokenStream stream = new Parser.TokenStream(); private static Parser parser = new Parser(stream); - private static DataTransferModel model = new DataTransferModel(); public static Expression parse(String expr) { stream.addLine(expr); - try { - return parser.parseTerm(stream, model); - } catch (ExpectedRightBracket | WrongJsonExpression | ExpectedColon | ExpectedDoubleQuotation e) { - e.printStackTrace(); - return null; - } + return parser.parseTerm(stream); } } diff --git a/src/test/java/utils/Utils.java b/src/test/java/utils/Utils.java index fcf7adc..95ed96f 100644 --- a/src/test/java/utils/Utils.java +++ b/src/test/java/utils/Utils.java @@ -1,32 +1,21 @@ package utils; +import constants.Types; import models.algebra.Expression; import models.algebra.Type; -import models.dataConstraintModel.DataConstraintModel; -import models.dataFlowModel.DataTransferModel; import parser.Parser; import parser.Parser.TokenStream; -import parser.exceptions.ExpectedColon; -import parser.exceptions.ExpectedDoubleQuotation; -import parser.exceptions.ExpectedRightBracket; -import parser.exceptions.WrongJsonExpression; public class Utils { - public static Type INT = DataConstraintModel.typeInt; + public static Type INT = Types.typeInt; private static TokenStream stream = new Parser.TokenStream(); private static Parser parser = new Parser(stream); - private static DataTransferModel model = new DataTransferModel(); public static Expression parse(String expr) { stream.addLine(expr); - try { - return parser.parseTerm(stream, model); - } catch (ExpectedRightBracket | WrongJsonExpression | ExpectedColon | ExpectedDoubleQuotation e) { - e.printStackTrace(); - return null; - } + return parser.parseTerm(stream); } }