]> gerrit.simantics Code Review - simantics/platform.git/blob
54f0bb7d84a500f6a5967d7e2463794647c5f80a
[simantics/platform.git] /
1 package org.simantics.scl.compiler.compilation;
2
3 import java.util.ArrayList;
4 import java.util.Arrays;
5
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;
37
38 import gnu.trove.map.hash.THashMap;
39
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>();
54     
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>();
59     
60     ArrayList<JavaMethodDeclaration> javaMethodDeclarations = new ArrayList<JavaMethodDeclaration>();
61     
62     StringBuilder moduleDocumentation = new StringBuilder();
63     
64     ArrayList<DAnnotationAst> currentAnnotations = new ArrayList<DAnnotationAst>(2); 
65     DDocumentationAst documentation;
66     String inJavaClass;
67     
68     ArrayList<DAnnotationAst> defaultAnnotations = new ArrayList<DAnnotationAst>();
69     
70     ErrorLog errorLog;
71     
72     public DeclarationClassification(ErrorLog errorLog) {
73         this.errorLog = errorLog;
74     }
75     
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);
109         else
110             throw new InternalCompilerError("Unknown declaration " + declaration.getClass().getSimpleName());
111     }
112
113     public void handle(DFixityAst declaration) {
114         if(!currentAnnotations.isEmpty()) {
115             errorLog.log(declaration.location, "Annotations not supported.");
116             currentAnnotations = new ArrayList<DAnnotationAst>(2);
117         }
118         fixityAst.add(declaration);   
119     }
120     
121     public void handle(DEffectAst declaration) {
122         if(!currentAnnotations.isEmpty()) {
123             errorLog.log(declaration.location, "Annotations not supported.");
124             currentAnnotations = new ArrayList<DAnnotationAst>(2);
125         }
126         if(documentation != null)
127             documentation = null;
128         effectsAst.add(declaration);
129     }
130
131     public void handle(DClassAst declaration) {
132         // TODO errorLog.log(declaration, "Class " + declaration.name + " has already been defined in this module.");
133
134         if(documentation != null) {
135             String name = declaration.name;
136             addClassDocumentation(name, documentation);
137             documentation = null;
138         }
139         
140         ArrayList<DValueTypeAst> typeDeclarations = 
141                 new ArrayList<DValueTypeAst>();
142         ValueRepository defaultValues = new ValueRepository();
143         
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);
152             }
153             else if(decl instanceof DValueAst) {
154                 curDocumentation = null;
155                 try {
156                     defaultValues.add((DValueAst)decl);
157                 } catch (NotPatternException e) {
158                     errorLog.log(e.getExpression().location, "Not a pattern.");
159                 }
160             }
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.");
165                 }
166                 curDocumentation = documentation;
167             }
168             else
169                 errorLog.log(decl.location, "Invalid declaration under class definition.");
170         }
171
172         if(!currentAnnotations.isEmpty()) {
173             declaration.setAnnotations(currentAnnotations);
174             currentAnnotations = new ArrayList<DAnnotationAst>(2);
175         }
176         typeClassesAst.add(new ProcessedDClassAst(declaration,  
177                 typeDeclarations, 
178                 defaultValues));
179     }
180
181     public void handle(ImportDeclaration declaration) {
182         if(!currentAnnotations.isEmpty()) {
183             errorLog.log(declaration.location, "Annotations not supported.");
184             currentAnnotations = new ArrayList<DAnnotationAst>(2);
185         }
186         importsAst.add(declaration);        
187     }
188     
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);
195                 }
196                 else
197                     errorLog.log(declaration.location, "The importJava declaration does not support annotation " + name + ".");
198             }
199             currentAnnotations = new ArrayList<DAnnotationAst>(2);
200         }
201         try {
202             inJavaClass = declaration.className;
203             for(DeclarationAst innerDeclaration : declaration.declarations)
204                 handle(innerDeclaration);
205         } finally {
206             defaultAnnotations.clear();
207             inJavaClass = null;
208         }
209     }
210
211     public void handle(DInstanceAst declaration) {
212         ValueRepository valueDefs = new ValueRepository();
213         
214         ArrayList<DAnnotationAst> localAnnotations = new ArrayList<DAnnotationAst>(2);
215         for(DeclarationAst decl : declaration.declarations) {
216             if(decl instanceof DValueAst) {
217                 try {
218                     String name = valueDefs.add((DValueAst)decl);
219                     if(!localAnnotations.isEmpty()) {
220                         valueDefs.addAnnotations(name, localAnnotations);
221                         localAnnotations = new ArrayList<DAnnotationAst>(2);
222                     }
223                 } catch (NotPatternException e) {
224                     errorLog.log(e.getExpression().location, "Not a pattern.");
225                 }
226             }
227             else if(decl instanceof DAnnotationAst)
228                 localAnnotations.add((DAnnotationAst)decl);
229             else
230                 errorLog.log(decl.location, "Invalid declaration under instance definition.");
231         }
232         for(DAnnotationAst decl : localAnnotations)
233             errorLog.log(decl.location, "Annotation is at invalid location.");
234
235         if(!currentAnnotations.isEmpty()) {
236             errorLog.log(declaration.location, "Annotations not supported.");
237             currentAnnotations = new ArrayList<DAnnotationAst>(2);
238         }
239         instancesAst.add(new ProcessedDInstanceAst(
240                 declaration,
241                 valueDefs));
242     }
243     
244     public void handle(DDerivingInstanceAst declaration) {
245         if(!currentAnnotations.isEmpty()) {
246             errorLog.log(declaration.location, "Annotations not supported.");
247             currentAnnotations = new ArrayList<DAnnotationAst>(2);
248         }
249         derivingInstancesAst.add(declaration);
250     }
251
252     public void handle(DTypeAst declaration) {
253         if(!currentAnnotations.isEmpty()) {
254             errorLog.log(declaration.location, "Annotations not supported.");
255             currentAnnotations = new ArrayList<DAnnotationAst>(2);
256         }
257         typeAliasesAst.add(declaration);
258     }
259
260     public void handle(DDataAst declaration) {
261         if(documentation != null) {
262             String name = declaration.name;
263             addTypeDocumentation(name, documentation);
264             documentation = null;
265         }
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);
272         }
273         dataTypesAst.add(declaration);
274     }
275
276     public void handle(DValueTypeAst declaration) {
277         if(documentation != null) {
278             for(EVar name : declaration.names) {
279                 addValueDocumentation(name.name, documentation);
280             }
281             documentation = null;
282         }
283         if(inJavaClass != null) {
284             for(EVar name : declaration.names)
285                 javaMethodDeclarations.add(new JavaMethodDeclaration(
286                         declaration.location, inJavaClass, name, declaration.type));   
287         }
288         else
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);
294         }
295         if(!defaultAnnotations.isEmpty()) {
296             for(EVar name : declaration.names)
297                 valueDefinitionsAst.addAnnotations(name.name, defaultAnnotations);
298         }
299     }
300     
301     public void handle(DValueAst declaration) {
302         String name;
303         try {
304             name = valueDefinitionsAst.add(declaration);
305         } catch (NotPatternException e) {
306             errorLog.log(e.getExpression().location, "Illegal left hand side of the definition.");
307             return;
308         }
309         if(documentation != null) {
310             addValueDocumentation(name, documentation);
311             documentation = null;
312         }
313         if(!currentAnnotations.isEmpty()) {
314             valueDefinitionsAst.addAnnotations(name, currentAnnotations);
315             currentAnnotations = new ArrayList<DAnnotationAst>(2);
316         }
317     }
318     
319     public void handle(DRelationAst declaration) {
320         String name;
321         try {
322             name = relationDefinitionsAst.add(declaration);
323         } catch (NotPatternException e) {
324             errorLog.log(e.getExpression().location, "Not a pattern.");
325             return;
326         }
327         if(documentation != null) {
328             addRelationDocumentation(name, documentation);
329             documentation = null;
330         }
331         if(!currentAnnotations.isEmpty()) {
332             relationDefinitionsAst.addAnnotations(name, currentAnnotations);
333             currentAnnotations = new ArrayList<DAnnotationAst>(2);
334         }
335     }
336     
337     public void handle(DDocumentationAst declaration) {
338         if(documentation != null) {
339             errorLog.log(documentation.location, "Invalid documentation string. It precedes another documentation string.");
340         }
341         documentation = declaration;                
342     }
343     
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.");
348                 return;
349             }
350             if(!(declaration.parameters[0] instanceof ELiteral)) {
351                 errorLog.log(documentation.location, "A documentation string expected after @documentation.");
352                 return;
353             }
354             ELiteral lit = (ELiteral)declaration.parameters[0];
355             if(!(lit.getValue() instanceof StringConstant)) {
356                 errorLog.log(documentation.location, "A documentation string expected after @documentation.");
357                 return;
358             }
359             String text = ((StringConstant)lit.getValue()).getValue();
360             moduleDocumentation.append(text);
361             moduleDocumentation.append("\n\n");
362         }
363         else
364             currentAnnotations.add(declaration);
365     }
366     
367     public void handle(DRuleAst declaration) {
368         rulesAst.add(declaration);
369     }
370     
371     public void handle(DMappingRelationAst declaration) {
372         mappingRelationsAst.add(declaration);
373     }
374     
375     public void addValueDocumentation(String valueName, DDocumentationAst documentation) {
376         DDocumentationAst oldDoc = valueDocumentation.put(valueName, documentation);
377         if(oldDoc != null) {
378             errorLog.log(oldDoc.location, "Multiple documentation strings given to " + valueName + ".");
379         }
380     }
381     
382     public void addRelationDocumentation(String relationName, DDocumentationAst documentation) {
383         DDocumentationAst oldDoc = relationDocumentation.put(relationName, documentation);
384         if(oldDoc != null) {
385             errorLog.log(oldDoc.location, "Multiple documentation strings given to " + relationName + ".");
386         }
387     }
388     
389     public void addTypeDocumentation(String valueName, DDocumentationAst documentation) {
390         DDocumentationAst oldDoc = typeDocumentation.put(valueName, documentation);
391         if(oldDoc != null) {
392             errorLog.log(oldDoc.location, "Multiple documentation strings given to the same type.");
393         }
394     }
395     
396     public void addClassDocumentation(String valueName, DDocumentationAst documentation) {
397         DDocumentationAst oldDoc = classDocumentation.put(valueName, documentation);
398         if(oldDoc != null) {
399             errorLog.log(oldDoc.location, "Multiple documentation strings given to the same class.");
400         }
401     }
402 }