using Canon.Core.Abstractions; using Canon.Core.CodeGenerators; using Canon.Core.LexicalParser; using Canon.Core.SyntaxNodes; using Canon.Server.DataTransferObjects; using Canon.Server.Entities; using Canon.Server.Models; using Microsoft.EntityFrameworkCore; namespace Canon.Server.Services; public class CompilerService( ILexer lexer, IGrammarParser grammarParser, CompileDbContext dbContext, GridFsService gridFsService, SyntaxTreePresentationService syntaxTreePresentationService, ILogger logger) { public async Task Compile(SourceCode sourceCode) { logger.LogInformation("Try to compile: '{}'.", sourceCode.Code); IQueryable resultQuery = from item in dbContext.CompileResults where item.SourceCode == sourceCode.Code select item; CompileResult? cachedResult = await resultQuery.FirstOrDefaultAsync(); if (cachedResult is not null) { return new CompileResponse(cachedResult); } CodeReader reader = new(sourceCode); IEnumerable tokens = lexer.Tokenize(reader); ProgramStruct root = grammarParser.Analyse(tokens); await using Stream imageStream = syntaxTreePresentationService.Present(root); string filename = await gridFsService.UploadStream(imageStream, "image/png"); CCodeBuilder builder = new(); root.GenerateCCode(builder); CompileResult result = new() { SourceCode = sourceCode.Code, CompileId = Guid.NewGuid().ToString(), CompiledCode = builder.Build(), SytaxTreeImageFilename = filename, CompileTime = DateTime.Now }; await dbContext.CompileResults.AddAsync(result); await dbContext.SaveChangesAsync(); return new CompileResponse(result); } }