]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/SCLCompiler.java
SCL compiler generates line numbers to bytecode
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / compilation / SCLCompiler.java
1 package org.simantics.scl.compiler.compilation;
2
3 import java.io.StringReader;
4 import java.util.ArrayList;
5 import java.util.Map;
6
7 import org.simantics.scl.compiler.environment.EnvironmentFactory;
8 import org.simantics.scl.compiler.errors.ErrorLog;
9 import org.simantics.scl.compiler.internal.codegen.types.JavaReferenceValidatorFactory;
10 import org.simantics.scl.compiler.internal.parsing.declarations.DeclarationAst;
11 import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
12 import org.simantics.scl.compiler.internal.parsing.parser.SCLParserImpl;
13 import org.simantics.scl.compiler.internal.parsing.parser.SCLParserOptions;
14 import org.simantics.scl.compiler.internal.parsing.utils.LineLocators;
15 import org.simantics.scl.compiler.module.ConcreteModule;
16 import org.simantics.scl.compiler.module.options.ModuleCompilationOptions;
17 import org.simantics.scl.compiler.top.ModuleInitializer;
18 import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
19 import org.simantics.scl.compiler.top.StandardModuleInitializer;
20
21 public class SCLCompiler {
22     CompilationContext compilationContext = new CompilationContext();
23     DeclarationClassification declarations = new DeclarationClassification(compilationContext);
24     
25     // publishable results
26     Map<String, byte[]> classes;
27     ConcreteModule module;
28     ModuleInitializer moduleInitializer;
29     
30     private CompilationTimer timer;
31     private ModuleCompilationOptions options;
32     
33     JavaReferenceValidatorFactory jrvFactory;
34     
35     public SCLCompiler(ModuleCompilationOptions options, JavaReferenceValidatorFactory jrvFactory) {
36         this.options = options == null ? ModuleCompilationOptions.STANDARD_OPTIONS : options;
37         this.jrvFactory = jrvFactory;
38     }
39
40     @SuppressWarnings("unchecked")
41     public void addSource(String source) {
42         if(SCLCompilerConfiguration.ENABLE_TIMING) initializeTiming();
43         try {
44             compilationContext.lineLocator = LineLocators.createLineLocator(source);
45             SCLParserImpl parser = new SCLParserImpl(new StringReader(source));
46             parser.setParserOptions(SCLParserOptions.MODULE_DEFAULT);
47             parser.setCompilationContext(compilationContext);
48             if(!parser.isEmpty())
49             for(DeclarationAst declaration : (ArrayList<DeclarationAst>)parser.parseModule())
50                 declarations.handle(declaration);
51         } catch(SCLSyntaxErrorException e) {
52             compilationContext.errorLog.log(e.location, e.getMessage());
53         } catch(Exception e) {
54             compilationContext.errorLog.log(e);
55         }
56         if(SCLCompilerConfiguration.ENABLE_TIMING) phaseFinished("Parsing");
57     }
58     
59     private boolean hasErrors() {
60         return !compilationContext.errorLog.hasNoErrors();
61     }
62     
63     public void compile(
64             EnvironmentFactory localEnvironmentFactory,
65             String moduleName) {
66         try {
67             if(hasErrors()) return;
68             Elaboration elaboration = new Elaboration(compilationContext,
69                     timer,
70                     localEnvironmentFactory,
71                     moduleName,
72                     compilationContext.header,
73                     declarations.importsAst,
74                     jrvFactory,
75                     declarations.valueDefinitionsAst,
76                     declarations.relationDefinitionsAst);
77             if(options.computeCoverage)
78                 elaboration.addCoverageBranchPoints();
79             if(options.collectDebugInfo)
80                 elaboration.collectDebugInfo();
81             // Elaboration
82             if(hasErrors()) return;
83             elaboration.prepareExports();
84             if(hasErrors()) return;
85             elaboration.addTypesToEnvironment(
86                     declarations.dataTypesAst,
87                     declarations.typeAliasesAst,
88                     declarations.effectsAst,
89                     declarations.rulesetsAst);
90             if(hasErrors()) return;
91             elaboration.processTypeAliases(declarations.typeAliasesAst);
92             if(hasErrors()) return;
93             elaboration.processDataTypes(declarations.dataTypesAst);
94             if(hasErrors()) return;
95             elaboration.processTypeClasses(declarations.typeClassesAst);
96             if(hasErrors()) return;
97             elaboration.processDerivingInstances(declarations.derivingInstancesAst, declarations.instancesAst);
98             if(hasErrors()) return;
99             elaboration.processInstances(declarations.instancesAst);
100             if(hasErrors()) return;
101             elaboration.processJavaMethods(declarations.javaMethodDeclarations);
102             if(hasErrors()) return;
103             elaboration.processRulesets(declarations.rulesetsAst);
104             if(hasErrors()) return;
105             elaboration.addDataTypesToEnvironment();
106             elaboration.addTypeClassesToEnvironment();
107             elaboration.preprocessValueDefinitions(declarations.typeAnnotationsAst);
108             elaboration.processMappingRelations(declarations.mappingRelationsAst);
109             elaboration.addFixityToEnvironment(declarations.fixityAst);
110             elaboration.addValueDefinitionsToEnvironment(declarations.typeAnnotationsAst);
111             elaboration.processRules(declarations.rulesAst);
112             elaboration.addSupplementedTypeAnnotationsToEnvironment();
113             elaboration.checkExports();
114             if(SCLCompilerConfiguration.ENABLE_TIMING) phaseFinished("Elaboration");
115             
116             // Type checking
117             if(hasErrors()) return;
118             //new TypeChecking(errorLog, elaboration.environment, elaboration.module).typeCheck();
119             new TypeChecking(compilationContext, elaboration.module).typeCheck();
120             
121             if(SCLCompilerConfiguration.ENABLE_TIMING) phaseFinished("Type checking");
122             
123             // FIXME HACK for testing
124             /*if(!elaboration.module.getRules().isEmpty()) {
125                 TransformationBuilder tb = new TransformationBuilder(elaboration.module.getRules());
126                 tb.compileRules(elaboration.environment);
127                 System.out.println(tb.getCompiledExpression(elaboration.environment));
128             }*/
129             
130             // Documentation generation
131             new DocumentationGeneration(
132                     declarations.valueDocumentation,
133                     declarations.typeDocumentation,
134                     declarations.classDocumentation,
135                     elaboration.module
136                     )
137                 .generateDocumentation();
138             this.declarations = null;
139             
140             // Code generation
141             if(hasErrors()) return;
142             CodeGeneration codeGeneration = new CodeGeneration(
143                     compilationContext,
144                     elaboration.javaReferenceValidator,
145                     elaboration.module);
146             codeGeneration.simplifyValues();
147             if(hasErrors()) return;
148             codeGeneration.convertToSSA();
149             if(hasErrors()) return;
150             codeGeneration.optimizeSSA();
151             
152             if(SCLCompilerConfiguration.ENABLE_TIMING) phaseFinished("SSA conversion and optimization");
153             
154             if(hasErrors()) return;
155             codeGeneration.generateCode();
156             if(hasErrors()) return;
157             codeGeneration.generateDataTypes(elaboration.dataTypes);
158             if(hasErrors()) return;
159             codeGeneration.generateTypeClasses();
160             if(hasErrors()) return;
161             codeGeneration.generateTypeClassInstances();
162             if(hasErrors()) return;
163
164             classes = codeGeneration.classes;
165             module =  codeGeneration.module;
166             moduleInitializer = StandardModuleInitializer.create(
167                     compilationContext.namingPolicy.getModuleClassName(),
168                     codeGeneration.externalConstants);
169             
170             module.setClasses(classes);
171             module.setParentClassLoader(elaboration.javaReferenceValidator.getClassLoader());
172             module.setModuleInitializer(moduleInitializer);
173             module.setBranchPoints(elaboration.branchPoints);
174             if(compilationContext.errorLog.hasErrorsOrWarnings())
175                 module.setWarnings(compilationContext.errorLog.getErrors());
176             
177             if(SCLCompilerConfiguration.ENABLE_TIMING) {
178                 phaseFinished("Code generation");
179                 reportTiming(moduleName);
180             }
181         } catch(Exception e) {
182             compilationContext.errorLog.log(e);
183         }
184     }
185
186     public ErrorLog getErrorLog() {
187         return compilationContext.errorLog;
188     }
189     
190     public Map<String, byte[]> getClasses() {
191         return classes;
192     }
193     
194     public ConcreteModule getModule() {
195         return module;
196     }
197     
198     public ModuleInitializer getModuleInitializer() {
199         return moduleInitializer;
200     }
201     
202     private void initializeTiming() {
203         timer = new CompilationTimer();
204     }
205     
206     private void phaseFinished(String phaseName) {
207         timer.phaseFinished(phaseName);
208     }
209     
210     private void reportTiming(String moduleName) {
211         timer.report(moduleName);
212     }
213 }