Evaluate char arrays and 'disp'

This commit is contained in:
Alexander Luzgarev 2020-07-14 20:12:38 +02:00
parent 886b897a4c
commit 0529e87d43
10 changed files with 180 additions and 8 deletions

10
Parser/EvaluationScope.cs Normal file
View File

@ -0,0 +1,10 @@
using Parser.Objects;
using System.Collections.Generic;
namespace Parser
{
internal class EvaluationScope
{
public Dictionary<string, MObject> Variables { get; } = new Dictionary<string, MObject>();
}
}

View File

@ -4,14 +4,10 @@ using Parser.Objects;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
namespace Parser
{
internal class EvaluationScope
{
public Dictionary<string, MObject> Variables { get; } = new Dictionary<string, MObject>();
}
internal class Evaluator
{
private readonly SyntaxTree _syntaxTree;
@ -218,7 +214,59 @@ namespace Parser
private MObject? EvaluateFunctionCall(FunctionCallExpressionSyntaxNode expression)
{
throw new NotImplementedException();
var arguments = new List<MObject>();
var nodes = expression.Nodes.Where(n => n.IsNode).Select(n => (ExpressionSyntaxNode)n.AsNode()!);
var allGood = true;
foreach (var node in nodes)
{
var argument = EvaluateExpression(node);
if (argument is null)
{
_diagnostics.ReportCannotEvaluateExpression(
new TextSpan(node.Position, node.FullWidth));
allGood = false;
}
else
{
arguments.Add(argument);
}
}
if (!allGood)
{
return null;
}
var function = GetFunctionSymbol(expression.FunctionName);
if (function.Name == "disp")
{
return EvaluateDisp(arguments);
}
else
{
throw new NotImplementedException("Functions are not supported.");
}
}
private MObject? EvaluateDisp(List<MObject> arguments)
{
if (arguments.Count != 1)
{
throw new NotImplementedException($"Cannot evaluate disp() with {arguments.Count} arguments.");
}
Console.WriteLine(arguments[0]);
return null;
}
private FunctionSymbol GetFunctionSymbol(ExpressionSyntaxNode functionName)
{
if (functionName.Kind == TokenKind.IdentifierNameExpression)
{
return new FunctionSymbol(((IdentifierNameExpressionSyntaxNode)functionName).Text);
}
throw new NotImplementedException($"Unknown function symbol '{functionName.Text}'.");
}
private MObject? EvaluateCellArrayElementAccess(CellArrayElementAccessExpressionSyntaxNode expression)
@ -248,7 +296,11 @@ namespace Parser
private MObject? EvaluateStringLiteralExpression(StringLiteralSyntaxNode expression)
{
throw new NotImplementedException();
return expression.StringToken.Value switch
{
string s => MObject.CreateCharArray(s.ToCharArray()),
_ => null,
};
}
private MObject? EvaluateNumberLiteralExpression(NumberLiteralSyntaxNode expression)

12
Parser/FunctionSymbol.cs Normal file
View File

@ -0,0 +1,12 @@
namespace Parser
{
internal class FunctionSymbol
{
public string Name { get; }
public FunctionSymbol(string name)
{
Name = name;
}
}
}

View File

@ -0,0 +1,22 @@
namespace Parser.Objects
{
public class MCharArray : MObject
{
private MCharArray(char[] chars)
{
Chars = chars;
}
public char[] Chars { get; }
public static MCharArray Create(char[] chars)
{
return new MCharArray(chars);
}
public override string ToString()
{
return new string(Chars);
}
}
}

View File

@ -6,5 +6,10 @@
{
return MDoubleNumber.Create(value);
}
public static MCharArray CreateCharArray(char[] chars)
{
return MCharArray.Create(chars);
}
}
}

View File

@ -21,7 +21,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Repl", "Repl\Repl.csproj", "{8FEDFE5D-3320-418F-88A6-09C1B51C4441}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MApplication", "MApplication\MApplication.csproj", "{A7EE271C-8822-43EA-BA13-5D6D5DC5B581}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MApplication", "MApplication\MApplication.csproj", "{A7EE271C-8822-43EA-BA13-5D6D5DC5B581}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cmi", "cmi\cmi.csproj", "{C2447F0B-733D-4755-A104-5B82E24D3F47}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -57,6 +59,10 @@ Global
{A7EE271C-8822-43EA-BA13-5D6D5DC5B581}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A7EE271C-8822-43EA-BA13-5D6D5DC5B581}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A7EE271C-8822-43EA-BA13-5D6D5DC5B581}.Release|Any CPU.Build.0 = Release|Any CPU
{C2447F0B-733D-4755-A104-5B82E24D3F47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C2447F0B-733D-4755-A104-5B82E24D3F47}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C2447F0B-733D-4755-A104-5B82E24D3F47}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C2447F0B-733D-4755-A104-5B82E24D3F47}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

1
cmi.cmd Normal file
View File

@ -0,0 +1 @@
dotnet run --project cmi -- %*

47
cmi/Program.cs Normal file
View File

@ -0,0 +1,47 @@
using Parser;
using System;
using System.IO;
namespace cmi
{
class Program
{
static void Main(string[] args)
{
if (args.Length != 1)
{
Console.Error.WriteLine("Usage: cmi <file.m>");
}
var fileName = args[0];
var text = File.ReadAllText(fileName);
var tree = SyntaxTree.Parse(text);
var compilation = Compilation.Create(tree);
if (tree.Diagnostics.Diagnostics.Count > 0)
{
foreach (var diagnostic in tree.Diagnostics.Diagnostics)
{
Console.ForegroundColor = ConsoleColor.DarkRed;
Console.WriteLine($"{diagnostic.Span}: {diagnostic.Message}");
Console.ResetColor();
}
}
var context = new CompilationContext();
var evaluationResult = compilation.Evaluate(context);
foreach (var diagnostic in evaluationResult.Diagnostics)
{
Console.ForegroundColor = ConsoleColor.DarkRed;
Console.WriteLine($"{diagnostic.Span}: {diagnostic.Message}");
Console.ResetColor();
}
var result = evaluationResult.Value?.ToString();
if (result is not null)
{
Console.WriteLine(result);
}
}
}
}

14
cmi/cmi.csproj Normal file
View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<Nullable>enable</Nullable>
<LangVersion>preview</LangVersion>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Parser\Parser.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,3 @@
x = 1;
disp(x + 2);
disp('Hello world!');