From 649c8133873f6f66e8aa214405049b0a6b3ad515 Mon Sep 17 00:00:00 2001
From: Niklas Fors <niklas.fors@cs.lth.se>
Date: Wed, 4 Jul 2018 13:01:48 +0200
Subject: [PATCH] Generate aspect [WIP] and use ? for 0..1

---
 spec/jastadd/Analysis.jrag                    | 25 +++++
 spec/jastadd/Backend.jadd                     | 95 ++++++++++++++++++-
 spec/parser/RelAstBase.parser                 |  8 +-
 spec/scanner/RelAst.flex                      |  3 +-
 .../org/jastadd/relast/compiler/Compiler.java |  1 +
 5 files changed, 125 insertions(+), 7 deletions(-)

diff --git a/spec/jastadd/Analysis.jrag b/spec/jastadd/Analysis.jrag
index 6972b05..6464747 100644
--- a/spec/jastadd/Analysis.jrag
+++ b/spec/jastadd/Analysis.jrag
@@ -87,6 +87,31 @@ aspect ComponentAnalysis {
 		for toTypeDecl();
 }
 
+aspect Constructors {
+	syn Collection<Component> TypeDecl.componentsTransitive() {
+		ArrayList<Component> list = new ArrayList<>();
+		if (hasSuper() && getSuper().decl() != null) {
+			list.addAll(getSuper().decl().componentsTransitive());
+		}
+		for (Component c: getComponents()) {
+			list.add(c);
+		}
+		return list;
+	}
+
+	syn boolean TypeDecl.needsConstructor() {
+		if (componentsTransitive().isEmpty()) {
+			return false;
+		}
+		if (!relationComponents().isEmpty()) {
+			return true;
+		}
+		return hasSuper()
+			&& getSuper().decl() != null
+			&& getSuper().decl().needsConstructor();
+	}
+}
+
 aspect Utils {
 	public String TypeUse.toString() {
 		return getID();
diff --git a/spec/jastadd/Backend.jadd b/spec/jastadd/Backend.jadd
index 3aee5c4..e12ba7f 100644
--- a/spec/jastadd/Backend.jadd
+++ b/spec/jastadd/Backend.jadd
@@ -31,7 +31,7 @@ aspect BackendAbstractGrammar {
 			sb.append(" ");
 			sb.append(c.generateAbstractGrammar());
 		}
-		
+
 		sb.append(";\n");
 	}
 
@@ -58,4 +58,97 @@ aspect BackendAbstractGrammar {
 	public String ManyRelationComponent.generateAbstractGrammar() {
 		return "<_impl_" + getID() + ":MySet<" + ofTypeDecl() + ">>";
 	}
+}
+
+aspect BackendAspect {
+	public String Program.generateAspect() {
+		StringBuilder sb = new StringBuilder();
+		generateAspect(sb);
+		return sb.toString();
+	}
+
+	public void Program.generateAspect(StringBuilder sb) {
+		sb.append("aspect RelAstAPI {\n");
+		for (TypeDecl td: getTypeDecls()) {
+			if (td.needsConstructor()) {
+				td.generateConstructor(sb);
+			}
+		}
+		for (Relation r: getRelations()) {
+			r.generateAPI(sb);
+		}
+
+		sb.append("}\n");
+	}
+
+	public void TypeDecl.generateConstructor(StringBuilder sb) {
+		sb.append(ind(1) + "public " + getID() + "." + getID() + "(");
+		int i = 0;
+		for (Component c: componentsTransitive()) {
+			sb.append(c.getTypeUse() + " " + c.getID());
+			if (++i < componentsTransitive().size()) {
+				sb.append(", ");
+			}
+		}
+		sb.append(") {\n");
+		for (Component c: componentsTransitive()) {
+			sb.append(ind(2) + "set" + c.getID() + "(" + c.getID() + ");\n");
+		}
+		sb.append(ind(1) + "}\n");
+	}
+}
+
+aspect BackendAPI {
+	public void Relation.generateAPI(StringBuilder sb) {
+		sb.append(ind(1) + "// " + prettyPrint() + "\n");
+		getDirection().generateAPI(sb);
+	}
+	public abstract void Direction.generateAPI(StringBuilder sb);
+	public void RightDirection.generateAPI(StringBuilder sb) {
+
+	}
+	public void Bidirectional.generateAPI(StringBuilder sb) {
+
+	}
+
+}
+
+aspect PrettyPrint {
+	public String Relation.prettyPrint() {
+		return "rel "
+			+ getLeft().prettyPrint() + " "
+			+ getDirection().prettyPrint() + " "
+			+ getRight().prettyPrint();
+	}
+	public String RelationComponent.prettyPrint() {
+		if (getID().isEmpty()) {
+			return getTypeUse().toString();
+		} else {
+			return getTypeUse() + "." +  getID();
+		}
+	}
+	public String OptionalRelationComponent.prettyPrint() {
+		return "[" + super.prettyPrint() + "]";
+	}
+	public String ManyRelationComponent.prettyPrint() {
+		return super.prettyPrint() + "*";
+	}
+	abstract public String Direction.prettyPrint();
+	public String RightDirection.prettyPrint() {
+		return "->";
+	}
+	public String Bidirectional.prettyPrint() {
+		return "<->";
+	}
+
+}
+
+aspect Utils {
+	public String ASTNode.ind(int n) {
+		String s = "";
+		for (int i = 0; i < n; i++) {
+			s += "  ";
+		}
+		return s;
+	}
 }
\ No newline at end of file
diff --git a/spec/parser/RelAstBase.parser b/spec/parser/RelAstBase.parser
index 3948cf2..7c12f1f 100644
--- a/spec/parser/RelAstBase.parser
+++ b/spec/parser/RelAstBase.parser
@@ -41,8 +41,8 @@ Component component =
 	| ID COL type_use.u STAR {: return new ListComponent(ID, u); :}
 	| type_use.u STAR {: return new ListComponent(u.getID(), u); :}
 	// Opt
-	| LBRACKET ID COL type_use.u RBRACKET {: return new OptComponent(ID, u); :}
-	| LBRACKET type_use.u RBRACKET {: return new OptComponent(u.getID(), u); :}
+	| ID COL type_use.u QUESTION_MARK {: return new OptComponent(ID, u); :}
+	| type_use.u QUESTION_MARK {: return new OptComponent(u.getID(), u); :}
 	// Token
 	| LT ID COL type_use.u GT {: return new TokenComponent(ID, u); :}
 	| LT ID GT {: return new TokenComponent(ID, new TypeUse("String")); :}
@@ -63,8 +63,8 @@ RelationComponent relation_comp =
 	type_use.u DOT ID {: return new OneRelationComponent(ID, u); :}
 	| type_use.u {: return new OneRelationComponent("", u); :}
 	// Optional
-	| LBRACKET type_use.u DOT ID RBRACKET {: return new OptionalRelationComponent(ID, u); :}
-	| LBRACKET type_use.u RBRACKET {: return new OptionalRelationComponent("", u); :}
+	| type_use.u DOT ID QUESTION_MARK {: return new OptionalRelationComponent(ID, u); :}
+	| type_use.u QUESTION_MARK {: return new OptionalRelationComponent("", u); :}
 	// Many
 	| type_use.u DOT ID STAR {: return new ManyRelationComponent(ID, u); :}
 	| type_use.u STAR {: return new ManyRelationComponent("", u); :}
diff --git a/spec/scanner/RelAst.flex b/spec/scanner/RelAst.flex
index ecbf964..2039600 100644
--- a/spec/scanner/RelAst.flex
+++ b/spec/scanner/RelAst.flex
@@ -62,8 +62,7 @@ NUM = -?[0-9]+
 	"."				{ return sym(Terminals.DOT); }
 	"<"				{ return sym(Terminals.LT); }
 	">"				{ return sym(Terminals.GT); }
-	"["				{ return sym(Terminals.LBRACKET); }
-	"]"				{ return sym(Terminals.RBRACKET); }
+	"?"				{ return sym(Terminals.QUESTION_MARK); }
 	"->"			{ return sym(Terminals.RIGHT); }
 	"<->"			{ return sym(Terminals.BIDIRECTIONAL); }
 
diff --git a/src/java/org/jastadd/relast/compiler/Compiler.java b/src/java/org/jastadd/relast/compiler/Compiler.java
index 4fd6591..eeaeacf 100644
--- a/src/java/org/jastadd/relast/compiler/Compiler.java
+++ b/src/java/org/jastadd/relast/compiler/Compiler.java
@@ -41,6 +41,7 @@ public class Compiler {
 			System.exit(1);
 		} else {
 			System.out.println(p.generateAbstractGrammar());
+			System.out.println(p.generateAspect());
 		}
 /*		} else {
 			if (optionPrintDot.isSet()) {
-- 
GitLab