Reworked bound variables into specific LuaType class instead of anonymous objects

This commit is contained in:
Deukhoofd 2018-11-14 13:09:01 +01:00
parent dff1ddc0ba
commit deefe43d9f
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
17 changed files with 125 additions and 56 deletions

View File

@ -2,7 +2,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Upsilon", "Upsilon\Upsilon.csproj", "{030DBAFB-4E55-427E-82F9-1FD042F96B8F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yc", "Yc\Yc.csproj", "{EF232B73-CDD1-491A-A931-99A9704686E4}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ycicle", "Ycicle\Ycicle.csproj", "{EF232B73-CDD1-491A-A931-99A9704686E4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpsilonTests", "UpsilonTests\UpsilonTests.csproj", "{5CB3C59D-96A1-419E-803B-DE4A7DF806FD}"
EndProject

View File

@ -0,0 +1,33 @@
namespace Upsilon.BaseTypes
{
public class Boolean : LuaType
{
public Boolean(bool value)
{
Value = value;
}
public override Type Type => Type.Boolean;
public bool Value { get; }
public static implicit operator bool(Boolean b)
{
return b.Value;
}
public static implicit operator Boolean(bool b)
{
return new Boolean(b);
}
public static Boolean operator ! (Boolean n)
{
return new Boolean(!n.Value);
}
public override string ToString()
{
return Value.ToString();
}
}
}

View File

@ -0,0 +1,7 @@
namespace Upsilon.BaseTypes
{
public abstract class LuaType
{
public abstract Type Type { get; }
}
}

View File

@ -1,9 +1,11 @@
namespace Upsilon.BaseTypes.Number
{
public abstract class Number
public abstract class Number : LuaType
{
protected abstract bool IsFloat { get; }
public override Type Type => Type.Number;
#region Binary Operators
public static Number operator + (Number a, Number b)

View File

@ -21,5 +21,11 @@ namespace Upsilon.BaseTypes.Number
{
return Value.ToString(CultureInfo.InvariantCulture);
}
public static implicit operator double(NumberDouble n)
{
return n.Value;
}
}
}

View File

@ -23,7 +23,7 @@ namespace Upsilon.BaseTypes.Number
return Value.ToString(CultureInfo.InvariantCulture);
}
public static explicit operator long(NumberLong n)
public static implicit operator long(NumberLong n)
{
return n.Value;
}

View File

@ -1,7 +1,9 @@
using System;
using System.Collections.Immutable;
using Upsilon.BaseTypes;
using Upsilon.BaseTypes.Number;
using Upsilon.Parser;
using Boolean = Upsilon.BaseTypes.Boolean;
using Type = Upsilon.BaseTypes.Type;
namespace Upsilon.Binder
@ -94,7 +96,7 @@ namespace Upsilon.Binder
{
var value = e.Value;
var type = Type.Nil;
object outValue = null;
LuaType outValue = null;
switch (value)
{
case double d:
@ -105,9 +107,9 @@ namespace Upsilon.Binder
type = Type.Number;
outValue = new NumberLong(l);
break;
case bool _:
case bool b:
type = Type.Boolean;
outValue = value;
outValue = new Boolean(b);
break;
default:
_diagnostics.LogUnknownType(e.Span);

View File

@ -4,7 +4,7 @@ namespace Upsilon.Binder
{
public class BoundLiteralExpression : BoundExpression
{
public BoundLiteralExpression(object value, Type type)
public BoundLiteralExpression(LuaType value, Type type)
{
Value = value;
Type = type;
@ -12,6 +12,6 @@ namespace Upsilon.Binder
public override BoundKind Kind => BoundKind.BoundLiteralExpression;
public override Type Type { get; }
public object Value { get; }
public LuaType Value { get; }
}
}

View File

@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using Upsilon.BaseTypes;
namespace Upsilon.Binder
{
@ -13,7 +14,7 @@ namespace Upsilon.Binder
_parentScope = parentScope;
_variables = new Dictionary<string, VariableSymbol>();
}
public BoundScope(Dictionary<VariableSymbol, object> variables, BoundScope parentScope)
public BoundScope(Dictionary<VariableSymbol, LuaType> variables, BoundScope parentScope)
{
_parentScope = parentScope;
_variables = variables.ToDictionary(x => x.Key.Name, x => x.Key);

View File

@ -1,30 +1,32 @@
using System;
using System.Collections.Generic;
using Upsilon.BaseTypes;
using Upsilon.BaseTypes.Number;
using Upsilon.Binder;
using Boolean = Upsilon.BaseTypes.Boolean;
namespace Upsilon.Evaluator
{
public class Evaluator
{
private readonly Diagnostics _diagnostics;
private object _value;
private LuaType _value;
private Script Script { get; }
private readonly Dictionary<VariableSymbol, object> _variables = new Dictionary<VariableSymbol, object>();
private readonly Dictionary<VariableSymbol, LuaType> _variables = new Dictionary<VariableSymbol, LuaType>();
public Evaluator(Script script, Diagnostics diagnostics)
{
_diagnostics = diagnostics;
Script = script;
}
public Evaluator(Script script, Diagnostics diagnostics, Dictionary<VariableSymbol, object> vars)
public Evaluator(Script script, Diagnostics diagnostics, Dictionary<VariableSymbol, LuaType> vars)
{
_diagnostics = diagnostics;
Script = script;
_variables = vars;
}
public object Evaluate(BoundScript e)
public LuaType Evaluate(BoundScript e)
{
EvaluateStatement(e.Statement);
return _value;
@ -55,7 +57,7 @@ namespace Upsilon.Evaluator
_value = EvaluateExpression(e.Expression);
}
private object EvaluateExpression(BoundExpression e)
private LuaType EvaluateExpression(BoundExpression e)
{
switch (e.Kind)
{
@ -72,7 +74,7 @@ namespace Upsilon.Evaluator
}
}
private object EvaluateUnaryExpression(BoundUnaryExpression e)
private LuaType EvaluateUnaryExpression(BoundUnaryExpression e)
{
var operand = EvaluateExpression(e.InExpression);
switch (e.Operator.Kind)
@ -82,13 +84,13 @@ namespace Upsilon.Evaluator
case BoundUnaryOperator.OperatorKind.Negation:
return -((Number)operand);
case BoundUnaryOperator.OperatorKind.LogicalNegation:
return !(bool) operand;
return !(Boolean) operand;
default:
throw new Exception("Invalid Unary Operator: " + e.Operator.Kind);
}
}
private object EvaluateBinaryExpression(BoundBinaryExpression e)
private LuaType EvaluateBinaryExpression(BoundBinaryExpression e)
{
var left = EvaluateExpression(e.LeftExpression);
var right = EvaluateExpression(e.RightExpression);
@ -103,9 +105,9 @@ namespace Upsilon.Evaluator
case BoundBinaryOperator.OperatorKind.Division:
return ((Number)left) / ((Number)right);
case BoundBinaryOperator.OperatorKind.Equality:
return Equals(left, right);
return new Boolean(Equals(left, right));
case BoundBinaryOperator.OperatorKind.Inequality:
return !Equals(left, right);
return new Boolean(!Equals(left, right));
default:
throw new Exception("Invalid Binary Operator: " + e.Operator);
}
@ -118,7 +120,7 @@ namespace Upsilon.Evaluator
_value = val;
}
private object EvaluateVariableExpression(BoundVariableExpression e)
private LuaType EvaluateVariableExpression(BoundVariableExpression e)
{
return _variables[e.Variable];
}
@ -134,7 +136,7 @@ namespace Upsilon.Evaluator
private void EvaluateBoundIfStatement(BoundIfStatement boundBlockStatement)
{
var condition = EvaluateExpression(boundBlockStatement.Condition.Expression);
if ((bool) condition)
if ((Boolean) condition)
{
EvaluateBoundBlockStatement(boundBlockStatement.Block);
}

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using Upsilon.BaseTypes;
using Upsilon.Binder;
using Upsilon.Parser;
using Upsilon.Text;
@ -13,13 +14,13 @@ namespace Upsilon.Evaluator
public Diagnostics Diagnostics { get; }
private Binder.Binder Binder { get; }
public Script(string scriptString, Dictionary<VariableSymbol, object> variables = null)
public Script(string scriptString, Dictionary<VariableSymbol, LuaType> variables = null)
{
ScriptString = new SourceText(scriptString);
Diagnostics = new Diagnostics(ScriptString);
_parsed = Parser.Parser.Parse(scriptString, Diagnostics);
if (variables == null)
variables = new Dictionary<VariableSymbol, object>();
variables = new Dictionary<VariableSymbol, LuaType>();
Binder = new Binder.Binder(new BoundScope(variables, null), Diagnostics);
Evaluator = new Evaluator(this, Diagnostics, variables);
}
@ -34,7 +35,7 @@ namespace Upsilon.Evaluator
return Evaluator.Evaluate(Bind());
}
public T Evaluate<T>()
public T Evaluate<T>() where T : LuaType
{
return (T)Evaluator.Evaluate(Bind());
}

View File

@ -2,6 +2,7 @@ using System;
using System.Text;
using Upsilon.BaseTypes.Number;
using Upsilon.Binder;
using Boolean = Upsilon.BaseTypes.Boolean;
using Type = Upsilon.BaseTypes.Type;
namespace UpsilonCompiler
@ -59,7 +60,7 @@ namespace UpsilonCompiler
case Type.Nil:
return "null";
case Type.Boolean:
return ((bool)e.Value) ? "true" : "false";
return ((Boolean)e.Value) ? "true" : "false";
case Type.Number:
return ((Number) e.Value).ToString();
case Type.String:

View File

@ -1,3 +1,4 @@
using Upsilon.BaseTypes.Number;
using Upsilon.Evaluator;
using Upsilon.Parser;
using Xunit;
@ -16,7 +17,7 @@ namespace UpsilonTests
[InlineData("0.005 + 2.2", 2.205)]
public void Addition(string input, double expectedOutput)
{
var actual = new Script(input).Evaluate<double>();
var actual = new Script(input).Evaluate<NumberDouble>();
Assert.Equal(expectedOutput, actual, 8);
}
@ -29,7 +30,7 @@ namespace UpsilonTests
[InlineData("10.256-2.8546", 7.4014)]
public void Subtraction(string input, double expectedOutput)
{
var actual = new Script(input).Evaluate<double>();
var actual = new Script(input).Evaluate<NumberDouble>();
Assert.Equal(expectedOutput, actual, 8);
}
@ -39,7 +40,7 @@ namespace UpsilonTests
[InlineData("21312 * 41684", 888369408)]
public void Multiplication(string input, double expectedOutput)
{
var actual = new Script(input).Evaluate<double>();
var actual = new Script(input).Evaluate<NumberDouble>();
Assert.Equal(expectedOutput, actual, 8);
}
@ -49,7 +50,7 @@ namespace UpsilonTests
[InlineData("656486 / 5146", 127.57209483)]
public void Divison(string input, double expectedOutput)
{
var actual = new Script(input).Evaluate<double>();
var actual = new Script(input).Evaluate<NumberDouble>();
Assert.Equal(expectedOutput, actual, 8);
}

View File

@ -1,3 +1,4 @@
using Upsilon.BaseTypes;
using Upsilon.BaseTypes.Number;
using Upsilon.Evaluator;
using Xunit;
@ -12,7 +13,7 @@ namespace UpsilonTests
var input = "if true then val = true end";
var script = new Script(input);
Assert.Empty(script.Diagnostics.Messages);
var actual = script.Evaluate<bool>();
var actual = script.Evaluate<Boolean>();
Assert.True(actual);
}

View File

@ -1,3 +1,4 @@
using Upsilon.BaseTypes.Number;
using Upsilon.Evaluator;
using Upsilon.Parser;
using Xunit;
@ -11,7 +12,7 @@ namespace UpsilonTests
[InlineData("(10 + 5) * 5", 75)]
public void Parenthesis(string input, double expectedOutput)
{
var actual = new Script(input).Evaluate<double>();
var actual = new Script(input).Evaluate<NumberDouble>();
Assert.Equal(expectedOutput, actual, 8);
}
@ -20,7 +21,7 @@ namespace UpsilonTests
[InlineData("5 + 10 * 5", 55)]
public void MultiplicationBeforeAddition(string input, double expectedOutput)
{
var actual = new Script(input).Evaluate<double>();
var actual = new Script(input).Evaluate<NumberDouble>();
Assert.Equal(expectedOutput, actual, 8);
}

View File

@ -1,25 +1,31 @@
using System;
using System.Collections.Generic;
using Upsilon;
using Upsilon.BaseTypes;
using Upsilon.Binder;
using Upsilon.Evaluator;
using UpsilonCompiler;
namespace Yc
namespace Ycicle
{
static class Program
internal static class Program
{
static void Main(string[] args)
private static void Main()
{
Console.WriteLine("Upsilon REPL");
Dictionary<VariableSymbol, object> variables = new Dictionary<VariableSymbol, object>();
var variables = new Dictionary<VariableSymbol, LuaType>();
var showTranspiledOutput = false;
while (true)
{
Console.Write("» ");
var input = Console.ReadLine();
if (input == "exit")
switch (input)
{
return;
case "exit":
return;
case "compiled":
showTranspiledOutput = !showTranspiledOutput;
break;
}
var parsed = new Script(input, variables);
@ -35,31 +41,36 @@ namespace Yc
continue;
}
var compiler = new Transpiler();
var compiled = compiler.TranspilerToCSharp(parsed.Bind());
Console.WriteLine(compiled);
/*
var evaluate = parsed.Evaluate();
if (parsed.Diagnostics.Messages.Count > 0)
if (showTranspiledOutput)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Errors were found during evaluating");
foreach (var diagnosticsMessage in parsed.Diagnostics.Messages)
{
LogError(diagnosticsMessage);
}
Console.ResetColor();
var transpiler = new Transpiler();
var transpiled = transpiler.TranspilerToCSharp(parsed.Bind());
Console.WriteLine(transpiled);
}
else
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine(evaluate);
Console.ResetColor();
}*/
var evaluate = parsed.Evaluate();
if (parsed.Diagnostics.Messages.Count > 0)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Errors were found during evaluating");
foreach (var diagnosticsMessage in parsed.Diagnostics.Messages)
{
LogError(diagnosticsMessage);
}
Console.ResetColor();
}
else
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine(evaluate);
Console.ResetColor();
}
}
}
}
public static void LogError(DiagnosticsMessage message)
private static void LogError(DiagnosticsMessage message)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(message.Message);