1 package org.simantics.scl.compiler.compilation;
3 import java.util.ArrayList;
4 import java.util.Arrays;
6 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
7 import org.simantics.scl.compiler.constants.StringConstant;
8 import org.simantics.scl.compiler.elaboration.errors.NotPatternException;
9 import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
10 import org.simantics.scl.compiler.elaboration.expressions.EVar;
11 import org.simantics.scl.compiler.elaboration.expressions.Expression;
12 import org.simantics.scl.compiler.elaboration.java.JavaMethodDeclaration;
13 import org.simantics.scl.compiler.errors.ErrorLog;
14 import org.simantics.scl.compiler.errors.Locations;
15 import org.simantics.scl.compiler.internal.parsing.Token;
16 import org.simantics.scl.compiler.internal.parsing.declarations.DAnnotationAst;
17 import org.simantics.scl.compiler.internal.parsing.declarations.DClassAst;
18 import org.simantics.scl.compiler.internal.parsing.declarations.DDataAst;
19 import org.simantics.scl.compiler.internal.parsing.declarations.DDerivingInstanceAst;
20 import org.simantics.scl.compiler.internal.parsing.declarations.DDocumentationAst;
21 import org.simantics.scl.compiler.internal.parsing.declarations.DEffectAst;
22 import org.simantics.scl.compiler.internal.parsing.declarations.DFixityAst;
23 import org.simantics.scl.compiler.internal.parsing.declarations.DImportJavaAst;
24 import org.simantics.scl.compiler.internal.parsing.declarations.DInstanceAst;
25 import org.simantics.scl.compiler.internal.parsing.declarations.DMappingRelationAst;
26 import org.simantics.scl.compiler.internal.parsing.declarations.DRelationAst;
27 import org.simantics.scl.compiler.internal.parsing.declarations.DRuleAst;
28 import org.simantics.scl.compiler.internal.parsing.declarations.DTypeAst;
29 import org.simantics.scl.compiler.internal.parsing.declarations.DValueAst;
30 import org.simantics.scl.compiler.internal.parsing.declarations.DValueTypeAst;
31 import org.simantics.scl.compiler.internal.parsing.declarations.DeclarationAst;
32 import org.simantics.scl.compiler.internal.parsing.translation.ProcessedDClassAst;
33 import org.simantics.scl.compiler.internal.parsing.translation.ProcessedDInstanceAst;
34 import org.simantics.scl.compiler.internal.parsing.translation.RelationRepository;
35 import org.simantics.scl.compiler.internal.parsing.translation.ValueRepository;
36 import org.simantics.scl.compiler.module.ImportDeclaration;
38 import gnu.trove.map.hash.THashMap;
40 public class DeclarationClassification {
41 ArrayList<ImportDeclaration> importsAst = new ArrayList<ImportDeclaration>();
42 ArrayList<DDataAst> dataTypesAst = new ArrayList<DDataAst>();
43 ArrayList<DTypeAst> typeAliasesAst = new ArrayList<DTypeAst>();
44 ValueRepository valueDefinitionsAst = new ValueRepository();
45 RelationRepository relationDefinitionsAst = new RelationRepository();
46 ArrayList<DValueTypeAst> typeAnnotationsAst = new ArrayList<DValueTypeAst>();
47 ArrayList<DFixityAst> fixityAst = new ArrayList<DFixityAst>();
48 ArrayList<ProcessedDClassAst> typeClassesAst = new ArrayList<ProcessedDClassAst>();
49 ArrayList<ProcessedDInstanceAst> instancesAst = new ArrayList<ProcessedDInstanceAst>();
50 ArrayList<DDerivingInstanceAst> derivingInstancesAst = new ArrayList<DDerivingInstanceAst>();
51 ArrayList<DEffectAst> effectsAst = new ArrayList<DEffectAst>();
52 ArrayList<DRuleAst> rulesAst = new ArrayList<DRuleAst>();
53 ArrayList<DMappingRelationAst> mappingRelationsAst = new ArrayList<DMappingRelationAst>();
55 THashMap<String, DDocumentationAst> valueDocumentation = new THashMap<String, DDocumentationAst>();
56 THashMap<String, DDocumentationAst> relationDocumentation = new THashMap<String, DDocumentationAst>();
57 THashMap<String, DDocumentationAst> typeDocumentation = new THashMap<String, DDocumentationAst>();
58 THashMap<String, DDocumentationAst> classDocumentation = new THashMap<String, DDocumentationAst>();
60 ArrayList<JavaMethodDeclaration> javaMethodDeclarations = new ArrayList<JavaMethodDeclaration>();
62 StringBuilder moduleDocumentation = new StringBuilder();
64 ArrayList<DAnnotationAst> currentAnnotations = new ArrayList<DAnnotationAst>(2);
65 DDocumentationAst documentation;
68 ArrayList<DAnnotationAst> defaultAnnotations = new ArrayList<DAnnotationAst>();
72 public DeclarationClassification(CompilationContext compilationContext) {
73 this.errorLog = compilationContext.errorLog;
76 public void handle(DeclarationAst declaration) {
77 if(declaration instanceof DValueAst)
78 handle((DValueAst)declaration);
79 else if(declaration instanceof DValueTypeAst)
80 handle((DValueTypeAst)declaration);
81 else if(declaration instanceof DDataAst)
82 handle((DDataAst)declaration);
83 else if(declaration instanceof DTypeAst)
84 handle((DTypeAst)declaration);
85 else if(declaration instanceof DInstanceAst)
86 handle((DInstanceAst)declaration);
87 else if(declaration instanceof DDerivingInstanceAst)
88 handle((DDerivingInstanceAst)declaration);
89 else if(declaration instanceof ImportDeclaration)
90 handle((ImportDeclaration)declaration);
91 else if(declaration instanceof DClassAst)
92 handle((DClassAst)declaration);
93 else if(declaration instanceof DFixityAst)
94 handle((DFixityAst)declaration);
95 else if(declaration instanceof DDocumentationAst)
96 handle((DDocumentationAst)declaration);
97 else if(declaration instanceof DAnnotationAst)
98 handle((DAnnotationAst)declaration);
99 else if(declaration instanceof DEffectAst)
100 handle((DEffectAst)declaration);
101 else if(declaration instanceof DImportJavaAst)
102 handle((DImportJavaAst)declaration);
103 else if(declaration instanceof DRuleAst)
104 handle((DRuleAst)declaration);
105 else if(declaration instanceof DMappingRelationAst)
106 handle((DMappingRelationAst)declaration);
107 else if(declaration instanceof DRelationAst)
108 handle((DRelationAst)declaration);
110 throw new InternalCompilerError("Unknown declaration " + declaration.getClass().getSimpleName());
113 public void handle(DFixityAst declaration) {
114 if(!currentAnnotations.isEmpty()) {
115 errorLog.log(declaration.location, "Annotations not supported.");
116 currentAnnotations = new ArrayList<DAnnotationAst>(2);
118 fixityAst.add(declaration);
121 public void handle(DEffectAst declaration) {
122 if(!currentAnnotations.isEmpty()) {
123 errorLog.log(declaration.location, "Annotations not supported.");
124 currentAnnotations = new ArrayList<DAnnotationAst>(2);
126 if(documentation != null)
127 documentation = null;
128 effectsAst.add(declaration);
131 public void handle(DClassAst declaration) {
132 // TODO errorLog.log(declaration, "Class " + declaration.name + " has already been defined in this module.");
134 if(documentation != null) {
135 String name = declaration.name;
136 addClassDocumentation(name, documentation);
137 documentation = null;
140 ArrayList<DValueTypeAst> typeDeclarations =
141 new ArrayList<DValueTypeAst>();
142 ValueRepository defaultValues = new ValueRepository();
144 DDocumentationAst curDocumentation = null;
145 for(DeclarationAst decl : declaration.declarations) {
146 if(decl instanceof DValueTypeAst) {
147 DValueTypeAst valueType = (DValueTypeAst)decl;
148 for(EVar name : valueType.names)
149 valueDocumentation.put(name.name, curDocumentation);
150 curDocumentation = null;
151 typeDeclarations.add(valueType);
153 else if(decl instanceof DValueAst) {
154 curDocumentation = null;
156 defaultValues.add((DValueAst)decl);
157 } catch (NotPatternException e) {
158 errorLog.log(e.getExpression().location, "Not a pattern.");
161 else if(decl instanceof DDocumentationAst) {
162 DDocumentationAst documentation = (DDocumentationAst)decl;
163 if(curDocumentation != null) {
164 errorLog.log(documentation.location, "Invalid documentation string. It precedes another documentation string.");
166 curDocumentation = documentation;
169 errorLog.log(decl.location, "Invalid declaration under class definition.");
172 if(!currentAnnotations.isEmpty()) {
173 declaration.setAnnotations(currentAnnotations);
174 currentAnnotations = new ArrayList<DAnnotationAst>(2);
176 typeClassesAst.add(new ProcessedDClassAst(declaration,
181 public void handle(ImportDeclaration declaration) {
182 if(!currentAnnotations.isEmpty()) {
183 errorLog.log(declaration.location, "Annotations not supported.");
184 currentAnnotations = new ArrayList<DAnnotationAst>(2);
186 importsAst.add(declaration);
189 public void handle(DImportJavaAst declaration) {
190 if(!currentAnnotations.isEmpty()) {
191 for(DAnnotationAst annotation : currentAnnotations) {
192 String name = annotation.id.text;
193 if(name.equals("@private")) {
194 defaultAnnotations.add(annotation);
197 errorLog.log(declaration.location, "The importJava declaration does not support annotation " + name + ".");
199 currentAnnotations = new ArrayList<DAnnotationAst>(2);
202 inJavaClass = declaration.className;
203 for(DeclarationAst innerDeclaration : declaration.declarations)
204 handle(innerDeclaration);
206 defaultAnnotations.clear();
211 public void handle(DInstanceAst declaration) {
212 ValueRepository valueDefs = new ValueRepository();
214 ArrayList<DAnnotationAst> localAnnotations = new ArrayList<DAnnotationAst>(2);
215 for(DeclarationAst decl : declaration.declarations) {
216 if(decl instanceof DValueAst) {
218 String name = valueDefs.add((DValueAst)decl);
219 if(!localAnnotations.isEmpty()) {
220 valueDefs.addAnnotations(name, localAnnotations);
221 localAnnotations = new ArrayList<DAnnotationAst>(2);
223 } catch (NotPatternException e) {
224 errorLog.log(e.getExpression().location, "Not a pattern.");
227 else if(decl instanceof DAnnotationAst)
228 localAnnotations.add((DAnnotationAst)decl);
230 errorLog.log(decl.location, "Invalid declaration under instance definition.");
232 for(DAnnotationAst decl : localAnnotations)
233 errorLog.log(decl.location, "Annotation is at invalid location.");
235 if(!currentAnnotations.isEmpty()) {
236 errorLog.log(declaration.location, "Annotations not supported.");
237 currentAnnotations = new ArrayList<DAnnotationAst>(2);
239 instancesAst.add(new ProcessedDInstanceAst(
244 public void handle(DDerivingInstanceAst declaration) {
245 if(!currentAnnotations.isEmpty()) {
246 errorLog.log(declaration.location, "Annotations not supported.");
247 currentAnnotations = new ArrayList<DAnnotationAst>(2);
249 derivingInstancesAst.add(declaration);
252 public void handle(DTypeAst declaration) {
253 if(!currentAnnotations.isEmpty()) {
254 errorLog.log(declaration.location, "Annotations not supported.");
255 currentAnnotations = new ArrayList<DAnnotationAst>(2);
257 typeAliasesAst.add(declaration);
260 public void handle(DDataAst declaration) {
261 if(documentation != null) {
262 String name = declaration.name;
263 addTypeDocumentation(name, documentation);
264 documentation = null;
266 if(inJavaClass != null)
267 currentAnnotations.add(new DAnnotationAst(new Token(0, Locations.NO_LOCATION, "@JavaType"),
268 Arrays.<Expression>asList(new ELiteral(new StringConstant(inJavaClass)))));
269 if(!currentAnnotations.isEmpty()) {
270 declaration.setAnnotations(currentAnnotations);
271 currentAnnotations = new ArrayList<DAnnotationAst>(2);
273 dataTypesAst.add(declaration);
276 public void handle(DValueTypeAst declaration) {
277 if(documentation != null) {
278 for(EVar name : declaration.names) {
279 addValueDocumentation(name.name, documentation);
281 documentation = null;
283 if(inJavaClass != null) {
284 for(EVar name : declaration.names)
285 javaMethodDeclarations.add(new JavaMethodDeclaration(
286 declaration.location, inJavaClass, name, declaration.type));
289 typeAnnotationsAst.add(declaration);
290 if(!currentAnnotations.isEmpty()) {
291 for(EVar name : declaration.names)
292 valueDefinitionsAst.addAnnotations(name.name, currentAnnotations);
293 currentAnnotations = new ArrayList<DAnnotationAst>(2);
295 if(!defaultAnnotations.isEmpty()) {
296 for(EVar name : declaration.names)
297 valueDefinitionsAst.addAnnotations(name.name, defaultAnnotations);
301 public void handle(DValueAst declaration) {
304 name = valueDefinitionsAst.add(declaration);
305 } catch (NotPatternException e) {
306 errorLog.log(e.getExpression().location, "Illegal left hand side of the definition.");
309 if(documentation != null) {
310 addValueDocumentation(name, documentation);
311 documentation = null;
313 if(!currentAnnotations.isEmpty()) {
314 valueDefinitionsAst.addAnnotations(name, currentAnnotations);
315 currentAnnotations = new ArrayList<DAnnotationAst>(2);
319 public void handle(DRelationAst declaration) {
322 name = relationDefinitionsAst.add(declaration);
323 } catch (NotPatternException e) {
324 errorLog.log(e.getExpression().location, "Not a pattern.");
327 if(documentation != null) {
328 addRelationDocumentation(name, documentation);
329 documentation = null;
331 if(!currentAnnotations.isEmpty()) {
332 relationDefinitionsAst.addAnnotations(name, currentAnnotations);
333 currentAnnotations = new ArrayList<DAnnotationAst>(2);
337 public void handle(DDocumentationAst declaration) {
338 if(documentation != null) {
339 errorLog.log(documentation.location, "Invalid documentation string. It precedes another documentation string.");
341 documentation = declaration;
344 public void handle(DAnnotationAst declaration) {
345 if(declaration.id.text.equals("@documentation")) {
346 if(declaration.parameters.length != 1) {
347 errorLog.log(documentation.location, "One parameter, a documentation string, expected after @documentation.");
350 if(!(declaration.parameters[0] instanceof ELiteral)) {
351 errorLog.log(documentation.location, "A documentation string expected after @documentation.");
354 ELiteral lit = (ELiteral)declaration.parameters[0];
355 if(!(lit.getValue() instanceof StringConstant)) {
356 errorLog.log(documentation.location, "A documentation string expected after @documentation.");
359 String text = ((StringConstant)lit.getValue()).getValue();
360 moduleDocumentation.append(text);
361 moduleDocumentation.append("\n\n");
364 currentAnnotations.add(declaration);
367 public void handle(DRuleAst declaration) {
368 rulesAst.add(declaration);
371 public void handle(DMappingRelationAst declaration) {
372 mappingRelationsAst.add(declaration);
375 public void addValueDocumentation(String valueName, DDocumentationAst documentation) {
376 DDocumentationAst oldDoc = valueDocumentation.put(valueName, documentation);
378 errorLog.log(oldDoc.location, "Multiple documentation strings given to " + valueName + ".");
382 public void addRelationDocumentation(String relationName, DDocumentationAst documentation) {
383 DDocumentationAst oldDoc = relationDocumentation.put(relationName, documentation);
385 errorLog.log(oldDoc.location, "Multiple documentation strings given to " + relationName + ".");
389 public void addTypeDocumentation(String valueName, DDocumentationAst documentation) {
390 DDocumentationAst oldDoc = typeDocumentation.put(valueName, documentation);
392 errorLog.log(oldDoc.location, "Multiple documentation strings given to the same type.");
396 public void addClassDocumentation(String valueName, DDocumentationAst documentation) {
397 DDocumentationAst oldDoc = classDocumentation.put(valueName, documentation);
399 errorLog.log(oldDoc.location, "Multiple documentation strings given to the same class.");