--- /dev/null
+package org.simantics.scl.compiler.compilation;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Map;
+
+import org.simantics.scl.compiler.environment.EnvironmentFactory;
+import org.simantics.scl.compiler.errors.ErrorLog;
+import org.simantics.scl.compiler.internal.codegen.types.JavaReferenceValidator;
+import org.simantics.scl.compiler.internal.parsing.declarations.DeclarationAst;
+import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
+import org.simantics.scl.compiler.internal.parsing.parser.SCLParserImpl;
+import org.simantics.scl.compiler.module.ConcreteModule;
+import org.simantics.scl.compiler.module.options.ModuleCompilationOptions;
+import org.simantics.scl.compiler.top.ModuleInitializer;
+import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
+import org.simantics.scl.compiler.top.StandardModuleInitializer;
+
+public class SCLCompiler {
+ ErrorLog errorLog = new ErrorLog();
+ DeclarationClassification declarations = new DeclarationClassification(errorLog);
+
+ // publishable results
+ Map<String, byte[]> classes;
+ ConcreteModule module;
+ ModuleInitializer moduleInitializer;
+
+ private CompilationTimer timer;
+ private ModuleCompilationOptions options;
+
+ public SCLCompiler(ModuleCompilationOptions options) {
+ this.options = options == null ? ModuleCompilationOptions.STANDARD_OPTIONS : options;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void addSource(Reader sourceReader) {
+ if(SCLCompilerConfiguration.ENABLE_TIMING) initializeTiming();
+ try {
+ SCLParserImpl parser = new SCLParserImpl(sourceReader);
+ if(!parser.isEmpty())
+ for(DeclarationAst declaration : (ArrayList<DeclarationAst>)parser.parseModule())
+ declarations.handle(declaration);
+ } catch(SCLSyntaxErrorException e) {
+ errorLog.log(e.location, e.getMessage());
+ } catch(Exception e) {
+ errorLog.log(e);
+ } finally {
+ try {
+ sourceReader.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ if(SCLCompilerConfiguration.ENABLE_TIMING) phaseFinished("Parsing");
+ }
+
+ public void compile(
+ EnvironmentFactory localEnvironmentFactory,
+ String moduleName,
+ JavaReferenceValidator<?, ?, ?, ?> javaReferenceValidator) {
+ try {
+ if(!errorLog.isEmpty()) return;
+ Elaboration elaboration = new Elaboration(errorLog,
+ timer,
+ localEnvironmentFactory,
+ moduleName,
+ declarations.importsAst,
+ javaReferenceValidator,
+ declarations.valueDefinitionsAst,
+ declarations.relationDefinitionsAst);
+ if(options.computeCoverage)
+ elaboration.addCoverageBranchPoints();
+ // Elaboration
+ if(!errorLog.isEmpty()) return;
+ elaboration.addTypesToEnvironment(
+ declarations.dataTypesAst,
+ declarations.typeAliasesAst,
+ declarations.effectsAst);
+ if(!errorLog.isEmpty()) return;
+ elaboration.processTypeAliases(declarations.typeAliasesAst);
+ if(!errorLog.isEmpty()) return;
+ elaboration.processDataTypes(declarations.dataTypesAst);
+ if(!errorLog.isEmpty()) return;
+ elaboration.processTypeClasses(declarations.typeClassesAst);
+ if(!errorLog.isEmpty()) return;
+ elaboration.processDerivingInstances(declarations.derivingInstancesAst, declarations.instancesAst);
+ if(!errorLog.isEmpty()) return;
+ elaboration.processInstances(declarations.instancesAst);
+ if(!errorLog.isEmpty()) return;
+ elaboration.processJavaMethods(declarations.javaMethodDeclarations);
+ if(!errorLog.isEmpty()) return;
+ elaboration.addDataTypesToEnvironment();
+ elaboration.addTypeClassesToEnvironment();
+ elaboration.preprocessValueDefinitions(declarations.typeAnnotationsAst);
+ elaboration.processMappingRelations(declarations.mappingRelationsAst);
+ elaboration.addFixityToEnvironment(declarations.fixityAst);
+ elaboration.addValueDefinitionsToEnvironment(declarations.typeAnnotationsAst);
+ elaboration.processRules(declarations.rulesAst);
+ elaboration.addSupplementedTypeAnnotationsToEnvironment();
+ if(SCLCompilerConfiguration.ENABLE_TIMING) phaseFinished("Elaboration");
+
+ // Type checking
+ if(!errorLog.isEmpty()) return;
+ //new TypeChecking(errorLog, elaboration.environment, elaboration.module).typeCheck();
+ new TypeChecking(errorLog, elaboration.environment, elaboration.module).typeCheck();
+
+ if(SCLCompilerConfiguration.ENABLE_TIMING) phaseFinished("Type checking");
+
+ // FIXME HACK for testing
+ /*if(!elaboration.module.getRules().isEmpty()) {
+ TransformationBuilder tb = new TransformationBuilder(elaboration.module.getRules());
+ tb.compileRules(elaboration.environment);
+ System.out.println(tb.getCompiledExpression(elaboration.environment));
+ }*/
+
+ // Documentation generation
+ new DocumentationGeneration(
+ declarations.valueDocumentation,
+ declarations.typeDocumentation,
+ declarations.classDocumentation,
+ elaboration.module
+ )
+ .generateDocumentation();
+ this.declarations = null;
+
+ // Code generation
+ if(!errorLog.isEmpty()) return;
+ CodeGeneration codeGeneration = new CodeGeneration(
+ errorLog,
+ elaboration.environment,
+ elaboration.namingPolicy,
+ elaboration.javaTypeTranslator,
+ elaboration.javaReferenceValidator,
+ elaboration.module);
+ codeGeneration.simplifyValues();
+ if(!errorLog.isEmpty()) return;
+ codeGeneration.convertToSSA();
+ if(!errorLog.isEmpty()) return;
+ codeGeneration.optimizeSSA();
+
+ if(SCLCompilerConfiguration.ENABLE_TIMING) phaseFinished("SSA conversion and optimization");
+
+ if(!errorLog.isEmpty()) return;
+ codeGeneration.generateCode();
+ if(!errorLog.isEmpty()) return;
+ codeGeneration.generateDataTypes(elaboration.dataTypes);
+ if(!errorLog.isEmpty()) return;
+ codeGeneration.generateTypeClasses();
+ if(!errorLog.isEmpty()) return;
+ codeGeneration.generateTypeClassInstances();
+ if(!errorLog.isEmpty()) return;
+
+ classes = codeGeneration.classes;
+ module = codeGeneration.module;
+ moduleInitializer = StandardModuleInitializer.create(
+ codeGeneration.namingPolicy.getModuleClassName(),
+ codeGeneration.externalConstants);
+
+ module.setClasses(classes);
+ module.setModuleInitializer(moduleInitializer);
+ module.setBranchPoints(elaboration.branchPoints);
+
+ if(SCLCompilerConfiguration.ENABLE_TIMING) {
+ phaseFinished("Code generation");
+ reportTiming(moduleName);
+ }
+ } catch(Exception e) {
+ errorLog.log(e);
+ }
+ }
+
+ public ErrorLog getErrorLog() {
+ return errorLog;
+ }
+
+ public Map<String, byte[]> getClasses() {
+ return classes;
+ }
+
+ public ConcreteModule getModule() {
+ return module;
+ }
+
+ public ModuleInitializer getModuleInitializer() {
+ return moduleInitializer;
+ }
+
+ private void initializeTiming() {
+ timer = new CompilationTimer();
+ }
+
+ private void phaseFinished(String phaseName) {
+ timer.phaseFinished(phaseName);
+ }
+
+ private void reportTiming(String moduleName) {
+ timer.report(moduleName);
+ }
+}