using System.Linq; using System.Reactive.Linq; using System.Text; using Intromat.Model.Compiler; using Intromat.Model.Compiler.Error; using ReactiveUI; namespace Intromat.ViewModels { public class CodePreviewViewModel : ReactiveObject { private readonly ObservableAsPropertyHelper _compiledCode; private IStatement? _code; private string? _compilerError; public CodePreviewViewModel() { this.WhenAnyValue(vm => vm.Code).Where(c => c != null) .Select(Compile) .ToProperty(this, vm => vm.CompiledCode, out _compiledCode); } public IStatement? Code { get => _code; set => this.RaiseAndSetIfChanged(ref _code, value); } public string? CompilerError { get => _compilerError; set => this.RaiseAndSetIfChanged(ref _compilerError, value); } public string CompiledCode => _compiledCode.Value; private string Compile(IStatement? c) { if (c == null) { CompilerError = "No code provided"; return string.Empty; } CompilerError = string.Empty; CompilerContext ctx = new(); var sb = new StringBuilder(); try { c.CompileHeader(ctx, sb); c.Compile(ctx, sb); return sb.ToString(); } catch (CompilerException e) { string trace = string.Join("\n", ctx.VariablesScopesStack.Select(s => s.Identifier)); CompilerError = e.Message + "\nProblem is near:\n" + trace; return string.Empty; } } } }