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 Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Upsilon", "Upsilon\Upsilon.csproj", "{030DBAFB-4E55-427E-82F9-1FD042F96B8F}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Upsilon", "Upsilon\Upsilon.csproj", "{030DBAFB-4E55-427E-82F9-1FD042F96B8F}"
EndProject 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 EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpsilonTests", "UpsilonTests\UpsilonTests.csproj", "{5CB3C59D-96A1-419E-803B-DE4A7DF806FD}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpsilonTests", "UpsilonTests\UpsilonTests.csproj", "{5CB3C59D-96A1-419E-803B-DE4A7DF806FD}"
EndProject 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 namespace Upsilon.BaseTypes.Number
{ {
public abstract class Number public abstract class Number : LuaType
{ {
protected abstract bool IsFloat { get; } protected abstract bool IsFloat { get; }
public override Type Type => Type.Number;
#region Binary Operators #region Binary Operators
public static Number operator + (Number a, Number b) public static Number operator + (Number a, Number b)

View File

@ -21,5 +21,11 @@ namespace Upsilon.BaseTypes.Number
{ {
return Value.ToString(CultureInfo.InvariantCulture); 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); return Value.ToString(CultureInfo.InvariantCulture);
} }
public static explicit operator long(NumberLong n) public static implicit operator long(NumberLong n)
{ {
return n.Value; return n.Value;
} }

View File

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

View File

@ -4,7 +4,7 @@ namespace Upsilon.Binder
{ {
public class BoundLiteralExpression : BoundExpression public class BoundLiteralExpression : BoundExpression
{ {
public BoundLiteralExpression(object value, Type type) public BoundLiteralExpression(LuaType value, Type type)
{ {
Value = value; Value = value;
Type = type; Type = type;
@ -12,6 +12,6 @@ namespace Upsilon.Binder
public override BoundKind Kind => BoundKind.BoundLiteralExpression; public override BoundKind Kind => BoundKind.BoundLiteralExpression;
public override Type Type { get; } 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.Collections.Generic;
using System.Linq; using System.Linq;
using Upsilon.BaseTypes;
namespace Upsilon.Binder namespace Upsilon.Binder
{ {
@ -13,7 +14,7 @@ namespace Upsilon.Binder
_parentScope = parentScope; _parentScope = parentScope;
_variables = new Dictionary<string, VariableSymbol>(); _variables = new Dictionary<string, VariableSymbol>();
} }
public BoundScope(Dictionary<VariableSymbol, object> variables, BoundScope parentScope) public BoundScope(Dictionary<VariableSymbol, LuaType> variables, BoundScope parentScope)
{ {
_parentScope = parentScope; _parentScope = parentScope;
_variables = variables.ToDictionary(x => x.Key.Name, x => x.Key); _variables = variables.ToDictionary(x => x.Key.Name, x => x.Key);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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