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 if(declaration.name.name.equals("Eq") || declaration.name.name.equals("Hashable")) {
240 errorLog.logWarning(declaration.location, "Skipped instance definition for " + declaration.name + " for " + declaration.types[0]);
243 instancesAst.add(new ProcessedDInstanceAst(
248 public void handle(DDerivingInstanceAst declaration) {
249 if(!currentAnnotations.isEmpty()) {
250 errorLog.log(declaration.location, "Annotations not supported.");
251 currentAnnotations = new ArrayList<DAnnotationAst>(2);
253 if(declaration.name.name.equals("Eq") || declaration.name.name.equals("Hashable")) {
254 errorLog.logWarning(declaration.location, "Skipped instance definition for " + declaration.name + " for " + declaration.types[0]);
257 derivingInstancesAst.add(declaration);
260 public void handle(DTypeAst declaration) {
261 if(!currentAnnotations.isEmpty()) {
262 errorLog.log(declaration.location, "Annotations not supported.");
263 currentAnnotations = new ArrayList<DAnnotationAst>(2);
265 typeAliasesAst.add(declaration);
268 public void handle(DDataAst declaration) {
269 if(documentation != null) {
270 String name = declaration.name;
271 addTypeDocumentation(name, documentation);
272 documentation = null;
274 if(inJavaClass != null)
275 currentAnnotations.add(new DAnnotationAst(new Token(0, Locations.NO_LOCATION, "@JavaType"),
276 Arrays.<Expression>asList(new ELiteral(new StringConstant(inJavaClass)))));
277 if(!currentAnnotations.isEmpty()) {
278 declaration.setAnnotations(currentAnnotations);
279 currentAnnotations = new ArrayList<DAnnotationAst>(2);
281 dataTypesAst.add(declaration);
284 public void handle(DValueTypeAst declaration) {
285 if(documentation != null) {
286 for(EVar name : declaration.names) {
287 addValueDocumentation(name.name, documentation);
289 documentation = null;
291 if(inJavaClass != null) {
292 for(EVar name : declaration.names)
293 javaMethodDeclarations.add(new JavaMethodDeclaration(
294 declaration.location, inJavaClass, name, declaration.type));
297 typeAnnotationsAst.add(declaration);
298 if(!currentAnnotations.isEmpty()) {
299 for(EVar name : declaration.names)
300 valueDefinitionsAst.addAnnotations(name.name, currentAnnotations);
301 currentAnnotations = new ArrayList<DAnnotationAst>(2);
303 if(!defaultAnnotations.isEmpty()) {
304 for(EVar name : declaration.names)
305 valueDefinitionsAst.addAnnotations(name.name, defaultAnnotations);
309 public void handle(DValueAst declaration) {
312 name = valueDefinitionsAst.add(declaration);
313 } catch (NotPatternException e) {
314 errorLog.log(e.getExpression().location, "Illegal left hand side of the definition.");
317 if(documentation != null) {
318 addValueDocumentation(name, documentation);
319 documentation = null;
321 if(!currentAnnotations.isEmpty()) {
322 valueDefinitionsAst.addAnnotations(name, currentAnnotations);
323 currentAnnotations = new ArrayList<DAnnotationAst>(2);
327 public void handle(DRelationAst declaration) {
330 name = relationDefinitionsAst.add(declaration);
331 } catch (NotPatternException e) {
332 errorLog.log(e.getExpression().location, "Not a pattern.");
335 if(documentation != null) {
336 addRelationDocumentation(name, documentation);
337 documentation = null;
339 if(!currentAnnotations.isEmpty()) {
340 relationDefinitionsAst.addAnnotations(name, currentAnnotations);
341 currentAnnotations = new ArrayList<DAnnotationAst>(2);
345 public void handle(DDocumentationAst declaration) {
346 if(documentation != null) {
347 errorLog.log(documentation.location, "Invalid documentation string. It precedes another documentation string.");
349 documentation = declaration;
352 public void handle(DAnnotationAst declaration) {
353 if(declaration.id.text.equals("@documentation")) {
354 if(declaration.parameters.length != 1) {
355 errorLog.log(documentation.location, "One parameter, a documentation string, expected after @documentation.");
358 if(!(declaration.parameters[0] instanceof ELiteral)) {
359 errorLog.log(documentation.location, "A documentation string expected after @documentation.");
362 ELiteral lit = (ELiteral)declaration.parameters[0];
363 if(!(lit.getValue() instanceof StringConstant)) {
364 errorLog.log(documentation.location, "A documentation string expected after @documentation.");
367 String text = ((StringConstant)lit.getValue()).getValue();
368 moduleDocumentation.append(text);
369 moduleDocumentation.append("\n\n");
372 currentAnnotations.add(declaration);
375 public void handle(DRuleAst declaration) {
376 rulesAst.add(declaration);
379 public void handle(DMappingRelationAst declaration) {
380 mappingRelationsAst.add(declaration);
383 public void addValueDocumentation(String valueName, DDocumentationAst documentation) {
384 DDocumentationAst oldDoc = valueDocumentation.put(valueName, documentation);
386 errorLog.log(oldDoc.location, "Multiple documentation strings given to " + valueName + ".");
390 public void addRelationDocumentation(String relationName, DDocumentationAst documentation) {
391 DDocumentationAst oldDoc = relationDocumentation.put(relationName, documentation);
393 errorLog.log(oldDoc.location, "Multiple documentation strings given to " + relationName + ".");
397 public void addTypeDocumentation(String valueName, DDocumentationAst documentation) {
398 DDocumentationAst oldDoc = typeDocumentation.put(valueName, documentation);
400 errorLog.log(oldDoc.location, "Multiple documentation strings given to the same type.");
404 public void addClassDocumentation(String valueName, DDocumentationAst documentation) {
405 DDocumentationAst oldDoc = classDocumentation.put(valueName, documentation);
407 errorLog.log(oldDoc.location, "Multiple documentation strings given to the same class.");