From 638394d25b80aac3ca20d9160ee38d157bb829eb Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Fri, 23 Nov 2018 18:18:07 +0100 Subject: [PATCH] Generic For Loops --- .../BaseTypes/LuaTypeInterfaces/IITerable.cs | 8 -- .../BaseTypes/LuaTypeInterfaces/IIndexable.cs | 11 -- Upsilon/BaseTypes/Number/Number.cs | 99 -------------- Upsilon/BaseTypes/Number/ScriptNumber.cs | 99 ++++++++++++++ ...{NumberDouble.cs => ScriptNumberDouble.cs} | 6 +- .../{NumberLong.cs => ScriptNumberLong.cs} | 6 +- .../{LuaBoolean.cs => ScriptBoolean.cs} | 14 +- .../{LuaFunction.cs => ScriptFunction.cs} | 20 +-- .../BaseTypes/{LuaNull.cs => ScriptNull.cs} | 2 +- .../{LuaString.cs => ScriptString.cs} | 45 +++--- .../BaseTypes/{LuaTable.cs => ScriptTable.cs} | 40 ++---- .../BaseTypes/{LuaType.cs => ScriptType.cs} | 2 +- .../ScriptTypeInterfaces/IITerable.cs | 9 ++ .../ScriptTypeInterfaces/IIndexable.cs | 13 ++ .../IScopeOwner.cs | 2 +- ...SimpleLuaTable.cs => SimpleScriptTable.cs} | 15 +- Upsilon/BaseTypes/Type.cs | 2 +- Upsilon/BaseTypes/TypeConversion.cs | 20 +-- .../BaseTypes/UserData/DictionaryUserData.cs | 8 +- Upsilon/BaseTypes/UserData/GenericUserData.cs | 10 +- Upsilon/BaseTypes/UserData/IUserData.cs | 2 + Upsilon/BaseTypes/UserData/ListUserData.cs | 17 ++- Upsilon/BaseTypes/UserData/UserDataMethod.cs | 9 +- Upsilon/BaseTypes/UserData/UserDataType.cs | 14 +- Upsilon/Binder/Binder.cs | 49 +++++-- .../BoundLiteralExpression.cs | 4 +- Upsilon/Binder/BoundKind.cs | 3 +- .../BoundGenericForStatement.cs | 21 +++ Upsilon/Evaluator/EvaluationScope.cs | 34 +++-- Upsilon/Evaluator/Evaluator.cs | 128 ++++++++++++------ Upsilon/Evaluator/Script.cs | 8 +- Upsilon/Parser/Parser.cs | 22 ++- .../GenericForStatementSyntax.cs | 41 ++++++ Upsilon/Parser/SyntaxKind.cs | 3 +- Upsilon/StandardLibraries/BasicFunctions.cs | 24 +++- Upsilon/StandardLibraries/LuaLibrary.cs | 6 +- Upsilon/StandardLibraries/StaticScope.cs | 4 +- UpsilonTests/GeneralTests/ForLoopTests.cs | 37 +++++ 38 files changed, 530 insertions(+), 327 deletions(-) delete mode 100644 Upsilon/BaseTypes/LuaTypeInterfaces/IITerable.cs delete mode 100644 Upsilon/BaseTypes/LuaTypeInterfaces/IIndexable.cs delete mode 100644 Upsilon/BaseTypes/Number/Number.cs create mode 100644 Upsilon/BaseTypes/Number/ScriptNumber.cs rename Upsilon/BaseTypes/Number/{NumberDouble.cs => ScriptNumberDouble.cs} (80%) rename Upsilon/BaseTypes/Number/{NumberLong.cs => ScriptNumberLong.cs} (82%) rename Upsilon/BaseTypes/{LuaBoolean.cs => ScriptBoolean.cs} (60%) rename Upsilon/BaseTypes/{LuaFunction.cs => ScriptFunction.cs} (75%) rename Upsilon/BaseTypes/{LuaNull.cs => ScriptNull.cs} (89%) rename Upsilon/BaseTypes/{LuaString.cs => ScriptString.cs} (57%) rename Upsilon/BaseTypes/{LuaTable.cs => ScriptTable.cs} (55%) rename Upsilon/BaseTypes/{LuaType.cs => ScriptType.cs} (83%) create mode 100644 Upsilon/BaseTypes/ScriptTypeInterfaces/IITerable.cs create mode 100644 Upsilon/BaseTypes/ScriptTypeInterfaces/IIndexable.cs rename Upsilon/BaseTypes/{LuaTypeInterfaces => ScriptTypeInterfaces}/IScopeOwner.cs (71%) rename Upsilon/BaseTypes/{SimpleLuaTable.cs => SimpleScriptTable.cs} (68%) create mode 100644 Upsilon/Binder/BoundStatements/BoundGenericForStatement.cs create mode 100644 Upsilon/Parser/StatementSyntax/GenericForStatementSyntax.cs diff --git a/Upsilon/BaseTypes/LuaTypeInterfaces/IITerable.cs b/Upsilon/BaseTypes/LuaTypeInterfaces/IITerable.cs deleted file mode 100644 index e3138d4..0000000 --- a/Upsilon/BaseTypes/LuaTypeInterfaces/IITerable.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Upsilon.BaseTypes.LuaTypeInterfaces -{ - public interface IIterable - { - bool Next(out LuaType key, out LuaType next); - void Reset(); - } -} \ No newline at end of file diff --git a/Upsilon/BaseTypes/LuaTypeInterfaces/IIndexable.cs b/Upsilon/BaseTypes/LuaTypeInterfaces/IIndexable.cs deleted file mode 100644 index ef382fc..0000000 --- a/Upsilon/BaseTypes/LuaTypeInterfaces/IIndexable.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Upsilon.Evaluator; -using Upsilon.Text; - -namespace Upsilon.BaseTypes -{ - internal interface IIndexable - { - LuaType Get(Diagnostics diagnostics, TextSpan span, LuaType index, EvaluationScope scope); - void Set(Diagnostics diagnostics, TextSpan span, LuaType index, LuaType value); - } -} \ No newline at end of file diff --git a/Upsilon/BaseTypes/Number/Number.cs b/Upsilon/BaseTypes/Number/Number.cs deleted file mode 100644 index ca537e3..0000000 --- a/Upsilon/BaseTypes/Number/Number.cs +++ /dev/null @@ -1,99 +0,0 @@ -namespace Upsilon.BaseTypes.Number -{ - internal 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) - { - if (!a.IsFloat && !b.IsFloat) - return new NumberLong(((NumberLong) a).Value + ((NumberLong) b).Value); - if (a.IsFloat && b.IsFloat) - return new NumberDouble(((NumberDouble) a).Value + ((NumberDouble) b).Value); - if (a.IsFloat) - return new NumberDouble(((NumberDouble) a).Value + ((NumberLong) b).Value); - return new NumberDouble(((NumberLong) a).Value + ((NumberDouble) b).Value); - } - - public static Number operator - (Number a, Number b) - { - if (!a.IsFloat && !b.IsFloat) - return new NumberLong(((NumberLong) a).Value - ((NumberLong) b).Value); - if (a.IsFloat && b.IsFloat) - return new NumberDouble(((NumberDouble) a).Value - ((NumberDouble) b).Value); - if (a.IsFloat) - return new NumberDouble(((NumberDouble) a).Value - ((NumberLong) b).Value); - return new NumberDouble(((NumberLong) a).Value - ((NumberDouble) b).Value); - } - - public static Number operator * (Number a, Number b) - { - if (!a.IsFloat && !b.IsFloat) - return new NumberLong(((NumberLong) a).Value * ((NumberLong) b).Value); - if (a.IsFloat && b.IsFloat) - return new NumberDouble(((NumberDouble) a).Value * ((NumberDouble) b).Value); - if (a.IsFloat) - return new NumberDouble(((NumberDouble) a).Value * ((NumberLong) b).Value); - return new NumberDouble(((NumberLong) a).Value * ((NumberDouble) b).Value); - } - - public static Number operator / (Number a, Number b) - { - if (!a.IsFloat && !b.IsFloat) - return new NumberLong(((NumberLong) a).Value / ((NumberLong) b).Value); - if (a.IsFloat && b.IsFloat) - return new NumberDouble(((NumberDouble) a).Value / ((NumberDouble) b).Value); - if (a.IsFloat) - return new NumberDouble(((NumberDouble) a).Value / ((NumberLong) b).Value); - return new NumberDouble(((NumberLong) a).Value / ((NumberDouble) b).Value); - } - #endregion - - public static Number operator - (Number n) - { - if (n.IsFloat) - return new NumberDouble(-((NumberDouble)n).Value); - return new NumberLong(-((NumberLong)n).Value); - } - - #region Equality - private bool Equals(Number other) - { - if (!IsFloat && !other.IsFloat) - return ((NumberLong) this).Value.Equals(((NumberLong) other).Value); - if (IsFloat && other.IsFloat) - return ((NumberDouble) this).Value.Equals(((NumberDouble) other).Value); - return false; - } - -#pragma warning disable 659 - public override bool Equals(object obj) -#pragma warning restore 659 - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; - return Equals((Number) obj); - } - - #endregion - - public static explicit operator double(Number n) - { - if (n.IsFloat) - return ((NumberDouble) n); - return ((NumberLong) n).Value; - } - - public static explicit operator long(Number n) - { - if (n.IsFloat) - return (long)((NumberDouble) n).Value; - return ((NumberLong) n).Value; - } - } -} \ No newline at end of file diff --git a/Upsilon/BaseTypes/Number/ScriptNumber.cs b/Upsilon/BaseTypes/Number/ScriptNumber.cs new file mode 100644 index 0000000..63447bb --- /dev/null +++ b/Upsilon/BaseTypes/Number/ScriptNumber.cs @@ -0,0 +1,99 @@ +namespace Upsilon.BaseTypes.Number +{ + internal abstract class ScriptNumber : ScriptType + { + protected abstract bool IsFloat { get; } + + public override Type Type => Type.Number; + + #region Binary Operators + + public static ScriptNumber operator + (ScriptNumber a, ScriptNumber b) + { + if (!a.IsFloat && !b.IsFloat) + return new ScriptNumberLong(((ScriptNumberLong) a).Value + ((ScriptNumberLong) b).Value); + if (a.IsFloat && b.IsFloat) + return new ScriptNumberDouble(((ScriptNumberDouble) a).Value + ((ScriptNumberDouble) b).Value); + if (a.IsFloat) + return new ScriptNumberDouble(((ScriptNumberDouble) a).Value + ((ScriptNumberLong) b).Value); + return new ScriptNumberDouble(((ScriptNumberLong) a).Value + ((ScriptNumberDouble) b).Value); + } + + public static ScriptNumber operator - (ScriptNumber a, ScriptNumber b) + { + if (!a.IsFloat && !b.IsFloat) + return new ScriptNumberLong(((ScriptNumberLong) a).Value - ((ScriptNumberLong) b).Value); + if (a.IsFloat && b.IsFloat) + return new ScriptNumberDouble(((ScriptNumberDouble) a).Value - ((ScriptNumberDouble) b).Value); + if (a.IsFloat) + return new ScriptNumberDouble(((ScriptNumberDouble) a).Value - ((ScriptNumberLong) b).Value); + return new ScriptNumberDouble(((ScriptNumberLong) a).Value - ((ScriptNumberDouble) b).Value); + } + + public static ScriptNumber operator * (ScriptNumber a, ScriptNumber b) + { + if (!a.IsFloat && !b.IsFloat) + return new ScriptNumberLong(((ScriptNumberLong) a).Value * ((ScriptNumberLong) b).Value); + if (a.IsFloat && b.IsFloat) + return new ScriptNumberDouble(((ScriptNumberDouble) a).Value * ((ScriptNumberDouble) b).Value); + if (a.IsFloat) + return new ScriptNumberDouble(((ScriptNumberDouble) a).Value * ((ScriptNumberLong) b).Value); + return new ScriptNumberDouble(((ScriptNumberLong) a).Value * ((ScriptNumberDouble) b).Value); + } + + public static ScriptNumber operator / (ScriptNumber a, ScriptNumber b) + { + if (!a.IsFloat && !b.IsFloat) + return new ScriptNumberLong(((ScriptNumberLong) a).Value / ((ScriptNumberLong) b).Value); + if (a.IsFloat && b.IsFloat) + return new ScriptNumberDouble(((ScriptNumberDouble) a).Value / ((ScriptNumberDouble) b).Value); + if (a.IsFloat) + return new ScriptNumberDouble(((ScriptNumberDouble) a).Value / ((ScriptNumberLong) b).Value); + return new ScriptNumberDouble(((ScriptNumberLong) a).Value / ((ScriptNumberDouble) b).Value); + } + #endregion + + public static ScriptNumber operator - (ScriptNumber n) + { + if (n.IsFloat) + return new ScriptNumberDouble(-((ScriptNumberDouble)n).Value); + return new ScriptNumberLong(-((ScriptNumberLong)n).Value); + } + + #region Equality + private bool Equals(ScriptNumber other) + { + if (!IsFloat && !other.IsFloat) + return ((ScriptNumberLong) this).Value.Equals(((ScriptNumberLong) other).Value); + if (IsFloat && other.IsFloat) + return ((ScriptNumberDouble) this).Value.Equals(((ScriptNumberDouble) other).Value); + return false; + } + +#pragma warning disable 659 + public override bool Equals(object obj) +#pragma warning restore 659 + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != this.GetType()) return false; + return Equals((ScriptNumber) obj); + } + + #endregion + + public static explicit operator double(ScriptNumber n) + { + if (n.IsFloat) + return ((ScriptNumberDouble) n); + return ((ScriptNumberLong) n).Value; + } + + public static explicit operator long(ScriptNumber n) + { + if (n.IsFloat) + return (long)((ScriptNumberDouble) n).Value; + return ((ScriptNumberLong) n).Value; + } + } +} \ No newline at end of file diff --git a/Upsilon/BaseTypes/Number/NumberDouble.cs b/Upsilon/BaseTypes/Number/ScriptNumberDouble.cs similarity index 80% rename from Upsilon/BaseTypes/Number/NumberDouble.cs rename to Upsilon/BaseTypes/Number/ScriptNumberDouble.cs index a39069d..f64eac9 100644 --- a/Upsilon/BaseTypes/Number/NumberDouble.cs +++ b/Upsilon/BaseTypes/Number/ScriptNumberDouble.cs @@ -2,12 +2,12 @@ using System.Globalization; namespace Upsilon.BaseTypes.Number { - internal class NumberDouble : Number + internal class ScriptNumberDouble : ScriptNumber { public double Value { get; } protected override bool IsFloat { get; } = true; - public NumberDouble(double value) + public ScriptNumberDouble(double value) { Value = value; } @@ -22,7 +22,7 @@ namespace Upsilon.BaseTypes.Number return Value.ToString(CultureInfo.InvariantCulture); } - public static implicit operator double(NumberDouble n) + public static implicit operator double(ScriptNumberDouble n) { return n.Value; } diff --git a/Upsilon/BaseTypes/Number/NumberLong.cs b/Upsilon/BaseTypes/Number/ScriptNumberLong.cs similarity index 82% rename from Upsilon/BaseTypes/Number/NumberLong.cs rename to Upsilon/BaseTypes/Number/ScriptNumberLong.cs index 8ec4118..ca766ed 100644 --- a/Upsilon/BaseTypes/Number/NumberLong.cs +++ b/Upsilon/BaseTypes/Number/ScriptNumberLong.cs @@ -3,12 +3,12 @@ using System.Globalization; namespace Upsilon.BaseTypes.Number { - internal class NumberLong : Number + internal class ScriptNumberLong : ScriptNumber { public long Value { get; set; } protected override bool IsFloat { get; } = false; - public NumberLong(long val) + public ScriptNumberLong(long val) { Value = val; } @@ -23,7 +23,7 @@ namespace Upsilon.BaseTypes.Number return Value.ToString(CultureInfo.InvariantCulture); } - public static implicit operator long(NumberLong n) + public static implicit operator long(ScriptNumberLong n) { if (n == null) return 0; diff --git a/Upsilon/BaseTypes/LuaBoolean.cs b/Upsilon/BaseTypes/ScriptBoolean.cs similarity index 60% rename from Upsilon/BaseTypes/LuaBoolean.cs rename to Upsilon/BaseTypes/ScriptBoolean.cs index 6dee64b..72731df 100644 --- a/Upsilon/BaseTypes/LuaBoolean.cs +++ b/Upsilon/BaseTypes/ScriptBoolean.cs @@ -1,8 +1,8 @@ namespace Upsilon.BaseTypes { - internal class LuaBoolean : LuaType + internal class ScriptBoolean : ScriptType { - public LuaBoolean(bool value) + public ScriptBoolean(bool value) { Value = value; } @@ -20,19 +20,19 @@ namespace Upsilon.BaseTypes public bool Value { get; } - public static implicit operator bool(LuaBoolean b) + public static implicit operator bool(ScriptBoolean b) { return b.Value; } - public static implicit operator LuaBoolean(bool b) + public static implicit operator ScriptBoolean(bool b) { - return new LuaBoolean(b); + return new ScriptBoolean(b); } - public static LuaBoolean operator ! (LuaBoolean n) + public static ScriptBoolean operator ! (ScriptBoolean n) { - return new LuaBoolean(!n.Value); + return new ScriptBoolean(!n.Value); } public override string ToString() diff --git a/Upsilon/BaseTypes/LuaFunction.cs b/Upsilon/BaseTypes/ScriptFunction.cs similarity index 75% rename from Upsilon/BaseTypes/LuaFunction.cs rename to Upsilon/BaseTypes/ScriptFunction.cs index 771c9da..4056733 100644 --- a/Upsilon/BaseTypes/LuaFunction.cs +++ b/Upsilon/BaseTypes/ScriptFunction.cs @@ -1,14 +1,14 @@ using System.Collections.Immutable; using System.Linq; using System.Reflection; -using Upsilon.BaseTypes.LuaTypeInterfaces; +using Upsilon.BaseTypes.ScriptTypeInterfaces; using Upsilon.BaseTypes.UserData; using Upsilon.Binder; using Upsilon.Evaluator; namespace Upsilon.BaseTypes { - internal abstract class LuaFunction : LuaType + internal abstract class ScriptFunction : ScriptType { public override Type Type => Type.Function; public override object ToCSharpObject() @@ -21,16 +21,16 @@ namespace Upsilon.BaseTypes return null; } - public abstract LuaType Run(Diagnostics diagnostics, LuaType[] variables); + public abstract ScriptType Run(Diagnostics diagnostics, ScriptType[] variables); } - internal class LuaInternalFunction : LuaFunction, IScopeOwner + internal class ScriptInternalFunction : ScriptFunction, IScopeOwner { public BoundBlockStatement Block { get; } public ImmutableArray Parameters { get; } public EvaluationScope EvaluationScope { get; } - public LuaInternalFunction(ImmutableArray parameters, BoundBlockStatement block, + public ScriptInternalFunction(ImmutableArray parameters, BoundBlockStatement block, EvaluationScope evaluationScope) { Parameters = parameters; @@ -38,22 +38,22 @@ namespace Upsilon.BaseTypes EvaluationScope = evaluationScope; } - public override LuaType Run(Diagnostics diagnostics, LuaType[] variables) + public override ScriptType Run(Diagnostics diagnostics, ScriptType[] variables) { var innerEvaluator = new Evaluator.Evaluator(diagnostics, EvaluationScope); for (var i = 0; i < Parameters.Length; i++) { var parameterVariable = Parameters[i]; var parameterValue = variables[i]; - innerEvaluator.Scope.Set(parameterVariable, parameterValue); + innerEvaluator.Scope.Set(parameterVariable, parameterValue, true); } return innerEvaluator.EvaluateNode(Block); } } - internal class LuaMethodInfoFunction : LuaFunction + internal class ScriptMethodInfoFunction : ScriptFunction { - public LuaMethodInfoFunction(UserDataMethod method, object o) + public ScriptMethodInfoFunction(UserDataMethod method, object o) { _method = method; _object = o; @@ -62,7 +62,7 @@ namespace Upsilon.BaseTypes private readonly UserDataMethod _method; private readonly object _object; - public override LuaType Run(Diagnostics diagnostics, LuaType[] variables) + public override ScriptType Run(Diagnostics diagnostics, ScriptType[] variables) { var types = variables.Select(x => x.GetCSharpType()); var method = _method.GetMethod(types.ToArray()); diff --git a/Upsilon/BaseTypes/LuaNull.cs b/Upsilon/BaseTypes/ScriptNull.cs similarity index 89% rename from Upsilon/BaseTypes/LuaNull.cs rename to Upsilon/BaseTypes/ScriptNull.cs index 32c026d..ef7dcfb 100644 --- a/Upsilon/BaseTypes/LuaNull.cs +++ b/Upsilon/BaseTypes/ScriptNull.cs @@ -1,6 +1,6 @@ namespace Upsilon.BaseTypes { - internal class LuaNull : LuaType + internal class ScriptNull : ScriptType { public override Type Type => Type.Nil; public override object ToCSharpObject() diff --git a/Upsilon/BaseTypes/LuaString.cs b/Upsilon/BaseTypes/ScriptString.cs similarity index 57% rename from Upsilon/BaseTypes/LuaString.cs rename to Upsilon/BaseTypes/ScriptString.cs index 428a539..bbd99b0 100644 --- a/Upsilon/BaseTypes/LuaString.cs +++ b/Upsilon/BaseTypes/ScriptString.cs @@ -1,13 +1,14 @@ using System; using Upsilon.BaseTypes.Number; +using Upsilon.BaseTypes.ScriptTypeInterfaces; using Upsilon.Evaluator; using Upsilon.Text; namespace Upsilon.BaseTypes { - internal class LuaString : LuaType, IIndexable + internal class ScriptString : ScriptType, IIndexable { - public LuaString(string value) + public ScriptString(string value) { Value = value; } @@ -28,7 +29,7 @@ namespace Upsilon.BaseTypes { if (obj == null) return false; - if (!(obj is LuaString s)) + if (!(obj is ScriptString s)) return false; return Equals(s); } @@ -38,45 +39,45 @@ namespace Upsilon.BaseTypes return (Value != null ? Value.GetHashCode() : 0); } - private bool Equals(LuaString s) + private bool Equals(ScriptString s) { return s != null && string.Equals(s.Value, Value); } - public static LuaString operator +(LuaString a, LuaType b) + public static ScriptString operator +(ScriptString a, ScriptType b) { switch (b) { - case LuaString s: + case ScriptString s: return a + s; - case LuaBoolean bl: + case ScriptBoolean bl: return a + bl; - case NumberLong l: + case ScriptNumberLong l: return a + l; - case NumberDouble d: + case ScriptNumberDouble d: return a + d; } throw new ArgumentException($"Adding Type '{b.Type}' to a LuaString is not supported."); } - public static LuaString operator +(LuaString a, LuaString b) + public static ScriptString operator +(ScriptString a, ScriptString b) { - return new LuaString(a.Value + b.Value); + return new ScriptString(a.Value + b.Value); } - public static LuaString operator +(LuaString a, LuaBoolean b) + public static ScriptString operator +(ScriptString a, ScriptBoolean b) { - return new LuaString(a.Value + b.Value); + return new ScriptString(a.Value + b.Value); } - public static LuaString operator +(LuaString a, NumberLong b) + public static ScriptString operator +(ScriptString a, ScriptNumberLong b) { - return new LuaString(a.Value + b.Value); + return new ScriptString(a.Value + b.Value); } - public static LuaString operator +(LuaString a, NumberDouble b) + public static ScriptString operator +(ScriptString a, ScriptNumberDouble b) { - return new LuaString(a.Value + b.Value); + return new ScriptString(a.Value + b.Value); } public override string ToString() @@ -84,27 +85,27 @@ namespace Upsilon.BaseTypes return Value; } - public LuaType Get(Diagnostics diagnostics, TextSpan span, LuaType index, EvaluationScope scope) + public ScriptType Get(Diagnostics diagnostics, TextSpan span, ScriptType index, EvaluationScope scope) { int i; if (index.Type == Type.String) { - var str = (LuaString)index; + var str = (ScriptString)index; i = int.Parse(str.Value); } else if (index.Type == Type.Number) { - var ind = (Number.NumberLong) index; + var ind = (Number.ScriptNumberLong) index; i = (int) ind.Value; } else { return null; } - return new LuaString(Value[i - 1].ToString()); + return new ScriptString(Value[i - 1].ToString()); } - public void Set(Diagnostics diagnostics, TextSpan span, LuaType index, LuaType value) + public void Set(Diagnostics diagnostics, TextSpan span, ScriptType index, ScriptType value) { throw new NotSupportedException(); } diff --git a/Upsilon/BaseTypes/LuaTable.cs b/Upsilon/BaseTypes/ScriptTable.cs similarity index 55% rename from Upsilon/BaseTypes/LuaTable.cs rename to Upsilon/BaseTypes/ScriptTable.cs index 9fd3779..bf8cffe 100644 --- a/Upsilon/BaseTypes/LuaTable.cs +++ b/Upsilon/BaseTypes/ScriptTable.cs @@ -1,17 +1,17 @@ using System.Collections.Generic; using System.Linq; -using Upsilon.BaseTypes.LuaTypeInterfaces; +using Upsilon.BaseTypes.ScriptTypeInterfaces; using Upsilon.Binder; using Upsilon.Evaluator; using Upsilon.Text; namespace Upsilon.BaseTypes { - internal class LuaTable : LuaType, IIndexable, IScopeOwner, IIterable + internal class ScriptTable : ScriptType, IIndexable, IScopeOwner, IIterable { public EvaluationScope EvaluationScope { get; } - public LuaTable(EvaluationScope scope) + public ScriptTable(EvaluationScope scope) { EvaluationScope = scope; } @@ -27,7 +27,7 @@ namespace Upsilon.BaseTypes return typeof(Dictionary); } - public LuaType Get(Diagnostics diagnostics, TextSpan span, LuaType index, EvaluationScope scope) + public ScriptType Get(Diagnostics diagnostics, TextSpan span, ScriptType index, EvaluationScope scope) { var s = index.ToString(); if (EvaluationScope.TryGet(s, out var o)) @@ -35,36 +35,26 @@ namespace Upsilon.BaseTypes return o; } diagnostics.LogError("Cannot find member 's' on Table", span); - return new LuaNull(); + return new ScriptNull(); } - public void Set(Diagnostics diagnostics, TextSpan span, LuaType index, LuaType value) + public void Set(Diagnostics diagnostics, TextSpan span, ScriptType index, ScriptType value) { var s = index.ToString(); - EvaluationScope.Set(new VariableSymbol(s, value.Type, false), value); + EvaluationScope.Set(new VariableSymbol(s, value.Type, false), value, true); } - - private IEnumerator> _enumerator; - - public bool Next(out LuaType key, out LuaType next) + public IEnumerator<(string Key, ScriptType value)> GetEnumerator() { - if (_enumerator == null) _enumerator = EvaluationScope.Variables.GetEnumerator(); - if (_enumerator.MoveNext()) + return Enumerator(); + } + + private IEnumerator<(string Key, ScriptType value)> Enumerator() + { + foreach (var variable in EvaluationScope.Variables) { - key = _enumerator.Current.Key.ToLuaType(); - next = _enumerator.Current.Value; - return true; + yield return (variable.Key, variable.Value); } - key = null; - next = null; - Reset(); - return false; - } - - public void Reset() - { - _enumerator = null; } } } \ No newline at end of file diff --git a/Upsilon/BaseTypes/LuaType.cs b/Upsilon/BaseTypes/ScriptType.cs similarity index 83% rename from Upsilon/BaseTypes/LuaType.cs rename to Upsilon/BaseTypes/ScriptType.cs index 41e34e5..13635ac 100644 --- a/Upsilon/BaseTypes/LuaType.cs +++ b/Upsilon/BaseTypes/ScriptType.cs @@ -1,6 +1,6 @@ namespace Upsilon.BaseTypes { - public abstract class LuaType + public abstract class ScriptType { public abstract Type Type { get; } public abstract object ToCSharpObject(); diff --git a/Upsilon/BaseTypes/ScriptTypeInterfaces/IITerable.cs b/Upsilon/BaseTypes/ScriptTypeInterfaces/IITerable.cs new file mode 100644 index 0000000..d76f82f --- /dev/null +++ b/Upsilon/BaseTypes/ScriptTypeInterfaces/IITerable.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace Upsilon.BaseTypes.ScriptTypeInterfaces +{ + internal interface IIterable + { + IEnumerator<(string Key, ScriptType value)> GetEnumerator(); + } +} \ No newline at end of file diff --git a/Upsilon/BaseTypes/ScriptTypeInterfaces/IIndexable.cs b/Upsilon/BaseTypes/ScriptTypeInterfaces/IIndexable.cs new file mode 100644 index 0000000..ba4c8fd --- /dev/null +++ b/Upsilon/BaseTypes/ScriptTypeInterfaces/IIndexable.cs @@ -0,0 +1,13 @@ +using System.Collections; +using System.Collections.Generic; +using Upsilon.Evaluator; +using Upsilon.Text; + +namespace Upsilon.BaseTypes.ScriptTypeInterfaces +{ + internal interface IIndexable + { + ScriptType Get(Diagnostics diagnostics, TextSpan span, ScriptType index, EvaluationScope scope); + void Set(Diagnostics diagnostics, TextSpan span, ScriptType index, ScriptType value); + } +} \ No newline at end of file diff --git a/Upsilon/BaseTypes/LuaTypeInterfaces/IScopeOwner.cs b/Upsilon/BaseTypes/ScriptTypeInterfaces/IScopeOwner.cs similarity index 71% rename from Upsilon/BaseTypes/LuaTypeInterfaces/IScopeOwner.cs rename to Upsilon/BaseTypes/ScriptTypeInterfaces/IScopeOwner.cs index 8460a3e..a1b3e5a 100644 --- a/Upsilon/BaseTypes/LuaTypeInterfaces/IScopeOwner.cs +++ b/Upsilon/BaseTypes/ScriptTypeInterfaces/IScopeOwner.cs @@ -1,6 +1,6 @@ using Upsilon.Evaluator; -namespace Upsilon.BaseTypes.LuaTypeInterfaces +namespace Upsilon.BaseTypes.ScriptTypeInterfaces { internal interface IScopeOwner { diff --git a/Upsilon/BaseTypes/SimpleLuaTable.cs b/Upsilon/BaseTypes/SimpleScriptTable.cs similarity index 68% rename from Upsilon/BaseTypes/SimpleLuaTable.cs rename to Upsilon/BaseTypes/SimpleScriptTable.cs index e9d021e..ae1697b 100644 --- a/Upsilon/BaseTypes/SimpleLuaTable.cs +++ b/Upsilon/BaseTypes/SimpleScriptTable.cs @@ -1,32 +1,33 @@ using System.Collections.Generic; +using Upsilon.BaseTypes.ScriptTypeInterfaces; using Upsilon.Evaluator; using Upsilon.Text; namespace Upsilon.BaseTypes { - internal class SimpleLuaTable : LuaType, IIndexable + internal class SimpleScriptTable : ScriptType, IIndexable { - private readonly IList _objects; + private readonly IList _objects; - public SimpleLuaTable(IList objects) + public SimpleScriptTable(IList objects) { _objects = objects; } - public LuaType Get(Diagnostics diagnostics, TextSpan span, LuaType index, EvaluationScope scope) + public ScriptType Get(Diagnostics diagnostics, TextSpan span, ScriptType index, EvaluationScope scope) { int i; switch (index.Type) { case Type.String: { - var str = (LuaString)index; + var str = (ScriptString)index; i = int.Parse(str.Value) - 1; break; } case Type.Number: { - var ind = (Number.NumberLong) index; + var ind = (Number.ScriptNumberLong) index; i = (int) ind.Value - 1; break; } @@ -37,7 +38,7 @@ namespace Upsilon.BaseTypes return _objects[i]; } - public void Set(Diagnostics diagnostics, TextSpan span, LuaType index, LuaType value) + public void Set(Diagnostics diagnostics, TextSpan span, ScriptType index, ScriptType value) { throw new System.NotImplementedException(); } diff --git a/Upsilon/BaseTypes/Type.cs b/Upsilon/BaseTypes/Type.cs index d350132..a6b9991 100644 --- a/Upsilon/BaseTypes/Type.cs +++ b/Upsilon/BaseTypes/Type.cs @@ -10,6 +10,6 @@ namespace Upsilon.BaseTypes Function, UserData, Thread, - Table + Table, } } \ No newline at end of file diff --git a/Upsilon/BaseTypes/TypeConversion.cs b/Upsilon/BaseTypes/TypeConversion.cs index c8bc9c4..9adb9e4 100644 --- a/Upsilon/BaseTypes/TypeConversion.cs +++ b/Upsilon/BaseTypes/TypeConversion.cs @@ -6,31 +6,31 @@ namespace Upsilon.BaseTypes { internal static class TypeConversion { - public static LuaType ToLuaType(this object o) + public static ScriptType ToLuaType(this object o) { - if (o is LuaType type) return type; + if (o is ScriptType type) return type; switch (o) { case bool b: - return new LuaBoolean(b); + return new ScriptBoolean(b); case int i: - return new NumberLong(i); + return new ScriptNumberLong(i); case long i: - return new NumberLong(i); + return new ScriptNumberLong(i); case float f: - return new NumberDouble(f); + return new ScriptNumberDouble(f); case double f: - return new NumberDouble(f); + return new ScriptNumberDouble(f); case string s: - return new LuaString(s); + return new ScriptString(s); case null: - return new LuaNull(); + return new ScriptNull(); default: return ConvertUserData(o); } } - private static LuaType ConvertUserData(object o) + private static ScriptType ConvertUserData(object o) { if (o is IList ls) { diff --git a/Upsilon/BaseTypes/UserData/DictionaryUserData.cs b/Upsilon/BaseTypes/UserData/DictionaryUserData.cs index ffc8b5b..0af89c5 100644 --- a/Upsilon/BaseTypes/UserData/DictionaryUserData.cs +++ b/Upsilon/BaseTypes/UserData/DictionaryUserData.cs @@ -4,7 +4,7 @@ using Upsilon.Text; namespace Upsilon.BaseTypes.UserData { - internal class DictionaryUserData : LuaType, IUserData + internal class DictionaryUserData : ScriptType, IUserData { public IDictionary Dictionary { get; } @@ -13,7 +13,7 @@ namespace Upsilon.BaseTypes.UserData Dictionary = dictionary; } - public LuaType Get(Diagnostics diagnostics, TextSpan span, LuaType index, EvaluationScope scope) + public ScriptType Get(Diagnostics diagnostics, TextSpan span, ScriptType index, EvaluationScope scope) { var key = index.ToCSharpObject(); if (Dictionary.Contains(key)) @@ -21,10 +21,10 @@ namespace Upsilon.BaseTypes.UserData return Dictionary[key].ToLuaType(); } //TODO: log error - return new LuaNull(); + return new ScriptNull(); } - public void Set(Diagnostics diagnostics, TextSpan span, LuaType index, LuaType value) + public void Set(Diagnostics diagnostics, TextSpan span, ScriptType index, ScriptType value) { var key = index.ToCSharpObject(); if (Dictionary.Contains(key)) diff --git a/Upsilon/BaseTypes/UserData/GenericUserData.cs b/Upsilon/BaseTypes/UserData/GenericUserData.cs index 785cdd0..3930fb9 100644 --- a/Upsilon/BaseTypes/UserData/GenericUserData.cs +++ b/Upsilon/BaseTypes/UserData/GenericUserData.cs @@ -3,7 +3,7 @@ using Upsilon.Text; namespace Upsilon.BaseTypes.UserData { - internal class GenericUserData : LuaType, IUserData + internal class GenericUserData : ScriptType, IUserData { public GenericUserData(object dictionary) { @@ -25,7 +25,7 @@ namespace Upsilon.BaseTypes.UserData return Value.GetType(); } - public virtual LuaType Get(Diagnostics diagnostics, TextSpan span, LuaType index, EvaluationScope scope) + public virtual ScriptType Get(Diagnostics diagnostics, TextSpan span, ScriptType index, EvaluationScope scope) { var s = index.ToCSharpObject().ToString(); var (type, failed, error) = _typeInfo.Get(Value, s); @@ -36,7 +36,7 @@ namespace Upsilon.BaseTypes.UserData return type; } - public virtual void Set(Diagnostics diagnostics, TextSpan span, LuaType index, LuaType value) + public virtual void Set(Diagnostics diagnostics, TextSpan span, ScriptType index, ScriptType value) { var s = index.ToCSharpObject().ToString(); var (failed, error) = _typeInfo.Set(Value, s, value); @@ -46,12 +46,12 @@ namespace Upsilon.BaseTypes.UserData } } - public (LuaType Type, bool Failed) BinaryOperator(LuaType par1, OperatorType op, LuaType par2) + public (ScriptType Type, bool Failed) BinaryOperator(ScriptType par1, OperatorType op, ScriptType par2) { return _typeInfo.BinaryOperator(Value, par1, op, par2); } - public (LuaType Type, bool Failed) UnaryOperator(LuaType par1, OperatorType op) + public (ScriptType Type, bool Failed) UnaryOperator(ScriptType par1, OperatorType op) { return _typeInfo.UnaryOperator(Value, par1, op); } diff --git a/Upsilon/BaseTypes/UserData/IUserData.cs b/Upsilon/BaseTypes/UserData/IUserData.cs index 622c503..3bff951 100644 --- a/Upsilon/BaseTypes/UserData/IUserData.cs +++ b/Upsilon/BaseTypes/UserData/IUserData.cs @@ -1,3 +1,5 @@ +using Upsilon.BaseTypes.ScriptTypeInterfaces; + namespace Upsilon.BaseTypes.UserData { internal interface IUserData : IIndexable diff --git a/Upsilon/BaseTypes/UserData/ListUserData.cs b/Upsilon/BaseTypes/UserData/ListUserData.cs index f94dbef..badec7b 100644 --- a/Upsilon/BaseTypes/UserData/ListUserData.cs +++ b/Upsilon/BaseTypes/UserData/ListUserData.cs @@ -1,10 +1,12 @@ using System.Collections; +using System.Collections.Generic; +using Upsilon.BaseTypes.ScriptTypeInterfaces; using Upsilon.Evaluator; using Upsilon.Text; namespace Upsilon.BaseTypes.UserData { - internal class ListUserData : LuaType, IUserData + internal class ListUserData : ScriptType, IUserData, IIterable { private IList List { get; } @@ -13,17 +15,17 @@ namespace Upsilon.BaseTypes.UserData List = list; } - public LuaType Get(Diagnostics diagnostics, TextSpan span, LuaType index, EvaluationScope scope) + public ScriptType Get(Diagnostics diagnostics, TextSpan span, ScriptType index, EvaluationScope scope) { int i; if (index.Type == Type.String) { - var str = (LuaString)index; + var str = (ScriptString)index; i = int.Parse(str.Value) - 1; } else if (index.Type == Type.Number) { - var ind = (Number.NumberLong) index; + var ind = (Number.ScriptNumberLong) index; i = (int) ind.Value - 1; } else @@ -33,7 +35,7 @@ namespace Upsilon.BaseTypes.UserData return List[i].ToLuaType(); } - public void Set(Diagnostics diagnostics, TextSpan span, LuaType index, LuaType value) + public void Set(Diagnostics diagnostics, TextSpan span, ScriptType index, ScriptType value) { throw new System.NotImplementedException(); } @@ -48,5 +50,10 @@ namespace Upsilon.BaseTypes.UserData { return List.GetType(); } + + public IEnumerator<(string Key, ScriptType value)> GetEnumerator() + { + throw new System.NotImplementedException(); + } } } \ No newline at end of file diff --git a/Upsilon/BaseTypes/UserData/UserDataMethod.cs b/Upsilon/BaseTypes/UserData/UserDataMethod.cs index d7f7993..f02477d 100644 --- a/Upsilon/BaseTypes/UserData/UserDataMethod.cs +++ b/Upsilon/BaseTypes/UserData/UserDataMethod.cs @@ -22,11 +22,11 @@ namespace Upsilon.BaseTypes.UserData { public UserDataMethodParameter(ParameterInfo info) { - TypeHash = info.ParameterType.GetHashCode(); + Type = info.ParameterType; IsOptional = info.IsOptional; } - public int TypeHash { get; } + public System.Type Type { get; } public bool IsOptional { get; } } @@ -62,8 +62,9 @@ namespace Upsilon.BaseTypes.UserData valid = false; break; } - var parameterHash = parameterTypes[index].GetHashCode(); - if (userDataMethodParameter.TypeHash != parameterHash) + var parameter = parameterTypes[index]; + if (userDataMethodParameter.Type != parameter && + !userDataMethodParameter.Type.IsAssignableFrom(parameter)) { valid = false; break; diff --git a/Upsilon/BaseTypes/UserData/UserDataType.cs b/Upsilon/BaseTypes/UserData/UserDataType.cs index 01f0ef3..9538077 100644 --- a/Upsilon/BaseTypes/UserData/UserDataType.cs +++ b/Upsilon/BaseTypes/UserData/UserDataType.cs @@ -33,7 +33,7 @@ namespace Upsilon.BaseTypes.UserData private Dictionary Methods { get; } private UserDataTypeOperators OperatorHandler { get; } - public (LuaType Type, bool Failed, string Error) Get(object value, string member) + public (ScriptType Type, bool Failed, string Error) Get(object value, string member) { if (value.GetType() != Type) return (null, true, "Invalid Type"); @@ -48,13 +48,13 @@ namespace Upsilon.BaseTypes.UserData } if (Methods.TryGetValue(member, out var method)) { - return (new LuaMethodInfoFunction(method, value), false, null); + return (new ScriptMethodInfoFunction(method, value), false, null); } return (null, true, $"Can't find public member '{member}' on type '{Type}'."); } - public (bool Failed, string Error) Set(object value, string member, LuaType newValue) + public (bool Failed, string Error) Set(object value, string member, ScriptType newValue) { member = member.ToLowerInvariant(); if (value.GetType() != Type) @@ -77,22 +77,22 @@ namespace Upsilon.BaseTypes.UserData return (true, $"Cannot find member '{member}' on type '{Type}'"); } - public (LuaType Type, bool Failed) BinaryOperator(object value, LuaType par1, OperatorType op, LuaType par2) + public (ScriptType Type, bool Failed) BinaryOperator(object value, ScriptType par1, OperatorType op, ScriptType par2) { var method = OperatorHandler.GetBinaryOperator(op, par1.GetCSharpType(), par2.GetCSharpType()); if (method == null) { - return (new LuaNull(), true); + return (new ScriptNull(), true); } return (method.Invoke(value, new[] {par1.ToCSharpObject(), par2.ToCSharpObject()}).ToLuaType(), false); } - public (LuaType Type, bool Failed) UnaryOperator(object value, LuaType par1, OperatorType op) + public (ScriptType Type, bool Failed) UnaryOperator(object value, ScriptType par1, OperatorType op) { var method = OperatorHandler.GetUnaryOperator(op, par1.GetCSharpType()); if (method == null) { - return (new LuaNull(), true); + return (new ScriptNull(), true); } return (method.Invoke(value, new[] {par1.ToCSharpObject()}).ToLuaType(), false); diff --git a/Upsilon/Binder/Binder.cs b/Upsilon/Binder/Binder.cs index 81589f9..a49db90 100644 --- a/Upsilon/Binder/Binder.cs +++ b/Upsilon/Binder/Binder.cs @@ -70,6 +70,9 @@ namespace Upsilon.Binder return BindMultiAssignmentStatement((MultiAssignmentStatementSyntax) s); case SyntaxKind.NumericForStatement: return BindNumericForStatement((NumericForStatementSyntax) s); + case SyntaxKind.GenericForStatement: + return BindGenericForStatement((GenericForStatementSyntax) s); + case SyntaxKind.BreakStatement: return new BoundBreakStatement(); } @@ -140,23 +143,23 @@ namespace Upsilon.Binder private BoundExpression BindLiteralExpression(LiteralExpressionSyntax e) { var value = e.Value; - LuaType outValue = null; + ScriptType outValue = null; switch (value) { case double d: - outValue = new NumberDouble(d); + outValue = new ScriptNumberDouble(d); break; case long l: - outValue = new NumberLong(l); + outValue = new ScriptNumberLong(l); break; case bool b: - outValue = new LuaBoolean(b); + outValue = new ScriptBoolean(b); break; case string s: - outValue = new LuaString(s); + outValue = new ScriptString(s); break; case null: - outValue = new LuaNull(); + outValue = new ScriptNull(); break; default: @@ -221,7 +224,7 @@ namespace Upsilon.Binder if (!Scope.TryGetVariable(name, true, out var variable)) { _diagnostics.LogUnknownVariable(e.Identifier.Span, name); - return new BoundLiteralExpression(new LuaNull()); + return new BoundLiteralExpression(new ScriptNull()); } return new BoundVariableExpression(variable); @@ -301,7 +304,7 @@ namespace Upsilon.Binder } - return new BoundExpressionStatement(new BoundLiteralExpression(new LuaNull())); + return new BoundExpressionStatement(new BoundLiteralExpression(new ScriptNull())); } private BoundStatement BindMultiAssignmentStatement(MultiAssignmentStatementSyntax s) @@ -430,7 +433,7 @@ namespace Upsilon.Binder else { _diagnostics.LogCannotConvert(Type.Function, variable.Type, e.Span); - return new BoundExpressionStatement(new BoundLiteralExpression(new LuaNull())); + return new BoundExpressionStatement(new BoundLiteralExpression(new ScriptNull())); } } } @@ -474,7 +477,7 @@ namespace Upsilon.Binder if (index.Type != Type.Number && index.Type != Type.String && index.Type != Type.Unknown) { _diagnostics.LogInvalidIndexExpression(expression.Type, index.Type, e.Span); - return new BoundLiteralExpression(new LuaNull()); + return new BoundLiteralExpression(new ScriptNull()); } switch (expression.Type) { @@ -486,7 +489,7 @@ namespace Upsilon.Binder return new BoundIndexExpression(expression, index, Type.String); default: _diagnostics.LogInvalidIndexExpression(expression.Type, index.Type, e.Span); - return new BoundLiteralExpression(new LuaNull()); + return new BoundLiteralExpression(new ScriptNull()); } } @@ -504,7 +507,7 @@ namespace Upsilon.Binder return new BoundFullStopIndexExpression(expression, index); default: _diagnostics.LogInvalidIndexExpression(expression.Type, Type.String, e.Span); - return new BoundLiteralExpression(new LuaNull()); + return new BoundLiteralExpression(new ScriptNull()); } } @@ -526,14 +529,30 @@ namespace Upsilon.Binder Scope = new BoundScope(Scope); var variable = new VariableSymbol(variableName, Type.Number, true); Scope.SetVariable(variable); - var boundStart = BindExpression(e.StartExpression); - var boundStop = BindExpression(e.StopExpression); - BoundExpression boundStep = null; + var boundStart = BindExpression(e.StartExpression); + var boundStop = BindExpression(e.StopExpression); + BoundExpression boundStep = null; if (e.StepExpression != null) boundStep = BindExpression(e.StepExpression); var block = BindBlockStatement((BlockStatementSyntax) e.Block); Scope = Scope.ParentScope; return new BoundNumericForStatement(variable, boundStart, boundStop, boundStep, (BoundBlockStatement) block); } + + private BoundStatement BindGenericForStatement(GenericForStatementSyntax e) + { + Scope = new BoundScope(Scope); + var array = ImmutableArray.CreateBuilder(); + foreach (var variableIdentifier in e.Variables) + { + var variable = new VariableSymbol(variableIdentifier.Name, Type.Unknown, true); + Scope.SetVariable(variable); + array.Add(variable); + } + var boundEnumerableExpression = BindExpression(e.EnumerableExpression); + var block = BindBlockStatement(e.Block); + + return new BoundGenericForStatement(array.ToImmutable(), boundEnumerableExpression, block); + } } } \ No newline at end of file diff --git a/Upsilon/Binder/BoundExpressions/BoundLiteralExpression.cs b/Upsilon/Binder/BoundExpressions/BoundLiteralExpression.cs index 2b9b57a..0e78ec5 100644 --- a/Upsilon/Binder/BoundExpressions/BoundLiteralExpression.cs +++ b/Upsilon/Binder/BoundExpressions/BoundLiteralExpression.cs @@ -4,13 +4,13 @@ namespace Upsilon.Binder { internal class BoundLiteralExpression : BoundExpression { - public BoundLiteralExpression(LuaType value) + public BoundLiteralExpression(ScriptType value) { Value = value; } public override BoundKind Kind => BoundKind.BoundLiteralExpression; public override Type Type => Value.Type; - public LuaType Value { get; } + public ScriptType Value { get; } } } \ No newline at end of file diff --git a/Upsilon/Binder/BoundKind.cs b/Upsilon/Binder/BoundKind.cs index b4e90e0..60f0e84 100644 --- a/Upsilon/Binder/BoundKind.cs +++ b/Upsilon/Binder/BoundKind.cs @@ -26,6 +26,7 @@ namespace Upsilon.Binder BoundFullstopIndexExpression, BoundMultiAssignmentStatement, BoundNumericForStatement, - BoundBreakStatement + BoundGenericForStatement, + BoundBreakStatement, } } \ No newline at end of file diff --git a/Upsilon/Binder/BoundStatements/BoundGenericForStatement.cs b/Upsilon/Binder/BoundStatements/BoundGenericForStatement.cs new file mode 100644 index 0000000..0116dd9 --- /dev/null +++ b/Upsilon/Binder/BoundStatements/BoundGenericForStatement.cs @@ -0,0 +1,21 @@ +using System.Collections.Immutable; + +namespace Upsilon.Binder +{ + public class BoundGenericForStatement : BoundStatement + { + public ImmutableArray Variables { get; } + public BoundExpression BoundEnumerableExpression { get; } + public BoundStatement Block { get; } + + public BoundGenericForStatement(ImmutableArray variables, + BoundExpression boundEnumerableExpression, BoundStatement block) + { + Variables = variables; + BoundEnumerableExpression = boundEnumerableExpression; + Block = block; + } + + public override BoundKind Kind => BoundKind.BoundGenericForStatement; + } +} \ No newline at end of file diff --git a/Upsilon/Evaluator/EvaluationScope.cs b/Upsilon/Evaluator/EvaluationScope.cs index d9268f6..68cf529 100644 --- a/Upsilon/Evaluator/EvaluationScope.cs +++ b/Upsilon/Evaluator/EvaluationScope.cs @@ -9,32 +9,32 @@ namespace Upsilon.Evaluator private readonly EvaluationScope _parentScope; private EvaluationScope _getOnlyParentScope; - public readonly Dictionary Variables; - private readonly Dictionary _localVariables; + public readonly Dictionary Variables; + private readonly Dictionary _localVariables; internal EvaluationScope(EvaluationScope parentScope) { _parentScope = parentScope; - Variables = new Dictionary(); - _localVariables = new Dictionary(); + Variables = new Dictionary(); + _localVariables = new Dictionary(); } - internal EvaluationScope(Dictionary vars) + internal EvaluationScope(Dictionary vars) { Variables = vars; - _localVariables = new Dictionary(); + _localVariables = new Dictionary(); } internal static EvaluationScope CreateWithGetOnlyParent(EvaluationScope parent) { - var scope = new EvaluationScope(new Dictionary()) {_getOnlyParentScope = parent}; + var scope = new EvaluationScope(new Dictionary()) {_getOnlyParentScope = parent}; return scope; } - public void Set(VariableSymbol symbol, LuaType obj) + public void Set(VariableSymbol symbol, ScriptType obj, bool createNew) { - if (symbol.Local) + if (symbol.Local && createNew) { if (_localVariables.ContainsKey(symbol.Name)) { @@ -51,6 +51,14 @@ namespace Upsilon.Evaluator { Variables[symbol.Name] = obj; } + else if (_localVariables.ContainsKey(symbol.Name)) + { + _localVariables[symbol.Name] = obj; + } + else if (_parentScope != null && _parentScope.TryGet(symbol.Name, out _)) + { + _parentScope.Set(symbol, obj, false); + } else { Variables.Add(symbol.Name, obj); @@ -59,17 +67,17 @@ namespace Upsilon.Evaluator } } - public void SetGlobal(VariableSymbol symbol, LuaType obj) + public void SetGlobal(VariableSymbol symbol, ScriptType obj) { if (_parentScope != null) _parentScope.SetGlobal(symbol, obj); else { - Set(symbol, obj); + Set(symbol, obj, true); } } - public bool TryGet(VariableSymbol symbol, out LuaType obj) + public bool TryGet(VariableSymbol symbol, out ScriptType obj) { if (_localVariables.TryGetValue(symbol.Name, out obj)) return true; @@ -84,7 +92,7 @@ namespace Upsilon.Evaluator return false; } - public bool TryGet(string variable, out LuaType obj) + public bool TryGet(string variable, out ScriptType obj) { if (_localVariables.TryGetValue(variable, out obj)) return true; diff --git a/Upsilon/Evaluator/Evaluator.cs b/Upsilon/Evaluator/Evaluator.cs index 6c0ac0e..f4c67e8 100644 --- a/Upsilon/Evaluator/Evaluator.cs +++ b/Upsilon/Evaluator/Evaluator.cs @@ -2,8 +2,8 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; using Upsilon.BaseTypes; -using Upsilon.BaseTypes.LuaTypeInterfaces; using Upsilon.BaseTypes.Number; +using Upsilon.BaseTypes.ScriptTypeInterfaces; using Upsilon.BaseTypes.UserData; using Upsilon.Binder; using Type = Upsilon.BaseTypes.Type; @@ -13,13 +13,13 @@ namespace Upsilon.Evaluator internal class Evaluator { private Diagnostics _diagnostics; - private LuaType _lastValue; - private LuaType _returnValue; + private ScriptType _lastValue; + private ScriptType _returnValue; internal EvaluationScope Scope { get; private set; } private bool HasReturned { get; set; } private bool HasBroken { get; set; } - internal Evaluator(Diagnostics diagnostics, Dictionary variables) + internal Evaluator(Diagnostics diagnostics, Dictionary variables) { _diagnostics = diagnostics; Scope = new EvaluationScope(variables); @@ -38,7 +38,7 @@ namespace Upsilon.Evaluator return new Evaluator {_diagnostics = diagnostics, Scope = scope}; } - public LuaType Evaluate(BoundScript e) + public ScriptType Evaluate(BoundScript e) { EvaluateNode(e.Statement); if (_returnValue == null) @@ -46,27 +46,27 @@ namespace Upsilon.Evaluator return _returnValue; } - public LuaType Evaluate(BoundScript e, string functionName, ImmutableArray parameters) + public ScriptType Evaluate(BoundScript e, string functionName, ImmutableArray parameters) { EvaluateNode(e.Statement); if (!Scope.TryGet(functionName, out var statement) || statement.Type != Type.Function) { throw new ArgumentException(($"Function '{functionName}' could not be found")); } - var function = (LuaInternalFunction) statement; + var function = (ScriptInternalFunction) statement; var innerEvaluator = new Evaluator(_diagnostics, Scope); for (var index = 0; index < parameters.Length; index++) { var parameter = parameters[index]; var parameterName = function.Parameters[index]; - innerEvaluator.Scope.Set(parameterName, parameter); + innerEvaluator.Scope.Set(parameterName, parameter, true); } var result = innerEvaluator.EvaluateNode(function.Block); return result; } - internal LuaType EvaluateNode(BoundNode b) + internal ScriptType EvaluateNode(BoundNode b) { switch (b.Kind) { @@ -95,6 +95,8 @@ namespace Upsilon.Evaluator case BoundKind.BoundTableAssigmentStatement: case BoundKind.BoundMultiAssignmentStatement: case BoundKind.BoundNumericForStatement: + case BoundKind.BoundGenericForStatement: + case BoundKind.BoundBreakStatement: EvaluateStatement((BoundStatement) b); break; default: @@ -136,6 +138,9 @@ namespace Upsilon.Evaluator case BoundKind.BoundBreakStatement: HasBroken = true; return; + case BoundKind.BoundGenericForStatement: + EvaluateGenericForStatement((BoundGenericForStatement) e); + break; default: EvaluateExpressionStatement((BoundExpressionStatement) e); break; @@ -148,7 +153,7 @@ namespace Upsilon.Evaluator _lastValue = EvaluateExpression(e.Expression); } - internal LuaType EvaluateExpression(BoundExpression e) + internal ScriptType EvaluateExpression(BoundExpression e) { switch (e.Kind) { @@ -177,7 +182,7 @@ namespace Upsilon.Evaluator } } - private LuaType EvaluateUnaryExpression(BoundUnaryExpression e) + private ScriptType EvaluateUnaryExpression(BoundUnaryExpression e) { var operand = EvaluateExpression(e.InExpression); switch (e.Operator.Kind) @@ -186,7 +191,7 @@ namespace Upsilon.Evaluator return operand; case BoundUnaryOperator.OperatorKind.Negation: if (operand.Type == Type.Number) - return -((Number)operand); + return -((ScriptNumber)operand); else if (operand.Type == Type.UserData) { var ud = (GenericUserData) operand; @@ -197,7 +202,7 @@ namespace Upsilon.Evaluator goto default; case BoundUnaryOperator.OperatorKind.LogicalNegation: if (operand.Type == Type.Boolean) - return !(LuaBoolean) operand; + return !(ScriptBoolean) operand; else if (operand.Type == Type.UserData) { var ud = (GenericUserData) operand; @@ -212,7 +217,7 @@ namespace Upsilon.Evaluator } } - private LuaType EvaluateBinaryExpression(BoundBinaryExpression e) + private ScriptType EvaluateBinaryExpression(BoundBinaryExpression e) { var left = EvaluateExpression(e.LeftExpression); var right = EvaluateExpression(e.RightExpression); @@ -220,10 +225,16 @@ namespace Upsilon.Evaluator { case BoundBinaryOperator.OperatorKind.Addition: if (left.Type == Type.Number) - return ((Number)left) + ((Number)right); + { + if (right.Type == Type.Number) + { + return ((ScriptNumber)left) + ((ScriptNumber)right); + } + goto default; + } else if (left.Type == Type.String) { - return ((LuaString) left) + right; + return ((ScriptString) left) + right; } else if (left.Type == Type.UserData) { @@ -236,7 +247,7 @@ namespace Upsilon.Evaluator case BoundBinaryOperator.OperatorKind.Subtraction: if (left.Type == Type.Number) { - return ((Number)left) - ((Number)right); + return ((ScriptNumber)left) - ((ScriptNumber)right); } else if (left.Type == Type.UserData) { @@ -249,7 +260,7 @@ namespace Upsilon.Evaluator case BoundBinaryOperator.OperatorKind.Multiplication: if (left.Type == Type.Number) { - return ((Number)left) * ((Number)right); + return ((ScriptNumber)left) * ((ScriptNumber)right); } else if (left.Type == Type.UserData) { @@ -262,7 +273,7 @@ namespace Upsilon.Evaluator case BoundBinaryOperator.OperatorKind.Division: if (left.Type == Type.Number) { - return ((Number)left) / ((Number)right); + return ((ScriptNumber)left) / ((ScriptNumber)right); } else if (left.Type == Type.UserData) { @@ -273,9 +284,9 @@ namespace Upsilon.Evaluator } goto default; case BoundBinaryOperator.OperatorKind.Equality: - return new LuaBoolean(Equals(left, right)); + return new ScriptBoolean(Equals(left, right)); case BoundBinaryOperator.OperatorKind.Inequality: - return new LuaBoolean(!Equals(left, right)); + return new ScriptBoolean(!Equals(left, right)); default: throw new Exception("Invalid Binary Operator: " + e.Operator); } @@ -286,7 +297,7 @@ namespace Upsilon.Evaluator var val = EvaluateExpression(e.BoundExpression); if (e.Variable.Local) { - Scope.Set(e.Variable, val); + Scope.Set(e.Variable, val, true); } else { @@ -307,9 +318,9 @@ namespace Upsilon.Evaluator continue; if (variableSymbol.Name == "_") continue; - var value = table.Get(_diagnostics, e.Span, new NumberLong(i + 1), Scope); + var value = table.Get(_diagnostics, e.Span, new ScriptNumberLong(i + 1), Scope); if (variableSymbol.Local) - Scope.Set(variableSymbol, value); + Scope.Set(variableSymbol, value, true); else Scope.SetGlobal(variableSymbol, value); } @@ -321,7 +332,7 @@ namespace Upsilon.Evaluator _lastValue = val; } - private LuaType EvaluateVariableExpression(BoundVariableExpression e) + private ScriptType EvaluateVariableExpression(BoundVariableExpression e) { if (Scope.TryGet(e.Variable, out var val)) { @@ -345,7 +356,7 @@ namespace Upsilon.Evaluator private void EvaluateBoundIfStatement(BoundIfStatement boundBlockStatement) { var condition = EvaluateExpression(boundBlockStatement.Condition.Expression); - if ((LuaBoolean) condition) + if ((ScriptBoolean) condition) { EvaluateStatement(boundBlockStatement.Block); } @@ -363,31 +374,31 @@ namespace Upsilon.Evaluator { var func = EvaluateBoundFunctionStatement(e.Func); if (e.Variable.Local) - Scope.Set(e.Variable, func); + Scope.Set(e.Variable, func, true); else Scope.SetGlobal(e.Variable, func); } - private LuaType EvaluateBoundFunctionStatement(BoundFunctionExpression boundFunctionExpression) + private ScriptType EvaluateBoundFunctionStatement(BoundFunctionExpression boundFunctionExpression) { - var func = new LuaInternalFunction(boundFunctionExpression.Parameters, boundFunctionExpression.Block, Scope); + var func = new ScriptInternalFunction(boundFunctionExpression.Parameters, boundFunctionExpression.Block, Scope); return func; } - private LuaType EvaluateUnboundFunctionStatement(UnboundFunctionExpression unboundFunctionExpression) + private ScriptType EvaluateUnboundFunctionStatement(UnboundFunctionExpression unboundFunctionExpression) { - var func = new LuaInternalFunction(unboundFunctionExpression.Parameters, unboundFunctionExpression.Block, Scope); + var func = new ScriptInternalFunction(unboundFunctionExpression.Parameters, unboundFunctionExpression.Block, Scope); return func; } - private LuaType EvaluateBoundFunctionCallExpression(BoundFunctionCallExpression boundFunctionCallExpression) + private ScriptType EvaluateBoundFunctionCallExpression(BoundFunctionCallExpression boundFunctionCallExpression) { var variable = EvaluateExpression(boundFunctionCallExpression.Identifier); - if (!(variable is LuaFunction function)) + if (!(variable is ScriptFunction function)) { throw new Exception($"Variable is not a function."); } - var ls = new List(); + var ls = new List(); foreach (var t in boundFunctionCallExpression.Parameters) { var evaluate = EvaluateExpression(t); @@ -405,7 +416,7 @@ namespace Upsilon.Evaluator HasReturned = true; } - private LuaType EvaluateTableExpression(BoundTableExpression e) + private ScriptType EvaluateTableExpression(BoundTableExpression e) { var tableScope = EvaluationScope.CreateWithGetOnlyParent(Scope); var innerEvaluator = new Evaluator(_diagnostics, tableScope); @@ -424,7 +435,7 @@ namespace Upsilon.Evaluator innerEvaluator.EvaluateStatement(boundStatement); if (innerEvaluator._lastValue != null) tableScope.Set(new VariableSymbol(currentPos.ToString(), innerEvaluator._lastValue.Type, false), - innerEvaluator._lastValue); + innerEvaluator._lastValue, true); innerEvaluator._lastValue = null; break; } @@ -432,10 +443,10 @@ namespace Upsilon.Evaluator currentPos++; } - return new LuaTable(tableScope); + return new ScriptTable(tableScope); } - private LuaType EvaluateIndexExpression(BoundIndexExpression e) + private ScriptType EvaluateIndexExpression(BoundIndexExpression e) { var variable = EvaluateExpression(e.Identifier); if (!(variable is IIndexable indexable)) @@ -451,7 +462,7 @@ namespace Upsilon.Evaluator var indexer = EvaluateExpression(e.Index); return indexable.Get(_diagnostics, e.Span, indexer, scope); } - private LuaType EvaluateFullStopIndexExpression(BoundFullStopIndexExpression e) + private ScriptType EvaluateFullStopIndexExpression(BoundFullStopIndexExpression e) { var variable = EvaluateExpression(e.Expression); if (!(variable is IIndexable indexable)) @@ -470,8 +481,8 @@ namespace Upsilon.Evaluator private void EvaluateTableAssignmentStatement(BoundTableAssigmentStatement e) { - LuaType table; - LuaType index; + ScriptType table; + ScriptType index; if (e.TableIndexExpression.Kind == BoundKind.BoundIndexExpression) { table = EvaluateExpression(((BoundIndexExpression)e.TableIndexExpression).Identifier); @@ -494,13 +505,13 @@ namespace Upsilon.Evaluator private void EvaluateNumericForStatement(BoundNumericForStatement e) { var innerEvaluator = new Evaluator(_diagnostics, Scope); - var startVal = (NumberLong)innerEvaluator.EvaluateExpression(e.BoundStart); - innerEvaluator.Scope.Set(e.Variable, startVal); - var stopVal = (NumberLong)innerEvaluator.EvaluateExpression(e.BoundStop); + var startVal = (ScriptNumberLong)innerEvaluator.EvaluateExpression(e.BoundStart); + innerEvaluator.Scope.Set(e.Variable, startVal, true); + var stopVal = (ScriptNumberLong)innerEvaluator.EvaluateExpression(e.BoundStop); long step = 1; if (e.BoundStep != null) { - var stepVal = (NumberLong)innerEvaluator.EvaluateExpression(e.BoundStep); + var stepVal = (ScriptNumberLong)innerEvaluator.EvaluateExpression(e.BoundStep); step = stepVal.Value; } @@ -523,5 +534,32 @@ namespace Upsilon.Evaluator } } } + + private void EvaluateGenericForStatement(BoundGenericForStatement e) + { + var innerEvaluator = new Evaluator(_diagnostics, Scope); + var enumeratorObject = EvaluateExpression(e.BoundEnumerableExpression); + if (!(enumeratorObject is IIterable iterable)) + { + throw new Exception($"Can't iterate over object with type '{enumeratorObject.Type}'"); + } + + using (var enumerator = iterable.GetEnumerator()) + { + bool first = true; + while (enumerator.MoveNext()) + { + var (key, value) = enumerator.Current; + if (e.Variables[0].Name != "_") + innerEvaluator.Scope.Set(e.Variables[0], key.ToLuaType(), first); + if (e.Variables[1].Name != "_") + innerEvaluator.Scope.Set(e.Variables[1], value, first); + innerEvaluator.EvaluateBoundBlockStatement((BoundBlockStatement) e.Block); + if (innerEvaluator.HasBroken) + break; + first = false; + } + } + } } } \ No newline at end of file diff --git a/Upsilon/Evaluator/Script.cs b/Upsilon/Evaluator/Script.cs index 270a855..2881bf9 100644 --- a/Upsilon/Evaluator/Script.cs +++ b/Upsilon/Evaluator/Script.cs @@ -64,7 +64,7 @@ namespace Upsilon.Evaluator public object EvaluateFunction(string functionName, object[] parameters = null) { - var luaParameters = ImmutableArray.CreateBuilder(); + var luaParameters = ImmutableArray.CreateBuilder(); if (parameters != null) { foreach (var parameter in parameters) @@ -75,7 +75,7 @@ namespace Upsilon.Evaluator return Convert(Evaluator.Evaluate(Bind(), functionName, luaParameters.ToImmutable())); } - private static T Convert(LuaType t) + private static T Convert(ScriptType t) { if (typeof(T) == typeof(double)) return (T)(object)System.Convert.ToDouble(t.ToCSharpObject()); @@ -84,7 +84,7 @@ namespace Upsilon.Evaluator return (T) t.ToCSharpObject(); } - private static object Convert(LuaType t) + private static object Convert(ScriptType t) { return t?.ToCSharpObject(); } @@ -98,7 +98,7 @@ namespace Upsilon.Evaluator public T EvaluateFunction(string functionName, object[] parameters = null) { - var luaParameters = ImmutableArray.CreateBuilder(); + var luaParameters = ImmutableArray.CreateBuilder(); if (parameters != null) { foreach (var parameter in parameters) diff --git a/Upsilon/Parser/Parser.cs b/Upsilon/Parser/Parser.cs index c1e03cc..25cd513 100644 --- a/Upsilon/Parser/Parser.cs +++ b/Upsilon/Parser/Parser.cs @@ -166,13 +166,29 @@ namespace Upsilon.Parser var doToken = MatchToken(SyntaxKind.DoKeyword); var block = ParseBlockStatement(new []{SyntaxKind.EndKeyword}); var endToken = MatchToken(SyntaxKind.EndKeyword); - return new NumericForStatementSyntax(forToken, identifier, equals, v1, comma1, v2, comma2, v3, doToken, - block, endToken); + return new NumericForStatementSyntax(forToken, identifier, equals, v1, comma1, + v2, comma2, v3, doToken, block, endToken); } private StatementSyntax ParseGenericForStatement(SyntaxToken forToken) { - throw new NotImplementedException(); + var arr = ImmutableArray.CreateBuilder(); + while (true) + { + var identifier = MatchToken(SyntaxKind.Identifier); + arr.Add((IdentifierToken) identifier); + if (Current.Kind == SyntaxKind.InKeyword) + break; + MatchToken(SyntaxKind.Comma); + } + + var inKeyword = MatchToken(SyntaxKind.InKeyword); + var enumerableExpression = ParseExpression(); + var doKeyword = MatchToken(SyntaxKind.DoKeyword); + var block = ParseBlockStatement(new[] {SyntaxKind.EndKeyword}); + var endKeyword = MatchToken(SyntaxKind.EndKeyword); + return new GenericForStatementSyntax(forToken, arr.ToImmutable(), inKeyword, enumerableExpression, + doKeyword, (BlockStatementSyntax) block, endKeyword); } private ExpressionSyntax ParseFunctionExpression() diff --git a/Upsilon/Parser/StatementSyntax/GenericForStatementSyntax.cs b/Upsilon/Parser/StatementSyntax/GenericForStatementSyntax.cs new file mode 100644 index 0000000..9acacce --- /dev/null +++ b/Upsilon/Parser/StatementSyntax/GenericForStatementSyntax.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using System.Collections.Immutable; + +namespace Upsilon.Parser +{ + public class GenericForStatementSyntax : StatementSyntax + { + public SyntaxToken ForKeyword { get; } + public ImmutableArray Variables { get; } + public SyntaxToken InKeyword { get; } + public ExpressionSyntax EnumerableExpression { get; } + public SyntaxToken DoKeyword { get; } + public BlockStatementSyntax Block { get; } + public SyntaxToken EndKeyword { get; } + + public GenericForStatementSyntax(SyntaxToken forKeyword, ImmutableArray variables, SyntaxToken inKeyword, + ExpressionSyntax enumerableExpression, SyntaxToken doKeyword, BlockStatementSyntax block, SyntaxToken endKeyword) + { + ForKeyword = forKeyword; + Variables = variables; + InKeyword = inKeyword; + EnumerableExpression = enumerableExpression; + DoKeyword = doKeyword; + Block = block; + EndKeyword = endKeyword; + } + + public override SyntaxKind Kind => SyntaxKind.GenericForStatement; + public override IEnumerable ChildNodes() + { + yield return ForKeyword; + foreach (var identifierToken in Variables) + yield return identifierToken; + yield return InKeyword; + yield return EnumerableExpression; + yield return DoKeyword; + yield return Block; + yield return EndKeyword; + } + } +} \ No newline at end of file diff --git a/Upsilon/Parser/SyntaxKind.cs b/Upsilon/Parser/SyntaxKind.cs index 8f5ff18..ef3b43b 100644 --- a/Upsilon/Parser/SyntaxKind.cs +++ b/Upsilon/Parser/SyntaxKind.cs @@ -78,6 +78,7 @@ namespace Upsilon.Parser FunctionAssignmentStatement, TableAssignmentStatement, NumericForStatement, - BreakStatement + BreakStatement, + GenericForStatement } } \ No newline at end of file diff --git a/Upsilon/StandardLibraries/BasicFunctions.cs b/Upsilon/StandardLibraries/BasicFunctions.cs index 255e43f..0b32de6 100644 --- a/Upsilon/StandardLibraries/BasicFunctions.cs +++ b/Upsilon/StandardLibraries/BasicFunctions.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; using Upsilon.BaseTypes; -using Upsilon.BaseTypes.LuaTypeInterfaces; +using Upsilon.BaseTypes.Number; +using Upsilon.BaseTypes.ScriptTypeInterfaces; +using Type = Upsilon.BaseTypes.Type; // ReSharper disable UnusedMember.Global // ReSharper disable MemberCanBePrivate.Global @@ -25,15 +27,29 @@ namespace Upsilon.StandardLibraries throw new Exception(message); } + /* [LuaFunction("ipairs")] - public LuaType Pairs(IIterable table) + public ScriptType Pairs(IIterable table) { if (!table.Next(out var key, out var next)) { - return new LuaNull(); + return new ScriptNull(); } - return new SimpleLuaTable(new List() {key, next}); + return new SimpleScriptTable(new List() {key, next}); + }*/ + + [LuaFunction("tonumber")] + public ScriptNumber ToNumber(string str) + { + if (str.Contains(".")) + { + return new ScriptNumberDouble(double.Parse(str)); + } + else + { + return new ScriptNumberLong(long.Parse(str)); + } } } } \ No newline at end of file diff --git a/Upsilon/StandardLibraries/LuaLibrary.cs b/Upsilon/StandardLibraries/LuaLibrary.cs index ad57039..d4453f1 100644 --- a/Upsilon/StandardLibraries/LuaLibrary.cs +++ b/Upsilon/StandardLibraries/LuaLibrary.cs @@ -7,16 +7,16 @@ namespace Upsilon.StandardLibraries { internal abstract class LuaLibrary { - public Dictionary LoadMethods() + public Dictionary LoadMethods() { - var dictionary = new Dictionary(); + var dictionary = new Dictionary(); var methods = GetType().GetMethods(); foreach (var methodInfo in methods) { var attr = methodInfo.GetCustomAttribute(); if (attr != null) { - dictionary.Add(attr.Name, new LuaMethodInfoFunction(new UserDataMethod(methodInfo), this)); + dictionary.Add(attr.Name, new ScriptMethodInfoFunction(new UserDataMethod(methodInfo), this)); } } diff --git a/Upsilon/StandardLibraries/StaticScope.cs b/Upsilon/StandardLibraries/StaticScope.cs index 0131a07..fd0cc4e 100644 --- a/Upsilon/StandardLibraries/StaticScope.cs +++ b/Upsilon/StandardLibraries/StaticScope.cs @@ -42,7 +42,7 @@ namespace Upsilon.StandardLibraries public static (EvaluationScope, BoundScope) CreateStandardLibrary() { var basicFunctions = new BasicFunctions().LoadMethods(); - var scope = new EvaluationScope(basicFunctions.ToDictionary(x => x.Key, x => (LuaType)x.Value)); + var scope = new EvaluationScope(basicFunctions.ToDictionary(x => x.Key, x => (ScriptType)x.Value)); var boundScope = new BoundScope( scope.Variables.ToDictionary(x => x.Key @@ -56,7 +56,7 @@ namespace Upsilon.StandardLibraries var luaVariable = value.ToLuaType(); var varSymbol = new VariableSymbol(name, luaVariable.Type, false); BoundScope.SetVariable(varSymbol); - Scope.Set(varSymbol, luaVariable); + Scope.Set(varSymbol, luaVariable, true); } } } \ No newline at end of file diff --git a/UpsilonTests/GeneralTests/ForLoopTests.cs b/UpsilonTests/GeneralTests/ForLoopTests.cs index bdda217..0a6a499 100644 --- a/UpsilonTests/GeneralTests/ForLoopTests.cs +++ b/UpsilonTests/GeneralTests/ForLoopTests.cs @@ -79,5 +79,42 @@ return a Assert.Equal(15, result); } + [Fact] + public void GenericForLoopValueTest() + { + const string input = @" +arr = {100, 56, 28} +value = 0 +for key, val in arr do + value = value + val +end +return value +"; + var script = new Script(input, BoundScope, StaticScope); + Assert.Empty(script.Diagnostics.Messages); + var result = script.Evaluate(); + Assert.Empty(script.Diagnostics.Messages); + Assert.Equal(184, result); + } + + [Fact] + public void GenericForLoopKeyTest() + { + const string input = @" +arr = {100, 56, 28} +value = 0 +for key, val in arr do + local keyInt = tonumber(key) + value = value + keyInt +end +return value +"; + var script = new Script(input, BoundScope, StaticScope); + Assert.Empty(script.Diagnostics.Messages); + var result = script.Evaluate(); + Assert.Empty(script.Diagnostics.Messages); + Assert.Equal(6, result); + } + } } \ No newline at end of file