diff --git a/Parser/ExpressionParser.cs b/Parser/ExpressionParser.cs index 937bc95..36f6751 100644 --- a/Parser/ExpressionParser.cs +++ b/Parser/ExpressionParser.cs @@ -1,12 +1,62 @@ using Flee.PublicTypes; -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -namespace Convention.RScript.Parser +namespace Convention.RScript { + public static class ExpressionMath + { + public static int Sign(double value, double accuracy = ExpressionExtension.DefaultDoubleAccuracy) + { + if (value.IsCloseToZero(accuracy)) + return 0; + return value > 0 ? 1 : -1; + } + + public static int Compare(double value1, double value2, double accuracy = ExpressionExtension.DefaultDoubleAccuracy) + { + if (value1.IsClose(value2, accuracy)) + return 0; + return value1 > value2 ? 1 : -1; + } + + public static bool IsBetween(double value, double minValue, double maxValue, double accuracy = ExpressionExtension.DefaultDoubleAccuracy) + { + return Compare(value, minValue, accuracy) >= 0 && Compare(value, maxValue, accuracy) <= 0; + } + + public static bool IsBetweenExclusive(double value, double minValue, double maxValue, double accuracy = ExpressionExtension.DefaultDoubleAccuracy) + { + return Compare(value, minValue, accuracy) > 0 && Compare(value, maxValue, accuracy) < 0; + } + + public static int ToInt(double value) + { + return (int)value; + } + + public static int ToInt(float value) + { + return (int)value; + } + public static int ToInt(int value) + { + return (int)value; + } + + public static double ToDouble(float value) + { + return (double)value; + } + + public static double ToDouble(int value) + { + return (double)value; + } + public static double ToDouble(double value) + { + return (double)value; + } + } public static class ExpressionExtension { public const double DefaultDoubleAccuracy = 1e-7; @@ -32,7 +82,10 @@ namespace Convention.RScript.Parser return !(double.IsInfinity(value) || double.IsNaN(value) || value > maximumAbsoluteError || value < -maximumAbsoluteError); } } +} +namespace Convention.RScript.Parser +{ public class ExpressionParser { public readonly ExpressionContext context; diff --git a/PublicTypes/RScriptVariables.cs b/PublicTypes/RScriptVariables.cs index 2502924..bd4a110 100644 --- a/PublicTypes/RScriptVariables.cs +++ b/PublicTypes/RScriptVariables.cs @@ -11,7 +11,34 @@ namespace Convention.RScript public struct RScriptVariableEntry { public Type type; - public object data; + public object data + { + readonly get + { + return internalData; + } + set + { + if (type == null) + { + type = value.GetType(); + internalData = value; + return; + } + internalData = Convert.ChangeType(value, type); + } + } + private object internalData; + + public RScriptVariableEntry(object data) : this() + { + this.data = data; + } + public RScriptVariableEntry(Type type, object data) : this() + { + this.type = type; + this.data = data; + } } public class RScriptVariables : IDictionary { diff --git a/RScriptContext.cs b/RScriptContext.cs index 40275b2..c312358 100644 --- a/RScriptContext.cs +++ b/RScriptContext.cs @@ -206,7 +206,7 @@ namespace Convention.RScript } if (CurrentLocalSpaceVariableNames.Peek().Contains(varName) == false) { - Variables.Add(varName, new() { type = varType, data = varDefaultValue }); + Variables.Add(varName, new(varType, varDefaultValue)); parser.context.Variables[varName] = varDefaultValue; CurrentLocalSpaceVariableNames.Peek().Add(varName); } @@ -350,48 +350,59 @@ namespace Convention.RScript private object RunNextStep(ExpressionParser parser) { var sentence = CurrentSentence; - switch (sentence.mode) + try { - case RScriptSentence.Mode.Expression: - return parser.Evaluate(sentence.content); - case RScriptSentence.Mode.DefineVariable: - { - DoDefineVariable(parser, sentence); - } - break; - case RScriptSentence.Mode.EnterNamespace: - { - DoEnterNamespace(parser); - } - break; - case RScriptSentence.Mode.ExitNamespace: - { - DoExitNamespace(parser); - } - break; - case RScriptSentence.Mode.Goto: - { - DoGoto(parser, sentence); - } - break; - case RScriptSentence.Mode.Breakpoint: - { - DoBreakpoint(parser, sentence); - } - break; - case RScriptSentence.Mode.Backpoint: - { - DoBackpoint(parser, sentence); - } - break; - case RScriptSentence.Mode.NamedSpace: - { - DoEnterNamedSpace(sentence); - } - break; - default: - // Do nothing - break; + switch (sentence.mode) + { + case RScriptSentence.Mode.Expression: + return parser.Evaluate(sentence.content); + case RScriptSentence.Mode.DefineVariable: + { + DoDefineVariable(parser, sentence); + } + break; + case RScriptSentence.Mode.EnterNamespace: + { + DoEnterNamespace(parser); + } + break; + case RScriptSentence.Mode.ExitNamespace: + { + DoExitNamespace(parser); + } + break; + case RScriptSentence.Mode.Goto: + { + DoGoto(parser, sentence); + } + break; + case RScriptSentence.Mode.Breakpoint: + { + DoBreakpoint(parser, sentence); + } + break; + case RScriptSentence.Mode.Backpoint: + { + DoBackpoint(parser, sentence); + } + break; + case RScriptSentence.Mode.NamedSpace: + { + DoEnterNamedSpace(sentence); + } + break; + default: + // Do nothing + break; + } + } + catch (RScriptRuntimeException) + { + throw; + } + catch (Exception ex) + { + throw new RScriptRuntimeException($"Runtime error: {ex.Message}", CurrentRuntimePointer, ex); } return null; }