diff --git a/Upsilon.sln b/Upsilon.sln index 3e3d066..8106d0d 100644 --- a/Upsilon.sln +++ b/Upsilon.sln @@ -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 diff --git a/Upsilon/BaseTypes/Boolean.cs b/Upsilon/BaseTypes/Boolean.cs new file mode 100644 index 0000000..11fdd60 --- /dev/null +++ b/Upsilon/BaseTypes/Boolean.cs @@ -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(); + } + } +} \ No newline at end of file diff --git a/Upsilon/BaseTypes/LuaType.cs b/Upsilon/BaseTypes/LuaType.cs new file mode 100644 index 0000000..5298f9b --- /dev/null +++ b/Upsilon/BaseTypes/LuaType.cs @@ -0,0 +1,7 @@ +namespace Upsilon.BaseTypes +{ + public abstract class LuaType + { + public abstract Type Type { get; } + } +} \ No newline at end of file diff --git a/Upsilon/BaseTypes/Number/Number.cs b/Upsilon/BaseTypes/Number/Number.cs index 1f59f8f..634e589 100644 --- a/Upsilon/BaseTypes/Number/Number.cs +++ b/Upsilon/BaseTypes/Number/Number.cs @@ -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) diff --git a/Upsilon/BaseTypes/Number/NumberDouble.cs b/Upsilon/BaseTypes/Number/NumberDouble.cs index 1140fc2..86187d7 100644 --- a/Upsilon/BaseTypes/Number/NumberDouble.cs +++ b/Upsilon/BaseTypes/Number/NumberDouble.cs @@ -21,5 +21,11 @@ namespace Upsilon.BaseTypes.Number { return Value.ToString(CultureInfo.InvariantCulture); } + + public static implicit operator double(NumberDouble n) + { + return n.Value; + } + } } \ No newline at end of file diff --git a/Upsilon/BaseTypes/Number/NumberLong.cs b/Upsilon/BaseTypes/Number/NumberLong.cs index fab60e5..43fb20f 100644 --- a/Upsilon/BaseTypes/Number/NumberLong.cs +++ b/Upsilon/BaseTypes/Number/NumberLong.cs @@ -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; } diff --git a/Upsilon/Binder/Binder.cs b/Upsilon/Binder/Binder.cs index f3e9c2e..36d72ef 100644 --- a/Upsilon/Binder/Binder.cs +++ b/Upsilon/Binder/Binder.cs @@ -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); diff --git a/Upsilon/Binder/BoundExpressions/BoundLiteralExpression.cs b/Upsilon/Binder/BoundExpressions/BoundLiteralExpression.cs index e185602..0d46d16 100644 --- a/Upsilon/Binder/BoundExpressions/BoundLiteralExpression.cs +++ b/Upsilon/Binder/BoundExpressions/BoundLiteralExpression.cs @@ -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; } } } \ No newline at end of file diff --git a/Upsilon/Binder/BoundScope.cs b/Upsilon/Binder/BoundScope.cs index c47ce65..835149c 100644 --- a/Upsilon/Binder/BoundScope.cs +++ b/Upsilon/Binder/BoundScope.cs @@ -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(); } - public BoundScope(Dictionary variables, BoundScope parentScope) + public BoundScope(Dictionary variables, BoundScope parentScope) { _parentScope = parentScope; _variables = variables.ToDictionary(x => x.Key.Name, x => x.Key); diff --git a/Upsilon/Evaluator/Evaluator.cs b/Upsilon/Evaluator/Evaluator.cs index 6fc3c12..d55fe2d 100644 --- a/Upsilon/Evaluator/Evaluator.cs +++ b/Upsilon/Evaluator/Evaluator.cs @@ -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 _variables = new Dictionary(); + private readonly Dictionary _variables = new Dictionary(); public Evaluator(Script script, Diagnostics diagnostics) { _diagnostics = diagnostics; Script = script; } - public Evaluator(Script script, Diagnostics diagnostics, Dictionary vars) + public Evaluator(Script script, Diagnostics diagnostics, Dictionary 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); } diff --git a/Upsilon/Evaluator/Script.cs b/Upsilon/Evaluator/Script.cs index 11e36f4..c8b7abe 100644 --- a/Upsilon/Evaluator/Script.cs +++ b/Upsilon/Evaluator/Script.cs @@ -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 variables = null) + public Script(string scriptString, Dictionary variables = null) { ScriptString = new SourceText(scriptString); Diagnostics = new Diagnostics(ScriptString); _parsed = Parser.Parser.Parse(scriptString, Diagnostics); if (variables == null) - variables = new Dictionary(); + variables = new Dictionary(); 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() + public T Evaluate() where T : LuaType { return (T)Evaluator.Evaluate(Bind()); } diff --git a/UpsilonCompiler/Compiler.cs b/UpsilonCompiler/Compiler.cs index 8050e71..b6f32fb 100644 --- a/UpsilonCompiler/Compiler.cs +++ b/UpsilonCompiler/Compiler.cs @@ -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: diff --git a/UpsilonTests/BasicMathExpressions.cs b/UpsilonTests/BasicMathExpressions.cs index e9ed4a5..604e0d9 100644 --- a/UpsilonTests/BasicMathExpressions.cs +++ b/UpsilonTests/BasicMathExpressions.cs @@ -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(); + var actual = new Script(input).Evaluate(); 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(); + var actual = new Script(input).Evaluate(); 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(); + var actual = new Script(input).Evaluate(); 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(); + var actual = new Script(input).Evaluate(); Assert.Equal(expectedOutput, actual, 8); } diff --git a/UpsilonTests/IfTests.cs b/UpsilonTests/IfTests.cs index 5d87909..a5b9f93 100644 --- a/UpsilonTests/IfTests.cs +++ b/UpsilonTests/IfTests.cs @@ -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(); + var actual = script.Evaluate(); Assert.True(actual); } diff --git a/UpsilonTests/MathPrecedence.cs b/UpsilonTests/MathPrecedence.cs index 32b970d..d13c10b 100644 --- a/UpsilonTests/MathPrecedence.cs +++ b/UpsilonTests/MathPrecedence.cs @@ -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(); + var actual = new Script(input).Evaluate(); 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(); + var actual = new Script(input).Evaluate(); Assert.Equal(expectedOutput, actual, 8); } diff --git a/Yc/Program.cs b/Ycicle/Program.cs similarity index 50% rename from Yc/Program.cs rename to Ycicle/Program.cs index cedb457..0936696 100644 --- a/Yc/Program.cs +++ b/Ycicle/Program.cs @@ -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 variables = new Dictionary(); + var variables = new Dictionary(); + 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); diff --git a/Yc/Yc.csproj b/Ycicle/Ycicle.csproj similarity index 100% rename from Yc/Yc.csproj rename to Ycicle/Ycicle.csproj