MParser/Parser/Evaluator.cs

389 lines
15 KiB
C#

using Parser.Internal;
using Parser.MFunctions;
using Parser.Objects;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
namespace Parser
{
internal class EvaluationScope
{
public Dictionary<string, MObject> Variables { get; } = new Dictionary<string, MObject>();
}
internal class Evaluator
{
private readonly SyntaxTree _syntaxTree;
private readonly CompilationContext _context;
private readonly DiagnosticsBag _diagnostics = new DiagnosticsBag();
private bool _insideFunction = false;
private readonly Stack<EvaluationScope> _scopeStack = new Stack<EvaluationScope>();
public Evaluator(SyntaxTree syntaxTree, CompilationContext context)
{
_syntaxTree = syntaxTree;
_context = context;
var outerScope = new EvaluationScope();
_scopeStack.Push(outerScope);
}
internal EvaluationResult Evaluate()
{
var result = EvaluateFile(_syntaxTree.Root);
return new EvaluationResult(result, _diagnostics.ToImmutableArray());
}
private MObject? EvaluateFile(FileSyntaxNode root)
{
MObject? lastResult = null;
foreach (var nodeOrToken in root.StatementList)
{
if (nodeOrToken.IsNode)
{
var statement = (StatementSyntaxNode)nodeOrToken.AsNode()!;
lastResult = EvaluateStatement(statement) ?? lastResult;
}
}
return lastResult;
}
private MObject? EvaluateStatement(StatementSyntaxNode statement)
{
return statement.Kind switch
{
TokenKind.AbstractMethodDeclaration =>
EvaluateAbstractMethodDeclaration((AbstractMethodDeclarationSyntaxNode)statement),
TokenKind.ClassDeclaration =>
EvaluateClassDeclaration((ClassDeclarationSyntaxNode)statement),
TokenKind.EmptyStatement =>
EvaluateEmptyStatement((EmptyStatementSyntaxNode)statement),
TokenKind.ExpressionStatement =>
EvaluateExpressionStatement((ExpressionStatementSyntaxNode)statement),
TokenKind.ForStatement =>
EvaluateForStatement((ForStatementSyntaxNode)statement),
TokenKind.FunctionDeclaration =>
EvaluateFunctionDeclaration((FunctionDeclarationSyntaxNode)statement),
TokenKind.IfStatement =>
EvaluateIfStatement((IfStatementSyntaxNode)statement),
TokenKind.ConcreteMethodDeclaration =>
EvaluateMethodDefinition((MethodDefinitionSyntaxNode)statement),
TokenKind.SwitchStatement =>
EvaluateSwitchStatement((SwitchStatementSyntaxNode)statement),
TokenKind.TryCatchStatement =>
EvaluateTryCatchStatement((TryCatchStatementSyntaxNode)statement),
TokenKind.WhileStatement =>
EvaluateWhileStatement((WhileStatementSyntaxNode)statement),
_ => throw new NotImplementedException($"Invalid statement kind '{statement.Kind}'."),
};
}
private MObject? EvaluateClassDeclaration(ClassDeclarationSyntaxNode statement)
{
throw new NotImplementedException();
}
private MObject? EvaluateEmptyStatement(EmptyStatementSyntaxNode statement)
{
throw new NotImplementedException();
}
private MObject? EvaluateTryCatchStatement(TryCatchStatementSyntaxNode statement)
{
throw new NotImplementedException();
}
private MObject? EvaluateForStatement(ForStatementSyntaxNode statement)
{
throw new NotImplementedException();
}
private MObject? EvaluateIfStatement(IfStatementSyntaxNode statement)
{
throw new NotImplementedException();
}
private MObject? EvaluateWhileStatement(WhileStatementSyntaxNode statement)
{
throw new NotImplementedException();
}
private MObject? EvaluateSwitchStatement(SwitchStatementSyntaxNode statement)
{
throw new NotImplementedException();
}
private MObject? EvaluateFunctionDeclaration(FunctionDeclarationSyntaxNode statement)
{
throw new NotImplementedException();
}
private MObject? EvaluateAbstractMethodDeclaration(AbstractMethodDeclarationSyntaxNode statement)
{
throw new NotImplementedException();
}
private MObject? EvaluateMethodDefinition(MethodDefinitionSyntaxNode statement)
{
throw new NotImplementedException();
}
private MObject? EvaluateExpressionStatement(ExpressionStatementSyntaxNode statement)
{
return EvaluateExpression(statement.Expression);
}
private MObject? EvaluateExpression(ExpressionSyntaxNode expression)
{
return expression.Kind switch
{
TokenKind.ArrayLiteralExpression =>
EvaluateArrayLiteralExpression((ArrayLiteralExpressionSyntaxNode)expression),
TokenKind.AssignmentExpression =>
EvaluateAssignmentExpression((AssignmentExpressionSyntaxNode)expression),
TokenKind.BinaryOperationExpression =>
EvaluateBinaryOperation((BinaryOperationExpressionSyntaxNode)expression),
TokenKind.CellArrayElementAccessExpression =>
EvaluateCellArrayElementAccess((CellArrayElementAccessExpressionSyntaxNode)expression),
TokenKind.CellArrayLiteralExpression =>
EvaluateCellArrayLiteralExpression((CellArrayLiteralExpressionSyntaxNode)expression),
TokenKind.ClassInvokationExpression =>
EvaluateClassInvokation((BaseClassInvokationSyntaxNode)expression),
TokenKind.CommandExpression =>
EvaluateCommand((CommandExpressionSyntaxNode)expression),
TokenKind.CompoundNameExpression =>
EvaluateCompoundName((CompoundNameExpressionSyntaxNode)expression),
TokenKind.DoubleQuotedStringLiteralExpression =>
EvaluateDoubleQuotedStringLiteralExpression((DoubleQuotedStringLiteralSyntaxNode)expression),
TokenKind.EmptyExpression =>
EvaluateEmptyExpression((EmptyExpressionSyntaxNode)expression),
TokenKind.FunctionCallExpression =>
EvaluateFunctionCall((FunctionCallExpressionSyntaxNode)expression),
TokenKind.IdentifierNameExpression =>
EvaluateIdentifierNameExpression((IdentifierNameExpressionSyntaxNode)expression),
TokenKind.IndirectMemberAccessExpression =>
EvaluateIndirectMemberAccess((IndirectMemberAccessSyntaxNode)expression),
TokenKind.LambdaExpression =>
EvaluateLambdaExpression((LambdaExpressionSyntaxNode)expression),
TokenKind.MemberAccessExpression =>
EvaluateMemberAccess((MemberAccessSyntaxNode)expression),
TokenKind.NamedFunctionHandleExpression =>
EvaluateNamedFunctionHandleExpression((NamedFunctionHandleExpressionSyntaxNode)expression),
TokenKind.NumberLiteralExpression =>
EvaluateNumberLiteralExpression((NumberLiteralSyntaxNode)expression),
TokenKind.ParenthesizedExpression =>
EvaluateParenthesizedExpression((ParenthesizedExpressionSyntaxNode)expression),
TokenKind.StringLiteralExpression =>
EvaluateStringLiteralExpression((StringLiteralSyntaxNode)expression),
TokenKind.UnaryPrefixOperationExpression =>
EvaluateUnaryPrefixOperationExpression((UnaryPrefixOperationExpressionSyntaxNode)expression),
TokenKind.UnaryPostfixOperationExpression =>
EvaluateUnaryPostfixOperationExpression((UnaryPostixOperationExpressionSyntaxNode)expression),
TokenKind.UnquotedStringLiteralExpression =>
EvaluateUnquotedStringLiteralExpression((UnquotedStringLiteralSyntaxNode)expression),
_ => throw new NotImplementedException($"Invalid expression kind '{expression.Kind}'."),
};
}
private MObject? EvaluateParenthesizedExpression(ParenthesizedExpressionSyntaxNode expression)
{
return EvaluateExpression(expression.Expression);
}
private MObject? EvaluateClassInvokation(BaseClassInvokationSyntaxNode expression)
{
throw new NotImplementedException();
}
private MObject? EvaluateCommand(CommandExpressionSyntaxNode expression)
{
throw new NotImplementedException();
}
private MObject? EvaluateIndirectMemberAccess(IndirectMemberAccessSyntaxNode expression)
{
throw new NotImplementedException();
}
private MObject? EvaluateUnaryPostfixOperationExpression(UnaryPostixOperationExpressionSyntaxNode expression)
{
throw new NotImplementedException();
}
private MObject? EvaluateMemberAccess(MemberAccessSyntaxNode expression)
{
throw new NotImplementedException();
}
private MObject? EvaluateFunctionCall(FunctionCallExpressionSyntaxNode expression)
{
throw new NotImplementedException();
}
private MObject? EvaluateCellArrayElementAccess(CellArrayElementAccessExpressionSyntaxNode expression)
{
throw new NotImplementedException();
}
private MObject? EvaluateCellArrayLiteralExpression(CellArrayLiteralExpressionSyntaxNode expression)
{
throw new NotImplementedException();
}
private MObject? EvaluateArrayLiteralExpression(ArrayLiteralExpressionSyntaxNode expression)
{
throw new NotImplementedException();
}
private MObject? EvaluateUnquotedStringLiteralExpression(UnquotedStringLiteralSyntaxNode expression)
{
throw new NotImplementedException();
}
private MObject? EvaluateDoubleQuotedStringLiteralExpression(DoubleQuotedStringLiteralSyntaxNode expression)
{
throw new NotImplementedException();
}
private MObject? EvaluateStringLiteralExpression(StringLiteralSyntaxNode expression)
{
throw new NotImplementedException();
}
private MObject? EvaluateNumberLiteralExpression(NumberLiteralSyntaxNode expression)
{
return expression.Number.Value is double value
? MObject.CreateDoubleNumber(value)
: null;
}
private MObject? EvaluateIdentifierNameExpression(IdentifierNameExpressionSyntaxNode expression)
{
var variableName = expression.Name.Text;
var maybeValue = GetVariableValue(variableName);
if (maybeValue is null)
{
_diagnostics.ReportVariableNotFound(
new TextSpan(expression.Name.Position, expression.Name.Text.Length),
variableName);
}
return maybeValue;
}
private MObject? EvaluateBinaryOperation(BinaryOperationExpressionSyntaxNode expression)
{
var left = EvaluateExpression(expression.Lhs);
if (left is null)
{
return null;
}
var right = EvaluateExpression(expression.Rhs);
if (right is null)
{
return null;
}
return expression.Operation.Kind switch
{
TokenKind.PlusToken => MOperations.Plus(left, right),
TokenKind.MinusToken => MOperations.Minus(left, right),
TokenKind.StarToken => MOperations.Star(left, right),
TokenKind.SlashToken => MOperations.Slash(left, right),
_ => throw new NotImplementedException($"Binary operation {expression.Operation.Kind} is not implemented."),
};
}
private MObject? EvaluateCompoundName(CompoundNameExpressionSyntaxNode expression)
{
throw new NotImplementedException();
}
private MObject? EvaluateUnaryPrefixOperationExpression(UnaryPrefixOperationExpressionSyntaxNode expression)
{
throw new NotImplementedException();
}
private MObject? EvaluateEmptyExpression(EmptyExpressionSyntaxNode expression)
{
throw new NotImplementedException();
}
private MObject? EvaluateAssignmentExpression(AssignmentExpressionSyntaxNode expression)
{
var rightValue = EvaluateExpression(expression.Rhs);
if (rightValue is null)
{
_diagnostics.ReportCannotEvaluateExpression(
new TextSpan(expression.Rhs.Position, expression.Rhs.Position + expression.Rhs.FullWidth));
return null;
}
var left = expression.Lhs;
if (left.Kind == TokenKind.IdentifierNameExpression)
{
var leftIdentifier = (IdentifierNameExpressionSyntaxNode)left;
var variableName = leftIdentifier.Name.Text;
SetVariableValue(variableName, rightValue);
return rightValue;
}
throw new NotImplementedException();
}
private MObject? GetVariableValue(string name)
{
if (_insideFunction)
{
if (_context.Variables.TryGetValue(name, out var globalValue))
{
return globalValue;
}
var currentScope = _scopeStack.Peek();
return currentScope.Variables.TryGetValue(name, out var localValue) ? globalValue : null;
}
else
{
if (_context.Variables.TryGetValue(name, out var globalValue))
{
return globalValue;
}
return null;
}
}
private void SetVariableValue(string name, MObject value)
{
if (_insideFunction)
{
if (_context.Variables.ContainsKey(name))
{
_context.Variables[name] = value;
}
else
{
var currentScope = _scopeStack.Peek();
currentScope.Variables[name] = value;
}
}
else
{
_context.Variables[name] = value;
}
}
private MObject? EvaluateLambdaExpression(LambdaExpressionSyntaxNode expression)
{
throw new NotImplementedException();
}
private MObject? EvaluateNamedFunctionHandleExpression(NamedFunctionHandleExpressionSyntaxNode expression)
{
throw new NotImplementedException();
}
}
}