package scotch.compiler;
import static java.util.Arrays.asList;
import java.util.List;
import java.util.Map;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import scotch.compiler.analyzer.DependencyAccumulator;
import scotch.compiler.analyzer.NameAccumulator;
import scotch.compiler.analyzer.OperatorAccumulator;
import scotch.compiler.analyzer.PatternAnalyzer;
import scotch.compiler.analyzer.PrecedenceParser;
import scotch.compiler.analyzer.NameQualifier;
import scotch.compiler.analyzer.TypeChecker;
import scotch.compiler.intermediate.IntermediateGenerator;
import scotch.compiler.intermediate.IntermediateGraph;
import scotch.compiler.output.GeneratedClass;
import scotch.compiler.parser.ModulesMapper;
import scotch.compiler.parser.ScotchLayoutLexer;
import scotch.compiler.parser.ScotchLexer;
import scotch.compiler.parser.ScotchParser;
import scotch.compiler.parser.ScotchParser.ModuleContext;
import scotch.compiler.parser.ScotchParser.ModulesContext;
import scotch.compiler.parser.SyntaxTransformer;
import scotch.compiler.syntax.definition.DefinitionGraph;
import scotch.compiler.target.BytecodeGenerator;
import scotch.symbol.SymbolResolver;
import scotch.compiler.syntax.util.DefaultSymbolGenerator;
// TODO multiple file compilation
// TODO incremental compilation
public class Compiler {
public static Compiler compiler(SymbolResolver symbolResolver, String... lines) {
ANTLRInputStream input = new ANTLRInputStream(String.join("\n", lines));
ScotchLayoutLexer tokenSource = new ScotchLayoutLexer(new ScotchLexer(input));
ModulesContext modules = new ScotchParser(new CommonTokenStream(tokenSource)).modules();
return new Compiler(symbolResolver, new ModulesMapper().map(asList(modules)));
}
private final SymbolResolver symbolResolver;
private final Map<String, List<ModuleContext>> modules;
public Compiler(SymbolResolver symbolResolver, Map<String, List<ModuleContext>> modules) {
this.symbolResolver = symbolResolver;
this.modules = modules;
}
public List<GeneratedClass> generateBytecode() {
return new BytecodeGenerator(generateIntermediateCode()).generateBytecode();
}
public DefinitionGraph accumulateDependencies() {
return new DependencyAccumulator(reducePatterns()).accumulateDependencies();
}
public DefinitionGraph accumulateNames() {
return new NameAccumulator(parsePrecedence()).accumulateNames();
}
public DefinitionGraph accumulateOperators() {
return new OperatorAccumulator(transformSyntax()).accumulateOperators();
}
public DefinitionGraph checkTypes() {
return new TypeChecker(accumulateDependencies()).checkTypes();
}
public IntermediateGraph generateIntermediateCode() {
return new IntermediateGenerator(checkTypes()).generateIntermediateCode();
}
public DefinitionGraph transformSyntax() {
return new SyntaxTransformer(symbolResolver, new DefaultSymbolGenerator()).transform(modules);
}
public DefinitionGraph parsePrecedence() {
return new PrecedenceParser(accumulateOperators()).parsePrecedence();
}
public DefinitionGraph qualifyNames() {
return new NameQualifier(accumulateNames()).qualifyNames();
}
public DefinitionGraph reducePatterns() {
return new PatternAnalyzer(qualifyNames()).reducePatterns();
}
}