1 package org.simantics.graph.compiler;
3 import java.io.ByteArrayInputStream;
4 import java.io.ByteArrayOutputStream;
5 import java.io.DataInputStream;
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.io.PrintStream;
10 import java.util.ArrayList;
11 import java.util.Collection;
12 import java.util.Formatter;
13 import java.util.Locale;
15 import org.simantics.databoard.Bindings;
16 import org.simantics.databoard.Files;
17 import org.simantics.databoard.adapter.AdaptException;
18 import org.simantics.databoard.binding.error.BindingException;
19 import org.simantics.databoard.binding.error.RuntimeBindingConstructionException;
20 import org.simantics.databoard.binding.mutable.Variant;
21 import org.simantics.databoard.container.DataContainer;
22 import org.simantics.databoard.container.DataContainers;
23 import org.simantics.databoard.serialization.SerializationException;
24 import org.simantics.graph.compiler.internal.parsing.Parsing;
25 import org.simantics.graph.compiler.internal.procedures.AddConsistsOf;
26 import org.simantics.graph.compiler.internal.procedures.ApplyTemplates;
27 import org.simantics.graph.compiler.internal.procedures.Compactify;
28 import org.simantics.graph.compiler.internal.procedures.ConvertPreValues;
29 import org.simantics.graph.compiler.internal.procedures.CreateInverseRelations;
30 import org.simantics.graph.compiler.internal.procedures.CreateTemplates;
31 import org.simantics.graph.compiler.internal.procedures.DefaultValueTyping;
32 import org.simantics.graph.compiler.internal.procedures.MergeEqualResources;
33 import org.simantics.graph.compiler.internal.procedures.PropagateNewMarks;
34 import org.simantics.graph.compiler.internal.resourceFiles.ResourceFileGenerator;
35 import org.simantics.graph.compiler.internal.store.LocationStore;
36 import org.simantics.graph.compiler.internal.store.VariableStore;
37 import org.simantics.graph.compiler.internal.validation.ReportCollisions;
38 import org.simantics.graph.compiler.internal.validation.ValidateGraph;
39 import org.simantics.graph.query.CompositeGraph;
40 import org.simantics.graph.query.Paths;
41 import org.simantics.graph.query.TransferableGraphConversion;
42 import org.simantics.graph.representation.TransferableGraph1;
43 import org.simantics.graph.store.GraphStore;
44 import org.simantics.ltk.FileSource;
45 import org.simantics.ltk.ISource;
46 import org.simantics.ltk.Location;
47 import org.simantics.ltk.Problem;
49 public class GraphCompiler {
51 public static PrintStream out = System.out;
53 public static TransferableGraph1 read(File file) throws Exception {
54 DataContainer container = DataContainers.readFile(file);
55 return (TransferableGraph1)container.content.getValue(TransferableGraph1.BINDING);
58 public static TransferableGraph1 read(InputStream stream) throws AdaptException, IOException {
59 DataContainer container = DataContainers.readFile(new DataInputStream(stream));
61 return (TransferableGraph1)container.content.getValue(TransferableGraph1.BINDING);
64 public static InputStream write(TransferableGraph1 tg) throws BindingException, IOException {
65 byte[] buffer = DataContainers.writeFile(
66 new DataContainer("graph", 1, new Variant(TransferableGraph1.BINDING, tg))
68 return new ByteArrayInputStream(buffer);
71 public static CompilationResult compile(
73 Collection<ISource> sources,
74 Collection<TransferableGraph1> dependencies,
75 ExternalFileLoader fileLoader,
76 GraphCompilerPreferences preferences) {
77 out.println(preferences);
79 Collection<Problem> errors = new ArrayList<Problem>();
80 GraphStore store = new GraphStore();
82 CompilationResult compilationResult = new CompilationResult();
83 compilationResult.errors = errors;
84 compilationResult.warnings = new ArrayList<Problem>();
86 Paths paths = new Paths(Layer0Version);
89 run(new Parsing(paths, sources, errors, store));
92 return compilationResult;
94 // Create composite graph of the new statements and dependencies
97 long beginTime = System.nanoTime();
98 graph = TransferableGraphConversion.convert(paths, dependencies);
99 graph.addFragment(store);
100 long endTime = System.nanoTime();
101 reportTime("Composition", beginTime, endTime);
105 run(new MergeEqualResources(paths, store));
107 int[] unfoundedIdentitities = store.identities.getUnfoundedIdentities();
108 if(unfoundedIdentitities.length > 0) {
109 LocationStore locations = store.getStore(LocationStore.class);
110 for(int id : unfoundedIdentitities) {
111 errors.add(new Problem(
112 locations.getLocation(id),
113 "URIless resource used as a parent."));
115 return compilationResult;
118 store.identities.createPathToId(paths.ConsistsOf);
119 run(new CreateTemplates(graph, store, errors));
120 run(new ApplyTemplates(graph, store, errors, fileLoader));
121 run(new DefaultValueTyping(paths, store));
122 run(new Compactify(store));
123 run(new PropagateNewMarks(store));
124 run(new CreateInverseRelations(graph, store));
125 run(new AddConsistsOf(paths, store));
126 run(new ConvertPreValues(graph, store, errors));
127 run(new ReportCollisions(preferences, errors, store));
128 if(preferences.validate)
129 run(new ValidateGraph(graph, errors, store, preferences));
133 long beginTime = System.nanoTime();
134 compilationResult.graph = TransferableGraphConversion.convert(graph, store);
135 long endTime = System.nanoTime();
136 reportTime("Generate TG", beginTime, endTime);
139 // Create resource files
141 long beginTime = System.nanoTime();
142 compilationResult.resourceFiles = ResourceFileGenerator.generate(paths, store);
143 long endTime = System.nanoTime();
144 reportTime("Generate resources", beginTime, endTime);
147 // Create source info
149 VariableStore variableStore = store.getStore(VariableStore.class);
150 compilationResult.sourceInfo = variableStore.getSourceInfo();
153 // Fix source location of problems whose location is null at this point
155 for(Problem problem : compilationResult.errors) {
156 if(problem.getLocation() == null)
157 for(ISource source : sources) {
158 problem.setLocation(new Location(source));
161 else if(problem.getLocation().getSource() == null)
162 for(ISource source : sources) {
163 problem.getLocation().setSource(source);
167 for(Problem problem : compilationResult.warnings) {
168 if(problem.getLocation() == null)
169 for(ISource source : sources) {
170 problem.setLocation(new Location(source));
173 else if(problem.getLocation().getSource() == null)
174 for(ISource source : sources) {
175 problem.getLocation().setSource(source);
180 } catch(Exception e) {
182 ByteArrayOutputStream stream = new ByteArrayOutputStream();
183 e.printStackTrace(new PrintStream(stream));
184 String description = "Internal error: " +
185 new String(stream.toByteArray());
186 for(ISource source : sources)
187 errors.add(new Problem(new Location(source), description));
190 return compilationResult;
193 private static void run(Runnable runnable) {
194 long beginTime = System.nanoTime();
196 long endTime = System.nanoTime();
198 reportTime(runnable.getClass().getSimpleName(), beginTime, endTime);
201 public static void reportTime(String taskName, long beginTime, long endTime) {
202 StringBuilder sb = new StringBuilder();
203 Formatter formatter = new Formatter(sb, Locale.US);
204 formatter.format("%-25s %8.4f ms", taskName, (endTime - beginTime)*1e-6);
206 out.println(sb.toString());
209 public static void reportTime(String taskName, long beginTime) {
210 reportTime(taskName, beginTime, System.nanoTime());
213 public static void main(String[] args) {
214 Collection<ISource> sources = new ArrayList<ISource>();
215 Collection<TransferableGraph1> dependencies = new ArrayList<TransferableGraph1>();
216 String outputFile = null;
218 for(int i=0;i<args.length;++i) {
219 String arg = args[i];
220 if(arg.equals("-o")) {
221 if(++i < args.length)
222 outputFile = args[i];
225 if(arg.endsWith(".tg")) {
227 dependencies.add(read(new File(arg)));
228 } catch (Exception e) {
233 else if(arg.endsWith(".graph") || arg.endsWith(".pgraph")) {
234 sources.add(new FileSource(arg));
237 System.err.println("Invalid input file extension " + arg);
243 if(sources.isEmpty()) {
244 System.err.println("No source files");
248 if(outputFile == null) {
249 System.err.println("Name of the output file is not given (use -o flag).");
253 CompilationResult result = compile("1.0", sources, dependencies, null, new GraphCompilerPreferences());
254 for(Problem problem : result.getErrors())
255 out.println(problem.getLocation() + ": " + problem.getDescription());
257 if(result.getGraph() != null)
259 Files.createFile(new File(outputFile), TransferableGraph1.BINDING, result.getGraph());
260 } catch (Exception e) {