Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 130 additions & 0 deletions mc/LanguageRepl.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Language.CodeAnalysis;
using Language.CodeAnalysis.Text;

namespace Language
{
internal sealed class LanguageRepl : Repl
{
private Compilation _previous;
private bool _showTree;
private bool _showProgram;
private readonly Dictionary<VariableSymbol, object> _variables = new Dictionary<VariableSymbol, object>();

protected override void RenderLine(string line)
{
var tokens = SyntaxTree.ParseTokens(line, false);
foreach (var token in tokens)
{
var isKeyword = token.Kind.ToString().EndsWith("Keyword");
var isNumber = token.Kind == SyntaxKind.NumberToken;
if (isKeyword)
Console.ForegroundColor = ConsoleColor.Blue;
else if(!isNumber)
Console.ForegroundColor = ConsoleColor.White;

Console.WriteLine(token.Text);
Console.ResetColor();
}
}

protected override void EvaluateMetaCommand(string input)
{
switch (input)
{
case "/showtree":
_showTree = !_showTree;
Console.WriteLine(_showTree ? "Now showing parse trees" : "No longer showing parse trees");
break;
case "/showprogram":
_showProgram = !_showProgram;
Console.WriteLine(_showProgram ? "Now showing bound tree" : "No longer showing bound tree");
break;
case "/cls":
Console.Clear();
break;
case "/reset":
_previous = null;
_variables.Clear();
break;
default:
base.EvaluateMetaCommand(input);
break;
}
}

protected override bool IsCompleteSubmission(string text)
{
if (string.IsNullOrEmpty(text))
return true;

var syntaxTree = SyntaxTree.Parse(text);
if(syntaxTree.Diagnostics.Any())
return false;

return true;
}

protected override void EvaluateSubmission(string text)
{
var syntaxTree = SyntaxTree.Parse(text);

var compilation = _previous == null
? new Compilation(syntaxTree)
: _previous.ContinueWith(syntaxTree);

if (_showTree)
syntaxTree.Root.WriteTo(Console.Out);

if (_showProgram)
compilation.EmitTree(Console.Out);

var result = compilation.Evaluate(_variables);

if (!result.Diagnostics.Any())
{
Console.WriteLine(result.Value);
_previous = compilation;
}
else
{
foreach (var diagnostic in result.Diagnostics)
{
var lineIndex = syntaxTree.Text.GetLineIndex(diagnostic.Span.Start);
var line = syntaxTree.Text.Lines[lineIndex];
var lineNumber = lineIndex + 1;
var character = diagnostic.Span.Start - line.Start + 1;

Console.WriteLine();

Console.ForegroundColor = ConsoleColor.DarkRed;
Console.Write($"({lineNumber}, {character}): ");
Console.WriteLine(diagnostic);
Console.ResetColor();

var prefixSpan = TextSpan.FromBounds(line.Start, diagnostic.Span.Start);
var suffixSpan = TextSpan.FromBounds(diagnostic.Span.End, line.End);

var prefix = syntaxTree.Text.ToString(prefixSpan);
var error = syntaxTree.Text.ToString(diagnostic.Span);
var suffix = syntaxTree.Text.ToString(suffixSpan);

Console.Write(" ");
Console.Write(prefix);

Console.ForegroundColor = ConsoleColor.DarkRed;
Console.Write(error);
Console.ResetColor();

Console.Write(suffix);

Console.WriteLine();
}

Console.WriteLine();
}
}
}
}
127 changes: 6 additions & 121 deletions mc/Program.cs
Original file line number Diff line number Diff line change
@@ -1,129 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Language.CodeAnalysis;
using Language.CodeAnalysis.Binding;
using Language.CodeAnalysis.Binding;
using Language.CodeAnalysis.Syntax;
using Language.CodeAnalysis.Text;

namespace Language
{
internal class Program
internal static class Program
{
private static void Main(string[] args)
private static void Main()
{
var showTree = false;
var showProgram = false;
var variables = new Dictionary<VariableSymbol, object>();
var textBuilder = new StringBuilder();

Compilation previous = null;

while(true)
{
if (textBuilder.Length == 0)
Console.Write("> ");
else
Console.Write("· ");

var input = Console.ReadLine();
var isBlank = string.IsNullOrWhiteSpace(input);

if(textBuilder.Length == 0)
{
if (isBlank)
{
break;
}
else if (input == "/showtree")
{
showTree = !showTree;
Console.WriteLine(showTree ? "Now showing parse trees" : "No longer showing parse trees");
continue;
}
else if (input == "/showprogram")
{
showProgram = !showProgram;
Console.WriteLine(showProgram ? "Now showing bound tree" : "No longer showing bound tree");
continue;
}
else if (input == "/cls")
{
Console.Clear();
continue;
}
else if(input == "/reset")
{
previous = null;
continue;
}
}

textBuilder.AppendLine(input);
var text = textBuilder.ToString();

var syntaxTree = SyntaxTree.Parse(text);

if (!isBlank && syntaxTree.Diagnostics.Any())
continue;

var compilation = previous == null ? new Compilation(syntaxTree) : previous.ContinueWith(syntaxTree);


if (showTree)
syntaxTree.Root.WriteTo(Console.Out);

if (showProgram)
compilation.EmitTree(Console.Out);

var result = compilation.Evaluate(variables);

if (!result.Diagnostics.Any())
{
Console.WriteLine(result.Value);
previous = compilation;
}
else
{
foreach (var diagnostic in result.Diagnostics)
{
var lineIndex = syntaxTree.Text.GetLineIndex(diagnostic.Span.Start);
var line = syntaxTree.Text.Lines[lineIndex];
var lineNumber = lineIndex + 1;

var character = diagnostic.Span.Start - line.Start + 1;

Console.WriteLine();

Console.ForegroundColor = ConsoleColor.DarkRed;
Console.Write($"({lineNumber}, {character}): ");
Console.WriteLine(diagnostic);
Console.ResetColor();

var prefixSpan = TextSpan.FromBounds(line.Start, diagnostic.Span.Start);
var suffixSpan = TextSpan.FromBounds(diagnostic.Span.End, line.End);

var prefix = syntaxTree.Text.ToString(prefixSpan);
var error = syntaxTree.Text.ToString(diagnostic.Span);
var suffix = syntaxTree.Text.ToString(suffixSpan);

Console.Write(" ");
Console.Write(prefix);

Console.ForegroundColor = ConsoleColor.DarkRed;
Console.Write(error);
Console.ResetColor();

Console.Write(suffix);
Console.WriteLine();
}

Console.WriteLine();
}

textBuilder.Clear();
}
var repl = new LanguageRepl();
repl.Run();
}
}
}
}
Loading