diff --git a/spec/jastadd/Backend.jadd b/spec/jastadd/Backend.jadd
index b7a4b101064bb652fcaf77bfeacecb9b777588fe..3506e24eff9307f7bb677217f43d216bbfe966c4 100644
--- a/spec/jastadd/Backend.jadd
+++ b/spec/jastadd/Backend.jadd
@@ -53,10 +53,14 @@ aspect BackendAbstractGrammar {
 	}
 
 	public String RelationComponent.generateAbstractGrammar() {
-		return "<_impl_" + getID() + ":" + ofTypeDecl() + ">";
+		return "<" + getImplAttributeName() + ":" + ofTypeDecl() + ">";
 	}
 	public String ManyRelationComponent.generateAbstractGrammar() {
-		return "<_impl_" + getID() + ":MySet<" + ofTypeDecl() + ">>";
+		return "<" + getImplAttributeName() + ":ArrayList<" + ofTypeDecl() + ">>";
+	}
+
+	public String RelationComponent.getImplAttributeName() {
+		return "_impl_" + getID();
 	}
 }
 
@@ -68,6 +72,7 @@ aspect BackendAspect {
 	}
 
 	public void Program.generateAspect(StringBuilder sb) {
+		sb.append("import java.util.*;\n");
 		sb.append("aspect RelAstAPI {\n");
 		for (TypeDecl td: getTypeDecls()) {
 			if (td.needsConstructor()) {
@@ -78,6 +83,11 @@ aspect BackendAspect {
 			r.generateAPI(sb);
 		}
 
+		sb.append(ind(1) + "public void ASTNode.assertNotNull(Object obj) {\n");
+		sb.append(ind(2) + "if (obj == null) {\n");
+		sb.append(ind(3) + "throw new NullPointerException();\n");
+		sb.append(ind(2) + "}\n");
+		sb.append(ind(1) + "}\n");
 		sb.append("}\n");
 	}
 
@@ -105,12 +115,79 @@ aspect BackendAPI {
 	}
 	public abstract void Direction.generateAPI(StringBuilder sb);
 	public void RightDirection.generateAPI(StringBuilder sb) {
-
+		relation().getLeft().generateDirectedAPI(sb);
 	}
 	public void Bidirectional.generateAPI(StringBuilder sb) {
 
 	}
 
+	public abstract void RelationComponent.generateDirectedAPI(StringBuilder sb);
+	public void OneRelationComponent.generateDirectedAPI(StringBuilder sb) {
+		generateDirectedZeroOneAPI(sb, false);
+	}
+	public void OptionalRelationComponent.generateDirectedAPI(StringBuilder sb) {
+		generateDirectedZeroOneAPI(sb, true);
+		
+		// has
+		sb.append(ind(1) + "public boolean " + toTypeDecl());
+		sb.append(".has" + nameCapitalized() + "() {\n");
+		sb.append(ind(2) + "return " + name() + "() != null;\n");
+		sb.append(ind(1) + "}\n");
+	}
+	public void RelationComponent.generateDirectedZeroOneAPI(StringBuilder sb, boolean optional) {
+		// Get
+		sb.append(ind(1) + "public " + ofTypeDecl() + " " + toTypeDecl());
+		sb.append("." + name() + "() {\n");
+		sb.append(ind(2) + "return get" + getImplAttributeName() + "();\n");
+		sb.append(ind(1) + "}\n");
+
+		// Set
+		sb.append(ind(1) + "public void " + toTypeDecl());
+		sb.append(".set" + nameCapitalized() + "(" + ofTypeDecl() + " o) {\n");
+		if (!optional) {
+			sb.append(ind(2) + "assertNotNull(o);\n");
+		}
+		sb.append(ind(2) + "set" + getImplAttributeName() + "(o);\n");
+		sb.append(ind(1) + "}\n");
+	}
+
+	public void ManyRelationComponent.generateDirectedAPI(StringBuilder sb) {
+		// Get
+		sb.append(ind(1) + "public Collection<" + ofTypeDecl() + "> " + toTypeDecl());
+		sb.append("." + name() + "() {\n");
+		sb.append(ind(2) + "return get" + getImplAttributeName() + "();\n");
+		sb.append(ind(1) + "}\n");
+
+		// Add
+		sb.append(ind(1) + "public void " + toTypeDecl() + ".addTo");
+		sb.append(nameCapitalized() + "(" + ofTypeDecl() + " o) {\n");
+		sb.append(ind(2) + "assertNotNull(o);\n");
+		sb.append(ind(2) + "ArrayList<" + ofTypeDecl() + "> list = get" + getImplAttributeName() + "();\n");
+		sb.append(ind(2) + "if (list == null) {\n");
+		sb.append(ind(3) + "list = new ArrayList<>();\n");
+		sb.append(ind(2) + "}\n");
+		sb.append(ind(2) + "list.add(o);\n");
+		sb.append(ind(2) + "set" + getImplAttributeName() + "(list);\n");
+		sb.append(ind(1) + "}\n");
+
+		// Remove
+		sb.append(ind(1) + "public void " + toTypeDecl() + ".removeFrom");
+		sb.append(nameCapitalized() + "(" + ofTypeDecl() + " o) {\n");
+		sb.append(ind(2) + "assertNotNull(o);\n");
+		sb.append(ind(2) + "ArrayList<" + ofTypeDecl() + "> list = get" + getImplAttributeName() + "();\n");
+		sb.append(ind(2) + "if (list != null && list.remove(o)) {\n");
+		sb.append(ind(3) + "set" + getImplAttributeName() + "(list);\n");
+		sb.append(ind(2) + "}\n");
+		sb.append(ind(1) + "}\n");
+	}
+
+	inh Relation Direction.relation();
+	eq Relation.getChild().relation() = this;
+	eq Program.getChild().relation() = null;
+
+	public String RelationComponent.nameCapitalized() {
+		return name().substring(0,1).toUpperCase() + name().substring(1);
+	}
 }
 
 aspect PrettyPrint {
diff --git a/src/java/org/jastadd/relast/compiler/Compiler.java b/src/java/org/jastadd/relast/compiler/Compiler.java
index 0a0cf2a9f3280612b8b76f7b0ba62ec53b6e0b6b..27f50ac2bad23c1ce3417adc90c4bf1e6acc6d55 100644
--- a/src/java/org/jastadd/relast/compiler/Compiler.java
+++ b/src/java/org/jastadd/relast/compiler/Compiler.java
@@ -1,7 +1,6 @@
 package org.jastadd.relast.compiler;
 import org.jastadd.relast.ast.*;
 
-
 import static org.jastadd.relast.compiler.Utils.filterToList;
 
 import java.io.*;
@@ -20,8 +19,7 @@ import beaver.Parser;
 
 public class Compiler {
 	protected ArrayList<Option<?>> options;
-	protected FlagOption optionPrintDot;
-	protected FlagOption optionFlatPrettyPrint;
+	protected FlagOption optionWriteToFile;
 	protected CommandLine commandLine;
 
 	public Compiler(String args[]) throws CommandLineException {
@@ -31,7 +29,12 @@ public class Compiler {
 		commandLine = new CommandLine(options);
 		commandLine.parse(args);
 
-		Program p = parseProgram(commandLine.getArguments().get(0));
+		if (commandLine.getArguments().size() != 1) {
+			error("specify one input file");
+		}
+
+		String filename = commandLine.getArguments().get(0);
+		Program p = parseProgram(filename);
 
 		if (!p.errors().isEmpty()) {
 			System.out.println(p.dumpTree());
@@ -41,38 +44,33 @@ public class Compiler {
 			}
 			System.exit(1);
 		} else {
-			System.out.println(p.generateAbstractGrammar());
-			System.out.println(p.generateAspect());
-		}
-/*		} else {
-			if (optionPrintDot.isSet()) {
-				System.out.println(p.genDot());
-			} else if (optionFlatPrettyPrint.isSet()) {
-				System.out.println(p.flatPrettyPrint());
-			} else {
-				System.out.println("# AST");
-				System.out.println(p.dumpTree());
-
-				FlatState s = p.stoppingState();
-				for (FlatDependency d: s.getDependencyList()) {
-					System.out.println(d.sourceDecl());
-					System.out.println(d.sourceDecl().getAccess() + " " + d.targetDecl().getAccess());
-				}
-				for (Node n: s.getNodes()) {
-					System.out.println(n + ", succ: " + n.succ());
-				}
-				System.out.println(s.startingNodes());
-				System.out.println(s.endingNodes());
-				System.out.println("# Transitive reduction");
-				System.out.println(p.startingState().transitiveReduction());
+			if (optionWriteToFile.isSet()) {
+				File file = new File(filename);
+				String absPath = file.getAbsolutePath();
+				String absPathExclExt = absPath.substring(0, absPath.lastIndexOf('.'));
+				writeToFile(absPathExclExt + "Gen.ast", p.generateAbstractGrammar());
+				writeToFile(absPathExclExt + "Gen.jadd", p.generateAspect());
 			}
-		}*/
+			else {
+				System.out.println(p.generateAbstractGrammar());
+				System.out.println(p.generateAspect());
+			}
+		}
 	}
 
+	protected void writeToFile(String filename, String str) {
+		try {
+			PrintWriter writer = new PrintWriter(filename, "UTF-8");
+			writer.print(str);
+			writer.close();
+		} catch (Exception e) {
+			e.printStackTrace();
+			System.exit(1);
+		}
+	}
 
 	protected void addOptions() {
-		optionPrintDot = addOption(new FlagOption("dot", "print DOT format"));
-		optionFlatPrettyPrint = addOption(new FlagOption("flat", "flat pretty print"));
+		optionWriteToFile = addOption(new FlagOption("file", "write output to file"));
 	}
 
 	protected <OptionType extends Option<?>> OptionType addOption(OptionType option) {
@@ -98,8 +96,7 @@ public class Compiler {
 		try {
 			return (Program) parser.parse(scanner);
 		} catch (IOException e) {
-			System.err.println(e.getMessage());
-			System.exit(1);
+			error(e.getMessage());
 		} catch (Parser.Exception e) {
 			System.err.println("Parse error in file " + file);
 			System.err.println(e.getMessage());
@@ -112,6 +109,11 @@ public class Compiler {
 		return null;
 	}
 
+	protected void error(String message) {
+		System.err.println("Error: " + message);
+		System.exit(1);
+	}
+
 	private void showUsageAndExit() {
 		//System.out.println("Usage: java -jar bloqqi-compiler.jar [--option1] [--option2=value] ...  <filename1> [filename2] [filename3] ...");
 		//System.exit(1);